feat: preview config (#21561)

* feat: base files for static preview

* feat: preview config

* Update packages/core/content-manager/server/src/preview/routes/index.ts

Co-authored-by: Rémi de Juvigny <8087692+remidej@users.noreply.github.com>

* chore: empty handler

* chore: comment controllers type

* fix: remove is enabled check from load

* feat: test preview config

* chore: refactor type

* fix: pr comments

---------

Co-authored-by: Rémi de Juvigny <8087692+remidej@users.noreply.github.com>
This commit is contained in:
Marc Roig 2024-10-07 21:16:25 +02:00 committed by GitHub
parent bbe5b7f1f4
commit 840550dc97
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 138 additions and 5 deletions

View File

@ -18,4 +18,12 @@ module.exports = ({ env }) => ({
nps: env.bool('FLAG_NPS', true),
promoteEE: env.bool('FLAG_PROMOTE_EE', true),
},
preview: {
enabled: env.bool('PREVIEW_ENABLED', true),
config: {
handler: (uid, { documentId, locale, status }) => {
return `/preview/${uid}/${documentId}/${locale}/${status}`;
},
},
},
});

View File

@ -4,6 +4,7 @@ import { FEATURE_ID } from './constants';
import { routes } from './routes';
import { controllers } from './controllers';
import { services } from './services';
import { getService } from './utils';
/**
* Check once if the feature is enabled before loading it,
@ -24,11 +25,8 @@ const getFeature = (): Partial<Plugin.LoadedPlugin> => {
// eslint-disable-next-line no-console -- TODO remove when we have real functionality
console.log('Bootstrapping preview server');
// eslint-disable-next-line @typescript-eslint/no-unused-vars -- TODO: Remove when implemented
const config = strapi.config.get('admin.preview');
// TODO: Validation
// TODO: Disable feature if config is not valid
const config = getService(strapi, 'preview-config');
config.validate();
},
routes,
controllers,

View File

@ -0,0 +1,55 @@
import { createPreviewConfigService } from '../preview-config';
const getConfig = (enabled: boolean, handler: () => void) => {
return {
enabled,
config: {
handler,
},
};
};
describe('Preview Config', () => {
test('Is not enabled by default', () => {
const strapi = {
config: {
get: () => undefined,
},
} as any;
expect(createPreviewConfigService({ strapi }).isEnabled()).toBe(false);
});
test('Is enabled when configuration is set', () => {
const strapi = {
config: {
get: () => getConfig(true, () => {}),
},
} as any;
expect(createPreviewConfigService({ strapi }).isEnabled()).toBe(true);
});
describe('Validation', () => {
test('Passes on valid configuration', () => {
const strapi = {
config: {
get: () => getConfig(true, () => {}),
},
} as any;
createPreviewConfigService({ strapi }).validate();
});
test('Fails on missing handler', () => {
const strapi = {
config: {
// @ts-expect-error - invalid handler
get: () => getConfig(true, 3),
},
} as any;
expect(() => createPreviewConfigService({ strapi }).validate()).toThrowError();
});
});
});

View File

@ -1,6 +1,9 @@
import type { Plugin } from '@strapi/types';
import { createPreviewService } from './preview';
import { createPreviewConfigService } from './preview-config';
export const services = {
preview: createPreviewService,
'preview-config': createPreviewConfigService,
} satisfies Plugin.LoadedPlugin['services'];

View File

@ -0,0 +1,69 @@
import type { Core, UID } from '@strapi/types';
import { errors } from '@strapi/utils';
export type HandlerParams = {
documentId: string;
locale: string;
status: 'published' | 'draft';
};
export interface PreviewConfig {
enabled: boolean;
config: {
handler: (uid: UID.Schema, params: HandlerParams) => string | undefined;
};
}
/**
* Read configuration for static preview
*/
const createPreviewConfigService = ({ strapi }: { strapi: Core.Strapi }) => {
return {
isEnabled() {
const config = strapi.config.get('admin.preview') as PreviewConfig;
if (!config) {
return false;
}
return config?.enabled ?? true;
},
/**
* Validate if the configuration is valid
*/
validate() {
if (!this.isEnabled()) {
return;
}
const handler = this.getPreviewHandler();
// Handler must be a function
if (typeof handler !== 'function') {
throw new errors.ValidationError(
'Preview configuration is invalid. Handler must be a function'
);
}
},
/**
* Utility to get the preview handler from the configuration
*/
getPreviewHandler(): PreviewConfig['config']['handler'] {
const config = strapi.config.get('admin.preview') as PreviewConfig;
const emptyHandler = () => {
return undefined;
};
if (!this.isEnabled()) {
return emptyHandler;
}
return config?.config?.handler || emptyHandler;
},
};
};
export { createPreviewConfigService };