diff --git a/packages/cli/src/lib/commands/push.ts b/packages/cli/src/lib/commands/push.ts index af331490..f30884e7 100644 --- a/packages/cli/src/lib/commands/push.ts +++ b/packages/cli/src/lib/commands/push.ts @@ -1,6 +1,11 @@ import { Container } from 'typedi'; import pino from 'pino'; -import { ConfigService, MigrationClient, SnapshotClient } from '../services'; +import { + ConfigService, + MigrationClient, + PingClient, + SnapshotClient, +} from '../services'; import { loadCollections } from '../loader'; import { LOGGER } from '../constants'; @@ -16,6 +21,10 @@ export async function runPush() { // Snapshot if (snapshotConfig.enabled) { + // Test if the directus extension is installed + // At this point, it could be not installed and cause an issue with the snapshot push + await Container.get(PingClient).test(); + logger.info(`---- Push schema ----`); await Container.get(SnapshotClient).push(); } else { diff --git a/packages/cli/src/lib/services/collections/base/id-mapper-client.ts b/packages/cli/src/lib/services/collections/base/id-mapper-client.ts index 5893b26a..4aba687d 100644 --- a/packages/cli/src/lib/services/collections/base/id-mapper-client.ts +++ b/packages/cli/src/lib/services/collections/base/id-mapper-client.ts @@ -1,5 +1,5 @@ import { MigrationClient } from '../../migration-client'; -import { ExtensionClient } from '../../extension-client'; +import { ExtensionClient, NO_ID_MAP_MESSAGE } from '../../extension-client'; import pino from 'pino'; export interface IdMap { @@ -40,7 +40,7 @@ export abstract class IdMapperClient extends ExtensionClient { const idMap = await this.fetch( `/table/${this.table}/sync_id/${syncId}`, ).catch((error) => { - if (error.message === 'No id map found') { + if (error.message === NO_ID_MAP_MESSAGE) { return undefined; } throw error; @@ -62,7 +62,7 @@ export abstract class IdMapperClient extends ExtensionClient { const idMap = await this.fetch( `/table/${this.table}/local_id/${localId}`, ).catch((error) => { - if (error.message === 'No id map found') { + if (error.message === NO_ID_MAP_MESSAGE) { return undefined; } throw error; diff --git a/packages/cli/src/lib/services/extension-client.ts b/packages/cli/src/lib/services/extension-client.ts index dab2d7c0..42571baa 100644 --- a/packages/cli/src/lib/services/extension-client.ts +++ b/packages/cli/src/lib/services/extension-client.ts @@ -2,6 +2,8 @@ import createHttpError from 'http-errors'; import { MigrationClient } from './migration-client'; import { Cacheable } from 'typescript-cacheable'; +export const NO_ID_MAP_MESSAGE = 'No id map found'; + /** * This class provides an interface to interact with the Directus extension sync endpoints. */ diff --git a/packages/cli/src/lib/services/index.ts b/packages/cli/src/lib/services/index.ts index 7bcab2fb..c5604499 100644 --- a/packages/cli/src/lib/services/index.ts +++ b/packages/cli/src/lib/services/index.ts @@ -1,6 +1,7 @@ export * from './config'; export * from './migration-client'; export * from './extension-client'; +export * from './ping-client'; export * from './helpers-client'; export * from './snapshot'; export * from './specifications'; diff --git a/packages/cli/src/lib/services/ping-client.ts b/packages/cli/src/lib/services/ping-client.ts new file mode 100644 index 00000000..0d0a840b --- /dev/null +++ b/packages/cli/src/lib/services/ping-client.ts @@ -0,0 +1,30 @@ +import { ExtensionClient, NO_ID_MAP_MESSAGE } from './extension-client'; +import { MigrationClient } from './migration-client'; +import { Service } from 'typedi'; + +@Service() +export class PingClient extends ExtensionClient { + constructor(migrationClient: MigrationClient) { + super(migrationClient); + } + + /** Try to get a fake id map in order to check if the server is up and the extension is installed */ + async test() { + const response = await this.fetch( + `/table/__ping_test__/sync_id/__ping_test__`, + 'GET', + ) + .then(() => ({ success: true })) + .catch((error: Error) => ({ error })); + + if ('success' in response) { + return; // Should not happen + } + + if (response.error.message === NO_ID_MAP_MESSAGE) { + return; + } + + throw response.error; + } +} diff --git a/packages/e2e/spec/config/config-path-info.ts b/packages/e2e/spec/config/config-path-info.ts index 72e5c1cb..ccb6160c 100644 --- a/packages/e2e/spec/config/config-path-info.ts +++ b/packages/e2e/spec/config/config-path-info.ts @@ -9,10 +9,10 @@ export const configPathInfo = (context: Context) => { ); const output = await sync.diff(); - const first = output.shift(); + const log = output.find((l) => l.msg.includes('No config file found')); - expect(first?.msg).toContain('No config file found'); - expect(first?.msg).toContain('wrong-path/directus-sync.config.cjs'); + expect(log).toBeDefined(); + expect(log?.msg).toContain('wrong-path/directus-sync.config.cjs'); }); it('ensure log shows info about missing config file for default files', async () => { @@ -20,12 +20,12 @@ export const configPathInfo = (context: Context) => { const sync = await context.getSync('sources/empty-collections'); const output = await sync.diff(); - const first = output.shift(); + const log = output.find((l) => l.msg.includes('No config file found')); - expect(first?.msg).toContain('No config file found'); - expect(first?.msg).toContain('e2e/directus-sync.config.cjs'); - expect(first?.msg).toContain('e2e/directus-sync.config.js'); - expect(first?.msg).toContain('e2e/directus-sync.config.json'); + expect(log).toBeDefined(); + expect(log?.msg).toContain('e2e/directus-sync.config.cjs'); + expect(log?.msg).toContain('e2e/directus-sync.config.js'); + expect(log?.msg).toContain('e2e/directus-sync.config.json'); }); it('ensure logs show info when config path exists', async () => { @@ -36,9 +36,8 @@ export const configPathInfo = (context: Context) => { ); const output = await sync.diff(); - const first = output.shift(); + const log = output.find((l) => l.msg.includes('Loaded config file from')); - expect(first?.msg).toContain('Loaded config file from'); - expect(first?.msg).toContain('config-path-info/directus-sync.config.cjs'); + expect(log?.msg).toContain('config-path-info/directus-sync.config.cjs'); }); };