payload 3.91.0-internal.6e3dc85 → 3.91.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin.js +3 -14
- package/dist/auth/endpoints/refresh.d.ts.map +1 -1
- package/dist/auth/endpoints/refresh.js +4 -6
- package/dist/auth/endpoints/refresh.js.map +1 -1
- package/dist/bin/index.d.ts.map +1 -1
- package/dist/bin/index.js +15 -0
- package/dist/bin/index.js.map +1 -1
- package/dist/bin/index.spec.js +54 -0
- package/dist/bin/index.spec.js.map +1 -0
- package/dist/collections/operations/findByID.d.ts.map +1 -1
- package/dist/collections/operations/findByID.js +54 -6
- package/dist/collections/operations/findByID.js.map +1 -1
- package/dist/collections/operations/findVersionByID.d.ts.map +1 -1
- package/dist/collections/operations/findVersionByID.js +7 -0
- package/dist/collections/operations/findVersionByID.js.map +1 -1
- package/dist/collections/operations/findVersions.d.ts.map +1 -1
- package/dist/collections/operations/findVersions.js +5 -0
- package/dist/collections/operations/findVersions.js.map +1 -1
- package/dist/database/createSchemaBuildContext.d.ts +12 -0
- package/dist/database/createSchemaBuildContext.d.ts.map +1 -0
- package/dist/database/createSchemaBuildContext.js +24 -0
- package/dist/database/createSchemaBuildContext.js.map +1 -0
- package/dist/database/createSchemaBuildContext.spec.js +146 -0
- package/dist/database/createSchemaBuildContext.spec.js.map +1 -0
- package/dist/database/sanitizeJoinQuery.d.ts.map +1 -1
- package/dist/database/sanitizeJoinQuery.js +2 -1
- package/dist/database/sanitizeJoinQuery.js.map +1 -1
- package/dist/exports/internal.d.ts +2 -0
- package/dist/exports/internal.d.ts.map +1 -1
- package/dist/exports/internal.js +1 -0
- package/dist/exports/internal.js.map +1 -1
- package/dist/fields/baseFields/slug/generateSlug.js +3 -3
- package/dist/fields/baseFields/slug/generateSlug.js.map +1 -1
- package/dist/fields/baseFields/slug/generateSlug.spec.js +22 -0
- package/dist/fields/baseFields/slug/generateSlug.spec.js.map +1 -0
- package/dist/globals/operations/findVersionByID.d.ts.map +1 -1
- package/dist/globals/operations/findVersionByID.js +11 -3
- package/dist/globals/operations/findVersionByID.js.map +1 -1
- package/dist/globals/operations/findVersions.d.ts.map +1 -1
- package/dist/globals/operations/findVersions.js +5 -0
- package/dist/globals/operations/findVersions.js.map +1 -1
- package/dist/queues/utilities/updateJob.d.ts.map +1 -1
- package/dist/queues/utilities/updateJob.js +15 -0
- package/dist/queues/utilities/updateJob.js.map +1 -1
- package/dist/utilities/getNextJsHMRURL.d.ts.map +1 -1
- package/dist/utilities/getNextJsHMRURL.js +4 -2
- package/dist/utilities/getNextJsHMRURL.js.map +1 -1
- package/dist/utilities/getNextJsHMRURL.spec.js +11 -0
- package/dist/utilities/getNextJsHMRURL.spec.js.map +1 -1
- package/dist/utilities/getVersionsConfig.d.ts +4 -0
- package/dist/utilities/getVersionsConfig.d.ts.map +1 -1
- package/dist/utilities/getVersionsConfig.js +5 -0
- package/dist/utilities/getVersionsConfig.js.map +1 -1
- package/lexicalLoader.mjs +26 -0
- package/package.json +7 -6
|
@@ -3,8 +3,10 @@ import { combineQueries } from '../../database/combineQueries.js';
|
|
|
3
3
|
import { validateQueryPaths } from '../../database/queryValidation/validateQueryPaths.js';
|
|
4
4
|
import { validateSortQuery } from '../../database/queryValidation/validateSortQuery.js';
|
|
5
5
|
import { sanitizeWhereQuery } from '../../database/sanitizeWhereQuery.js';
|
|
6
|
+
import { NotFound } from '../../errors/index.js';
|
|
6
7
|
import { afterRead } from '../../fields/hooks/afterRead/index.js';
|
|
7
8
|
import { appendNonTrashedFilter } from '../../utilities/appendNonTrashedFilter.js';
|
|
9
|
+
import { hasVersionsEnabled } from '../../utilities/getVersionsConfig.js';
|
|
8
10
|
import { killTransaction } from '../../utilities/killTransaction.js';
|
|
9
11
|
import { sanitizeInternalFields } from '../../utilities/sanitizeInternalFields.js';
|
|
10
12
|
import { sanitizeSelect } from '../../utilities/sanitizeSelect.js';
|
|
@@ -13,6 +15,9 @@ import { getQueryDraftsSelect } from '../../versions/drafts/getQueryDraftsSelect
|
|
|
13
15
|
import { buildAfterOperation } from './utilities/buildAfterOperation.js';
|
|
14
16
|
import { buildBeforeOperation } from './utilities/buildBeforeOperation.js';
|
|
15
17
|
export const findVersionsOperation = async (args)=>{
|
|
18
|
+
if (!hasVersionsEnabled(args.collection.config)) {
|
|
19
|
+
throw new NotFound(args.req.t);
|
|
20
|
+
}
|
|
16
21
|
try {
|
|
17
22
|
// /////////////////////////////////////
|
|
18
23
|
// beforeOperation - Collection
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/collections/operations/findVersions.ts"],"sourcesContent":["import type { AccessResult } from '../../config/types.js'\nimport type { PaginatedDocs } from '../../database/types.js'\nimport type { PayloadRequest, PopulateType, SelectType, Sort, Where } from '../../types/index.js'\nimport type { TypeWithVersion } from '../../versions/types.js'\nimport type { Collection } from '../config/types.js'\nimport type { FindOptions } from './local/find.js'\n\nimport { executeAccess } from '../../auth/executeAccess.js'\nimport { combineQueries } from '../../database/combineQueries.js'\nimport { validateQueryPaths } from '../../database/queryValidation/validateQueryPaths.js'\nimport { validateSortQuery } from '../../database/queryValidation/validateSortQuery.js'\nimport { sanitizeWhereQuery } from '../../database/sanitizeWhereQuery.js'\nimport { afterRead } from '../../fields/hooks/afterRead/index.js'\nimport { appendNonTrashedFilter } from '../../utilities/appendNonTrashedFilter.js'\nimport { killTransaction } from '../../utilities/killTransaction.js'\nimport { sanitizeInternalFields } from '../../utilities/sanitizeInternalFields.js'\nimport { sanitizeSelect } from '../../utilities/sanitizeSelect.js'\nimport { buildVersionCollectionFields } from '../../versions/buildCollectionFields.js'\nimport { getQueryDraftsSelect } from '../../versions/drafts/getQueryDraftsSelect.js'\nimport { buildAfterOperation } from './utilities/buildAfterOperation.js'\nimport { buildBeforeOperation } from './utilities/buildBeforeOperation.js'\n\nexport type Arguments = {\n collection: Collection\n depth?: number\n limit?: number\n overrideAccess?: boolean\n page?: number\n pagination?: boolean\n populate?: PopulateType\n req?: PayloadRequest\n showHiddenFields?: boolean\n sort?: Sort\n trash?: boolean\n where?: Where\n} & Pick<FindOptions<string, SelectType>, 'select'>\n\nexport const findVersionsOperation = async <TData extends TypeWithVersion<TData>>(\n args: Arguments,\n): Promise<PaginatedDocs<TData>> => {\n try {\n // /////////////////////////////////////\n // beforeOperation - Collection\n // /////////////////////////////////////\n\n args = await buildBeforeOperation({\n args,\n collection: args.collection.config,\n operation: 'findVersions',\n overrideAccess: args.overrideAccess!,\n })\n\n const {\n collection: { config: collectionConfig },\n depth,\n limit,\n overrideAccess,\n page,\n pagination = true,\n populate,\n select: incomingSelect,\n showHiddenFields,\n sort,\n trash = false,\n where,\n } = args\n\n const req = args.req!\n const { fallbackLocale, locale, payload } = req\n\n // /////////////////////////////////////\n // Access\n // /////////////////////////////////////\n\n let accessResults!: AccessResult\n\n if (!overrideAccess) {\n accessResults = await executeAccess({ req }, collectionConfig.access.readVersions)\n }\n\n const versionFields = buildVersionCollectionFields(payload.config, collectionConfig, true)\n\n await validateQueryPaths({\n collectionConfig,\n overrideAccess: overrideAccess!,\n req,\n versionFields,\n where: where!,\n })\n\n await validateSortQuery({\n collectionConfig,\n overrideAccess: overrideAccess!,\n req,\n sort,\n versionFields,\n })\n\n let fullWhere = combineQueries(where!, accessResults)\n\n // Exclude trashed documents when trash: false\n fullWhere = appendNonTrashedFilter({\n deletedAtPath: 'version.deletedAt',\n enableTrash: collectionConfig.trash,\n trash,\n where: fullWhere,\n })\n\n sanitizeWhereQuery({ fields: versionFields, payload, where: fullWhere })\n\n const select = sanitizeSelect({\n fields: versionFields,\n forceSelect: getQueryDraftsSelect({ select: collectionConfig.forceSelect }),\n select: incomingSelect,\n versions: true,\n })\n\n // /////////////////////////////////////\n // Find\n // /////////////////////////////////////\n\n const usePagination = pagination && limit !== 0\n const sanitizedLimit = limit ?? (usePagination ? 10 : 0)\n const sanitizedPage = page || 1\n\n const paginatedDocs = await payload.db.findVersions<TData>({\n collection: collectionConfig.slug,\n limit: sanitizedLimit,\n locale: locale!,\n page: sanitizedPage,\n pagination,\n req,\n select,\n sort,\n where: fullWhere,\n })\n\n // /////////////////////////////////////\n // beforeRead - Collection\n // /////////////////////////////////////\n let result: PaginatedDocs<TData> = paginatedDocs as unknown as PaginatedDocs<TData>\n result.docs = (await Promise.all(\n paginatedDocs.docs.map(async (doc) => {\n const docRef = doc\n // Fallback if not selected\n if (!docRef.version) {\n ;(docRef as any).version = {}\n }\n\n if (collectionConfig.hooks?.beforeRead?.length) {\n for (const hook of collectionConfig.hooks.beforeRead) {\n docRef.version =\n (await hook({\n collection: collectionConfig,\n context: req.context,\n doc: docRef.version,\n overrideAccess,\n query: fullWhere,\n req,\n })) || docRef.version\n }\n }\n\n return docRef\n }),\n )) as TData[]\n // /////////////////////////////////////\n // afterRead - Fields\n // /////////////////////////////////////\n\n result.docs = await Promise.all(\n result.docs.map(async (data) => {\n data.version = await afterRead({\n collection: collectionConfig,\n context: req.context,\n depth: depth!,\n doc: data.version,\n // @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve\n draft: undefined,\n fallbackLocale: fallbackLocale!,\n findMany: true,\n global: null,\n locale: locale!,\n overrideAccess: overrideAccess!,\n populate,\n req,\n select: typeof select?.version === 'object' ? select.version : undefined,\n showHiddenFields: showHiddenFields!,\n })\n return data\n }),\n )\n\n // /////////////////////////////////////\n // afterRead - Collection\n // /////////////////////////////////////\n\n if (collectionConfig.hooks.afterRead?.length) {\n result.docs = await Promise.all(\n result.docs.map(async (doc) => {\n const docRef = doc\n\n for (const hook of collectionConfig.hooks.afterRead) {\n docRef.version =\n (await hook({\n collection: collectionConfig,\n context: req.context,\n doc: doc.version,\n findMany: true,\n overrideAccess,\n query: fullWhere,\n req,\n })) || doc.version\n }\n\n return docRef\n }),\n )\n }\n\n // /////////////////////////////////////\n // Return results\n // /////////////////////////////////////\n result.docs = result.docs.map((doc) => sanitizeInternalFields<TData>(doc))\n\n // /////////////////////////////////////\n // afterOperation - Collection\n // /////////////////////////////////////\n\n result = await buildAfterOperation({\n args,\n collection: collectionConfig,\n operation: 'findVersions',\n overrideAccess,\n result,\n })\n\n return result\n } catch (error: unknown) {\n await killTransaction(args.req!)\n throw error\n }\n}\n"],"names":["executeAccess","combineQueries","validateQueryPaths","validateSortQuery","sanitizeWhereQuery","afterRead","appendNonTrashedFilter","killTransaction","sanitizeInternalFields","sanitizeSelect","buildVersionCollectionFields","getQueryDraftsSelect","buildAfterOperation","buildBeforeOperation","findVersionsOperation","args","collection","config","operation","overrideAccess","collectionConfig","depth","limit","page","pagination","populate","select","incomingSelect","showHiddenFields","sort","trash","where","req","fallbackLocale","locale","payload","accessResults","access","readVersions","versionFields","fullWhere","deletedAtPath","enableTrash","fields","forceSelect","versions","usePagination","sanitizedLimit","sanitizedPage","paginatedDocs","db","findVersions","slug","result","docs","Promise","all","map","doc","docRef","version","hooks","beforeRead","length","hook","context","query","data","draft","undefined","findMany","global","error"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../../src/collections/operations/findVersions.ts"],"sourcesContent":["import type { AccessResult } from '../../config/types.js'\nimport type { PaginatedDocs } from '../../database/types.js'\nimport type { PayloadRequest, PopulateType, SelectType, Sort, Where } from '../../types/index.js'\nimport type { TypeWithVersion } from '../../versions/types.js'\nimport type { Collection } from '../config/types.js'\nimport type { FindOptions } from './local/find.js'\n\nimport { executeAccess } from '../../auth/executeAccess.js'\nimport { combineQueries } from '../../database/combineQueries.js'\nimport { validateQueryPaths } from '../../database/queryValidation/validateQueryPaths.js'\nimport { validateSortQuery } from '../../database/queryValidation/validateSortQuery.js'\nimport { sanitizeWhereQuery } from '../../database/sanitizeWhereQuery.js'\nimport { NotFound } from '../../errors/index.js'\nimport { afterRead } from '../../fields/hooks/afterRead/index.js'\nimport { appendNonTrashedFilter } from '../../utilities/appendNonTrashedFilter.js'\nimport { hasVersionsEnabled } from '../../utilities/getVersionsConfig.js'\nimport { killTransaction } from '../../utilities/killTransaction.js'\nimport { sanitizeInternalFields } from '../../utilities/sanitizeInternalFields.js'\nimport { sanitizeSelect } from '../../utilities/sanitizeSelect.js'\nimport { buildVersionCollectionFields } from '../../versions/buildCollectionFields.js'\nimport { getQueryDraftsSelect } from '../../versions/drafts/getQueryDraftsSelect.js'\nimport { buildAfterOperation } from './utilities/buildAfterOperation.js'\nimport { buildBeforeOperation } from './utilities/buildBeforeOperation.js'\n\nexport type Arguments = {\n collection: Collection\n depth?: number\n limit?: number\n overrideAccess?: boolean\n page?: number\n pagination?: boolean\n populate?: PopulateType\n req?: PayloadRequest\n showHiddenFields?: boolean\n sort?: Sort\n trash?: boolean\n where?: Where\n} & Pick<FindOptions<string, SelectType>, 'select'>\n\nexport const findVersionsOperation = async <TData extends TypeWithVersion<TData>>(\n args: Arguments,\n): Promise<PaginatedDocs<TData>> => {\n if (!hasVersionsEnabled(args.collection.config)) {\n throw new NotFound(args.req!.t)\n }\n\n try {\n // /////////////////////////////////////\n // beforeOperation - Collection\n // /////////////////////////////////////\n\n args = await buildBeforeOperation({\n args,\n collection: args.collection.config,\n operation: 'findVersions',\n overrideAccess: args.overrideAccess!,\n })\n\n const {\n collection: { config: collectionConfig },\n depth,\n limit,\n overrideAccess,\n page,\n pagination = true,\n populate,\n select: incomingSelect,\n showHiddenFields,\n sort,\n trash = false,\n where,\n } = args\n\n const req = args.req!\n const { fallbackLocale, locale, payload } = req\n\n // /////////////////////////////////////\n // Access\n // /////////////////////////////////////\n\n let accessResults!: AccessResult\n\n if (!overrideAccess) {\n accessResults = await executeAccess({ req }, collectionConfig.access.readVersions)\n }\n\n const versionFields = buildVersionCollectionFields(payload.config, collectionConfig, true)\n\n await validateQueryPaths({\n collectionConfig,\n overrideAccess: overrideAccess!,\n req,\n versionFields,\n where: where!,\n })\n\n await validateSortQuery({\n collectionConfig,\n overrideAccess: overrideAccess!,\n req,\n sort,\n versionFields,\n })\n\n let fullWhere = combineQueries(where!, accessResults)\n\n // Exclude trashed documents when trash: false\n fullWhere = appendNonTrashedFilter({\n deletedAtPath: 'version.deletedAt',\n enableTrash: collectionConfig.trash,\n trash,\n where: fullWhere,\n })\n\n sanitizeWhereQuery({ fields: versionFields, payload, where: fullWhere })\n\n const select = sanitizeSelect({\n fields: versionFields,\n forceSelect: getQueryDraftsSelect({ select: collectionConfig.forceSelect }),\n select: incomingSelect,\n versions: true,\n })\n\n // /////////////////////////////////////\n // Find\n // /////////////////////////////////////\n\n const usePagination = pagination && limit !== 0\n const sanitizedLimit = limit ?? (usePagination ? 10 : 0)\n const sanitizedPage = page || 1\n\n const paginatedDocs = await payload.db.findVersions<TData>({\n collection: collectionConfig.slug,\n limit: sanitizedLimit,\n locale: locale!,\n page: sanitizedPage,\n pagination,\n req,\n select,\n sort,\n where: fullWhere,\n })\n\n // /////////////////////////////////////\n // beforeRead - Collection\n // /////////////////////////////////////\n let result: PaginatedDocs<TData> = paginatedDocs as unknown as PaginatedDocs<TData>\n result.docs = (await Promise.all(\n paginatedDocs.docs.map(async (doc) => {\n const docRef = doc\n // Fallback if not selected\n if (!docRef.version) {\n ;(docRef as any).version = {}\n }\n\n if (collectionConfig.hooks?.beforeRead?.length) {\n for (const hook of collectionConfig.hooks.beforeRead) {\n docRef.version =\n (await hook({\n collection: collectionConfig,\n context: req.context,\n doc: docRef.version,\n overrideAccess,\n query: fullWhere,\n req,\n })) || docRef.version\n }\n }\n\n return docRef\n }),\n )) as TData[]\n // /////////////////////////////////////\n // afterRead - Fields\n // /////////////////////////////////////\n\n result.docs = await Promise.all(\n result.docs.map(async (data) => {\n data.version = await afterRead({\n collection: collectionConfig,\n context: req.context,\n depth: depth!,\n doc: data.version,\n // @ts-expect-error - vestiges of when tsconfig was not strict. Feel free to improve\n draft: undefined,\n fallbackLocale: fallbackLocale!,\n findMany: true,\n global: null,\n locale: locale!,\n overrideAccess: overrideAccess!,\n populate,\n req,\n select: typeof select?.version === 'object' ? select.version : undefined,\n showHiddenFields: showHiddenFields!,\n })\n return data\n }),\n )\n\n // /////////////////////////////////////\n // afterRead - Collection\n // /////////////////////////////////////\n\n if (collectionConfig.hooks.afterRead?.length) {\n result.docs = await Promise.all(\n result.docs.map(async (doc) => {\n const docRef = doc\n\n for (const hook of collectionConfig.hooks.afterRead) {\n docRef.version =\n (await hook({\n collection: collectionConfig,\n context: req.context,\n doc: doc.version,\n findMany: true,\n overrideAccess,\n query: fullWhere,\n req,\n })) || doc.version\n }\n\n return docRef\n }),\n )\n }\n\n // /////////////////////////////////////\n // Return results\n // /////////////////////////////////////\n result.docs = result.docs.map((doc) => sanitizeInternalFields<TData>(doc))\n\n // /////////////////////////////////////\n // afterOperation - Collection\n // /////////////////////////////////////\n\n result = await buildAfterOperation({\n args,\n collection: collectionConfig,\n operation: 'findVersions',\n overrideAccess,\n result,\n })\n\n return result\n } catch (error: unknown) {\n await killTransaction(args.req!)\n throw error\n }\n}\n"],"names":["executeAccess","combineQueries","validateQueryPaths","validateSortQuery","sanitizeWhereQuery","NotFound","afterRead","appendNonTrashedFilter","hasVersionsEnabled","killTransaction","sanitizeInternalFields","sanitizeSelect","buildVersionCollectionFields","getQueryDraftsSelect","buildAfterOperation","buildBeforeOperation","findVersionsOperation","args","collection","config","req","t","operation","overrideAccess","collectionConfig","depth","limit","page","pagination","populate","select","incomingSelect","showHiddenFields","sort","trash","where","fallbackLocale","locale","payload","accessResults","access","readVersions","versionFields","fullWhere","deletedAtPath","enableTrash","fields","forceSelect","versions","usePagination","sanitizedLimit","sanitizedPage","paginatedDocs","db","findVersions","slug","result","docs","Promise","all","map","doc","docRef","version","hooks","beforeRead","length","hook","context","query","data","draft","undefined","findMany","global","error"],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export type SchemaBuildContext<TSchema> = {
|
|
2
|
+
clear: () => void;
|
|
3
|
+
getOrCreate: (args: {
|
|
4
|
+
build: () => TSchema;
|
|
5
|
+
cacheKey: string;
|
|
6
|
+
definition: object;
|
|
7
|
+
}) => TSchema;
|
|
8
|
+
};
|
|
9
|
+
export declare const createSchemaBuildContext: <TSchema>({ isCacheEnabled, }?: {
|
|
10
|
+
isCacheEnabled?: boolean;
|
|
11
|
+
}) => SchemaBuildContext<TSchema>;
|
|
12
|
+
//# sourceMappingURL=createSchemaBuildContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"createSchemaBuildContext.d.ts","sourceRoot":"","sources":["../../src/database/createSchemaBuildContext.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,kBAAkB,CAAC,OAAO,IAAI;IACxC,KAAK,EAAE,MAAM,IAAI,CAAA;IACjB,WAAW,EAAE,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,MAAM,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,KAAK,OAAO,CAAA;CAC/F,CAAA;AAED,eAAO,MAAM,wBAAwB,GAAI,OAAO,wBAE7C;IACD,cAAc,CAAC,EAAE,OAAO,CAAA;CACzB,KAAQ,kBAAkB,CAAC,OAAO,CA2BlC,CAAA"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export const createSchemaBuildContext = ({ isCacheEnabled = true } = {})=>{
|
|
2
|
+
let schemasByDefinition = new WeakMap();
|
|
3
|
+
return {
|
|
4
|
+
clear: ()=>{
|
|
5
|
+
schemasByDefinition = new WeakMap();
|
|
6
|
+
},
|
|
7
|
+
getOrCreate: ({ build, cacheKey, definition })=>{
|
|
8
|
+
const schemasByKey = schemasByDefinition.get(definition);
|
|
9
|
+
if (!isCacheEnabled) {
|
|
10
|
+
return build();
|
|
11
|
+
}
|
|
12
|
+
if (schemasByKey?.has(cacheKey)) {
|
|
13
|
+
return schemasByKey.get(cacheKey);
|
|
14
|
+
}
|
|
15
|
+
const schema = build();
|
|
16
|
+
const storedSchemasByKey = schemasByKey ?? new Map();
|
|
17
|
+
storedSchemasByKey.set(cacheKey, schema);
|
|
18
|
+
schemasByDefinition.set(definition, storedSchemasByKey);
|
|
19
|
+
return schema;
|
|
20
|
+
}
|
|
21
|
+
};
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=createSchemaBuildContext.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/database/createSchemaBuildContext.ts"],"sourcesContent":["export type SchemaBuildContext<TSchema> = {\n clear: () => void\n getOrCreate: (args: { build: () => TSchema; cacheKey: string; definition: object }) => TSchema\n}\n\nexport const createSchemaBuildContext = <TSchema>({\n isCacheEnabled = true,\n}: {\n isCacheEnabled?: boolean\n} = {}): SchemaBuildContext<TSchema> => {\n let schemasByDefinition = new WeakMap<object, Map<string, TSchema>>()\n\n return {\n clear: () => {\n schemasByDefinition = new WeakMap<object, Map<string, TSchema>>()\n },\n getOrCreate: ({ build, cacheKey, definition }) => {\n const schemasByKey = schemasByDefinition.get(definition)\n\n if (!isCacheEnabled) {\n return build()\n }\n\n if (schemasByKey?.has(cacheKey)) {\n return schemasByKey.get(cacheKey)!\n }\n\n const schema = build()\n const storedSchemasByKey = schemasByKey ?? new Map<string, TSchema>()\n\n storedSchemasByKey.set(cacheKey, schema)\n schemasByDefinition.set(definition, storedSchemasByKey)\n\n return schema\n },\n }\n}\n"],"names":["createSchemaBuildContext","isCacheEnabled","schemasByDefinition","WeakMap","clear","getOrCreate","build","cacheKey","definition","schemasByKey","get","has","schema","storedSchemasByKey","Map","set"],"mappings":"AAKA,OAAO,MAAMA,2BAA2B,CAAU,EAChDC,iBAAiB,IAAI,EAGtB,GAAG,CAAC,CAAC;IACJ,IAAIC,sBAAsB,IAAIC;IAE9B,OAAO;QACLC,OAAO;YACLF,sBAAsB,IAAIC;QAC5B;QACAE,aAAa,CAAC,EAAEC,KAAK,EAAEC,QAAQ,EAAEC,UAAU,EAAE;YAC3C,MAAMC,eAAeP,oBAAoBQ,GAAG,CAACF;YAE7C,IAAI,CAACP,gBAAgB;gBACnB,OAAOK;YACT;YAEA,IAAIG,cAAcE,IAAIJ,WAAW;gBAC/B,OAAOE,aAAaC,GAAG,CAACH;YAC1B;YAEA,MAAMK,SAASN;YACf,MAAMO,qBAAqBJ,gBAAgB,IAAIK;YAE/CD,mBAAmBE,GAAG,CAACR,UAAUK;YACjCV,oBAAoBa,GAAG,CAACP,YAAYK;YAEpC,OAAOD;QACT;IACF;AACF,EAAC"}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { describe, expect, test, vi } from 'vitest';
|
|
2
|
+
import { createSchemaBuildContext } from './createSchemaBuildContext.js';
|
|
3
|
+
describe('createSchemaBuildContext', ()=>{
|
|
4
|
+
test('should build once for the same definition identity and variant', ()=>{
|
|
5
|
+
const context = createSchemaBuildContext();
|
|
6
|
+
const definition = {};
|
|
7
|
+
const artifact = {};
|
|
8
|
+
const build = vi.fn(()=>artifact);
|
|
9
|
+
const first = context.getOrCreate({
|
|
10
|
+
build,
|
|
11
|
+
definition,
|
|
12
|
+
cacheKey: 'block:hero'
|
|
13
|
+
});
|
|
14
|
+
const second = context.getOrCreate({
|
|
15
|
+
build,
|
|
16
|
+
definition,
|
|
17
|
+
cacheKey: 'block:hero'
|
|
18
|
+
});
|
|
19
|
+
expect(first).toBe(artifact);
|
|
20
|
+
expect(second).toBe(artifact);
|
|
21
|
+
expect(build).toHaveBeenCalledOnce();
|
|
22
|
+
});
|
|
23
|
+
test('should build separate artifacts for separate variants', ()=>{
|
|
24
|
+
const context = createSchemaBuildContext();
|
|
25
|
+
const definition = {};
|
|
26
|
+
const live = context.getOrCreate({
|
|
27
|
+
build: ()=>({
|
|
28
|
+
variant: 'live'
|
|
29
|
+
}),
|
|
30
|
+
definition,
|
|
31
|
+
cacheKey: 'block:hero'
|
|
32
|
+
});
|
|
33
|
+
const version = context.getOrCreate({
|
|
34
|
+
build: ()=>({
|
|
35
|
+
variant: 'version'
|
|
36
|
+
}),
|
|
37
|
+
definition,
|
|
38
|
+
cacheKey: 'block:hero-version'
|
|
39
|
+
});
|
|
40
|
+
expect(live).not.toBe(version);
|
|
41
|
+
});
|
|
42
|
+
test('should build a fresh artifact when caching is disabled', ()=>{
|
|
43
|
+
const context = createSchemaBuildContext({
|
|
44
|
+
isCacheEnabled: false
|
|
45
|
+
});
|
|
46
|
+
const definition = {};
|
|
47
|
+
const build = vi.fn(()=>({}));
|
|
48
|
+
const first = context.getOrCreate({
|
|
49
|
+
build,
|
|
50
|
+
definition,
|
|
51
|
+
cacheKey: 'block:hero'
|
|
52
|
+
});
|
|
53
|
+
const second = context.getOrCreate({
|
|
54
|
+
build,
|
|
55
|
+
definition,
|
|
56
|
+
cacheKey: 'block:hero'
|
|
57
|
+
});
|
|
58
|
+
expect(first).not.toBe(second);
|
|
59
|
+
expect(build).toHaveBeenCalledTimes(2);
|
|
60
|
+
});
|
|
61
|
+
test('should not merge equal definitions with different object identities', ()=>{
|
|
62
|
+
const context = createSchemaBuildContext();
|
|
63
|
+
const first = context.getOrCreate({
|
|
64
|
+
build: ()=>({
|
|
65
|
+
source: 'first'
|
|
66
|
+
}),
|
|
67
|
+
definition: {
|
|
68
|
+
slug: 'hero'
|
|
69
|
+
},
|
|
70
|
+
cacheKey: 'block:hero'
|
|
71
|
+
});
|
|
72
|
+
const second = context.getOrCreate({
|
|
73
|
+
build: ()=>({
|
|
74
|
+
source: 'second'
|
|
75
|
+
}),
|
|
76
|
+
definition: {
|
|
77
|
+
slug: 'hero'
|
|
78
|
+
},
|
|
79
|
+
cacheKey: 'block:hero'
|
|
80
|
+
});
|
|
81
|
+
expect(first).not.toBe(second);
|
|
82
|
+
});
|
|
83
|
+
test('should not share artifacts between contexts', ()=>{
|
|
84
|
+
const definition = {};
|
|
85
|
+
const firstContext = createSchemaBuildContext();
|
|
86
|
+
const secondContext = createSchemaBuildContext();
|
|
87
|
+
const first = firstContext.getOrCreate({
|
|
88
|
+
build: ()=>({
|
|
89
|
+
context: 'first'
|
|
90
|
+
}),
|
|
91
|
+
definition,
|
|
92
|
+
cacheKey: 'block:hero'
|
|
93
|
+
});
|
|
94
|
+
const second = secondContext.getOrCreate({
|
|
95
|
+
build: ()=>({
|
|
96
|
+
context: 'second'
|
|
97
|
+
}),
|
|
98
|
+
definition,
|
|
99
|
+
cacheKey: 'block:hero'
|
|
100
|
+
});
|
|
101
|
+
expect(first).not.toBe(second);
|
|
102
|
+
});
|
|
103
|
+
test('should retry after a builder throws', ()=>{
|
|
104
|
+
const context = createSchemaBuildContext();
|
|
105
|
+
const definition = {};
|
|
106
|
+
const artifact = {};
|
|
107
|
+
const build = vi.fn();
|
|
108
|
+
build.mockImplementationOnce(()=>{
|
|
109
|
+
throw new Error('build failed');
|
|
110
|
+
});
|
|
111
|
+
build.mockReturnValueOnce(artifact);
|
|
112
|
+
expect(()=>context.getOrCreate({
|
|
113
|
+
build,
|
|
114
|
+
cacheKey: 'block:hero',
|
|
115
|
+
definition
|
|
116
|
+
})).toThrow('build failed');
|
|
117
|
+
expect(context.getOrCreate({
|
|
118
|
+
build,
|
|
119
|
+
cacheKey: 'block:hero',
|
|
120
|
+
definition
|
|
121
|
+
})).toBe(artifact);
|
|
122
|
+
expect(build).toHaveBeenCalledTimes(2);
|
|
123
|
+
});
|
|
124
|
+
test('should reset artifacts when cleared', ()=>{
|
|
125
|
+
const context = createSchemaBuildContext();
|
|
126
|
+
const definition = {};
|
|
127
|
+
const first = context.getOrCreate({
|
|
128
|
+
build: ()=>({
|
|
129
|
+
build: 1
|
|
130
|
+
}),
|
|
131
|
+
definition,
|
|
132
|
+
cacheKey: 'block:hero'
|
|
133
|
+
});
|
|
134
|
+
context.clear();
|
|
135
|
+
const second = context.getOrCreate({
|
|
136
|
+
build: ()=>({
|
|
137
|
+
build: 2
|
|
138
|
+
}),
|
|
139
|
+
definition,
|
|
140
|
+
cacheKey: 'block:hero'
|
|
141
|
+
});
|
|
142
|
+
expect(second).not.toBe(first);
|
|
143
|
+
});
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
//# sourceMappingURL=createSchemaBuildContext.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/database/createSchemaBuildContext.spec.ts"],"sourcesContent":["import { describe, expect, test, vi } from 'vitest'\n\nimport { createSchemaBuildContext } from './createSchemaBuildContext.js'\n\ndescribe('createSchemaBuildContext', () => {\n test('should build once for the same definition identity and variant', () => {\n const context = createSchemaBuildContext<object>()\n const definition = {}\n const artifact = {}\n const build = vi.fn(() => artifact)\n\n const first = context.getOrCreate({\n build,\n definition,\n cacheKey: 'block:hero',\n })\n const second = context.getOrCreate({\n build,\n definition,\n cacheKey: 'block:hero',\n })\n\n expect(first).toBe(artifact)\n expect(second).toBe(artifact)\n expect(build).toHaveBeenCalledOnce()\n })\n\n test('should build separate artifacts for separate variants', () => {\n const context = createSchemaBuildContext<object>()\n const definition = {}\n\n const live = context.getOrCreate({\n build: () => ({ variant: 'live' }),\n definition,\n cacheKey: 'block:hero',\n })\n const version = context.getOrCreate({\n build: () => ({ variant: 'version' }),\n definition,\n cacheKey: 'block:hero-version',\n })\n\n expect(live).not.toBe(version)\n })\n\n test('should build a fresh artifact when caching is disabled', () => {\n const context = createSchemaBuildContext<object>({ isCacheEnabled: false })\n const definition = {}\n const build = vi.fn(() => ({}))\n\n const first = context.getOrCreate({\n build,\n definition,\n cacheKey: 'block:hero',\n })\n const second = context.getOrCreate({\n build,\n definition,\n cacheKey: 'block:hero',\n })\n\n expect(first).not.toBe(second)\n expect(build).toHaveBeenCalledTimes(2)\n })\n\n test('should not merge equal definitions with different object identities', () => {\n const context = createSchemaBuildContext<object>()\n const first = context.getOrCreate({\n build: () => ({ source: 'first' }),\n definition: { slug: 'hero' },\n cacheKey: 'block:hero',\n })\n const second = context.getOrCreate({\n build: () => ({ source: 'second' }),\n definition: { slug: 'hero' },\n cacheKey: 'block:hero',\n })\n\n expect(first).not.toBe(second)\n })\n\n test('should not share artifacts between contexts', () => {\n const definition = {}\n const firstContext = createSchemaBuildContext<object>()\n const secondContext = createSchemaBuildContext<object>()\n const first = firstContext.getOrCreate({\n build: () => ({ context: 'first' }),\n definition,\n cacheKey: 'block:hero',\n })\n const second = secondContext.getOrCreate({\n build: () => ({ context: 'second' }),\n definition,\n cacheKey: 'block:hero',\n })\n\n expect(first).not.toBe(second)\n })\n\n test('should retry after a builder throws', () => {\n const context = createSchemaBuildContext<object>()\n const definition = {}\n const artifact = {}\n const build = vi.fn<() => object>()\n build.mockImplementationOnce(() => {\n throw new Error('build failed')\n })\n build.mockReturnValueOnce(artifact)\n\n expect(() => context.getOrCreate({ build, cacheKey: 'block:hero', definition })).toThrow(\n 'build failed',\n )\n expect(context.getOrCreate({ build, cacheKey: 'block:hero', definition })).toBe(artifact)\n expect(build).toHaveBeenCalledTimes(2)\n })\n\n test('should reset artifacts when cleared', () => {\n const context = createSchemaBuildContext<object>()\n const definition = {}\n const first = context.getOrCreate({\n build: () => ({ build: 1 }),\n definition,\n cacheKey: 'block:hero',\n })\n\n context.clear()\n\n const second = context.getOrCreate({\n build: () => ({ build: 2 }),\n definition,\n cacheKey: 'block:hero',\n })\n\n expect(second).not.toBe(first)\n })\n})\n"],"names":["describe","expect","test","vi","createSchemaBuildContext","context","definition","artifact","build","fn","first","getOrCreate","cacheKey","second","toBe","toHaveBeenCalledOnce","live","variant","version","not","isCacheEnabled","toHaveBeenCalledTimes","source","slug","firstContext","secondContext","mockImplementationOnce","Error","mockReturnValueOnce","toThrow","clear"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sanitizeJoinQuery.d.ts","sourceRoot":"","sources":["../../src/database/sanitizeJoinQuery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAiB,MAAM,gCAAgC,CAAA;AAC9F,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;
|
|
1
|
+
{"version":3,"file":"sanitizeJoinQuery.d.ts","sourceRoot":"","sources":["../../src/database/sanitizeJoinQuery.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAiB,MAAM,gCAAgC,CAAA;AAC9F,OAAO,KAAK,EAAE,SAAS,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAA;AAUlE,KAAK,IAAI,GAAG;IACV,gBAAgB,EAAE,yBAAyB,CAAA;IAC3C,KAAK,CAAC,EAAE,SAAS,CAAA;IACjB,cAAc,EAAE,OAAO,CAAA;IACvB,GAAG,EAAE,cAAc,CAAA;CACpB,CAAA;AAgFD;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,kEAK3B,IAAI;;;;;;;;GA+CN,CAAA"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { executeAccess } from '../auth/executeAccess.js';
|
|
2
2
|
import { QueryError } from '../errors/QueryError.js';
|
|
3
|
+
import { deepCopyObjectSimple } from '../utilities/deepCopyObject.js';
|
|
3
4
|
import { combineQueries } from './combineQueries.js';
|
|
4
5
|
import { validateQueryPaths } from './queryValidation/validateQueryPaths.js';
|
|
5
6
|
import { validateSortQuery } from './queryValidation/validateSortQuery.js';
|
|
@@ -29,7 +30,7 @@ const sanitizeJoinFieldQuery = async ({ collectionSlug, errors, join, joinsQuery
|
|
|
29
30
|
joinQuery.where = {};
|
|
30
31
|
}
|
|
31
32
|
if (join.field.where) {
|
|
32
|
-
joinQuery.where = combineQueries(joinQuery.where, join.field.where);
|
|
33
|
+
joinQuery.where = combineQueries(joinQuery.where, deepCopyObjectSimple(join.field.where));
|
|
33
34
|
}
|
|
34
35
|
promises.push(validateQueryPaths({
|
|
35
36
|
collectionConfig: joinCollectionConfig,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/database/sanitizeJoinQuery.ts"],"sourcesContent":["import type { SanitizedCollectionConfig, SanitizedJoin } from '../collections/config/types.js'\nimport type { JoinQuery, PayloadRequest } from '../types/index.js'\n\nimport { executeAccess } from '../auth/executeAccess.js'\nimport { QueryError } from '../errors/QueryError.js'\nimport { combineQueries } from './combineQueries.js'\nimport { validateQueryPaths } from './queryValidation/validateQueryPaths.js'\nimport { validateSortQuery } from './queryValidation/validateSortQuery.js'\nimport { sanitizeWhereQuery } from './sanitizeWhereQuery.js'\n\ntype Args = {\n collectionConfig: SanitizedCollectionConfig\n joins?: JoinQuery\n overrideAccess: boolean\n req: PayloadRequest\n}\n\nconst sanitizeJoinFieldQuery = async ({\n collectionSlug,\n errors,\n join,\n joinsQuery,\n overrideAccess,\n promises,\n req,\n}: {\n collectionSlug: string\n errors: { path: string }[]\n join: SanitizedJoin\n joinsQuery: JoinQuery\n overrideAccess: boolean\n promises: Promise<void>[]\n req: PayloadRequest\n}) => {\n const { joinPath } = join\n\n // TODO: fix any's in joinsQuery[joinPath]\n\n if ((joinsQuery as any)[joinPath] === false) {\n return\n }\n\n const joinCollectionConfig = req.payload.collections[collectionSlug]!.config\n\n const accessResult = !overrideAccess\n ? await executeAccess({ disableErrors: true, req }, joinCollectionConfig.access.read)\n : true\n\n if (accessResult === false) {\n ;(joinsQuery as any)[joinPath] = false\n return\n }\n\n if (!(joinsQuery as any)[joinPath]) {\n ;(joinsQuery as any)[joinPath] = {}\n }\n\n const joinQuery = (joinsQuery as any)[joinPath]\n\n if (!joinQuery.where) {\n joinQuery.where = {}\n }\n\n if (join.field.where) {\n joinQuery.where = combineQueries(joinQuery.where, join.field.where)\n }\n\n promises.push(\n validateQueryPaths({\n collectionConfig: joinCollectionConfig,\n errors,\n overrideAccess,\n polymorphicJoin: Array.isArray(join.field.collection),\n req,\n // incoming where input, but we shouldn't validate generated from the access control.\n where: joinQuery.where,\n }),\n validateSortQuery({\n collectionConfig: joinCollectionConfig,\n overrideAccess,\n req,\n sort: joinQuery.sort || join.field.defaultSort || joinCollectionConfig.defaultSort,\n }),\n )\n\n if (typeof accessResult === 'object') {\n sanitizeWhereQuery({\n fields: joinCollectionConfig.flattenedFields,\n payload: req.payload,\n where: accessResult,\n })\n joinQuery.where = combineQueries(joinQuery.where, accessResult)\n }\n}\n\n/**\n * * Validates `where` for each join\n * * Combines the access result for joined collection\n * * Combines the default join's `where`\n */\nexport const sanitizeJoinQuery = async ({\n collectionConfig,\n joins: joinsQuery,\n overrideAccess,\n req,\n}: Args) => {\n if (joinsQuery === false) {\n return false\n }\n\n if (!joinsQuery) {\n joinsQuery = {}\n }\n\n const errors: { path: string }[] = []\n const promises: Promise<void>[] = []\n\n for (const collectionSlug in collectionConfig.joins) {\n for (const join of collectionConfig.joins[collectionSlug]!) {\n await sanitizeJoinFieldQuery({\n collectionSlug,\n errors,\n join,\n joinsQuery,\n overrideAccess,\n promises,\n req,\n })\n }\n }\n\n for (const join of collectionConfig.polymorphicJoins) {\n for (const collectionSlug of join.field.collection) {\n await sanitizeJoinFieldQuery({\n collectionSlug,\n errors,\n join,\n joinsQuery,\n overrideAccess,\n promises,\n req,\n })\n }\n }\n\n await Promise.all(promises)\n\n if (errors.length > 0) {\n throw new QueryError(errors)\n }\n\n return joinsQuery\n}\n"],"names":["executeAccess","QueryError","combineQueries","validateQueryPaths","validateSortQuery","sanitizeWhereQuery","sanitizeJoinFieldQuery","collectionSlug","errors","join","joinsQuery","overrideAccess","promises","req","joinPath","joinCollectionConfig","payload","collections","config","accessResult","disableErrors","access","read","joinQuery","where","field","push","collectionConfig","polymorphicJoin","Array","isArray","collection","sort","defaultSort","fields","flattenedFields","sanitizeJoinQuery","joins","polymorphicJoins","Promise","all","length"],"mappings":"AAGA,SAASA,aAAa,QAAQ,2BAA0B;AACxD,SAASC,UAAU,QAAQ,0BAAyB;AACpD,SAASC,cAAc,QAAQ,sBAAqB;AACpD,SAASC,kBAAkB,QAAQ,0CAAyC;AAC5E,SAASC,iBAAiB,QAAQ,yCAAwC;AAC1E,SAASC,kBAAkB,QAAQ,0BAAyB;AAS5D,MAAMC,yBAAyB,OAAO,EACpCC,cAAc,EACdC,MAAM,EACNC,IAAI,EACJC,UAAU,EACVC,cAAc,EACdC,QAAQ,EACRC,GAAG,EASJ;IACC,MAAM,EAAEC,QAAQ,EAAE,GAAGL;IAErB,0CAA0C;IAE1C,IAAI,AAACC,UAAkB,CAACI,SAAS,KAAK,OAAO;QAC3C;IACF;IAEA,MAAMC,uBAAuBF,IAAIG,OAAO,CAACC,WAAW,CAACV,eAAe,CAAEW,MAAM;IAE5E,MAAMC,eAAe,CAACR,iBAClB,
|
|
1
|
+
{"version":3,"sources":["../../src/database/sanitizeJoinQuery.ts"],"sourcesContent":["import type { SanitizedCollectionConfig, SanitizedJoin } from '../collections/config/types.js'\nimport type { JoinQuery, PayloadRequest } from '../types/index.js'\n\nimport { executeAccess } from '../auth/executeAccess.js'\nimport { QueryError } from '../errors/QueryError.js'\nimport { deepCopyObjectSimple } from '../utilities/deepCopyObject.js'\nimport { combineQueries } from './combineQueries.js'\nimport { validateQueryPaths } from './queryValidation/validateQueryPaths.js'\nimport { validateSortQuery } from './queryValidation/validateSortQuery.js'\nimport { sanitizeWhereQuery } from './sanitizeWhereQuery.js'\n\ntype Args = {\n collectionConfig: SanitizedCollectionConfig\n joins?: JoinQuery\n overrideAccess: boolean\n req: PayloadRequest\n}\n\nconst sanitizeJoinFieldQuery = async ({\n collectionSlug,\n errors,\n join,\n joinsQuery,\n overrideAccess,\n promises,\n req,\n}: {\n collectionSlug: string\n errors: { path: string }[]\n join: SanitizedJoin\n joinsQuery: JoinQuery\n overrideAccess: boolean\n promises: Promise<void>[]\n req: PayloadRequest\n}) => {\n const { joinPath } = join\n\n // TODO: fix any's in joinsQuery[joinPath]\n\n if ((joinsQuery as any)[joinPath] === false) {\n return\n }\n\n const joinCollectionConfig = req.payload.collections[collectionSlug]!.config\n\n const accessResult = !overrideAccess\n ? await executeAccess({ disableErrors: true, req }, joinCollectionConfig.access.read)\n : true\n\n if (accessResult === false) {\n ;(joinsQuery as any)[joinPath] = false\n return\n }\n\n if (!(joinsQuery as any)[joinPath]) {\n ;(joinsQuery as any)[joinPath] = {}\n }\n\n const joinQuery = (joinsQuery as any)[joinPath]\n\n if (!joinQuery.where) {\n joinQuery.where = {}\n }\n\n if (join.field.where) {\n joinQuery.where = combineQueries(joinQuery.where, deepCopyObjectSimple(join.field.where))\n }\n\n promises.push(\n validateQueryPaths({\n collectionConfig: joinCollectionConfig,\n errors,\n overrideAccess,\n polymorphicJoin: Array.isArray(join.field.collection),\n req,\n // incoming where input, but we shouldn't validate generated from the access control.\n where: joinQuery.where,\n }),\n validateSortQuery({\n collectionConfig: joinCollectionConfig,\n overrideAccess,\n req,\n sort: joinQuery.sort || join.field.defaultSort || joinCollectionConfig.defaultSort,\n }),\n )\n\n if (typeof accessResult === 'object') {\n sanitizeWhereQuery({\n fields: joinCollectionConfig.flattenedFields,\n payload: req.payload,\n where: accessResult,\n })\n joinQuery.where = combineQueries(joinQuery.where, accessResult)\n }\n}\n\n/**\n * * Validates `where` for each join\n * * Combines the access result for joined collection\n * * Combines the default join's `where`\n */\nexport const sanitizeJoinQuery = async ({\n collectionConfig,\n joins: joinsQuery,\n overrideAccess,\n req,\n}: Args) => {\n if (joinsQuery === false) {\n return false\n }\n\n if (!joinsQuery) {\n joinsQuery = {}\n }\n\n const errors: { path: string }[] = []\n const promises: Promise<void>[] = []\n\n for (const collectionSlug in collectionConfig.joins) {\n for (const join of collectionConfig.joins[collectionSlug]!) {\n await sanitizeJoinFieldQuery({\n collectionSlug,\n errors,\n join,\n joinsQuery,\n overrideAccess,\n promises,\n req,\n })\n }\n }\n\n for (const join of collectionConfig.polymorphicJoins) {\n for (const collectionSlug of join.field.collection) {\n await sanitizeJoinFieldQuery({\n collectionSlug,\n errors,\n join,\n joinsQuery,\n overrideAccess,\n promises,\n req,\n })\n }\n }\n\n await Promise.all(promises)\n\n if (errors.length > 0) {\n throw new QueryError(errors)\n }\n\n return joinsQuery\n}\n"],"names":["executeAccess","QueryError","deepCopyObjectSimple","combineQueries","validateQueryPaths","validateSortQuery","sanitizeWhereQuery","sanitizeJoinFieldQuery","collectionSlug","errors","join","joinsQuery","overrideAccess","promises","req","joinPath","joinCollectionConfig","payload","collections","config","accessResult","disableErrors","access","read","joinQuery","where","field","push","collectionConfig","polymorphicJoin","Array","isArray","collection","sort","defaultSort","fields","flattenedFields","sanitizeJoinQuery","joins","polymorphicJoins","Promise","all","length"],"mappings":"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"}
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
* Modules exported here are not part of the public API and are subject to change without notice and without a major version bump.
|
|
3
3
|
*/
|
|
4
4
|
export { applyUserReadAccess } from '../auth/applyUserReadAccess.js';
|
|
5
|
+
export { createSchemaBuildContext } from '../database/createSchemaBuildContext.js';
|
|
6
|
+
export type { SchemaBuildContext } from '../database/createSchemaBuildContext.js';
|
|
5
7
|
export { assertClientUploadAccess } from '../uploads/assertClientUploadAccess.js';
|
|
6
8
|
export { assertClientUploadAllowed, assertClientUploadFileSize, } from '../uploads/assertClientUploadAllowed.js';
|
|
7
9
|
export { createClientUploadReceipt, verifyClientUploadReceipt, } from '../uploads/clientUploadReceipt.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../src/exports/internal.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAA;AACjF,OAAO,EACL,yBAAyB,EACzB,0BAA0B,GAC3B,MAAM,yCAAyC,CAAA;AAChD,OAAO,EACL,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,mCAAmC,CAAA;AAC1C,YAAY,EACV,mBAAmB,EACnB,yBAAyB,GAC1B,MAAM,mCAAmC,CAAA;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAA;AAChF,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAA;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AACjE,OAAO,EAAE,8BAA8B,EAAE,MAAM,2CAA2C,CAAA;AAC1F,OAAO,EAAE,oBAAoB,EAAE,MAAM,2DAA2D,CAAA;AAChG,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAA"}
|
|
1
|
+
{"version":3,"file":"internal.d.ts","sourceRoot":"","sources":["../../src/exports/internal.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,mBAAmB,EAAE,MAAM,gCAAgC,CAAA;AACpE,OAAO,EAAE,wBAAwB,EAAE,MAAM,yCAAyC,CAAA;AAClF,YAAY,EAAE,kBAAkB,EAAE,MAAM,yCAAyC,CAAA;AACjF,OAAO,EAAE,wBAAwB,EAAE,MAAM,wCAAwC,CAAA;AACjF,OAAO,EACL,yBAAyB,EACzB,0BAA0B,GAC3B,MAAM,yCAAyC,CAAA;AAChD,OAAO,EACL,yBAAyB,EACzB,yBAAyB,GAC1B,MAAM,mCAAmC,CAAA;AAC1C,YAAY,EACV,mBAAmB,EACnB,yBAAyB,GAC1B,MAAM,mCAAmC,CAAA;AAC1C,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAA;AAChF,OAAO,EAAE,mBAAmB,EAAE,MAAM,mCAAmC,CAAA;AACvE,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAA;AAC/D,OAAO,EAAE,gBAAgB,EAAE,MAAM,gCAAgC,CAAA;AACjE,OAAO,EAAE,8BAA8B,EAAE,MAAM,2CAA2C,CAAA;AAC1F,OAAO,EAAE,oBAAoB,EAAE,MAAM,2DAA2D,CAAA;AAChG,OAAO,EAAE,mBAAmB,EAAE,MAAM,qCAAqC,CAAA"}
|
package/dist/exports/internal.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Modules exported here are not part of the public API and are subject to change without notice and without a major version bump.
|
|
3
3
|
*/ export { applyUserReadAccess } from '../auth/applyUserReadAccess.js';
|
|
4
|
+
export { createSchemaBuildContext } from '../database/createSchemaBuildContext.js';
|
|
4
5
|
export { assertClientUploadAccess } from '../uploads/assertClientUploadAccess.js';
|
|
5
6
|
export { assertClientUploadAllowed, assertClientUploadFileSize } from '../uploads/assertClientUploadAllowed.js';
|
|
6
7
|
export { createClientUploadReceipt, verifyClientUploadReceipt } from '../uploads/clientUploadReceipt.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/exports/internal.ts"],"sourcesContent":["/**\n * Modules exported here are not part of the public API and are subject to change without notice and without a major version bump.\n */\n\nexport { applyUserReadAccess } from '../auth/applyUserReadAccess.js'\nexport { assertClientUploadAccess } from '../uploads/assertClientUploadAccess.js'\nexport {\n assertClientUploadAllowed,\n assertClientUploadFileSize,\n} from '../uploads/assertClientUploadAllowed.js'\nexport {\n createClientUploadReceipt,\n verifyClientUploadReceipt,\n} from '../uploads/clientUploadReceipt.js'\nexport type {\n ClientUploadReceipt,\n SignedClientUploadReceipt,\n} from '../uploads/clientUploadReceipt.js'\nexport { getExternalFile } from '../uploads/getExternalFile.js'\nexport { isSvgMimeType, isXmlMimeType } from '../uploads/getFileTypeIdentity.js'\nexport { getRangeRequestInfo } from '../uploads/getRangeRequestInfo.js'\nexport { getSafeFileName } from '../uploads/getSafeFilename.js'\nexport { parseRangeHeader } from '../uploads/parseRangeHeader.js'\nexport { UPLOAD_CONTENT_SECURITY_POLICY } from '../uploads/uploadContentSecurityPolicy.js'\nexport { getEntityPermissions } from '../utilities/getEntityPermissions/getEntityPermissions.js'\nexport { sanitizePermissions } from '../utilities/sanitizePermissions.js'\n"],"names":["applyUserReadAccess","assertClientUploadAccess","assertClientUploadAllowed","assertClientUploadFileSize","createClientUploadReceipt","verifyClientUploadReceipt","getExternalFile","isSvgMimeType","isXmlMimeType","getRangeRequestInfo","getSafeFileName","parseRangeHeader","UPLOAD_CONTENT_SECURITY_POLICY","getEntityPermissions","sanitizePermissions"],"mappings":"AAAA;;CAEC,GAED,SAASA,mBAAmB,QAAQ,iCAAgC;AACpE,SAASC,wBAAwB,QAAQ,yCAAwC;AACjF,SACEC,yBAAyB,EACzBC,0BAA0B,QACrB,0CAAyC;AAChD,SACEC,yBAAyB,EACzBC,yBAAyB,QACpB,oCAAmC;AAK1C,SAASC,eAAe,QAAQ,gCAA+B;AAC/D,SAASC,aAAa,EAAEC,aAAa,QAAQ,oCAAmC;AAChF,SAASC,mBAAmB,QAAQ,oCAAmC;AACvE,SAASC,eAAe,QAAQ,gCAA+B;AAC/D,SAASC,gBAAgB,QAAQ,iCAAgC;AACjE,SAASC,8BAA8B,QAAQ,4CAA2C;AAC1F,SAASC,oBAAoB,QAAQ,4DAA2D;AAChG,SAASC,mBAAmB,QAAQ,sCAAqC"}
|
|
1
|
+
{"version":3,"sources":["../../src/exports/internal.ts"],"sourcesContent":["/**\n * Modules exported here are not part of the public API and are subject to change without notice and without a major version bump.\n */\n\nexport { applyUserReadAccess } from '../auth/applyUserReadAccess.js'\nexport { createSchemaBuildContext } from '../database/createSchemaBuildContext.js'\nexport type { SchemaBuildContext } from '../database/createSchemaBuildContext.js'\nexport { assertClientUploadAccess } from '../uploads/assertClientUploadAccess.js'\nexport {\n assertClientUploadAllowed,\n assertClientUploadFileSize,\n} from '../uploads/assertClientUploadAllowed.js'\nexport {\n createClientUploadReceipt,\n verifyClientUploadReceipt,\n} from '../uploads/clientUploadReceipt.js'\nexport type {\n ClientUploadReceipt,\n SignedClientUploadReceipt,\n} from '../uploads/clientUploadReceipt.js'\nexport { getExternalFile } from '../uploads/getExternalFile.js'\nexport { isSvgMimeType, isXmlMimeType } from '../uploads/getFileTypeIdentity.js'\nexport { getRangeRequestInfo } from '../uploads/getRangeRequestInfo.js'\nexport { getSafeFileName } from '../uploads/getSafeFilename.js'\nexport { parseRangeHeader } from '../uploads/parseRangeHeader.js'\nexport { UPLOAD_CONTENT_SECURITY_POLICY } from '../uploads/uploadContentSecurityPolicy.js'\nexport { getEntityPermissions } from '../utilities/getEntityPermissions/getEntityPermissions.js'\nexport { sanitizePermissions } from '../utilities/sanitizePermissions.js'\n"],"names":["applyUserReadAccess","createSchemaBuildContext","assertClientUploadAccess","assertClientUploadAllowed","assertClientUploadFileSize","createClientUploadReceipt","verifyClientUploadReceipt","getExternalFile","isSvgMimeType","isXmlMimeType","getRangeRequestInfo","getSafeFileName","parseRangeHeader","UPLOAD_CONTENT_SECURITY_POLICY","getEntityPermissions","sanitizePermissions"],"mappings":"AAAA;;CAEC,GAED,SAASA,mBAAmB,QAAQ,iCAAgC;AACpE,SAASC,wBAAwB,QAAQ,0CAAyC;AAElF,SAASC,wBAAwB,QAAQ,yCAAwC;AACjF,SACEC,yBAAyB,EACzBC,0BAA0B,QACrB,0CAAyC;AAChD,SACEC,yBAAyB,EACzBC,yBAAyB,QACpB,oCAAmC;AAK1C,SAASC,eAAe,QAAQ,gCAA+B;AAC/D,SAASC,aAAa,EAAEC,aAAa,QAAQ,oCAAmC;AAChF,SAASC,mBAAmB,QAAQ,oCAAmC;AACvE,SAASC,eAAe,QAAQ,gCAA+B;AAC/D,SAASC,gBAAgB,QAAQ,iCAAgC;AACjE,SAASC,8BAA8B,QAAQ,4CAA2C;AAC1F,SAASC,oBAAoB,QAAQ,4DAA2D;AAChG,SAASC,mBAAmB,QAAQ,sCAAqC"}
|
|
@@ -17,7 +17,7 @@ const slugify = ({ customSlugify, data, req, valueToSlugify })=>{
|
|
|
17
17
|
*/ export const generateSlug = ({ slugFieldName, slugify: customSlugify, useAsSlug })=>async ({ collection, data, global, operation, originalDoc, req, value: isChecked })=>{
|
|
18
18
|
if (operation === 'create') {
|
|
19
19
|
if (data) {
|
|
20
|
-
data[slugFieldName] = slugify({
|
|
20
|
+
data[slugFieldName] = await slugify({
|
|
21
21
|
customSlugify,
|
|
22
22
|
data,
|
|
23
23
|
req,
|
|
@@ -36,7 +36,7 @@ const slugify = ({ customSlugify, data, req, valueToSlugify })=>{
|
|
|
36
36
|
if (!hasAutosaveEnabled(collection || global)) {
|
|
37
37
|
// We can generate the slug at this point
|
|
38
38
|
if (data) {
|
|
39
|
-
data[slugFieldName] = slugify({
|
|
39
|
+
data[slugFieldName] = await slugify({
|
|
40
40
|
customSlugify,
|
|
41
41
|
data,
|
|
42
42
|
req,
|
|
@@ -53,7 +53,7 @@ const slugify = ({ customSlugify, data, req, valueToSlugify })=>{
|
|
|
53
53
|
if (data) {
|
|
54
54
|
// If the fallback is an empty string, we want the slug to return to `null`
|
|
55
55
|
// This will ensure that live preview conditions continue to run as expected
|
|
56
|
-
data[slugFieldName] = data?.[useAsSlug] ? slugify({
|
|
56
|
+
data[slugFieldName] = data?.[useAsSlug] ? await slugify({
|
|
57
57
|
customSlugify,
|
|
58
58
|
data,
|
|
59
59
|
req,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/fields/baseFields/slug/generateSlug.ts"],"sourcesContent":["import type { PayloadRequest } from '../../../types/index.js'\nimport type { FieldHook } from '../../config/types.js'\nimport type { SlugFieldArgs, Slugify } from './index.js'\n\nimport { hasAutosaveEnabled } from '../../../utilities/getVersionsConfig.js'\nimport { slugify as defaultSlugify } from '../../../utilities/slugify.js'\nimport { countVersions } from './countVersions.js'\n\ntype HookArgs = {\n slugFieldName: NonNullable<SlugFieldArgs['name']>\n} & Pick<SlugFieldArgs, 'slugify'> &\n Required<Pick<SlugFieldArgs, 'useAsSlug'>>\n\nconst slugify = ({\n customSlugify,\n data,\n req,\n valueToSlugify,\n}: {\n customSlugify?: Slugify\n data: Record<string, unknown>\n req: PayloadRequest\n valueToSlugify?: string\n}) => {\n if (customSlugify) {\n return customSlugify({ data, req, valueToSlugify })\n }\n\n return defaultSlugify(valueToSlugify)\n}\n\n/**\n * This is a `BeforeChange` field hook used to auto-generate the `slug` field.\n * See `slugField` for more details.\n */\nexport const generateSlug =\n ({ slugFieldName, slugify: customSlugify, useAsSlug }: HookArgs): FieldHook =>\n async ({ collection, data, global, operation, originalDoc, req, value: isChecked }) => {\n if (operation === 'create') {\n if (data) {\n data[slugFieldName] = slugify({\n customSlugify,\n data,\n req,\n // Ensure user-defined slugs are not overwritten during create\n // Use a generic falsy check here to include empty strings\n valueToSlugify: data?.[slugFieldName] || data?.[useAsSlug],\n })\n }\n\n return Boolean(!data?.[slugFieldName])\n }\n\n if (operation === 'update') {\n // Early return to avoid additional processing\n if (!isChecked) {\n return false\n }\n\n if (!hasAutosaveEnabled(collection || global!)) {\n // We can generate the slug at this point\n if (data) {\n data[slugFieldName] = slugify({\n customSlugify,\n data,\n req,\n valueToSlugify: data?.[useAsSlug],\n })\n }\n\n return Boolean(!data?.[slugFieldName])\n } else {\n // If we're publishing, we can avoid querying as we can safely assume we've exceeded the version threshold (2)\n const isPublishing = data?._status === 'published'\n\n // Ensure the user can take over the generated slug themselves without it ever being overridden back\n const userOverride = data?.[slugFieldName] !== originalDoc?.[slugFieldName]\n\n if (!userOverride) {\n if (data) {\n // If the fallback is an empty string, we want the slug to return to `null`\n // This will ensure that live preview conditions continue to run as expected\n data[slugFieldName] = data?.[useAsSlug]\n ? slugify({\n customSlugify,\n data,\n req,\n valueToSlugify: data?.[useAsSlug],\n })\n : null\n }\n }\n\n if (isPublishing || userOverride) {\n return false\n }\n\n // Important: ensure `countVersions` is not called unnecessarily often\n // That is why this is buried beneath all these conditions\n const versionCount = await countVersions({\n collectionSlug: collection?.slug,\n globalSlug: global?.slug,\n parentID: originalDoc?.id,\n req,\n })\n\n if (versionCount <= 2) {\n return true\n } else {\n return false\n }\n }\n }\n }\n"],"names":["hasAutosaveEnabled","slugify","defaultSlugify","countVersions","customSlugify","data","req","valueToSlugify","generateSlug","slugFieldName","useAsSlug","collection","global","operation","originalDoc","value","isChecked","Boolean","isPublishing","_status","userOverride","versionCount","collectionSlug","slug","globalSlug","parentID","id"],"mappings":"AAIA,SAASA,kBAAkB,QAAQ,0CAAyC;AAC5E,SAASC,WAAWC,cAAc,QAAQ,gCAA+B;AACzE,SAASC,aAAa,QAAQ,qBAAoB;AAOlD,MAAMF,UAAU,CAAC,EACfG,aAAa,EACbC,IAAI,EACJC,GAAG,EACHC,cAAc,EAMf;IACC,IAAIH,eAAe;QACjB,OAAOA,cAAc;YAAEC;YAAMC;YAAKC;QAAe;IACnD;IAEA,OAAOL,eAAeK;AACxB;AAEA;;;CAGC,GACD,OAAO,MAAMC,eACX,CAAC,EAAEC,aAAa,EAAER,SAASG,aAAa,EAAEM,SAAS,EAAY,GAC/D,OAAO,EAAEC,UAAU,EAAEN,IAAI,EAAEO,MAAM,EAAEC,SAAS,EAAEC,WAAW,EAAER,GAAG,EAAES,OAAOC,SAAS,EAAE;QAChF,IAAIH,cAAc,UAAU;YAC1B,IAAIR,MAAM;gBACRA,IAAI,CAACI,cAAc,
|
|
1
|
+
{"version":3,"sources":["../../../../src/fields/baseFields/slug/generateSlug.ts"],"sourcesContent":["import type { PayloadRequest } from '../../../types/index.js'\nimport type { FieldHook } from '../../config/types.js'\nimport type { SlugFieldArgs, Slugify } from './index.js'\n\nimport { hasAutosaveEnabled } from '../../../utilities/getVersionsConfig.js'\nimport { slugify as defaultSlugify } from '../../../utilities/slugify.js'\nimport { countVersions } from './countVersions.js'\n\ntype HookArgs = {\n slugFieldName: NonNullable<SlugFieldArgs['name']>\n} & Pick<SlugFieldArgs, 'slugify'> &\n Required<Pick<SlugFieldArgs, 'useAsSlug'>>\n\nconst slugify = ({\n customSlugify,\n data,\n req,\n valueToSlugify,\n}: {\n customSlugify?: Slugify\n data: Record<string, unknown>\n req: PayloadRequest\n valueToSlugify?: string\n}) => {\n if (customSlugify) {\n return customSlugify({ data, req, valueToSlugify })\n }\n\n return defaultSlugify(valueToSlugify)\n}\n\n/**\n * This is a `BeforeChange` field hook used to auto-generate the `slug` field.\n * See `slugField` for more details.\n */\nexport const generateSlug =\n ({ slugFieldName, slugify: customSlugify, useAsSlug }: HookArgs): FieldHook =>\n async ({ collection, data, global, operation, originalDoc, req, value: isChecked }) => {\n if (operation === 'create') {\n if (data) {\n data[slugFieldName] = await slugify({\n customSlugify,\n data,\n req,\n // Ensure user-defined slugs are not overwritten during create\n // Use a generic falsy check here to include empty strings\n valueToSlugify: data?.[slugFieldName] || data?.[useAsSlug],\n })\n }\n\n return Boolean(!data?.[slugFieldName])\n }\n\n if (operation === 'update') {\n // Early return to avoid additional processing\n if (!isChecked) {\n return false\n }\n\n if (!hasAutosaveEnabled(collection || global!)) {\n // We can generate the slug at this point\n if (data) {\n data[slugFieldName] = await slugify({\n customSlugify,\n data,\n req,\n valueToSlugify: data?.[useAsSlug],\n })\n }\n\n return Boolean(!data?.[slugFieldName])\n } else {\n // If we're publishing, we can avoid querying as we can safely assume we've exceeded the version threshold (2)\n const isPublishing = data?._status === 'published'\n\n // Ensure the user can take over the generated slug themselves without it ever being overridden back\n const userOverride = data?.[slugFieldName] !== originalDoc?.[slugFieldName]\n\n if (!userOverride) {\n if (data) {\n // If the fallback is an empty string, we want the slug to return to `null`\n // This will ensure that live preview conditions continue to run as expected\n data[slugFieldName] = data?.[useAsSlug]\n ? await slugify({\n customSlugify,\n data,\n req,\n valueToSlugify: data?.[useAsSlug],\n })\n : null\n }\n }\n\n if (isPublishing || userOverride) {\n return false\n }\n\n // Important: ensure `countVersions` is not called unnecessarily often\n // That is why this is buried beneath all these conditions\n const versionCount = await countVersions({\n collectionSlug: collection?.slug,\n globalSlug: global?.slug,\n parentID: originalDoc?.id,\n req,\n })\n\n if (versionCount <= 2) {\n return true\n } else {\n return false\n }\n }\n }\n }\n"],"names":["hasAutosaveEnabled","slugify","defaultSlugify","countVersions","customSlugify","data","req","valueToSlugify","generateSlug","slugFieldName","useAsSlug","collection","global","operation","originalDoc","value","isChecked","Boolean","isPublishing","_status","userOverride","versionCount","collectionSlug","slug","globalSlug","parentID","id"],"mappings":"AAIA,SAASA,kBAAkB,QAAQ,0CAAyC;AAC5E,SAASC,WAAWC,cAAc,QAAQ,gCAA+B;AACzE,SAASC,aAAa,QAAQ,qBAAoB;AAOlD,MAAMF,UAAU,CAAC,EACfG,aAAa,EACbC,IAAI,EACJC,GAAG,EACHC,cAAc,EAMf;IACC,IAAIH,eAAe;QACjB,OAAOA,cAAc;YAAEC;YAAMC;YAAKC;QAAe;IACnD;IAEA,OAAOL,eAAeK;AACxB;AAEA;;;CAGC,GACD,OAAO,MAAMC,eACX,CAAC,EAAEC,aAAa,EAAER,SAASG,aAAa,EAAEM,SAAS,EAAY,GAC/D,OAAO,EAAEC,UAAU,EAAEN,IAAI,EAAEO,MAAM,EAAEC,SAAS,EAAEC,WAAW,EAAER,GAAG,EAAES,OAAOC,SAAS,EAAE;QAChF,IAAIH,cAAc,UAAU;YAC1B,IAAIR,MAAM;gBACRA,IAAI,CAACI,cAAc,GAAG,MAAMR,QAAQ;oBAClCG;oBACAC;oBACAC;oBACA,8DAA8D;oBAC9D,0DAA0D;oBAC1DC,gBAAgBF,MAAM,CAACI,cAAc,IAAIJ,MAAM,CAACK,UAAU;gBAC5D;YACF;YAEA,OAAOO,QAAQ,CAACZ,MAAM,CAACI,cAAc;QACvC;QAEA,IAAII,cAAc,UAAU;YAC1B,8CAA8C;YAC9C,IAAI,CAACG,WAAW;gBACd,OAAO;YACT;YAEA,IAAI,CAAChB,mBAAmBW,cAAcC,SAAU;gBAC9C,yCAAyC;gBACzC,IAAIP,MAAM;oBACRA,IAAI,CAACI,cAAc,GAAG,MAAMR,QAAQ;wBAClCG;wBACAC;wBACAC;wBACAC,gBAAgBF,MAAM,CAACK,UAAU;oBACnC;gBACF;gBAEA,OAAOO,QAAQ,CAACZ,MAAM,CAACI,cAAc;YACvC,OAAO;gBACL,8GAA8G;gBAC9G,MAAMS,eAAeb,MAAMc,YAAY;gBAEvC,oGAAoG;gBACpG,MAAMC,eAAef,MAAM,CAACI,cAAc,KAAKK,aAAa,CAACL,cAAc;gBAE3E,IAAI,CAACW,cAAc;oBACjB,IAAIf,MAAM;wBACR,2EAA2E;wBAC3E,4EAA4E;wBAC5EA,IAAI,CAACI,cAAc,GAAGJ,MAAM,CAACK,UAAU,GACnC,MAAMT,QAAQ;4BACZG;4BACAC;4BACAC;4BACAC,gBAAgBF,MAAM,CAACK,UAAU;wBACnC,KACA;oBACN;gBACF;gBAEA,IAAIQ,gBAAgBE,cAAc;oBAChC,OAAO;gBACT;gBAEA,sEAAsE;gBACtE,0DAA0D;gBAC1D,MAAMC,eAAe,MAAMlB,cAAc;oBACvCmB,gBAAgBX,YAAYY;oBAC5BC,YAAYZ,QAAQW;oBACpBE,UAAUX,aAAaY;oBACvBpB;gBACF;gBAEA,IAAIe,gBAAgB,GAAG;oBACrB,OAAO;gBACT,OAAO;oBACL,OAAO;gBACT;YACF;QACF;IACF,EAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { describe, expect, it } from 'vitest';
|
|
2
|
+
import { generateSlug } from './generateSlug.js';
|
|
3
|
+
describe('generateSlug', ()=>{
|
|
4
|
+
it('should await a custom async slugify function', async ()=>{
|
|
5
|
+
const data = {
|
|
6
|
+
title: 'Async Slug'
|
|
7
|
+
};
|
|
8
|
+
const hook = generateSlug({
|
|
9
|
+
slugFieldName: 'slug',
|
|
10
|
+
slugify: async ({ valueToSlugify })=>String(valueToSlugify).toLowerCase().replace(' ', '-'),
|
|
11
|
+
useAsSlug: 'title'
|
|
12
|
+
});
|
|
13
|
+
await hook({
|
|
14
|
+
data,
|
|
15
|
+
operation: 'create',
|
|
16
|
+
req: {}
|
|
17
|
+
});
|
|
18
|
+
expect(data.slug).toBe('async-slug');
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
//# sourceMappingURL=generateSlug.spec.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/fields/baseFields/slug/generateSlug.spec.ts"],"sourcesContent":["import type { PayloadRequest } from '../../../types/index.js'\n\nimport { describe, expect, it } from 'vitest'\n\nimport { generateSlug } from './generateSlug.js'\n\ndescribe('generateSlug', () => {\n it('should await a custom async slugify function', async () => {\n const data: Record<string, unknown> = {\n title: 'Async Slug',\n }\n const hook = generateSlug({\n slugFieldName: 'slug',\n slugify: async ({ valueToSlugify }) => String(valueToSlugify).toLowerCase().replace(' ', '-'),\n useAsSlug: 'title',\n })\n\n await hook({\n data,\n operation: 'create',\n req: {} as PayloadRequest,\n } as Parameters<typeof hook>[0])\n\n expect(data.slug).toBe('async-slug')\n })\n})\n"],"names":["describe","expect","it","generateSlug","data","title","hook","slugFieldName","slugify","valueToSlugify","String","toLowerCase","replace","useAsSlug","operation","req","slug","toBe"],"mappings":"AAEA,SAASA,QAAQ,EAAEC,MAAM,EAAEC,EAAE,QAAQ,SAAQ;AAE7C,SAASC,YAAY,QAAQ,oBAAmB;AAEhDH,SAAS,gBAAgB;IACvBE,GAAG,gDAAgD;QACjD,MAAME,OAAgC;YACpCC,OAAO;QACT;QACA,MAAMC,OAAOH,aAAa;YACxBI,eAAe;YACfC,SAAS,OAAO,EAAEC,cAAc,EAAE,GAAKC,OAAOD,gBAAgBE,WAAW,GAAGC,OAAO,CAAC,KAAK;YACzFC,WAAW;QACb;QAEA,MAAMP,KAAK;YACTF;YACAU,WAAW;YACXC,KAAK,CAAC;QACR;QAEAd,OAAOG,KAAKY,IAAI,EAAEC,IAAI,CAAC;IACzB;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"findVersionByID.d.ts","sourceRoot":"","sources":["../../../src/globals/operations/findVersionByID.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4CAA4C,CAAA;AAE7E,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACpF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAC9D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;
|
|
1
|
+
{"version":3,"file":"findVersionByID.d.ts","sourceRoot":"","sources":["../../../src/globals/operations/findVersionByID.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,4CAA4C,CAAA;AAE7E,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,UAAU,EAAE,MAAM,sBAAsB,CAAA;AACpF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAA;AAC9D,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,oBAAoB,CAAA;AAa/D,MAAM,MAAM,SAAS,GAAG;IACtB,YAAY,CAAC,EAAE,MAAM,CAAA;IACrB,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,aAAa,CAAC,EAAE,OAAO,CAAA;IACvB,YAAY,EAAE,qBAAqB,CAAA;IACnC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAA;IACnB,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB,QAAQ,CAAC,EAAE,YAAY,CAAA;IACvB,GAAG,EAAE,cAAc,CAAA;IACnB,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAC3B,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,EAAE,UAAU,CAAC,EAAE,QAAQ,CAAC,CAAA;AAEnD,eAAO,MAAM,wBAAwB,GAAU,CAAC,SAAS,eAAe,CAAC,CAAC,CAAC,cACnE,SAAS,KACd,OAAO,CAAC,CAAC,CAuJX,CAAA"}
|
|
@@ -3,12 +3,19 @@ import { combineQueries } from '../../database/combineQueries.js';
|
|
|
3
3
|
import { Forbidden, NotFound } from '../../errors/index.js';
|
|
4
4
|
import { afterRead } from '../../fields/hooks/afterRead/index.js';
|
|
5
5
|
import { deepCopyObjectSimple } from '../../utilities/deepCopyObject.js';
|
|
6
|
+
import { hasVersionsEnabled } from '../../utilities/getVersionsConfig.js';
|
|
6
7
|
import { killTransaction } from '../../utilities/killTransaction.js';
|
|
7
8
|
import { sanitizeSelect } from '../../utilities/sanitizeSelect.js';
|
|
8
9
|
import { buildVersionGlobalFields } from '../../versions/buildGlobalFields.js';
|
|
9
10
|
import { getQueryDraftsSelect } from '../../versions/drafts/getQueryDraftsSelect.js';
|
|
10
11
|
export const findVersionByIDOperation = async (args)=>{
|
|
11
12
|
const { id, currentDepth, depth, disableErrors, globalConfig, overrideAccess, populate, req: { fallbackLocale, locale, payload }, req, select: incomingSelect, showHiddenFields } = args;
|
|
13
|
+
if (!hasVersionsEnabled(globalConfig)) {
|
|
14
|
+
if (disableErrors) {
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
throw new NotFound(req.t);
|
|
18
|
+
}
|
|
12
19
|
try {
|
|
13
20
|
// /////////////////////////////////////
|
|
14
21
|
// Access
|
|
@@ -22,6 +29,10 @@ export const findVersionByIDOperation = async (args)=>{
|
|
|
22
29
|
if (accessResults === false) {
|
|
23
30
|
return null;
|
|
24
31
|
}
|
|
32
|
+
const isValidID = typeof id === 'string' && id.length > 0 || typeof id === 'number' && Number.isFinite(id);
|
|
33
|
+
if (!isValidID) {
|
|
34
|
+
throw new NotFound(req.t);
|
|
35
|
+
}
|
|
25
36
|
const hasWhereAccess = typeof accessResults === 'object';
|
|
26
37
|
const select = sanitizeSelect({
|
|
27
38
|
fields: buildVersionGlobalFields(payload.config, globalConfig, true),
|
|
@@ -46,9 +57,6 @@ export const findVersionByIDOperation = async (args)=>{
|
|
|
46
57
|
// /////////////////////////////////////
|
|
47
58
|
// Find by ID
|
|
48
59
|
// /////////////////////////////////////
|
|
49
|
-
if (!findGlobalVersionsArgs.where?.and?.[0]?.id) {
|
|
50
|
-
throw new NotFound(req.t);
|
|
51
|
-
}
|
|
52
60
|
const { docs: results } = await payload.db.findGlobalVersions(findGlobalVersionsArgs);
|
|
53
61
|
if (!results || results?.length === 0) {
|
|
54
62
|
if (!disableErrors) {
|