Created
December 13, 2017 23:40
-
-
Save newhouse/c3b052a3548396274210827c6be66875 to your computer and use it in GitHub Desktop.
Objection.js: inconsistent typing of 'date-time' Model props
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
const _ = require('lodash'); | |
const objection = require('objection'); | |
const Model = objection.Model; | |
const knex = require('knex')({ | |
debug: false, | |
client: 'pg', | |
connection: 'INSERT CONNECTION STRING HERE', | |
pool: { | |
min: 2, | |
max: 2 | |
} | |
}); | |
Model.knex(knex); | |
/************************************************** | |
* ___ _ _ | |
* | \ __ _| |_ __ _| |__ __ _ ___ ___ | |
* | |) / _` | _/ _` | '_ \/ _` (_-</ -_) | |
* |___/\__,_|\__\__,_|_.__/\__,_/__/\___| | |
* | |
*/ | |
const createTables = () => { | |
return knex.schema.createTableIfNotExists('parents', table => { | |
table.string('id', 4).notNullable(); | |
table.timestamp('time').defaultTo(knex.fn.now()); | |
table.primary(['id']); | |
}) | |
.then(() => { | |
return knex.schema.createTableIfNotExists('children', table => { | |
table.string('id', 4).notNullable(); | |
table.string('parent_id', 4).references('parents.id').onDelete('CASCADE').notNullable(); | |
table.timestamp('time').defaultTo(knex.fn.now()); | |
table.primary(['id']); | |
}); | |
}); | |
}; | |
const dropTables = () => { | |
return knex.schema.dropTableIfExists('children') | |
.then(() => { | |
return knex.schema.dropTableIfExists('parents'); | |
}); | |
}; | |
/************************************************** | |
* __ __ _ _ | |
* | \/ |___ __| |___| |___ | |
* | |\/| / _ \/ _` / -_) (_-< | |
* |_| |_\___/\__,_\___|_/__/ | |
* | |
*/ | |
class Parent extends Model { | |
static get tableName() { | |
return 'parents'; | |
} | |
static get jsonSchema() { | |
return { | |
type: 'object', | |
required: ['id'], | |
properties: { | |
id: { | |
type: 'string', | |
maxLength: 4 | |
}, | |
time: { | |
type: 'string', | |
format: 'date-time' | |
} | |
} | |
}; | |
} | |
static get relationMappings() { | |
return { | |
children: { | |
relation: Model.HasManyRelation, | |
modelClass: Child, | |
join: { | |
from: 'parents.id', | |
to: 'children.parent_id' | |
} | |
} | |
}; | |
} | |
} | |
class Child extends Model { | |
static get tableName() { | |
return 'children'; | |
} | |
static get jsonSchema() { | |
return { | |
type: 'object', | |
required: ['id', 'parent_id'], | |
properties: { | |
id: { | |
type: 'string', | |
maxLength: 4 | |
}, | |
parent_id: { | |
type: 'string', | |
maxLength: 4 | |
}, | |
time: { | |
type: 'string', | |
format: 'date-time' | |
} | |
} | |
}; | |
} | |
} | |
// Let us know if things look weird. | |
function checkForNonString(things, where) { | |
if (things.constructor.name !== 'Array') { | |
things = [things]; | |
} | |
let ok = true; | |
for (let i=0; i < things.length; i++) { | |
const thing = things[i]; | |
if (typeof thing.time !== 'string') { | |
const msg = `** ${where}'s "time" is NOT a string:`; | |
console.log(msg); | |
// console.log({time: thing.time}); | |
// throw new Error(msg); | |
ok = false; | |
break; | |
} | |
} | |
if (ok) { | |
console.log(`All good in ${where}`); | |
} | |
} | |
const PARENT_ID = 'P1'; | |
const CHILD_ID_ONE = 'C1'; | |
const CHILD_ID_TWO = 'C2'; | |
// At no point am I using an object, just the String from it | |
const TIME = new Date().toISOString(); | |
// OH MAN, HERE WE GO | |
return dropTables() | |
.then(() => { | |
return createTables(); | |
}) | |
.then(() => { | |
// Insert a Parent alone | |
return Parent | |
.query() | |
.insert({ | |
id: PARENT_ID, | |
time: TIME | |
}) | |
}) | |
.then(parent => { | |
checkForNonString(parent, 'parent created by itself'); | |
// Insert a Child alone | |
return Child | |
.query() | |
.insert({ | |
id: CHILD_ID_ONE, | |
time: TIME, | |
parent_id: PARENT_ID | |
}); | |
}) | |
.then(child => { | |
checkForNonString(child, 'child created by itself'); | |
// Delete it all to begin again | |
return Parent.query().delete(); | |
}) | |
.then(() => { | |
// Graph insert a Parent and a Child | |
return Parent | |
.query() | |
.insertGraph({ | |
id: PARENT_ID, | |
time: TIME, | |
children: [ | |
{ | |
id: CHILD_ID_ONE, | |
time: TIME | |
} | |
] | |
}) | |
.returning('*'); | |
}) | |
.then(parent => { | |
checkForNonString(parent, 'parent created during graph insert'); | |
checkForNonString(parent.children, 'children created during graph insert'); | |
// Directly query for a Parent using where | |
return Parent | |
.query() | |
.where({ | |
id: PARENT_ID | |
}) | |
.limit(1) | |
.first(); | |
}) | |
.then(parent => { | |
checkForNonString(parent, 'parent queried directly with where'); | |
// Directly query for a Parent using findById | |
return Parent | |
.query() | |
.findById(PARENT_ID); | |
}) | |
.then(parent => { | |
checkForNonString(parent, 'parent queried directly with findById'); | |
// Eager query for some Children | |
return Parent | |
.query() | |
.eager('children') | |
.findById(PARENT_ID); | |
}) | |
.then(parent => { | |
checkForNonString(parent, 'parent fetched having an eager'); | |
checkForNonString(parent.children, 'children fetched via eager'); | |
// Load it up from JSON - This is what led me to this bug | |
const childFromJson = Child.fromJson({ | |
id: CHILD_ID_ONE, | |
parent_id: PARENT_ID, | |
time: TIME | |
}); | |
checkForNonString(childFromJson, 'child created via fromJson'); | |
return dropTables(); | |
}) | |
.catch(err => { | |
console.warn(err); | |
return dropTables(); | |
}) | |
.then(() => { | |
process.exit(); | |
}) | |
.catch(err => { | |
console.log(err); | |
process.exit(); | |
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"name": "objection-formatDatabaseJson", | |
"version": "0.0.1", | |
"description": "Objection 4-eva", | |
"main": "main.js", | |
"scripts": { | |
"start": "node ./app.js" | |
}, | |
"engines": { | |
"node": "6.11.1" | |
}, | |
"dependencies": { | |
"knex": "0.12.6", | |
"lodash": "latest", | |
"objection": "0.7.12", | |
"pg": "^6.1.0" | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment