diff --git a/packages/tc-api-express/index.js b/packages/tc-api-express/index.js index a423402f9..9ed13b89b 100644 --- a/packages/tc-api-express/index.js +++ b/packages/tc-api-express/index.js @@ -52,14 +52,13 @@ const getApp = async (options = {}) => { router.use(bodyParsers); router.use(restPath, restMiddlewares, getRestApi(options)); router.use(errorToErrors); - + schema.init(schemaOptions); const { isSchemaUpdating, graphqlHandler, listenForSchemaChanges: updateGraphqlApiOnSchemaChange, } = getGraphqlApi(options); - schema.init(); updateGraphqlApiOnSchemaChange(); updateConstraintsOnSchemaChange(); @@ -83,14 +82,12 @@ const getApp = async (options = {}) => { availableEvents, }; - schema.init(schemaOptions); updateGraphqlApiOnSchemaChange(); // avoids this running in every single spec file // instead we explictly set up the constraints once before we start the test suite if (!process.env.TREECREEPER_TEST) { updateConstraintsOnSchemaChange(); } - await schema.ready(); return app; diff --git a/packages/tc-schema-sdk/README.md b/packages/tc-schema-sdk/README.md index abd99b35f..e68a4b6d7 100644 --- a/packages/tc-schema-sdk/README.md +++ b/packages/tc-schema-sdk/README.md @@ -15,6 +15,15 @@ The package exports a singleton instance, and once initialised, `@financial-time ### Initialisation +This is a little odd (and should be improved in future) + +- When using local, static data (`schemaDirectory` or `schemaData` options below), the `init()` method populates the sdk with data immediately and its methods can be used to access the data immediately +- When using remote data (`schemaBaseUrl`), no data is populated, and `schema.ready()` must be awaited before using the sdk's synchronous methods. + +Be aware of the idiosyncrasy above if you ever come across errors complaining that no data is available. + +### `init(options)` + The package exports an `init(options)` function, that takes the following options: - `schemaDirectory` - absolute path to a directory that contains schema files as yaml. Will use the `TREECREEPER_SCHEMA_DIRECTORY` environment variable if defined. This is the preferred way of specifying the directory diff --git a/packages/tc-schema-sdk/browser.js b/packages/tc-schema-sdk/browser.js index e633af8fe..ad8eaae12 100644 --- a/packages/tc-schema-sdk/browser.js +++ b/packages/tc-schema-sdk/browser.js @@ -1,5 +1,5 @@ const { SDK } = require('./sdk'); -module.exports = new SDK({ init: false }); +module.exports = new SDK(); module.exports.SDK = SDK; diff --git a/packages/tc-schema-sdk/lib/__tests__/polling.spec.js b/packages/tc-schema-sdk/lib/__tests__/polling.spec.js index 59a5abe5d..ebd2b1c12 100644 --- a/packages/tc-schema-sdk/lib/__tests__/polling.spec.js +++ b/packages/tc-schema-sdk/lib/__tests__/polling.spec.js @@ -8,7 +8,11 @@ const { RawDataWrapper } = require('../raw-data-wrapper'); const { Cache } = require('../cache'); const create = options => - new SchemaUpdater(options, new RawDataWrapper(), new Cache()); + new SchemaUpdater({ + options, + rawData: new RawDataWrapper(), + cache: new Cache(), + }); const nextTick = () => new Promise(res => process.nextTick(res)); diff --git a/packages/tc-schema-sdk/lib/__tests__/stale.spec.js b/packages/tc-schema-sdk/lib/__tests__/stale.spec.js index 4e5f66507..4c0ed290e 100644 --- a/packages/tc-schema-sdk/lib/__tests__/stale.spec.js +++ b/packages/tc-schema-sdk/lib/__tests__/stale.spec.js @@ -7,7 +7,11 @@ const { RawDataWrapper } = require('../raw-data-wrapper'); const { Cache } = require('../cache'); const create = options => - new SchemaUpdater(options, new RawDataWrapper(), new Cache()); + new SchemaUpdater({ + options, + rawData: new RawDataWrapper(), + cache: new Cache(), + }); const timer = delay => new Promise(res => setTimeout(res, delay)); const nextTick = () => new Promise(res => process.nextTick(res)); diff --git a/packages/tc-schema-sdk/lib/__tests__/validate-code.spec.js b/packages/tc-schema-sdk/lib/__tests__/validate-code.spec.js index c8445a1ba..3f9e45b42 100644 --- a/packages/tc-schema-sdk/lib/__tests__/validate-code.spec.js +++ b/packages/tc-schema-sdk/lib/__tests__/validate-code.spec.js @@ -1,4 +1,4 @@ -const { SDK } = require('../../sdk'); +const { SDK } = require('../..'); describe('validateCode', () => { const { diff --git a/packages/tc-schema-sdk/lib/__tests__/validate-property-name.spec.js b/packages/tc-schema-sdk/lib/__tests__/validate-property-name.spec.js index e4c566b61..e2c70a068 100644 --- a/packages/tc-schema-sdk/lib/__tests__/validate-property-name.spec.js +++ b/packages/tc-schema-sdk/lib/__tests__/validate-property-name.spec.js @@ -1,4 +1,4 @@ -const { SDK } = require('../../sdk'); +const { SDK } = require('../..'); describe('validatePropertyName', () => { const { diff --git a/packages/tc-schema-sdk/lib/__tests__/validate-property.spec.js b/packages/tc-schema-sdk/lib/__tests__/validate-property.spec.js index 472f90817..cf597114d 100644 --- a/packages/tc-schema-sdk/lib/__tests__/validate-property.spec.js +++ b/packages/tc-schema-sdk/lib/__tests__/validate-property.spec.js @@ -1,4 +1,4 @@ -const { SDK } = require('../../sdk'); +const { SDK } = require('../..'); const readYaml = require('../read-yaml'); const getValidator = (type, { enums, relationshipTypes } = {}) => { diff --git a/packages/tc-schema-sdk/lib/__tests__/validate-type-name.spec.js b/packages/tc-schema-sdk/lib/__tests__/validate-type-name.spec.js index 9acc956b2..d7c9e5ba5 100644 --- a/packages/tc-schema-sdk/lib/__tests__/validate-type-name.spec.js +++ b/packages/tc-schema-sdk/lib/__tests__/validate-type-name.spec.js @@ -1,4 +1,4 @@ -const { SDK } = require('../../sdk'); +const { SDK } = require('../..'); describe('validateTypeName', () => { const { diff --git a/packages/tc-schema-sdk/lib/updater.js b/packages/tc-schema-sdk/lib/updater.js index 5a3960ba6..bb2fb7b1e 100644 --- a/packages/tc-schema-sdk/lib/updater.js +++ b/packages/tc-schema-sdk/lib/updater.js @@ -2,13 +2,15 @@ const EventEmitter = require('events'); const fetch = require('node-fetch'); class SchemaUpdater { - constructor(options, rawData, cache, readYaml) { + constructor({ options, rawData, cache, readYaml }) { this.eventEmitter = new EventEmitter(); this.lastRefreshDate = 0; this.rawData = rawData; this.cache = cache; this.readYaml = readYaml; - this.configure(options); + if (options) { + this.configure(options); + } } configure({ diff --git a/packages/tc-schema-sdk/sdk.js b/packages/tc-schema-sdk/sdk.js index 911e99073..6d722089d 100644 --- a/packages/tc-schema-sdk/sdk.js +++ b/packages/tc-schema-sdk/sdk.js @@ -14,12 +14,17 @@ const { SchemaUpdater } = require('./lib/updater'); const utils = require('./lib/utils'); class SDK { - constructor(options = {}) { + constructor(options) { this.cache = new Cache(); this.rawData = new RawDataWrapper(); - this.TreecreeperUserError = TreecreeperUserError; - this.subscribers = []; + this.updater = new SchemaUpdater({ + options, + rawData: this.rawData, + cache: this.cache, + readYaml: this.readYaml, + }); + this.TreecreeperUserError = TreecreeperUserError; this.getEnums = this.createEnrichedAccessor(enums); this.getPrimitiveTypes = this.createEnrichedAccessor(primitiveTypes); this.getStringValidator = this.createEnrichedAccessor(stringValidator); @@ -40,10 +45,6 @@ class SDK { Object.entries(utils).forEach(([name, method]) => { this[name] = method.bind(this); }); - - if (options.init !== false) { - this.init(options); - } } createEnrichedAccessor({ accessor, cacheKeyGenerator }) { @@ -53,19 +54,8 @@ class SDK { ); } - async init(options) { - const schemaUpdater = new SchemaUpdater( - options, - this.rawData, - this.cache, - this.readYaml, - ); - - // hook up schema updater to this.cache then - schemaUpdater.on('change', data => { - this.subscribers.forEach(handler => handler(data)); - }); - this.updater = schemaUpdater; + init(options) { + return this.updater.configure(options); } async ready() { @@ -82,7 +72,7 @@ class SDK { if (this.rawData.isHydrated) { handler(event); } - this.subscribers.push(handler); + this.updater.on('change', handler); } } diff --git a/packages/tc-schema-sdk/server.js b/packages/tc-schema-sdk/server.js index f93bb3a12..8f2a7e3d6 100644 --- a/packages/tc-schema-sdk/server.js +++ b/packages/tc-schema-sdk/server.js @@ -1,5 +1,5 @@ const { SDK } = require('./sdk'); SDK.prototype.readYaml = require('./lib/read-yaml'); -module.exports = new SDK({ init: false }); +module.exports = new SDK(); module.exports.SDK = SDK; diff --git a/packages/tc-schema-validator/tests/enums.js b/packages/tc-schema-validator/tests/enums.js index 7276b2fda..f1935c527 100644 --- a/packages/tc-schema-validator/tests/enums.js +++ b/packages/tc-schema-validator/tests/enums.js @@ -1,7 +1,9 @@ /* global it, describe, expect */ const { SDK } = require('@financial-times/tc-schema-sdk'); -const enums = new SDK().rawData.getEnums(); +const sdk = new SDK(); +sdk.init(); +const enums = sdk.rawData.getEnums(); describe('enums', () => { Object.entries(enums).forEach(([name, { description, options }]) => { diff --git a/packages/tc-schema-validator/tests/primitive-types.js b/packages/tc-schema-validator/tests/primitive-types.js index ce1cb4367..92992e128 100644 --- a/packages/tc-schema-validator/tests/primitive-types.js +++ b/packages/tc-schema-validator/tests/primitive-types.js @@ -1,7 +1,9 @@ /* global it, describe, expect */ const { SDK } = require('@financial-times/tc-schema-sdk'); -const primitiveTypes = new SDK().rawData.getPrimitiveTypes(); +const sdk = new SDK(); +sdk.init(); +const primitiveTypes = sdk.rawData.getPrimitiveTypes(); describe('primitive types', () => { Object.entries(primitiveTypes).forEach(([name, { component, graphql }]) => { diff --git a/packages/tc-schema-validator/tests/string-patterns.js b/packages/tc-schema-validator/tests/string-patterns.js index c5cb33908..fa81d7062 100644 --- a/packages/tc-schema-validator/tests/string-patterns.js +++ b/packages/tc-schema-validator/tests/string-patterns.js @@ -1,7 +1,9 @@ /* global it, describe, expect */ const { SDK } = require('@financial-times/tc-schema-sdk'); -const stringPatterns = new SDK().rawData.getStringPatterns(); +const sdk = new SDK(); +sdk.init(); +const stringPatterns = sdk.rawData.getStringPatterns(); const longString = 'x'.repeat(257); describe('string patterns', () => { diff --git a/packages/tc-schema-validator/tests/type-hierarchy.js b/packages/tc-schema-validator/tests/type-hierarchy.js index 537a64da9..46d5b61e0 100644 --- a/packages/tc-schema-validator/tests/type-hierarchy.js +++ b/packages/tc-schema-validator/tests/type-hierarchy.js @@ -2,6 +2,7 @@ const { SDK } = require('@financial-times/tc-schema-sdk'); const sdk = new SDK(); +sdk.init(); const { readYaml, rawData } = sdk; const typeHierarchy = rawData.getTypeHierarchy(); diff --git a/packages/tc-schema-validator/tests/type-test-suite.js b/packages/tc-schema-validator/tests/type-test-suite.js index 065fe87d2..55dd7504c 100644 --- a/packages/tc-schema-validator/tests/type-test-suite.js +++ b/packages/tc-schema-validator/tests/type-test-suite.js @@ -3,6 +3,7 @@ const validURL = require('valid-url'); const { SDK } = require('@financial-times/tc-schema-sdk'); const sdk = new SDK(); +sdk.init(); const primitiveTypesMap = sdk.getPrimitiveTypes(); const { getStringValidator } = sdk; const enums = sdk.rawData.getEnums(); diff --git a/packages/tc-schema-validator/tests/types.js b/packages/tc-schema-validator/tests/types.js index d7385ec51..78843a10a 100644 --- a/packages/tc-schema-validator/tests/types.js +++ b/packages/tc-schema-validator/tests/types.js @@ -5,6 +5,7 @@ const { SDK } = require('@financial-times/tc-schema-sdk'); const { typeTestSuite, relationshipTestSuite } = require('./type-test-suite'); const sdk = new SDK(); +sdk.init(); const { readYaml } = sdk; const makePath = dir =>