Skip to content

Commit

Permalink
Adding tests
Browse files Browse the repository at this point in the history
  • Loading branch information
cressie176 committed Jan 6, 2024
1 parent b20ee64 commit ea8a1e8
Show file tree
Hide file tree
Showing 13 changed files with 593 additions and 28 deletions.
10 changes: 4 additions & 6 deletions examples/migrations/0001.define-park-schema.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
define enums:

- name: park_calendar_event_type
values:
- Park Open - Owners
Expand All @@ -8,7 +7,6 @@ define enums:
- Park Close - Guests

define entities:

- name: park
version: 1
fields:
Expand Down Expand Up @@ -39,10 +37,10 @@ add projections:
- name: park
version: 1
dependencies:
- name: park
version: 1
- name: park_calendar
version: 1
- name: park
version: 1
- name: park_calendar
version: 1

add hooks:
- projection: park
Expand Down
2 changes: 1 addition & 1 deletion index.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ module.exports = class ReferenceDataFramework extends EventEmitter {

async #migrate(connection, directory) {
const migrations = await marv.scan(directory);
return marv.migrate(migrations, driver({ connection }));
await marv.migrate(migrations, driver({ connection }));
}

async startNotifications() {
Expand Down
39 changes: 33 additions & 6 deletions lib/marv-rdf-driver.js
Original file line number Diff line number Diff line change
@@ -1,14 +1,21 @@
const fs = require('fs');
const path = require('path');
const fs = require('node:fs');
const path = require('node:path');

const Ajv = require('ajv');
const addFormats = require("ajv-formats")
const YAML = require('yaml');
const Handlebars = require('handlebars');
const marvPgDriver = require('marv-pg-driver');

const schema = require('./schema');
const proxy = require('./proxy');
const helpers = require('./helpers');

const templateSource = fs.readFileSync(path.join(__dirname, 'template.hbs'), 'utf-8');
const template = Handlebars.compile(templateSource);
const template = fs.readFileSync(path.join(__dirname, 'template.hbs'), 'utf-8');
const render = Handlebars.compile(template);
const ajv = new Ajv();
addFormats(ajv);
const validate = ajv.compile(schema);

Handlebars.registerHelper(helpers);

Expand All @@ -18,13 +25,15 @@ module.exports = (options) => {

function runMigration(migration, cb) {
const fileType = getFileType(migration);

if (fileType === 'sql') return pgDriver.runMigration(migration, cb);

const script = parseMigrationScript(migration, fileType);
if (!validate(script)) throw createValidationError(validate);

decorateMigrationScript(script);

pgDriver.runMigration({ ...migration, script: template(script) }, cb);
const sql = render(script)
pgDriver.runMigration({ ...migration, script: sql }, cb);
}

function getFileType(migration) {
Expand All @@ -47,6 +56,24 @@ module.exports = (options) => {
}
};

function createValidationError(validate) {
let message;
const errors = validate.errors.filter((e => e.keyword !== 'oneOf'));
const instancePath = errors[0].instancePath || 'migration script';
switch (errors[0].keyword) {
case 'required': {
const missingProperties = errors.map(e => `'${e.params.missingProperty}'`).join(' or ');
message = `${instancePath} must have required property ${missingProperties}`;
break;
}
default: {
message = `${instancePath} ${errors[0].message.replace(/be object/, 'be an object')}`;
break;
}
}
return new Error(message);
}

function decorateMigrationScript(script) {
script.define_entities?.forEach((entity) => {
entity.table_name = entity.name.toLowerCase().replace(/\s/g, '_');
Expand Down
263 changes: 263 additions & 0 deletions lib/schema.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
{
"$schema": "http://json-schema.org/draft-07/schema#",
"title": "JSON Schema for RDF",
"type": "object",
"properties": {
"define enums": {
"$ref": "#/definitions/enumsType"
},
"define_enums": {
"$ref": "#/definitions/enumsType"
},
"define entities": {
"$ref": "#/definitions/entitiesType"
},
"define_entities": {
"$ref": "#/definitions/entitiesType"
},
"add projections": {
"$ref": "#/definitions/projectionsType"
},
"add_projections": {
"$ref": "#/definitions/projectionsType"
},
"add hooks": {
"$ref": "#/definitions/hooksType"
},
"add_hooks": {
"$ref": "#/definitions/hooksType"
},
"add change set": {
"$ref": "#/definitions/changeSetType"
},
"add_change_set": {
"$ref": "#/definitions/changeSetType"
}
},
"definitions": {
"enumsType": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"values": {
"type": "array",
"items": {
"type": "string"
}
}
},
"required": [
"name",
"values"
]
}
},
"entitiesType": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"version": {
"type": "integer"
},
"fields": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"type": {
"type": "string"
}
},
"required": [
"name",
"type"
]
}
},
"identified by": {
"type": "array",
"minItems": 1,
"items": {
"type": "string"
}
},
"checks": {
"type": "object",
"minProperties": 1,
"patternProperties": {
".+": {
"type": "string"
}
}
}
},
"oneOf": [
{
"required": [
"name",
"version",
"fields",
"identified by"
]
},
{
"required": [
"name",
"version",
"fields",
"identified_by"
]
}
]
}
},
"projectionsType": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"name": {
"type": "string"
},
"version": {
"type": "integer"
},
"dependencies": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"entity": {
"type": "string"
},
"version": {
"type": "integer"
}
},
"required": [
"entity",
"version"
]
}
}
},
"required": [
"name",
"version",
"dependencies"
]
}
},
"hooksType": {
"type": "array",
"items": {
"type": "object",
"properties": {
"projection": {
"type": "string"
},
"version": {
"type": "integer"
},
"event": {
"type": "string"
}
},
"oneOf": [
{
"required": [
"projection",
"version",
"event"
]
},
{
"required": [
"event"
]
}
]
}
},
"changeSetType": {
"type": "object",
"properties": {
"effective_from": {
"type": "string",
"format": "date-time"
},
"notes": {
"type": "string"
},
"frames": {
"type": "array",
"minItems": 1,
"items": {
"type": "object",
"properties": {
"entity": {
"type": "string"
},
"version": {
"type": "integer"
},
"action": {
"type": "string",
"enum": [
"POST",
"DELETE"
]
},
"data": {
"type": "array",
"minItems": 1,
"items": {
"type": "object"
}
}
},
"required": [
"entity",
"version",
"action",
"data"
]
}
}
},
"oneOf": [
{
"required": [
"effective_from",
"notes",
"frames"
]
},
{
"required": [
"effective from",
"notes",
"frames"
]
}
]
}
},
"required": []
}
4 changes: 2 additions & 2 deletions lib/template.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,11 @@ DECLARE

BEGIN
INSERT INTO rdf_projection (name, version) VALUES
('{{name}}', {{version}}){{#unless @last}}),{{/unless}}
('{{name}}', {{version}})
RETURNING id INTO v_projection_id;

{{#dependencies}}
SELECT id INTO v_entity_id FROM rdf_entity WHERE name = '{{name}}' AND version = {{version}};
SELECT id INTO v_entity_id FROM rdf_entity WHERE name = '{{entity}}' AND version = {{version}};

INSERT INTO rdf_projection_entity (projection_id, entity_id) VALUES
(v_projection_id, v_entity_id);
Expand Down
Loading

0 comments on commit ea8a1e8

Please sign in to comment.