UNPKG

@stackbit/types

Version:

Types for Stackbit config and Content Source Interface

607 lines 24.9 kB
import type { ContentSourceInterface, ParametersOfCSIMethod, ReturnTypeOfCSIMethod, User } from './content-source'; import type { DocumentWithSource, AssetWithSource } from './content-source-document'; import type { ModelExtension, ModelMatchFields, ModelWithSource, NamelessModelMap } from './models'; import { SSG_NAMES, CMS_NAMES } from './consts'; import type { SidebarButton } from './sidebar-button'; import type { ConfigDelegate } from './config-delegate'; import type { AssetSource } from './asset-source'; import type { CustomActionBulk, CustomActionGlobal, CustomActionModel } from './custom-actions'; import { DocumentPermissions, ModelPermissions } from './content-permissions'; import { ContentObjectSpecification } from './utility-types'; export interface StackbitConfig { /** * The version of the Stackbit configuration. */ stackbitVersion: string; /** * The name of the front-end framework. * * If you specify the `ssgName` property, you can omit the `devCommand` * property, and Stackbit will use a default value matching your front-end * framework. */ ssgName?: (typeof SSG_NAMES)[number]; /** * The version of your front-end framework. * This is particularly useful for Hugo, as it allows for the * pre-installation of the matching Hugo binary version. */ ssgVersion?: string; /** * The Node.js version to use for installing dependencies and running the * front-end framework. You should set it to one of the Node major versions * such as "18", "16" or "14". * * @example * nodeVersion: "18" */ nodeVersion?: string; /** * The `useESM` flag indicates if stackbit.config.ts should be compiled to * CJS or ESM module. * * If one of the stackbit.config.ts dependencies is ESM only, you can use * this flag to support it. * * This flag is parsed statically before stackbit.config.ts is * loaded as a module. */ useESM?: boolean; postGitCloneCommand?: string; preInstallCommand?: string; postInstallCommand?: string; /** * The command that should be executed to install the project dependencies. * * @example * installCommand: "npm install" */ installCommand?: string; /** * The command that should be executed to run the development server of your * front-end framework. When specifying the `devCommand` you must specify * the arguments for the host and port and set them to `{HOSTNAME}` and * `{PORT}` tokens respectively. Stackbit will replace these tokens with its * internal host and port. * * @example * devCommand: "node ./node_modules/.bin/gatsby develop -p {PORT} -H {HOSTNAME} * devCommand: "node ./node_modules/.bin/next dev --port {PORT} --hostname {HOSTNAME} * devCommand: "node custom-server.js --port {PORT} --hostname {HOSTNAME} */ devCommand?: string; /** @deprecated This property is deprecated in favor of using `contentSources` */ cmsName?: (typeof CMS_NAMES)[number]; import?: Import; buildCommand?: string; publishDir?: string; /** * The directory to store the cached content provided by the content-sources. * If the cacheDir is a relative path, it will be resolved relative to the * stackbit.config.ts file. * If not set, defaults to ".stackbit/cache" folder relative to stackbit.config.ts file. */ cacheDir?: string; /** @deprecated This property is deprecated in favor of using `GitContentSource` */ staticDir?: string; /** @deprecated This property is deprecated in favor of using `GitContentSource` */ uploadDir?: string; /** @deprecated This property is deprecated in favor of using `GitContentSource` */ assets?: Assets; /** @deprecated This property is deprecated in favor of using `GitContentSource` */ pagesDir?: string | null; /** @deprecated This property is deprecated in favor of using `GitContentSource` */ dataDir?: string | null; /** @deprecated This property is deprecated in favor of using `GitContentSource` */ pageLayoutKey?: string | null; /** @deprecated This property is deprecated in favor of using `GitContentSource` */ objectTypeKey?: string; /** @deprecated This property is deprecated in favor of using `GitContentSource` */ excludePages?: string | string[]; styleObjectModelName?: string | null; presetSource?: PresetSource; sidebarButtons?: SidebarButton[]; /** * @alias {@link sitemap} * @deprecated use {@link sitemap} */ siteMap?: SiteMapFunction; /** * The `sitemap` function should return an array of {@link SiteMapEntry} * objects. Stackbit uses these objects to show the website's sitemap in its * UI. * * There are two types of sitemap entries: 'static' and 'dynamic'. * * Static sitemap entries represent static pages on your website and require * a [`urlPath`]{@link SiteMapBaseEntry.urlPath}, [`label`]{@link SiteMapBaseEntry.label}, * and [`stableId`]{@link SiteMapBaseEntry.stableId}. The `stableId` must be * a unique identifier that never changes, even if the entry's `urlPath` is * modified. * * Dynamic sitemap entries represent pages on your website that are * generated from content source documents. These entries require a * [`urlPath`]{@link SiteMapBaseEntry.urlPath} and a * [`document`]{@link SiteMapDocumentEntry.document} object with `id`, * `modelName`, `srcType`, and `srcProjectId` properties. * * To generate dynamic sitemap entries, use the `documents` and `models` * properties of the `options` parameter. * * @param {Object} options * @param {DocumentWithSource[]} options.documents * @param {ModelWithSource[]} options.models */ sitemap?: SiteMapFunction; /** * The `transformSitemap` method is used to transform sitemap entries available for specific user */ transformSitemap?: (options: ConfigDelegate & { sitemap: SiteMapEntry[]; userContext: User; }) => SiteMapEntry[]; treeViews?: TreeViewsFunction; /** * The `transformTreeViews` method is used to transform tree view entries available for specific user */ transformTreeViews?: (options: ConfigDelegate & { treeViews: TreeViewNode[]; userContext: User; }) => TreeViewNode[]; presetReferenceBehavior?: 'copyReference' | 'duplicateContents'; nonDuplicatableModels?: string[]; duplicatableModels?: string[]; customContentReload?: boolean; experimental?: Experimental; contentEngine?: ContentEngineOptions; contentSources?: ContentSourceInterface<any, any, any, any, any>[]; connectors?: { integration: any; config: any; }[]; assetSources?: AssetSource[]; viewports?: Viewport[]; /** * The `mapModels` method can be used to modify the models returned by * content sources. * * This method takes an `options` object with the `models` property * containing an array of `Model` objects. The `mapModels` method should * return an array of modified objects. * * @param options * @param {ModelWithSource[]} options.models */ mapModels?: (options: { models: ModelWithSource[]; }) => ModelWithSource[]; modelExtensions?: ModelExtension[]; permissionsForModel?: (options: ConfigDelegate & { model: ModelWithSource; userContext: User; }) => ModelPermissions | undefined; mapDocuments?: (options: { documents: DocumentWithSource[]; models: ModelWithSource[]; }) => DocumentWithSource[]; permissionsForDocument?: (options: ConfigDelegate & { document: DocumentWithSource; userContext: User; }) => DocumentPermissions | undefined; /** * The `filterAsset` method is used to hide or show asset for specific user */ filterAsset?: (options: ConfigDelegate & { asset: AssetWithSource; userContext: User; }) => boolean | undefined; /** * The `onContentCreate` method can be used to modify the values before * they are transformed into operations to create new documents. * * This method takes a single `options` parameter with an `object` property * containing the data needed to create one or more documents with links * between themselves. * * This method should modify the `options.object` and return the modified * object. * * For more information about the structure of the `options.object`, refer * to the [`object`]{@link OnContentCreateOptions.object} property documentation * * @example * // Iterate over 'object' fields, for every field of type "slug" sanitize * // its value using a custom 'sanitizeSlug' function. * mapDocuments: (options) { * const object = options.object; * for (const fieldName of Object.keys(object)) { * const modelField = options.model.fields.find((field) => field.name === fieldName); * if (modelField.type === 'slug') { * const fieldValue = object[fieldName]; * object[fieldName] = sanitizeSlug(fieldValue); * } * } * return object; * } * * @param {OnContentCreateOptions} options */ onContentCreate?: (options: OnContentCreateOptions) => Promise<Record<string, any>>; onDocumentCreate?: (options: OnDocumentCreateOptions) => ReturnType<ContentSourceInterface['createDocument']>; onDocumentUpdate?: (options: OnDocumentUpdateOptions) => ReturnType<ContentSourceInterface['updateDocument']>; onDocumentDelete?: (options: OnDocumentDeleteOptions) => ReturnType<ContentSourceInterface['deleteDocument']>; onDocumentArchive?: (options: OnDocumentArchiveOptions) => ReturnTypeOfCSIMethod<'archiveDocument'>; onDocumentUnarchive?: (options: OnDocumentUnarchiveOptions) => ReturnTypeOfCSIMethod<'unarchiveDocument'>; onDocumentsPublish?: (options: OnDocumentsPublishOptions) => ReturnType<ContentSourceInterface['publishDocuments']>; onDocumentsUnpublish?: (options: OnDocumentsUnpublishOptions) => ReturnTypeOfCSIMethod<'unpublishDocuments'>; /** * Use `actions` to extend the visual editor with custom actions that invoke * functions specified by the `run` method. */ actions?: (CustomActionGlobal | CustomActionBulk | CustomActionModel)[]; /** * @deprecated This property is deprecated in favor of using `contentSources` * and mapping content source models using the `mapModels` and `modelExtensions` * properties. */ models?: NamelessModelMap; /** @deprecated */ contentModels?: ContentModelMap; /** @deprecated */ modelsSource?: ModelsSource; /** @deprecated */ logicFields?: string[]; /** @deprecated */ noEncodeFields?: string[]; /** @deprecated */ omitFields?: string[]; /** @deprecated */ encodedFieldTypes?: string[]; } export type Import = ContentfulImport | SanityImport; export interface ContentfulImport { type: 'contentful'; contentFile: string; uploadAssets?: boolean; assetsDirectory?: string; spaceIdEnvVar?: string; accessTokenEnvVar?: string; deliveryTokenEnvVar?: string; previewTokenEnvVar?: string; } export interface SanityImport { type: 'sanity'; contentFile: string; sanityStudioPath: string; deployStudio?: boolean; deployGraphql?: boolean; projectIdEnvVar?: string; datasetEnvVar?: string; tokenEnvVar?: string; } export type Assets = StaticAssets | RelativeAssets; export interface StaticAssets { referenceType: 'static'; assetsDir?: string; staticDir: string; publicPath: string; uploadDir?: string; } export interface RelativeAssets { referenceType: 'relative'; assetsDir: string; staticDir?: string; publicPath?: string; uploadDir?: string; } export type ContentModelMap = Record<string, ContentModel>; export interface ContentModel extends ModelMatchFields { isPage?: boolean; urlPath?: string; hideContent?: boolean; newFilePath?: string; } export type PresetSource = PresetSourceFiles; export interface PresetSourceFiles { type: 'files'; presetDirs: string[]; } export type ModelsSource = ModelsSourceFiles | ModelsSourceContentful | ModelsSourceSanity; export interface ModelsSourceFiles { type: 'files'; modelDirs: string[]; } export interface ModelsSourceContentful { type: 'contentful'; module?: string; [key: string]: any; } export interface ModelsSourceSanity { type: 'sanity'; sanityStudioPath: string; module?: string; [key: string]: any; } export type SiteMapFunction = (options: SiteMapOptions) => SiteMapEntry[]; export type TreeViewsFunction = (options: ConfigDelegate) => Promise<TreeViewNode[]>; export interface SiteMapOptions extends ConfigDelegate { /** * When the sitemap function is called for the first time, this property * will include all the documents from all the content sources. * * When a new document is created or an existing document is changed, the * sitemap function will be called again and this property will contain only * the new and changed documents. * * To access other documents, use getDocumentById() and getDocuments() * functions. */ documents: DocumentWithSource[]; /** * This property includes all the models from all the content sources. */ models: ModelWithSource[]; } export type SiteMapEntry = SiteMapBaseEntry | SiteMapDocumentEntry; export interface SiteMapBaseEntry { /** The URL path of a page */ urlPath: string; /** * The human-readable string describing a page. * * When used with `document`, the `label` can be omitted, in which case it * will be computed using the document model's `labelField` property. */ label: string; /** * A stable ID that uniquely and consistently represents a website page. * If the `urlPath` of a particular page has changed, its stableId must * remain the same. The `stableId` allows Stackbit to redirect editors to * a different URL when the `urlPath` of the currently viewed page has been * changed. For example, one document can represent multiple website pages * if it has field-level localization. In this case, the srcDocumentId of * both sitemap entries should be the same, however the stableId must be * different. * * When used with `document`, the `stableId` can be omitted, in which case * it will be set to document's `id`. */ stableId: string; /** The locale of the page */ locale?: string; isHomePage?: boolean; } export interface TreeViewBaseNode { label: string; stableId: string; children?: TreeViewNode[]; } export interface TreeViewDocumentNode { label?: string; stableId?: string; document: { srcType: string; srcProjectId: string; id: string; }; children?: TreeViewNode[]; } export type TreeViewNode = TreeViewBaseNode | TreeViewDocumentNode; export interface SiteMapDocumentEntry extends Omit<SiteMapBaseEntry, 'label' | 'stableId'> { label?: string; stableId?: string; document: { srcType: string; srcProjectId: string; modelName: string; id: string; }; } export interface ContentEngineOptions { port?: number | string; host?: string; } export interface Experimental { ssg?: { name?: string; passthrough?: string[]; directRoutes?: Record<string, string>; proxyWebsockets?: boolean; watch?: { reinstallPackages?: string[]; }; logPatterns?: { up?: string[]; }; }; } export interface Viewport { label: string; size: { width?: number; height?: number; }; } export interface OnContentCreateOptions extends ConfigDelegate { /** * The `object` contains data for creating one or more new documents. * It must conform to the {@link ContentObjectSpecification}. */ object: ContentObjectSpecification; /** * The model representing the new document */ model: ModelWithSource; /** * The locale for the new document */ locale?: string; } export interface OnDocumentCreateOptions extends DocumentHookBaseOptions { /** * The `options` object is passed to the content source `createDocument` * method to create a document. You can transform this object and pass the * result to the `createDocument` parameter to create a different document. */ createDocumentOptions: Parameters<ContentSourceInterface['createDocument']>[0]; /** * This function creates a document. Pass the `createDocumentOptions` * parameter to this function to create a document. If you call this * function without passing any options, original options will be used. */ createDocument: (options?: Parameters<ContentSourceInterface['createDocument']>[0]) => ReturnType<ContentSourceInterface['createDocument']>; } export interface OnDocumentUpdateOptions extends DocumentHookBaseOptions { /** * The `options` object is passed to the content source `updateDocument` * method to update a document. You can transform this object and pass the * result to the `updateDocument` parameter to update the document in a * different way. */ updateDocumentOptions: Parameters<ContentSourceInterface['updateDocument']>[0]; /** * This function updates a document. Pass the `updateDocumentOptions` * parameter to this function to update a document. If you call this * function without passing any options, original options will be used. */ updateDocument: (options?: Parameters<ContentSourceInterface['updateDocument']>[0]) => ReturnType<ContentSourceInterface['updateDocument']>; } export interface OnDocumentDeleteOptions extends DocumentHookBaseOptions { /** * The `options` object is passed to the content source `deleteDocument` * method to delete a document. */ deleteDocumentOptions: Parameters<ContentSourceInterface['deleteDocument']>[0]; /** * This function deletes a document. Pass the `deleteDocumentOptions` * parameter to this function to delete a document. If you call this * function without passing any options, original options will be used. */ deleteDocument: (options?: Parameters<ContentSourceInterface['deleteDocument']>[0]) => ReturnType<ContentSourceInterface['deleteDocument']>; } export interface OnDocumentArchiveOptions extends DocumentHookBaseOptions { /** * The `options` object is passed to the content source `archiveDocument` * method to archive a document. */ archiveDocumentOptions: Parameters<NonNullable<ContentSourceInterface['archiveDocument']>>[0]; /** * This function archives a document. Pass the `archiveDocumentOptions` * parameter to this function to archive a document. If you call this * function without passing any options, original options will be used. */ archiveDocument: (options?: Parameters<NonNullable<ContentSourceInterface['archiveDocument']>>[0]) => ReturnType<NonNullable<ContentSourceInterface['archiveDocument']>>; } export interface OnDocumentUnarchiveOptions extends DocumentHookBaseOptions { /** * The `options` object is passed to the content source `unarchiveDocument` * method to unarchive a document. */ unarchiveDocumentOptions: ParametersOfCSIMethod<'unarchiveDocument'>[0]; /** * This function unarchives a document. Pass the `unarchiveDocumentOptions` * parameter to this function to unarchive a document. If you call this * function without passing any options, original options will be used. */ unarchiveDocument: (options?: ParametersOfCSIMethod<'unarchiveDocument'>[0]) => ReturnTypeOfCSIMethod<'unarchiveDocument'>; } export interface OnDocumentsPublishOptions extends DocumentHookBaseOptions { /** * The `options` object is passed to the content source `publishDocuments` * method to publish documents. */ publishDocumentsOptions: Parameters<ContentSourceInterface['publishDocuments']>[0]; /** * This function publishes documents. Pass the `publishDocumentsOptions` * parameter to this function to publish documents. */ publishDocuments: (options?: Parameters<ContentSourceInterface['publishDocuments']>[0]) => ReturnType<ContentSourceInterface['publishDocuments']>; } export interface OnDocumentsUnpublishOptions extends DocumentHookBaseOptions { /** * The `options` object is passed to the content source `unpublishDocuments` * method to unpublish documents. */ unpublishDocumentsOptions: ParametersOfCSIMethod<'unpublishDocuments'>[0]; /** * This function publishes documents. Pass the `unpublishDocumentsOptions` * parameter to this function to unpublish documents. */ unpublishDocuments: (options?: ParametersOfCSIMethod<'unpublishDocuments'>[0]) => ReturnTypeOfCSIMethod<'unpublishDocuments'>; } export interface DocumentHookBaseOptions extends ConfigDelegate { /** * The content source type of the current document */ srcType: string; /** * The content source project ID of the current document */ srcProjectId: string; /** * This object contains functions to create, update, delete and publish * documents in the content source of the current document. * * All functions receive an optional `userContext`. If the `userContext` * is not specified, a default `userContext` for the current user and the * content source will be used. * * Calling these functions will trigger onDocument hooks. Therefore, do not * use these function to create, update, delete and publish the current * document, otherwise you will introduce an infinite loop. */ contentSourceActions: ContentSourceActions; /** * This function returns an object containing functions to create, update, * delete and publish documents in the content source matching the received * `srType` and `srcProjectId`. * * The `srcProjectId` is optional. However, if there are multiple * content source instances of the `srcType`, `undefined` will be returned * * All functions receive an optional `userContext`. If the `userContext` * is not specified, a default `userContext` for the current user and the * content source will be used. * * Calling these functions will trigger onDocument hooks. Therefore, do not * use these function to create, update, delete and publish the current * document, otherwise you will introduce an infinite loop. * * @param options * @param {string} options.srcType The content source type * @param {string} [options.srcProjectId] The content source project ID */ getContentSourceActionsForSource: (options: { srcType: string; srcProjectId?: string; }) => ContentSourceActions | undefined; /** * Returns the `userContext` of the current user for the content source * specified by `srType`. * * The `userContext` can be used to create, update, delete and publish * documents on behalf of the current user. * * Generally you don't need to pass the `userContext` yourself as it will be * added automatically. * * @param {string} srcType The content source type */ getUserContextForContentSourceType: (srcType: string) => User | undefined; } export interface ContentSourceActions { createDocument: (...args: Parameters<ContentSourceInterface['createDocument']>) => ReturnType<ContentSourceInterface['createDocument']>; /** * Creates a document from the provided `object` and `modelName`. * The `object` structure must conform to the {@link ContentObjectSpecification}. */ createDocumentFromObject: (options: { object: ContentObjectSpecification; modelName: string; locale?: string; }) => ReturnType<ContentSourceInterface['createDocument']>; updateDocument: (...args: Parameters<ContentSourceInterface['updateDocument']>) => ReturnType<ContentSourceInterface['updateDocument']>; deleteDocument: (...args: Parameters<ContentSourceInterface['deleteDocument']>) => ReturnType<ContentSourceInterface['deleteDocument']>; publishDocuments: (...args: Parameters<ContentSourceInterface['publishDocuments']>) => ReturnType<ContentSourceInterface['publishDocuments']>; } //# sourceMappingURL=config.d.ts.map