diff --git a/.changeset/modern-walls-hammer.md b/.changeset/modern-walls-hammer.md new file mode 100644 index 00000000..7d496e31 --- /dev/null +++ b/.changeset/modern-walls-hammer.md @@ -0,0 +1,6 @@ +--- +"@kopflos-cms/core": patch +"kopflos": patch +--- + +New plugin hook: `onReady` diff --git a/packages/cli/lib/command/serve.ts b/packages/cli/lib/command/serve.ts index 4908f7ad..94e0a375 100644 --- a/packages/cli/lib/command/serve.ts +++ b/packages/cli/lib/command/serve.ts @@ -49,6 +49,7 @@ async function run({ const server = app.listen(port, host, () => { log.info(`Server running on ${port}. API URL: ${config.baseIri}`) + instance.ready() }) if (config.watch) { diff --git a/packages/core/lib/Kopflos.ts b/packages/core/lib/Kopflos.ts index b8f7055f..b3d34836 100644 --- a/packages/core/lib/Kopflos.ts +++ b/packages/core/lib/Kopflos.ts @@ -65,6 +65,7 @@ export interface PluginConfig { export interface KopflosPlugin { readonly name?: string onStart?(): Promise | void + onReady?(): Promise | void onStop?(): Promise | void apiTriples?(): Promise | DatasetCore | Stream } @@ -121,6 +122,7 @@ export default class Impl implements Kopflos { readonly env: KopflosEnvironment readonly plugins: Array readonly start: () => Promise + readonly ready: () => Promise constructor({ variables = {}, ...config }: KopflosConfig, private readonly options: Options = {}) { this.env = createEnv({ variables, ...config }) @@ -148,6 +150,10 @@ export default class Impl implements Kopflos { this.start = onetime(async function (this: Impl) { await Promise.all(this.plugins.map(plugin => plugin.onStart?.())) }).bind(this) + + this.ready = onetime(async function (this: Impl) { + await Promise.all(this.plugins.map(plugin => plugin.onReady?.())) + }).bind(this) } get graph() { diff --git a/packages/core/test/lib/Kopflos.test.ts b/packages/core/test/lib/Kopflos.test.ts index 45ffe0b5..075a7488 100644 --- a/packages/core/test/lib/Kopflos.test.ts +++ b/packages/core/test/lib/Kopflos.test.ts @@ -752,6 +752,46 @@ describe('lib/Kopflos', () => { await instance.stop() }) }) + + describe('ready', () => { + it('calls onReady on plugins', async function () { + // given + const onReady = sinon.spy() + const plugin = class { + onReady = onReady + } + const instance = new Kopflos({ + ...config, + sparql: { + default: inMemoryClients(this.rdf), + }, + }, { + plugins: [plugin], + }) + + // when + await instance.ready() + + // then + expect(onReady).to.have.been.called + }) + + it('ignores plugins without onReady', async function () { + // given + const plugin = class {} + const instance = new Kopflos({ + ...config, + sparql: { + default: inMemoryClients(this.rdf), + }, + }, { + plugins: [plugin], + }) + + // when + await instance.ready() + }) + }) }) const testHandler: Handler = ({ subject, property, object }) => ({