feat: events (#717)

This commit is contained in:
Daniel Lautzenheiser 2023-04-19 23:49:53 -04:00 committed by GitHub
parent 455bcdc0f2
commit 79877fcd1f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 72 additions and 56 deletions

View File

@ -49,7 +49,7 @@ function getConfigUrl() {
};
const configLinkEl = document.querySelector<HTMLLinkElement>('link[rel="cms-config-url"]');
if (configLinkEl && validTypes[configLinkEl.type] && configLinkEl.href) {
console.info(`Using config file path: "${configLinkEl.href}"`);
console.info(`[StaticCMS] Using config file path: "${configLinkEl.href}"`);
return configLinkEl.href;
}
return 'config.yml';
@ -294,7 +294,7 @@ async function getConfigYaml(file: string): Promise<Config> {
const contentType = response.headers.get('Content-Type') ?? 'Not-Found';
const isYaml = contentType.indexOf('yaml') !== -1;
if (!isYaml) {
console.info(`Response for ${file} was not yaml. (Content-Type: ${contentType})`);
console.info(`[StaticCMS] Response for ${file} was not yaml. (Content-Type: ${contentType})`);
}
return parseConfig(await response.text());
}
@ -338,7 +338,7 @@ export async function detectProxyServer(localBackend?: boolean | LocalBackend) {
: localBackend.url || defaultUrl.replace('localhost', location.hostname);
try {
console.info(`Looking for Static CMS Proxy Server at '${proxyUrl}'`);
console.info(`[StaticCMS] Looking for Static CMS Proxy Server at '${proxyUrl}'`);
const res = await fetch(`${proxyUrl}`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
@ -349,14 +349,16 @@ export async function detectProxyServer(localBackend?: boolean | LocalBackend) {
type?: string;
};
if (typeof repo === 'string' && typeof type === 'string') {
console.info(`Detected Static CMS Proxy Server at '${proxyUrl}' with repo: '${repo}'`);
console.info(
`[StaticCMS] Detected Static CMS Proxy Server at '${proxyUrl}' with repo: '${repo}'`,
);
return { proxyUrl, type };
} else {
console.info(`Static CMS Proxy Server not detected at '${proxyUrl}'`);
console.info(`[StaticCMS] Static CMS Proxy Server not detected at '${proxyUrl}'`);
return {};
}
} catch {
console.info(`Static CMS Proxy Server not detected at '${proxyUrl}'`);
console.info(`[StaticCMS] Static CMS Proxy Server not detected at '${proxyUrl}'`);
return {};
}
}

View File

@ -165,7 +165,7 @@ export function loadMedia(
.catch((error: { status?: number }) => {
console.error(error);
if (error.status === 404) {
console.info('This 404 was expected and handled appropriately.');
console.info('[StaticCMS] This 404 was expected and handled appropriately.');
dispatch(mediaLoaded([]));
} else {
dispatch(mediaLoadFailed());

View File

@ -29,7 +29,7 @@ export async function waitUntilWithTimeout<T>(
if (waitDone) {
resolve(null);
} else {
console.warn('Wait Action timed out');
console.warn('[StaticCMS] Wait Action timed out');
resolve(null);
}
}, timeout);

View File

@ -676,7 +676,7 @@ export class Backend<EF extends BaseField = UnknownField, BC extends BackendClas
const result = await localForage.setItem(getEntryBackupKey(), raw);
return result;
} catch (e) {
console.warn('persistLocalDraftBackup', e);
console.warn('[StaticCMS] persistLocalDraftBackup', e);
} finally {
this.backupSync.release();
}
@ -691,7 +691,7 @@ export class Backend<EF extends BaseField = UnknownField, BC extends BackendClas
const result = await this.deleteAnonymousBackup();
return result;
} catch (e) {
console.warn('deleteLocalDraftBackup', e);
console.warn('[StaticCMS] deleteLocalDraftBackup', e);
} finally {
this.backupSync.release();
}

View File

@ -83,7 +83,7 @@ export const API_NAME = 'Bitbucket';
function replace404WithEmptyResponse(err: FetchError) {
if (err && err.status === 404) {
console.info('This 404 was expected and handled appropriately.');
console.info('[StaticCMS] This 404 was expected and handled appropriately.');
return { size: 0, values: [] as BitBucketFile[] } as BitBucketSrcResult;
} else {
return Promise.reject(err);
@ -235,7 +235,7 @@ export default class API {
url: `${this.repoURL}/commits`,
params: { include: branch, pagelen: '100' },
}).catch(e => {
console.info(`Failed getting commits for branch '${branch}'`, e);
console.info(`[StaticCMS] Failed getting commits for branch '${branch}'`, e);
return [];
});

View File

@ -126,7 +126,7 @@ export default class BitbucketBackend implements BackendClass {
);
})
.catch(e => {
console.warn('Failed getting BitBucket status', e);
console.warn('[StaticCMS] Failed getting BitBucket status', e);
return true;
});
@ -138,7 +138,7 @@ export default class BitbucketBackend implements BackendClass {
?.user()
.then(user => !!user)
.catch(e => {
console.warn('Failed getting Bitbucket user', e);
console.warn('[StaticCMS] Failed getting Bitbucket user', e);
return false;
})) || false;
}
@ -373,7 +373,7 @@ export default class BitbucketBackend implements BackendClass {
.then(attributes => getLargeMediaPatternsFromGitAttributesFile(attributes as string))
.catch((err: FetchError) => {
if (err.status === 404) {
console.info('This 404 was expected and handled appropriately.');
console.info('[StaticCMS] This 404 was expected and handled appropriately.');
} else {
console.error(err);
}

View File

@ -54,7 +54,7 @@ const GitGatewayAuthenticationPage = ({ onLogin, t }: GitGatewayAuthenticationPa
}
if (window.netlifyIdentity) {
console.info('Manually initializing identity widget');
console.info('[StaticCMS] Manually initializing identity widget');
initialized = true;
window.netlifyIdentity.init();
clearInterval(interval);

View File

@ -175,7 +175,7 @@ export default class GitGateway implements BackendClass {
.every((statusComponent: GitGatewayStatus) => statusComponent.status === 'operational');
})
.catch(e => {
console.warn('Failed getting Git Gateway status', e);
console.warn('[StaticCMS] Failed getting Git Gateway status', e);
return true;
});
@ -186,7 +186,7 @@ export default class GitGateway implements BackendClass {
(await this.tokenPromise?.()
.then(token => !!token)
.catch(e => {
console.warn('Failed getting Identity token', e);
console.warn('[StaticCMS] Failed getting Identity token', e);
return false;
})) || false;
}
@ -415,7 +415,7 @@ export default class GitGateway implements BackendClass {
.then((patterns: string[]) => ({ err: null, patterns }))
.catch((err: Error) => {
if (err.message.includes('404')) {
console.info('This 404 was expected and handled appropriately.');
console.info('[StaticCMS] This 404 was expected and handled appropriately.');
return { err: null, patterns: [] as string[] };
} else {
return { err, patterns: [] as string[] };
@ -461,7 +461,7 @@ export default class GitGateway implements BackendClass {
const entry = items[0];
const pointerFile = parsePointerFile(entry.data);
if (!pointerFile.sha) {
console.warn(`Failed parsing pointer file ${path}`);
console.warn(`[StaticCMS] Failed parsing pointer file ${path}`);
return { url: path, blob: new Blob() };
}

View File

@ -354,7 +354,7 @@ export default class API {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (err: any) {
if (err && err.status === 404) {
console.info('This 404 was expected and handled appropriately.');
console.info('[StaticCMS] This 404 was expected and handled appropriately.');
return [];
} else {
throw err;

View File

@ -93,7 +93,7 @@ export default class Gitea implements BackendClass {
?.user()
.then(user => !!user)
.catch(e => {
console.warn('Failed getting Gitea user', e);
console.warn('[StaticCMS] Failed getting Gitea user', e);
return false;
})) || false;

View File

@ -369,7 +369,7 @@ export default class API {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
} catch (err: any) {
if (err && err.status === 404) {
console.info('This 404 was expected and handled appropriately.');
console.info('[StaticCMS] This 404 was expected and handled appropriately.');
return [];
} else {
throw err;

View File

@ -109,7 +109,7 @@ export default class GitHub implements BackendClass {
);
})
.catch(e => {
console.warn('Failed getting GitHub status', e);
console.warn('[StaticCMS] Failed getting GitHub status', e);
return true;
});
@ -121,7 +121,7 @@ export default class GitHub implements BackendClass {
?.getUser()
.then(user => !!user)
.catch(e => {
console.warn('Failed getting GitHub user', e);
console.warn('[StaticCMS] Failed getting GitHub user', e);
return false;
})) || false;
}

View File

@ -86,7 +86,7 @@ export default class GitLab implements BackendClass {
?.user()
.then(user => !!user)
.catch(e => {
console.warn('Failed getting GitLab user', e);
console.warn('[StaticCMS] Failed getting GitLab user', e);
return false;
})) || false;

View File

@ -40,6 +40,7 @@ const ROOT_ID = 'nc-root';
// @ts-ignore
// eslint-disable-next-line @typescript-eslint/no-unused-vars, import/order
import ReactDOM from 'react-dom';
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
ReactDOM.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED.usingClientEntryPoint = true;
@ -79,7 +80,7 @@ function bootstrap<F extends BaseField = UnknownField>(opts?: {
* Log the version number.
*/
if (typeof STATIC_CMS_CORE_VERSION === 'string') {
console.info(`static-cms-core ${STATIC_CMS_CORE_VERSION}`);
console.info(`[StaticCMS] Using @staticcms/core ${STATIC_CMS_CORE_VERSION}`);
}
/**

View File

@ -18,6 +18,7 @@ import { loginUser as loginUserAction } from '@staticcms/core/actions/auth';
import { discardDraft } from '@staticcms/core/actions/entries';
import { currentBackend } from '@staticcms/core/backend';
import { changeTheme } from '../actions/globalUI';
import { invokeEvent } from '../lib/registry';
import { getDefaultPath } from '../lib/util/collection.util';
import { selectTheme } from '../reducers/selectors/globalUI';
import { useAppDispatch, useAppSelector } from '../store/hooks';
@ -229,6 +230,12 @@ const App = ({
);
}, [authenticationPage, collections, defaultPath, isFetching, user]);
useEffect(() => {
setTimeout(() => {
invokeEvent({ name: 'mounted' });
});
}, []);
if (!config.config) {
return configError(t('app.app.configNotFound'));
}

View File

@ -62,7 +62,7 @@ function buildIssueUrl(title: string, config?: Config) {
return `${ISSUE_URL}${params.toString()}`;
} catch (e) {
console.info(e);
console.error(e);
return `${ISSUE_URL}template=bug_report.md`;
}
}
@ -72,7 +72,7 @@ interface RecoveredEntryProps {
}
const RecoveredEntry = ({ entry, t }: TranslatedProps<RecoveredEntryProps>) => {
console.info(entry);
console.info('[StaticCMS] Recovered entry', entry);
return (
<>
<hr />
@ -134,7 +134,7 @@ class ErrorBoundary extends Component<TranslatedProps<ErrorBoundaryProps>, Error
if (this.props.showBackup) {
const backup = await localForage.getItem<string>('backup');
if (backup) {
console.info(backup);
console.info('[StaticCMS] Recovered backup', backup);
this.setState({ backup });
}
}

View File

@ -67,7 +67,7 @@ function inferFrontmatterFormat(str: string) {
case '{':
return getFormatOpts(Languages.JSON);
default:
console.warn('Unrecognized front-matter format.');
console.warn('[StaticCMS] Unrecognized front-matter format.');
}
}

View File

@ -821,7 +821,7 @@ export interface EventData {
export type EventListenerOptions = Record<string, unknown>;
export type EventListenerHandler = (
data: EventData,
data: EventData | undefined,
options: EventListenerOptions,
) => Promise<EntryData | undefined | null | void>;

View File

@ -54,7 +54,9 @@ export function commitMessageFormatter<EF extends BaseField>(
case 'author-name':
return authorName || '';
default:
console.warn(`Ignoring unknown variable “${variable}” in commit message template.`);
console.warn(
`[StaticCMS] Ignoring unknown variable “${variable}” in commit message template.`,
);
return '';
}
});

View File

@ -246,7 +246,7 @@ function mergeValues<EF extends BaseField>(
let defaultEntry = values.find(e => e.locale === defaultLocale);
if (!defaultEntry) {
defaultEntry = values[0];
console.warn(`Could not locale entry for default locale '${defaultLocale}'`);
console.warn(`[StaticCMS] Could not locale entry for default locale '${defaultLocale}'`);
}
const i18n = values
.filter(e => e.locale !== defaultEntry!.locale)

View File

@ -26,7 +26,7 @@ import type {
WidgetValueSerializer,
} from '../interface';
export const allowedEvents = ['preSave', 'postSave'] as const;
export const allowedEvents = ['mounted', 'preSave', 'postSave'] as const;
export type AllowedEvent = (typeof allowedEvents)[number];
const eventHandlers = allowedEvents.reduce((acc, e) => {
@ -219,7 +219,7 @@ export function registerWidget<T = unknown, F extends BaseField = UnknownField>(
} = nameOrWidgetOrWidgets;
if (registry.widgets[widgetName]) {
console.warn(oneLine`
Multiple widgets registered with name "${widgetName}". Only the last widget registered with
[StaticCMS] Multiple widgets registered with name "${widgetName}". Only the last widget registered with
this name will be used.
`);
}
@ -323,22 +323,24 @@ export function registerEventListener(
registry.eventHandlers[name].push({ handler, options });
}
export async function invokeEvent({ name, data }: { name: AllowedEvent; data: EventData }) {
export async function invokeEvent({ name, data }: { name: AllowedEvent; data?: EventData }) {
validateEventName(name);
const handlers = registry.eventHandlers[name];
let _data = { ...data };
console.info(`[StaticCMS] Firing event ${name}`, data);
let _data = data ? { ...data } : undefined;
for (const { handler, options } of handlers) {
const result = await handler(_data, options);
if (result !== undefined) {
if (_data !== undefined && result !== undefined) {
const entry = {
..._data.entry,
data: result,
} as Entry;
_data = { ...data, entry };
_data = { ..._data, entry };
}
}
return _data.entry.data;
return _data?.entry.data;
}
export function removeEventListener({ name, handler }: EventListener) {

View File

@ -83,7 +83,7 @@ export async function requestWithBackoff(
if (!api.rateLimiter) {
const timeout = error.resetSeconds || attempt * attempt;
console.info(
`Pausing requests for ${timeout} ${
`[StaticCMS] Pausing requests for ${timeout} ${
attempt === 1 ? 'second' : 'seconds'
} due to fetch failures:`,
error.message,
@ -93,7 +93,7 @@ export async function requestWithBackoff(
setTimeout(() => {
api.rateLimiter?.release();
api.rateLimiter = undefined;
console.info(`Done pausing requests`);
console.info('[StaticCMS] Done pausing requests');
}, 1000 * timeout);
}
return requestWithBackoff(api, req, attempt + 1);

View File

@ -33,7 +33,7 @@ export function asyncLock(): AsyncLock {
if (e instanceof Error && e.message !== 'leave called too many times.') {
throw e;
} else {
console.warn('leave called too many times.');
console.warn('[StaticCMS] Leave called too many times.');
lock = semaphore(1);
}
}

View File

@ -114,7 +114,7 @@ export async function runWithLock(lock: AsyncLock, func: Function, message: stri
try {
const acquired = await lock.acquire();
if (!acquired) {
console.warn(message);
console.warn('[StaticCMS]', message);
}
const result = await func();
@ -315,7 +315,7 @@ export async function allEntriesByFolder({
const localTreeInBranch = await isShaExistsInBranch(branch.name, localTree.head);
if (!localTreeInBranch) {
console.info(
`Can't find local tree head '${localTree.head}' in branch '${branch.name}', rebuilding local tree`,
`[StaticCMS] Can't find local tree head '${localTree.head}' in branch '${branch.name}', rebuilding local tree`,
);
return listAllFilesAndPersist();
}
@ -329,12 +329,12 @@ export async function allEntriesByFolder({
getFileId,
filterFile,
}).catch(e => {
console.info('Failed getting diff from local tree:', e);
console.info('[StaticCMS] Failed getting diff from local tree:', e);
return null;
});
if (!diff) {
console.info(`Diff is null, rebuilding local tree`);
console.info(`[StaticCMS] Diff is null, rebuilding local tree`);
return listAllFilesAndPersist();
}

View File

@ -10,7 +10,7 @@ function localForageTest() {
.catch(err => {
if (err.code === 22) {
const message = 'Unable to set localStorage key. Quota exceeded! Full disk?';
console.warn(message);
console.warn('[StaticCMS]', message);
}
console.info(err);
});

View File

@ -89,7 +89,7 @@ export function getGroup(entry: Entry, selectedGroup: GroupMap) {
value = matched[0];
}
} catch (e: unknown) {
console.warn(`Invalid view group pattern '${pattern}' for field '${field}'`, e);
console.warn(`[StaticCMS] Invalid view group pattern '${pattern}' for field '${field}'`, e);
}
return {
id: `${label}${value}`,

View File

@ -50,7 +50,9 @@ function validateItem(field: ListField, item: ValueOrNestedValue) {
if (typeof item !== 'object') {
console.warn(
`'${field.name}' field item value value should be an object but is a '${typeof item}'`,
`[StaticCMS] '${
field.name
}' field item value value should be an object but is a '${typeof item}'`,
);
return false;
}

View File

@ -333,7 +333,7 @@ ${bodyRows.join('\n')}`;
)}${shortcodeConfig.closeTag}`;
default:
console.warn('Unrecognized slate node, proceeding as text', `"${type}"`, chunk);
console.warn('[StaticCMS] Unrecognized slate node, proceeding as text', `"${type}"`, chunk);
return children;
}
}

View File

@ -276,7 +276,7 @@ export default function deserializeMarkdown(node: MdastNode, options: Options) {
case 'br':
return { type: NodeTypes.paragraph, children: [{ text: '' }] };
default:
console.warn('unrecognized mdx flow element', node);
console.warn('[StaticCMS] Unrecognized mdx flow element', node);
break;
}
}
@ -335,7 +335,7 @@ export default function deserializeMarkdown(node: MdastNode, options: Options) {
...persistLeafFormats(children as Array<MdastNode>),
} as TextNode;
default:
console.warn('unrecognized mdx text element', node);
console.warn('[StaticCMS] Unrecognized mdx text element', node);
break;
}
}
@ -356,7 +356,7 @@ export default function deserializeMarkdown(node: MdastNode, options: Options) {
return nodes.map(node => (node.type === 'text' ? { text: node.value ?? '' } : node));
default:
console.warn('Unrecognized mdast node, proceeding as text', node);
console.warn('[StaticCMS] Unrecognized mdast node, proceeding as text', node);
return { text: node.value || '' };
}
}

View File

@ -92,7 +92,7 @@ CMS.registerEventListener({
});
```
Supported events are `preSave` and `postSave`. The `preSave` hook can be used to modify the entry data like so:
Supported events are `mounted`, `preSave` and `postSave`. The `preSave` hook can be used to modify the entry data like so:
```javascript
CMS.registerEventListener({