@payloadcms/plugin-search 3.70.0 → 3.71.0-internal.727c7a4
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/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +0 -2
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +34 -6
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utilities/generateReindexHandler.d.ts.map +1 -1
- package/dist/utilities/generateReindexHandler.js +54 -28
- package/dist/utilities/generateReindexHandler.js.map +1 -1
- package/dist/utilities/syncDocAsSearchIndex.d.ts.map +1 -1
- package/dist/utilities/syncDocAsSearchIndex.js +74 -54
- package/dist/utilities/syncDocAsSearchIndex.js.map +1 -1
- package/package.json +5 -5
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import type { Config } from 'payload';
|
|
2
2
|
import type { SearchPluginConfig } from './types.js';
|
|
3
|
-
export declare const searchPlugin: (incomingPluginConfig: SearchPluginConfig) => (config: Config) => Config;
|
|
3
|
+
export declare const searchPlugin: <ConfigTypes = unknown>(incomingPluginConfig: SearchPluginConfig<ConfigTypes>) => (config: Config) => Config;
|
|
4
4
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA6B,MAAM,EAAE,MAAM,SAAS,CAAA;AAEhE,OAAO,KAAK,EAA+B,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAQjF,eAAO,MAAM,YAAY,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAA6B,MAAM,EAAE,MAAM,SAAS,CAAA;AAEhE,OAAO,KAAK,EAA+B,kBAAkB,EAAE,MAAM,YAAY,CAAA;AAQjF,eAAO,MAAM,YAAY,GACtB,WAAW,kCAAkC,kBAAkB,CAAC,WAAW,CAAC,cACpE,MAAM,KAAG,MAuEjB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -8,7 +8,6 @@ export const searchPlugin = (incomingPluginConfig)=>(config)=>{
|
|
|
8
8
|
const shouldLocalize = typeof incomingPluginConfig.localize === 'boolean' ? incomingPluginConfig.localize : Boolean(config.localization);
|
|
9
9
|
incomingPluginConfig.localize = shouldLocalize;
|
|
10
10
|
if (collections) {
|
|
11
|
-
const locales = config.localization ? config.localization.locales.map((localeConfig)=>typeof localeConfig === 'string' ? localeConfig : localeConfig.code) : [];
|
|
12
11
|
const labels = Object.fromEntries(collections.filter(({ slug })=>incomingPluginConfig.collections?.includes(slug)).map((collection)=>[
|
|
13
12
|
collection.slug,
|
|
14
13
|
collection.labels
|
|
@@ -17,7 +16,6 @@ export const searchPlugin = (incomingPluginConfig)=>(config)=>{
|
|
|
17
16
|
// write any config defaults here
|
|
18
17
|
deleteDrafts: true,
|
|
19
18
|
labels,
|
|
20
|
-
locales,
|
|
21
19
|
reindexBatchSize: incomingPluginConfig?.reindexBatchSize || 50,
|
|
22
20
|
syncDrafts: false,
|
|
23
21
|
...incomingPluginConfig
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { CollectionAfterChangeHook, Config } from 'payload'\n\nimport type { SanitizedSearchPluginConfig, SearchPluginConfig } from './types.js'\n\nimport { deleteFromSearch } from './Search/hooks/deleteFromSearch.js'\nimport { syncWithSearch } from './Search/hooks/syncWithSearch.js'\nimport { generateSearchCollection } from './Search/index.js'\n\ntype CollectionAfterChangeHookArgs = Parameters<CollectionAfterChangeHook>[0]\n\nexport const searchPlugin =\n (incomingPluginConfig: SearchPluginConfig) =>\n (config: Config): Config => {\n const { collections } = config\n\n // If the user defines `localize` to either true or false, use that\n // Otherwise, set it based on if their config has localization enabled or disabled\n const shouldLocalize =\n typeof incomingPluginConfig.localize === 'boolean'\n ? incomingPluginConfig.localize\n : Boolean(config.localization)\n incomingPluginConfig.localize = shouldLocalize\n\n if (collections) {\n const
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { CollectionAfterChangeHook, Config } from 'payload'\n\nimport type { SanitizedSearchPluginConfig, SearchPluginConfig } from './types.js'\n\nimport { deleteFromSearch } from './Search/hooks/deleteFromSearch.js'\nimport { syncWithSearch } from './Search/hooks/syncWithSearch.js'\nimport { generateSearchCollection } from './Search/index.js'\n\ntype CollectionAfterChangeHookArgs = Parameters<CollectionAfterChangeHook>[0]\n\nexport const searchPlugin =\n <ConfigTypes = unknown>(incomingPluginConfig: SearchPluginConfig<ConfigTypes>) =>\n (config: Config): Config => {\n const { collections } = config\n\n // If the user defines `localize` to either true or false, use that\n // Otherwise, set it based on if their config has localization enabled or disabled\n const shouldLocalize =\n typeof incomingPluginConfig.localize === 'boolean'\n ? incomingPluginConfig.localize\n : Boolean(config.localization)\n incomingPluginConfig.localize = shouldLocalize\n\n if (collections) {\n const labels = Object.fromEntries(\n collections\n .filter(({ slug }) => incomingPluginConfig.collections?.includes(slug))\n .map((collection) => [collection.slug, collection.labels]),\n )\n\n const pluginConfig: SanitizedSearchPluginConfig<ConfigTypes> = {\n // write any config defaults here\n deleteDrafts: true,\n labels,\n reindexBatchSize: incomingPluginConfig?.reindexBatchSize || 50,\n syncDrafts: false,\n ...incomingPluginConfig,\n }\n\n // add afterChange and afterDelete hooks to every search-enabled collection\n const collectionsWithSearchHooks = config?.collections\n ?.map((collection) => {\n const { hooks: existingHooks } = collection\n\n const enabledCollections = pluginConfig.collections || []\n const isEnabled = enabledCollections.indexOf(collection.slug) > -1\n if (isEnabled) {\n return {\n ...collection,\n hooks: {\n ...collection.hooks,\n afterChange: [\n ...(existingHooks?.afterChange || []),\n async (args: CollectionAfterChangeHookArgs) => {\n await syncWithSearch({\n ...args,\n collection: collection.slug,\n pluginConfig,\n })\n },\n ],\n beforeDelete: [\n ...(existingHooks?.beforeDelete || []),\n deleteFromSearch(pluginConfig),\n ],\n },\n }\n }\n\n return collection\n })\n .filter(Boolean)\n\n return {\n ...config,\n collections: [\n ...(collectionsWithSearchHooks || []),\n generateSearchCollection(pluginConfig),\n ],\n }\n }\n\n return config\n }\n"],"names":["deleteFromSearch","syncWithSearch","generateSearchCollection","searchPlugin","incomingPluginConfig","config","collections","shouldLocalize","localize","Boolean","localization","labels","Object","fromEntries","filter","slug","includes","map","collection","pluginConfig","deleteDrafts","reindexBatchSize","syncDrafts","collectionsWithSearchHooks","hooks","existingHooks","enabledCollections","isEnabled","indexOf","afterChange","args","beforeDelete"],"mappings":"AAIA,SAASA,gBAAgB,QAAQ,qCAAoC;AACrE,SAASC,cAAc,QAAQ,mCAAkC;AACjE,SAASC,wBAAwB,QAAQ,oBAAmB;AAI5D,OAAO,MAAMC,eACX,CAAwBC,uBACxB,CAACC;QACC,MAAM,EAAEC,WAAW,EAAE,GAAGD;QAExB,mEAAmE;QACnE,kFAAkF;QAClF,MAAME,iBACJ,OAAOH,qBAAqBI,QAAQ,KAAK,YACrCJ,qBAAqBI,QAAQ,GAC7BC,QAAQJ,OAAOK,YAAY;QACjCN,qBAAqBI,QAAQ,GAAGD;QAEhC,IAAID,aAAa;YACf,MAAMK,SAASC,OAAOC,WAAW,CAC/BP,YACGQ,MAAM,CAAC,CAAC,EAAEC,IAAI,EAAE,GAAKX,qBAAqBE,WAAW,EAAEU,SAASD,OAChEE,GAAG,CAAC,CAACC,aAAe;oBAACA,WAAWH,IAAI;oBAAEG,WAAWP,MAAM;iBAAC;YAG7D,MAAMQ,eAAyD;gBAC7D,iCAAiC;gBACjCC,cAAc;gBACdT;gBACAU,kBAAkBjB,sBAAsBiB,oBAAoB;gBAC5DC,YAAY;gBACZ,GAAGlB,oBAAoB;YACzB;YAEA,2EAA2E;YAC3E,MAAMmB,6BAA6BlB,QAAQC,aACvCW,IAAI,CAACC;gBACL,MAAM,EAAEM,OAAOC,aAAa,EAAE,GAAGP;gBAEjC,MAAMQ,qBAAqBP,aAAab,WAAW,IAAI,EAAE;gBACzD,MAAMqB,YAAYD,mBAAmBE,OAAO,CAACV,WAAWH,IAAI,IAAI,CAAC;gBACjE,IAAIY,WAAW;oBACb,OAAO;wBACL,GAAGT,UAAU;wBACbM,OAAO;4BACL,GAAGN,WAAWM,KAAK;4BACnBK,aAAa;mCACPJ,eAAeI,eAAe,EAAE;gCACpC,OAAOC;oCACL,MAAM7B,eAAe;wCACnB,GAAG6B,IAAI;wCACPZ,YAAYA,WAAWH,IAAI;wCAC3BI;oCACF;gCACF;6BACD;4BACDY,cAAc;mCACRN,eAAeM,gBAAgB,EAAE;gCACrC/B,iBAAiBmB;6BAClB;wBACH;oBACF;gBACF;gBAEA,OAAOD;YACT,GACCJ,OAAOL;YAEV,OAAO;gBACL,GAAGJ,MAAM;gBACTC,aAAa;uBACPiB,8BAA8B,EAAE;oBACpCrB,yBAAyBiB;iBAC1B;YACH;QACF;QAEA,OAAOd;IACT,EAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -18,7 +18,15 @@ export type BeforeSync = (args: {
|
|
|
18
18
|
export type FieldsOverride = (args: {
|
|
19
19
|
defaultFields: Field[];
|
|
20
20
|
}) => Field[];
|
|
21
|
-
export type
|
|
21
|
+
export type SkipSyncFunction<ConfigTypes = unknown> = (args: {
|
|
22
|
+
collectionSlug: string;
|
|
23
|
+
doc: any;
|
|
24
|
+
locale: ConfigTypes extends {
|
|
25
|
+
locale: unknown;
|
|
26
|
+
} ? ConfigTypes['locale'] : string | undefined;
|
|
27
|
+
req: PayloadRequest;
|
|
28
|
+
}) => boolean | Promise<boolean>;
|
|
29
|
+
export type SearchPluginConfig<ConfigTypes = unknown> = {
|
|
22
30
|
/**
|
|
23
31
|
* @deprecated
|
|
24
32
|
* This plugin gets the api route from the config directly and does not need to be passed in.
|
|
@@ -47,6 +55,27 @@ export type SearchPluginConfig = {
|
|
|
47
55
|
searchOverrides?: {
|
|
48
56
|
fields?: FieldsOverride;
|
|
49
57
|
} & Partial<Omit<CollectionConfig, 'fields'>>;
|
|
58
|
+
/**
|
|
59
|
+
* Determine whether to skip syncing a document for a specific locale.
|
|
60
|
+
* Useful for multi-tenant applications, conditional indexing, or any scenario where
|
|
61
|
+
* sync behavior should vary by locale, document, or other factors.
|
|
62
|
+
*
|
|
63
|
+
* @default undefined - All configured locales will be synced
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* // Skip syncing based on document's tenant settings
|
|
67
|
+
* skipSync: async ({ locale, req, doc, collectionSlug }) => {
|
|
68
|
+
* // For non-localized collections, locale will be undefined
|
|
69
|
+
* if (!locale) return false
|
|
70
|
+
*
|
|
71
|
+
* const tenant = await req.payload.findByID({
|
|
72
|
+
* collection: 'tenants',
|
|
73
|
+
* id: doc.tenant.id
|
|
74
|
+
* })
|
|
75
|
+
* return !tenant.allowedLocales.includes(locale)
|
|
76
|
+
* }
|
|
77
|
+
*/
|
|
78
|
+
skipSync?: SkipSyncFunction<ConfigTypes>;
|
|
50
79
|
/**
|
|
51
80
|
* Controls whether drafts are synced to the search index
|
|
52
81
|
*
|
|
@@ -60,14 +89,13 @@ export type CollectionLabels = {
|
|
|
60
89
|
export type ResolvedCollectionLabels = {
|
|
61
90
|
[collection: string]: StaticLabel;
|
|
62
91
|
};
|
|
63
|
-
export type SearchPluginConfigWithLocales = {
|
|
92
|
+
export type SearchPluginConfigWithLocales<ConfigTypes = unknown> = {
|
|
64
93
|
labels?: CollectionLabels;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
export type SanitizedSearchPluginConfig = {
|
|
94
|
+
} & SearchPluginConfig<ConfigTypes>;
|
|
95
|
+
export type SanitizedSearchPluginConfig<ConfigTypes = unknown> = {
|
|
68
96
|
reindexBatchSize: number;
|
|
69
97
|
syncDrafts: boolean;
|
|
70
|
-
} & SearchPluginConfigWithLocales
|
|
98
|
+
} & SearchPluginConfigWithLocales<ConfigTypes>;
|
|
71
99
|
export type SyncWithSearchArgs = {
|
|
72
100
|
collection: string;
|
|
73
101
|
pluginConfig: SanitizedSearchPluginConfig;
|
package/dist/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EACzB,0BAA0B,EAC1B,gBAAgB,EAChB,KAAK,EACL,MAAM,EACN,OAAO,EACP,cAAc,EACd,WAAW,EACZ,MAAM,SAAS,CAAA;AAEhB,MAAM,MAAM,SAAS,GAAG;IACtB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;IAClB,GAAG,EAAE;QACH,UAAU,EAAE,MAAM,CAAA;QAClB,KAAK,EAAE,MAAM,CAAA;KACd,CAAA;IACD,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,MAAM,MAAM,UAAU,GAAG,CAAC,IAAI,EAAE;IAC9B,WAAW,EAAE;QACX,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KACnB,CAAA;IACD,OAAO,EAAE,OAAO,CAAA;IAChB,GAAG,EAAE,cAAc,CAAA;IACnB,SAAS,EAAE,SAAS,CAAA;CACrB,KAAK,SAAS,GAAG,OAAO,CAAC,SAAS,CAAC,CAAA;AAEpC,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE;IAAE,aAAa,EAAE,KAAK,EAAE,CAAA;CAAE,KAAK,KAAK,EAAE,CAAA;AAE1E,MAAM,MAAM,kBAAkB,GAAG;
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type {\n CollectionAfterChangeHook,\n CollectionBeforeDeleteHook,\n CollectionConfig,\n Field,\n Locale,\n Payload,\n PayloadRequest,\n StaticLabel,\n} from 'payload'\n\nexport type DocToSync = {\n [key: string]: any\n doc: {\n relationTo: string\n value: string\n }\n title: string\n}\n\nexport type BeforeSync = (args: {\n originalDoc: {\n [key: string]: any\n }\n payload: Payload\n req: PayloadRequest\n searchDoc: DocToSync\n}) => DocToSync | Promise<DocToSync>\n\nexport type FieldsOverride = (args: { defaultFields: Field[] }) => Field[]\n\nexport type SearchPluginConfig = {\n /**\n * @deprecated\n * This plugin gets the api route from the config directly and does not need to be passed in.\n * As long as you have `routes.api` set in your Payload config, the plugin will use that.\n * This property will be removed in the next major version.\n */\n apiBasePath?: string\n beforeSync?: BeforeSync\n collections?: string[]\n defaultPriorities?: {\n [collection: string]: ((doc: any) => number | Promise<number>) | number\n }\n /**\n * Controls whether drafts are deleted from the search index\n *\n * @default true\n */\n deleteDrafts?: boolean\n localize?: boolean\n /**\n * We use batching when re-indexing large collections. You can control the amount of items per batch, lower numbers should help with memory.\n *\n * @default 50\n */\n reindexBatchSize?: number\n searchOverrides?: { fields?: FieldsOverride } & Partial<Omit<CollectionConfig, 'fields'>>\n /**\n * Controls whether drafts are synced to the search index\n *\n * @default false\n */\n syncDrafts?: boolean\n}\n\nexport type CollectionLabels = {\n [collection: string]: CollectionConfig['labels']\n}\n\nexport type ResolvedCollectionLabels = {\n [collection: string]: StaticLabel\n}\n\nexport type SearchPluginConfigWithLocales = {\n labels?: CollectionLabels\n
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type {\n CollectionAfterChangeHook,\n CollectionBeforeDeleteHook,\n CollectionConfig,\n Field,\n Locale,\n Payload,\n PayloadRequest,\n StaticLabel,\n} from 'payload'\n\nexport type DocToSync = {\n [key: string]: any\n doc: {\n relationTo: string\n value: string\n }\n title: string\n}\n\nexport type BeforeSync = (args: {\n originalDoc: {\n [key: string]: any\n }\n payload: Payload\n req: PayloadRequest\n searchDoc: DocToSync\n}) => DocToSync | Promise<DocToSync>\n\nexport type FieldsOverride = (args: { defaultFields: Field[] }) => Field[]\n\nexport type SkipSyncFunction<ConfigTypes = unknown> = (args: {\n collectionSlug: string\n doc: any\n locale: ConfigTypes extends { locale: unknown } ? ConfigTypes['locale'] : string | undefined\n req: PayloadRequest\n}) => boolean | Promise<boolean>\n\nexport type SearchPluginConfig<ConfigTypes = unknown> = {\n /**\n * @deprecated\n * This plugin gets the api route from the config directly and does not need to be passed in.\n * As long as you have `routes.api` set in your Payload config, the plugin will use that.\n * This property will be removed in the next major version.\n */\n apiBasePath?: string\n beforeSync?: BeforeSync\n collections?: string[]\n defaultPriorities?: {\n [collection: string]: ((doc: any) => number | Promise<number>) | number\n }\n /**\n * Controls whether drafts are deleted from the search index\n *\n * @default true\n */\n deleteDrafts?: boolean\n localize?: boolean\n /**\n * We use batching when re-indexing large collections. You can control the amount of items per batch, lower numbers should help with memory.\n *\n * @default 50\n */\n reindexBatchSize?: number\n searchOverrides?: { fields?: FieldsOverride } & Partial<Omit<CollectionConfig, 'fields'>>\n /**\n * Determine whether to skip syncing a document for a specific locale.\n * Useful for multi-tenant applications, conditional indexing, or any scenario where\n * sync behavior should vary by locale, document, or other factors.\n *\n * @default undefined - All configured locales will be synced\n *\n * @example\n * // Skip syncing based on document's tenant settings\n * skipSync: async ({ locale, req, doc, collectionSlug }) => {\n * // For non-localized collections, locale will be undefined\n * if (!locale) return false\n *\n * const tenant = await req.payload.findByID({\n * collection: 'tenants',\n * id: doc.tenant.id\n * })\n * return !tenant.allowedLocales.includes(locale)\n * }\n */\n skipSync?: SkipSyncFunction<ConfigTypes>\n /**\n * Controls whether drafts are synced to the search index\n *\n * @default false\n */\n syncDrafts?: boolean\n}\n\nexport type CollectionLabels = {\n [collection: string]: CollectionConfig['labels']\n}\n\nexport type ResolvedCollectionLabels = {\n [collection: string]: StaticLabel\n}\n\nexport type SearchPluginConfigWithLocales<ConfigTypes = unknown> = {\n labels?: CollectionLabels\n} & SearchPluginConfig<ConfigTypes>\n\nexport type SanitizedSearchPluginConfig<ConfigTypes = unknown> = {\n reindexBatchSize: number\n syncDrafts: boolean\n} & SearchPluginConfigWithLocales<ConfigTypes>\n\nexport type SyncWithSearchArgs = {\n collection: string\n pluginConfig: SanitizedSearchPluginConfig\n} & Omit<Parameters<CollectionAfterChangeHook>[0], 'collection'>\n\nexport type SyncDocArgs = {\n locale?: Locale['code']\n onSyncError?: () => void\n} & Omit<SyncWithSearchArgs, 'context' | 'previousDoc'>\n\n// Extend the `CollectionAfterChangeHook` with more function args\n// Convert the `collection` arg from `SanitizedCollectionConfig` to a string\nexport type SyncWithSearch = (Args: SyncWithSearchArgs) => ReturnType<CollectionAfterChangeHook>\n\nexport type DeleteFromSearch = (args: SearchPluginConfig) => CollectionBeforeDeleteHook\n"],"names":[],"mappings":"AA6HA,WAAuF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"generateReindexHandler.d.ts","sourceRoot":"","sources":["../../src/utilities/generateReindexHandler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAS,MAAM,SAAS,CAAA;AAWpD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAA;AAS9D,eAAO,MAAM,sBAAsB,iBAClB,2BAA2B,KAAG,
|
|
1
|
+
{"version":3,"file":"generateReindexHandler.d.ts","sourceRoot":"","sources":["../../src/utilities/generateReindexHandler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAS,MAAM,SAAS,CAAA;AAWpD,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,aAAa,CAAA;AAS9D,eAAO,MAAM,sBAAsB,iBAClB,2BAA2B,KAAG,cA+M5C,CAAA"}
|
|
@@ -11,10 +11,7 @@ export const generateReindexHandler = (pluginConfig)=>async (req)=>{
|
|
|
11
11
|
const t = req.t;
|
|
12
12
|
const searchSlug = pluginConfig?.searchOverrides?.slug || 'search';
|
|
13
13
|
const searchCollections = pluginConfig?.collections || [];
|
|
14
|
-
|
|
15
|
-
req.locale
|
|
16
|
-
] : [];
|
|
17
|
-
const validatePermissions = async ()=>{
|
|
14
|
+
async function validatePermissions() {
|
|
18
15
|
const accessResults = await getAccessResults({
|
|
19
16
|
req
|
|
20
17
|
});
|
|
@@ -45,8 +42,8 @@ export const generateReindexHandler = (pluginConfig)=>async (req)=>{
|
|
|
45
42
|
isValid: false,
|
|
46
43
|
message: t('error:notAllowedToPerformAction')
|
|
47
44
|
};
|
|
48
|
-
}
|
|
49
|
-
|
|
45
|
+
}
|
|
46
|
+
function validateCollections() {
|
|
50
47
|
const collectionsAreValid = collections.every((col)=>searchCollections.includes(col));
|
|
51
48
|
return collections.length && collectionsAreValid ? {
|
|
52
49
|
isValid: true
|
|
@@ -56,7 +53,7 @@ export const generateReindexHandler = (pluginConfig)=>async (req)=>{
|
|
|
56
53
|
args: `'collections'`
|
|
57
54
|
})
|
|
58
55
|
};
|
|
59
|
-
}
|
|
56
|
+
}
|
|
60
57
|
const headers = headersWithCors({
|
|
61
58
|
headers: new Headers(),
|
|
62
59
|
req
|
|
@@ -94,7 +91,7 @@ export const generateReindexHandler = (pluginConfig)=>async (req)=>{
|
|
|
94
91
|
let aggregateDocsWithDrafts = 0;
|
|
95
92
|
let aggregateErrors = 0;
|
|
96
93
|
let aggregateDocs = 0;
|
|
97
|
-
|
|
94
|
+
async function countDocuments(collection, drafts) {
|
|
98
95
|
const { totalDocs } = await payload.count({
|
|
99
96
|
collection,
|
|
100
97
|
...defaultLocalApiProps,
|
|
@@ -102,8 +99,8 @@ export const generateReindexHandler = (pluginConfig)=>async (req)=>{
|
|
|
102
99
|
where: drafts ? undefined : whereStatusPublished
|
|
103
100
|
});
|
|
104
101
|
return totalDocs;
|
|
105
|
-
}
|
|
106
|
-
|
|
102
|
+
}
|
|
103
|
+
async function deleteIndexes(collection) {
|
|
107
104
|
await payload.delete({
|
|
108
105
|
collection: searchSlug,
|
|
109
106
|
depth: 0,
|
|
@@ -117,29 +114,58 @@ export const generateReindexHandler = (pluginConfig)=>async (req)=>{
|
|
|
117
114
|
},
|
|
118
115
|
...defaultLocalApiProps
|
|
119
116
|
});
|
|
120
|
-
}
|
|
121
|
-
|
|
117
|
+
}
|
|
118
|
+
async function reindexCollection(collection) {
|
|
122
119
|
const draftsEnabled = Boolean(payload.collections[collection]?.config.versions?.drafts);
|
|
123
120
|
const totalDocsWithDrafts = await countDocuments(collection, true);
|
|
124
121
|
const totalDocs = syncDrafts || !draftsEnabled ? totalDocsWithDrafts : await countDocuments(collection, !draftsEnabled);
|
|
125
122
|
const totalBatches = Math.ceil(totalDocs / batchSize);
|
|
126
123
|
aggregateDocsWithDrafts += totalDocsWithDrafts;
|
|
127
124
|
aggregateDocs += totalDocs;
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
const
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
125
|
+
// Loop through batches, then documents, then locales per document
|
|
126
|
+
for(let i = 0; i < totalBatches; i++){
|
|
127
|
+
const defaultLocale = req.payload.config.localization ? req.payload.config.localization.defaultLocale : req.locale;
|
|
128
|
+
const { docs } = await payload.find({
|
|
129
|
+
collection,
|
|
130
|
+
depth: 0,
|
|
131
|
+
limit: batchSize,
|
|
132
|
+
locale: defaultLocale,
|
|
133
|
+
page: i + 1,
|
|
134
|
+
where: syncDrafts || !draftsEnabled ? undefined : whereStatusPublished,
|
|
135
|
+
...defaultLocalApiProps
|
|
136
|
+
});
|
|
137
|
+
for (const doc of docs){
|
|
138
|
+
// Get all configured locales
|
|
139
|
+
// If no localization, use [undefined] to sync once without a locale
|
|
140
|
+
const allLocales = req.payload.config.localization ? req.payload.config.localization.localeCodes : [
|
|
141
|
+
undefined
|
|
142
|
+
];
|
|
143
|
+
// Loop through all locales and check each one
|
|
144
|
+
let firstAllowedLocale = true;
|
|
145
|
+
for (const localeToSync of allLocales){
|
|
146
|
+
// Check if we should skip this locale for this document
|
|
147
|
+
let shouldSkip = false;
|
|
148
|
+
if (typeof pluginConfig.skipSync === 'function') {
|
|
149
|
+
try {
|
|
150
|
+
shouldSkip = await pluginConfig.skipSync({
|
|
151
|
+
collectionSlug: collection,
|
|
152
|
+
doc,
|
|
153
|
+
locale: localeToSync,
|
|
154
|
+
req
|
|
155
|
+
});
|
|
156
|
+
} catch (err) {
|
|
157
|
+
req.payload.logger.error({
|
|
158
|
+
err,
|
|
159
|
+
msg: 'Search plugin: Error executing skipSync. Proceeding with sync.'
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
if (shouldSkip) {
|
|
164
|
+
continue; // Skip this locale
|
|
165
|
+
}
|
|
166
|
+
// Sync this locale (create first index, then update with other locales accordingly)
|
|
167
|
+
const operation = firstAllowedLocale ? 'create' : 'update';
|
|
168
|
+
firstAllowedLocale = false;
|
|
143
169
|
await syncDocAsSearchIndex({
|
|
144
170
|
collection,
|
|
145
171
|
data: doc,
|
|
@@ -153,7 +179,7 @@ export const generateReindexHandler = (pluginConfig)=>async (req)=>{
|
|
|
153
179
|
}
|
|
154
180
|
}
|
|
155
181
|
}
|
|
156
|
-
}
|
|
182
|
+
}
|
|
157
183
|
const shouldCommit = await initTransaction(req);
|
|
158
184
|
try {
|
|
159
185
|
const promises = collections.map(async (collection)=>{
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/generateReindexHandler.ts"],"sourcesContent":["import type { PayloadHandler, Where } from 'payload'\n\nimport {\n addLocalesToRequestFromData,\n commitTransaction,\n getAccessResults,\n headersWithCors,\n initTransaction,\n killTransaction,\n} from 'payload'\n\nimport type { SanitizedSearchPluginConfig } from '../types.js'\n\nimport { syncDocAsSearchIndex } from './syncDocAsSearchIndex.js'\n\ntype ValidationResult = {\n isValid: boolean\n message?: string\n}\n\nexport const generateReindexHandler =\n (pluginConfig: SanitizedSearchPluginConfig): PayloadHandler =>\n async (req) => {\n addLocalesToRequestFromData(req)\n if (!req.json) {\n return new Response('Req.json is undefined', { status: 400 })\n }\n const { collections = [] } = (await req.json()) as { collections: string[] }\n const t = req.t\n\n const searchSlug = pluginConfig?.searchOverrides?.slug || 'search'\n const searchCollections = pluginConfig?.collections || []\n const reindexLocales = pluginConfig?.locales?.length\n ? pluginConfig.locales\n : req.locale\n ? [req.locale]\n : []\n\n const validatePermissions = async (): Promise<ValidationResult> => {\n const accessResults = await getAccessResults({ req })\n const searchAccessResults = accessResults.collections?.[searchSlug]\n if (!searchAccessResults) {\n return { isValid: false, message: t('error:notAllowedToPerformAction') }\n }\n\n const permissions = [searchAccessResults.delete, searchAccessResults.update]\n // plugin doesn't allow create by default:\n // if user provided, then add it to check\n if (pluginConfig.searchOverrides?.access?.create) {\n permissions.push(searchAccessResults.create)\n }\n // plugin allows reads by anyone by default:\n // so if user provided, then add to check\n if (pluginConfig.searchOverrides?.access?.read) {\n permissions.push(searchAccessResults.read)\n }\n return permissions.every(Boolean)\n ? { isValid: true }\n : { isValid: false, message: t('error:notAllowedToPerformAction') }\n }\n\n const validateCollections = (): ValidationResult => {\n const collectionsAreValid = collections.every((col) => searchCollections.includes(col))\n return collections.length && collectionsAreValid\n ? { isValid: true }\n : { isValid: false, message: t('error:invalidRequestArgs', { args: `'collections'` }) }\n }\n\n const headers = headersWithCors({\n headers: new Headers(),\n req,\n })\n\n const { isValid: hasPermissions, message: permissionError } = await validatePermissions()\n if (!hasPermissions) {\n return Response.json({ message: permissionError }, { headers, status: 401 })\n }\n\n const { isValid: validCollections, message: collectionError } = validateCollections()\n if (!validCollections) {\n return Response.json({ message: collectionError }, { headers, status: 400 })\n }\n\n const payload = req.payload\n const { reindexBatchSize: batchSize, syncDrafts } = pluginConfig\n\n const defaultLocalApiProps = {\n overrideAccess: false,\n req,\n user: req.user,\n }\n const whereStatusPublished: Where = {\n _status: {\n equals: 'published',\n },\n }\n let aggregateDocsWithDrafts = 0\n let aggregateErrors = 0\n let aggregateDocs = 0\n\n const countDocuments = async (collection: string, drafts?: boolean): Promise<number> => {\n const { totalDocs } = await payload.count({\n collection,\n ...defaultLocalApiProps,\n req: undefined,\n where: drafts ? undefined : whereStatusPublished,\n })\n return totalDocs\n }\n\n const deleteIndexes = async (collection: string) => {\n await payload.delete({\n collection: searchSlug,\n depth: 0,\n select: { id: true },\n where: { 'doc.relationTo': { equals: collection } },\n ...defaultLocalApiProps,\n })\n }\n\n const reindexCollection = async (collection: string) => {\n const draftsEnabled = Boolean(payload.collections[collection]?.config.versions?.drafts)\n\n const totalDocsWithDrafts = await countDocuments(collection, true)\n const totalDocs =\n syncDrafts || !draftsEnabled\n ? totalDocsWithDrafts\n : await countDocuments(collection, !draftsEnabled)\n const totalBatches = Math.ceil(totalDocs / batchSize)\n\n aggregateDocsWithDrafts += totalDocsWithDrafts\n aggregateDocs += totalDocs\n\n for (let j = 0; j < reindexLocales.length; j++) {\n // create first index, then we update with other locales accordingly\n const operation = j === 0 ? 'create' : 'update'\n const localeToSync = reindexLocales[j]\n\n for (let i = 0; i < totalBatches; i++) {\n const { docs } = await payload.find({\n collection,\n depth: 0,\n limit: batchSize,\n locale: localeToSync,\n page: i + 1,\n where: syncDrafts || !draftsEnabled ? undefined : whereStatusPublished,\n ...defaultLocalApiProps,\n })\n\n for (const doc of docs) {\n await syncDocAsSearchIndex({\n collection,\n data: doc,\n doc,\n locale: localeToSync,\n onSyncError: () => operation === 'create' && aggregateErrors++,\n operation,\n pluginConfig,\n req,\n })\n }\n }\n }\n }\n\n const shouldCommit = await initTransaction(req)\n\n try {\n const promises = collections.map(async (collection) => {\n try {\n await deleteIndexes(collection)\n await reindexCollection(collection)\n } catch (err) {\n const message = t('error:unableToReindexCollection', { collection })\n payload.logger.error({ err, msg: message })\n }\n })\n\n await Promise.all(promises)\n } catch (err: any) {\n if (shouldCommit) {\n await killTransaction(req)\n }\n return Response.json({ message: err.message }, { headers, status: 500 })\n }\n\n const message = t('general:successfullyReindexed', {\n collections: collections.join(', '),\n count: aggregateDocs - aggregateErrors,\n skips: syncDrafts ? 0 : aggregateDocsWithDrafts - aggregateDocs,\n total: aggregateDocsWithDrafts,\n })\n\n if (shouldCommit) {\n await commitTransaction(req)\n }\n\n return Response.json({ message }, { headers, status: 200 })\n }\n"],"names":["addLocalesToRequestFromData","commitTransaction","getAccessResults","headersWithCors","initTransaction","killTransaction","syncDocAsSearchIndex","generateReindexHandler","pluginConfig","req","json","Response","status","collections","t","searchSlug","searchOverrides","slug","searchCollections","reindexLocales","locales","length","locale","validatePermissions","accessResults","searchAccessResults","isValid","message","permissions","delete","update","access","create","push","read","every","Boolean","validateCollections","collectionsAreValid","col","includes","args","headers","Headers","hasPermissions","permissionError","validCollections","collectionError","payload","reindexBatchSize","batchSize","syncDrafts","defaultLocalApiProps","overrideAccess","user","whereStatusPublished","_status","equals","aggregateDocsWithDrafts","aggregateErrors","aggregateDocs","countDocuments","collection","drafts","totalDocs","count","undefined","where","deleteIndexes","depth","select","id","reindexCollection","draftsEnabled","config","versions","totalDocsWithDrafts","totalBatches","Math","ceil","j","operation","localeToSync","i","docs","find","limit","page","doc","data","onSyncError","shouldCommit","promises","map","err","logger","error","msg","Promise","all","join","skips","total"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/generateReindexHandler.ts"],"sourcesContent":["import type { PayloadHandler, Where } from 'payload'\n\nimport {\n addLocalesToRequestFromData,\n commitTransaction,\n getAccessResults,\n headersWithCors,\n initTransaction,\n killTransaction,\n} from 'payload'\n\nimport type { SanitizedSearchPluginConfig } from '../types.js'\n\nimport { syncDocAsSearchIndex } from './syncDocAsSearchIndex.js'\n\ntype ValidationResult = {\n isValid: boolean\n message?: string\n}\n\nexport const generateReindexHandler =\n (pluginConfig: SanitizedSearchPluginConfig): PayloadHandler =>\n async (req) => {\n addLocalesToRequestFromData(req)\n if (!req.json) {\n return new Response('Req.json is undefined', { status: 400 })\n }\n const { collections = [] } = (await req.json()) as { collections: string[] }\n const t = req.t\n\n const searchSlug = pluginConfig?.searchOverrides?.slug || 'search'\n const searchCollections = pluginConfig?.collections || []\n\n async function validatePermissions(): Promise<ValidationResult> {\n const accessResults = await getAccessResults({ req })\n const searchAccessResults = accessResults.collections?.[searchSlug]\n if (!searchAccessResults) {\n return { isValid: false, message: t('error:notAllowedToPerformAction') }\n }\n\n const permissions = [searchAccessResults.delete, searchAccessResults.update]\n // plugin doesn't allow create by default:\n // if user provided, then add it to check\n if (pluginConfig.searchOverrides?.access?.create) {\n permissions.push(searchAccessResults.create)\n }\n // plugin allows reads by anyone by default:\n // so if user provided, then add to check\n if (pluginConfig.searchOverrides?.access?.read) {\n permissions.push(searchAccessResults.read)\n }\n return permissions.every(Boolean)\n ? { isValid: true }\n : { isValid: false, message: t('error:notAllowedToPerformAction') }\n }\n\n function validateCollections(): ValidationResult {\n const collectionsAreValid = collections.every((col) => searchCollections.includes(col))\n return collections.length && collectionsAreValid\n ? { isValid: true }\n : { isValid: false, message: t('error:invalidRequestArgs', { args: `'collections'` }) }\n }\n\n const headers = headersWithCors({\n headers: new Headers(),\n req,\n })\n\n const { isValid: hasPermissions, message: permissionError } = await validatePermissions()\n if (!hasPermissions) {\n return Response.json({ message: permissionError }, { headers, status: 401 })\n }\n\n const { isValid: validCollections, message: collectionError } = validateCollections()\n if (!validCollections) {\n return Response.json({ message: collectionError }, { headers, status: 400 })\n }\n\n const payload = req.payload\n const { reindexBatchSize: batchSize, syncDrafts } = pluginConfig\n\n const defaultLocalApiProps = {\n overrideAccess: false,\n req,\n user: req.user,\n }\n const whereStatusPublished: Where = {\n _status: {\n equals: 'published',\n },\n }\n let aggregateDocsWithDrafts = 0\n let aggregateErrors = 0\n let aggregateDocs = 0\n\n async function countDocuments(collection: string, drafts?: boolean): Promise<number> {\n const { totalDocs } = await payload.count({\n collection,\n ...defaultLocalApiProps,\n req: undefined,\n where: drafts ? undefined : whereStatusPublished,\n })\n return totalDocs\n }\n\n async function deleteIndexes(collection: string) {\n await payload.delete({\n collection: searchSlug,\n depth: 0,\n select: { id: true },\n where: { 'doc.relationTo': { equals: collection } },\n ...defaultLocalApiProps,\n })\n }\n\n async function reindexCollection(collection: string) {\n const draftsEnabled = Boolean(payload.collections[collection]?.config.versions?.drafts)\n\n const totalDocsWithDrafts = await countDocuments(collection, true)\n const totalDocs =\n syncDrafts || !draftsEnabled\n ? totalDocsWithDrafts\n : await countDocuments(collection, !draftsEnabled)\n const totalBatches = Math.ceil(totalDocs / batchSize)\n\n aggregateDocsWithDrafts += totalDocsWithDrafts\n aggregateDocs += totalDocs\n\n // Loop through batches, then documents, then locales per document\n for (let i = 0; i < totalBatches; i++) {\n const defaultLocale = req.payload.config.localization\n ? req.payload.config.localization.defaultLocale\n : req.locale\n\n const { docs } = await payload.find({\n collection,\n depth: 0,\n limit: batchSize,\n locale: defaultLocale,\n page: i + 1,\n where: syncDrafts || !draftsEnabled ? undefined : whereStatusPublished,\n ...defaultLocalApiProps,\n })\n\n for (const doc of docs) {\n // Get all configured locales\n // If no localization, use [undefined] to sync once without a locale\n const allLocales = req.payload.config.localization\n ? req.payload.config.localization.localeCodes\n : [undefined]\n\n // Loop through all locales and check each one\n let firstAllowedLocale = true\n for (const localeToSync of allLocales) {\n // Check if we should skip this locale for this document\n let shouldSkip = false\n if (typeof pluginConfig.skipSync === 'function') {\n try {\n shouldSkip = await pluginConfig.skipSync({\n collectionSlug: collection,\n doc,\n locale: localeToSync,\n req,\n })\n } catch (err) {\n req.payload.logger.error({\n err,\n msg: 'Search plugin: Error executing skipSync. Proceeding with sync.',\n })\n }\n }\n\n if (shouldSkip) {\n continue // Skip this locale\n }\n\n // Sync this locale (create first index, then update with other locales accordingly)\n const operation = firstAllowedLocale ? 'create' : 'update'\n firstAllowedLocale = false\n\n await syncDocAsSearchIndex({\n collection,\n data: doc,\n doc,\n locale: localeToSync,\n onSyncError: () => operation === 'create' && aggregateErrors++,\n operation,\n pluginConfig,\n req,\n })\n }\n }\n }\n }\n\n const shouldCommit = await initTransaction(req)\n\n try {\n const promises = collections.map(async (collection) => {\n try {\n await deleteIndexes(collection)\n await reindexCollection(collection)\n } catch (err) {\n const message = t('error:unableToReindexCollection', { collection })\n payload.logger.error({ err, msg: message })\n }\n })\n\n await Promise.all(promises)\n } catch (err: any) {\n if (shouldCommit) {\n await killTransaction(req)\n }\n return Response.json({ message: err.message }, { headers, status: 500 })\n }\n\n const message = t('general:successfullyReindexed', {\n collections: collections.join(', '),\n count: aggregateDocs - aggregateErrors,\n skips: syncDrafts ? 0 : aggregateDocsWithDrafts - aggregateDocs,\n total: aggregateDocsWithDrafts,\n })\n\n if (shouldCommit) {\n await commitTransaction(req)\n }\n\n return Response.json({ message }, { headers, status: 200 })\n }\n"],"names":["addLocalesToRequestFromData","commitTransaction","getAccessResults","headersWithCors","initTransaction","killTransaction","syncDocAsSearchIndex","generateReindexHandler","pluginConfig","req","json","Response","status","collections","t","searchSlug","searchOverrides","slug","searchCollections","validatePermissions","accessResults","searchAccessResults","isValid","message","permissions","delete","update","access","create","push","read","every","Boolean","validateCollections","collectionsAreValid","col","includes","length","args","headers","Headers","hasPermissions","permissionError","validCollections","collectionError","payload","reindexBatchSize","batchSize","syncDrafts","defaultLocalApiProps","overrideAccess","user","whereStatusPublished","_status","equals","aggregateDocsWithDrafts","aggregateErrors","aggregateDocs","countDocuments","collection","drafts","totalDocs","count","undefined","where","deleteIndexes","depth","select","id","reindexCollection","draftsEnabled","config","versions","totalDocsWithDrafts","totalBatches","Math","ceil","i","defaultLocale","localization","locale","docs","find","limit","page","doc","allLocales","localeCodes","firstAllowedLocale","localeToSync","shouldSkip","skipSync","collectionSlug","err","logger","error","msg","operation","data","onSyncError","shouldCommit","promises","map","Promise","all","join","skips","total"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"syncDocAsSearchIndex.d.ts","sourceRoot":"","sources":["../../src/utilities/syncDocAsSearchIndex.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,WAAW,EAAE,MAAM,aAAa,CAAA;AAEzD,eAAO,MAAM,oBAAoB,8FAS9B,WAAW,
|
|
1
|
+
{"version":3,"file":"syncDocAsSearchIndex.d.ts","sourceRoot":"","sources":["../../src/utilities/syncDocAsSearchIndex.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAa,WAAW,EAAE,MAAM,aAAa,CAAA;AAEzD,eAAO,MAAM,oBAAoB,8FAS9B,WAAW,iBA+Qb,CAAA"}
|
|
@@ -2,7 +2,26 @@ export const syncDocAsSearchIndex = async ({ collection, doc, locale, onSyncErro
|
|
|
2
2
|
const { id, _status: status, title } = doc || {};
|
|
3
3
|
const { beforeSync, defaultPriorities, deleteDrafts, searchOverrides, syncDrafts } = pluginConfig;
|
|
4
4
|
const searchSlug = searchOverrides?.slug || 'search';
|
|
5
|
-
|
|
5
|
+
// Determine sync locale
|
|
6
|
+
const syncLocale = locale || req.locale || undefined;
|
|
7
|
+
if (typeof pluginConfig.skipSync === 'function') {
|
|
8
|
+
try {
|
|
9
|
+
const skipSync = await pluginConfig.skipSync({
|
|
10
|
+
collectionSlug: collection,
|
|
11
|
+
doc,
|
|
12
|
+
locale: syncLocale,
|
|
13
|
+
req
|
|
14
|
+
});
|
|
15
|
+
if (skipSync) {
|
|
16
|
+
return doc;
|
|
17
|
+
}
|
|
18
|
+
} catch (err) {
|
|
19
|
+
req.payload.logger.error({
|
|
20
|
+
err,
|
|
21
|
+
msg: 'Search plugin: Error executing skipSync. Proceeding with sync.'
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
}
|
|
6
25
|
let dataToSave = {
|
|
7
26
|
doc: {
|
|
8
27
|
relationTo: collection,
|
|
@@ -11,7 +30,7 @@ export const syncDocAsSearchIndex = async ({ collection, doc, locale, onSyncErro
|
|
|
11
30
|
title
|
|
12
31
|
};
|
|
13
32
|
const docKeyPrefix = `${collection}:${id}`;
|
|
14
|
-
const docKey =
|
|
33
|
+
const docKey = req.payload.config.localization ? `${docKeyPrefix}:${syncLocale}` : docKeyPrefix;
|
|
15
34
|
const syncedDocsSet = req.context?.syncedDocsSet || new Set();
|
|
16
35
|
if (syncedDocsSet.has(docKey)) {
|
|
17
36
|
/*
|
|
@@ -115,27 +134,6 @@ export const syncDocAsSearchIndex = async ({ collection, doc, locale, onSyncErro
|
|
|
115
134
|
}
|
|
116
135
|
if (foundDoc) {
|
|
117
136
|
const { id: searchDocID } = foundDoc;
|
|
118
|
-
if (doSync) {
|
|
119
|
-
// update the doc normally
|
|
120
|
-
try {
|
|
121
|
-
await payload.update({
|
|
122
|
-
id: searchDocID,
|
|
123
|
-
collection: searchSlug,
|
|
124
|
-
data: {
|
|
125
|
-
...dataToSave,
|
|
126
|
-
priority: foundDoc.priority || defaultPriority
|
|
127
|
-
},
|
|
128
|
-
depth: 0,
|
|
129
|
-
locale: syncLocale,
|
|
130
|
-
req
|
|
131
|
-
});
|
|
132
|
-
} catch (err) {
|
|
133
|
-
payload.logger.error({
|
|
134
|
-
err,
|
|
135
|
-
msg: `Error updating ${searchSlug} document.`
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
137
|
// Check if document is trashed and delete from search
|
|
140
138
|
const isTrashDocument = doc && 'deletedAt' in doc && doc.deletedAt;
|
|
141
139
|
if (isTrashDocument) {
|
|
@@ -152,49 +150,71 @@ export const syncDocAsSearchIndex = async ({ collection, doc, locale, onSyncErro
|
|
|
152
150
|
msg: `Error deleting ${searchSlug} document for trashed doc.`
|
|
153
151
|
});
|
|
154
152
|
}
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
// We don't want to remove the search doc if there is a published version but a new draft has been created
|
|
159
|
-
const { docs: [docWithPublish] } = await payload.find({
|
|
160
|
-
collection,
|
|
161
|
-
depth: 0,
|
|
162
|
-
draft: false,
|
|
163
|
-
limit: 1,
|
|
164
|
-
locale: syncLocale,
|
|
165
|
-
pagination: false,
|
|
166
|
-
req,
|
|
167
|
-
where: {
|
|
168
|
-
and: [
|
|
169
|
-
{
|
|
170
|
-
_status: {
|
|
171
|
-
equals: 'published'
|
|
172
|
-
}
|
|
173
|
-
},
|
|
174
|
-
{
|
|
175
|
-
id: {
|
|
176
|
-
equals: id
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
]
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
if (!docWithPublish && !isTrashDocument) {
|
|
183
|
-
// do not include draft docs in search results, so delete the record
|
|
153
|
+
} else {
|
|
154
|
+
if (doSync) {
|
|
155
|
+
// update the doc normally
|
|
184
156
|
try {
|
|
185
|
-
await payload.
|
|
157
|
+
await payload.update({
|
|
186
158
|
id: searchDocID,
|
|
187
159
|
collection: searchSlug,
|
|
160
|
+
data: {
|
|
161
|
+
...dataToSave,
|
|
162
|
+
priority: foundDoc.priority || defaultPriority
|
|
163
|
+
},
|
|
188
164
|
depth: 0,
|
|
165
|
+
locale: syncLocale,
|
|
189
166
|
req
|
|
190
167
|
});
|
|
191
168
|
} catch (err) {
|
|
192
169
|
payload.logger.error({
|
|
193
170
|
err,
|
|
194
|
-
msg: `Error
|
|
171
|
+
msg: `Error updating ${searchSlug} document.`
|
|
195
172
|
});
|
|
196
173
|
}
|
|
197
174
|
}
|
|
175
|
+
if (deleteDrafts && status === 'draft') {
|
|
176
|
+
// Check to see if there's a published version of the doc
|
|
177
|
+
// We don't want to remove the search doc if there is a published version but a new draft has been created
|
|
178
|
+
const { docs: [docWithPublish] } = await payload.find({
|
|
179
|
+
collection,
|
|
180
|
+
depth: 0,
|
|
181
|
+
draft: false,
|
|
182
|
+
limit: 1,
|
|
183
|
+
locale: syncLocale,
|
|
184
|
+
pagination: false,
|
|
185
|
+
req,
|
|
186
|
+
where: {
|
|
187
|
+
and: [
|
|
188
|
+
{
|
|
189
|
+
_status: {
|
|
190
|
+
equals: 'published'
|
|
191
|
+
}
|
|
192
|
+
},
|
|
193
|
+
{
|
|
194
|
+
id: {
|
|
195
|
+
equals: id
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
]
|
|
199
|
+
}
|
|
200
|
+
});
|
|
201
|
+
if (!docWithPublish) {
|
|
202
|
+
// do not include draft docs in search results, so delete the record
|
|
203
|
+
try {
|
|
204
|
+
await payload.delete({
|
|
205
|
+
id: searchDocID,
|
|
206
|
+
collection: searchSlug,
|
|
207
|
+
depth: 0,
|
|
208
|
+
req
|
|
209
|
+
});
|
|
210
|
+
} catch (err) {
|
|
211
|
+
payload.logger.error({
|
|
212
|
+
err,
|
|
213
|
+
msg: `Error deleting ${searchSlug} document.`
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
198
218
|
}
|
|
199
219
|
} else if (doSync) {
|
|
200
220
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/utilities/syncDocAsSearchIndex.ts"],"sourcesContent":["import type { DocToSync, SyncDocArgs } from '../types.js'\n\nexport const syncDocAsSearchIndex = async ({\n collection,\n doc,\n locale,\n onSyncError,\n operation,\n pluginConfig,\n req: { payload },\n req,\n}: SyncDocArgs) => {\n const { id, _status: status, title } = doc || {}\n\n const { beforeSync, defaultPriorities, deleteDrafts, searchOverrides, syncDrafts } = pluginConfig\n\n const searchSlug = searchOverrides?.slug || 'search'\n const syncLocale = locale || req.locale\n\n let dataToSave: DocToSync = {\n doc: {\n relationTo: collection,\n value: id,\n },\n title,\n }\n const docKeyPrefix = `${collection}:${id}`\n const docKey = pluginConfig.locales?.length ? `${docKeyPrefix}:${syncLocale}` : docKeyPrefix\n const syncedDocsSet = (req.context?.syncedDocsSet as Set<string>) || new Set<string>()\n\n if (syncedDocsSet.has(docKey)) {\n /*\n * prevents duplicate syncing of documents in the same request\n * this can happen when hooks call `payload.update` within the create lifecycle\n * like the nested-docs plugin does\n */\n return doc\n } else {\n syncedDocsSet.add(docKey)\n }\n\n req.context.syncedDocsSet = syncedDocsSet\n\n if (typeof beforeSync === 'function') {\n let docToSyncWith = doc\n if (payload.config?.localization) {\n // Check if document is trashed (has deletedAt field)\n const isTrashDocument = doc && 'deletedAt' in doc && doc.deletedAt\n\n docToSyncWith = await payload.findByID({\n id,\n collection,\n locale: syncLocale,\n req,\n // Include trashed documents when the document being synced is trashed\n trash: isTrashDocument,\n })\n }\n dataToSave = await beforeSync({\n originalDoc: docToSyncWith,\n payload,\n req,\n searchDoc: dataToSave,\n })\n }\n\n let defaultPriority = 0\n if (defaultPriorities) {\n const { [collection]: priority } = defaultPriorities\n\n if (typeof priority === 'function') {\n try {\n defaultPriority = await priority(doc)\n } catch (err: unknown) {\n payload.logger.error(err)\n payload.logger.error(\n `Error gathering default priority for ${searchSlug} documents related to ${collection}`,\n )\n }\n } else if (priority !== undefined) {\n defaultPriority = priority\n }\n }\n\n const doSync = syncDrafts || (!syncDrafts && status !== 'draft')\n\n try {\n if (operation === 'create' && doSync) {\n await payload.create({\n collection: searchSlug,\n data: {\n ...dataToSave,\n priority: defaultPriority,\n },\n depth: 0,\n locale: syncLocale,\n req,\n })\n }\n\n if (operation === 'update') {\n try {\n // find the correct doc to sync with\n const searchDocQuery = await payload.find({\n collection: searchSlug,\n depth: 0,\n locale: syncLocale,\n req,\n where: {\n 'doc.relationTo': {\n equals: collection,\n },\n 'doc.value': {\n equals: id,\n },\n },\n })\n\n const docs: Array<{\n id: number | string\n priority?: number\n }> = searchDocQuery?.docs || []\n\n const [foundDoc, ...duplicativeDocs] = docs\n\n // delete all duplicative search docs (docs that reference the same page)\n // to ensure the same, out-of-date result does not appear twice (where only syncing the first found doc)\n if (duplicativeDocs.length > 0) {\n try {\n const duplicativeDocIDs = duplicativeDocs.map(({ id }) => id)\n await payload.delete({\n collection: searchSlug,\n depth: 0,\n req,\n where: { id: { in: duplicativeDocIDs } },\n })\n } catch (err: unknown) {\n payload.logger.error({\n err,\n msg: `Error deleting duplicative ${searchSlug} documents.`,\n })\n }\n }\n\n if (foundDoc) {\n const { id: searchDocID } = foundDoc\n\n if (doSync) {\n // update the doc normally\n try {\n await payload.update({\n id: searchDocID,\n collection: searchSlug,\n data: {\n ...dataToSave,\n priority: foundDoc.priority || defaultPriority,\n },\n depth: 0,\n locale: syncLocale,\n req,\n })\n } catch (err: unknown) {\n payload.logger.error({ err, msg: `Error updating ${searchSlug} document.` })\n }\n }\n\n // Check if document is trashed and delete from search\n const isTrashDocument = doc && 'deletedAt' in doc && doc.deletedAt\n\n if (isTrashDocument) {\n try {\n await payload.delete({\n id: searchDocID,\n collection: searchSlug,\n depth: 0,\n req,\n })\n } catch (err: unknown) {\n payload.logger.error({\n err,\n msg: `Error deleting ${searchSlug} document for trashed doc.`,\n })\n }\n }\n\n if (deleteDrafts && status === 'draft') {\n // Check to see if there's a published version of the doc\n // We don't want to remove the search doc if there is a published version but a new draft has been created\n const {\n docs: [docWithPublish],\n } = await payload.find({\n collection,\n depth: 0,\n draft: false,\n limit: 1,\n locale: syncLocale,\n pagination: false,\n req,\n where: {\n and: [\n {\n _status: {\n equals: 'published',\n },\n },\n {\n id: {\n equals: id,\n },\n },\n ],\n },\n })\n\n if (!docWithPublish && !isTrashDocument) {\n // do not include draft docs in search results, so delete the record\n try {\n await payload.delete({\n id: searchDocID,\n collection: searchSlug,\n depth: 0,\n req,\n })\n } catch (err: unknown) {\n payload.logger.error({ err, msg: `Error deleting ${searchSlug} document.` })\n }\n }\n }\n } else if (doSync) {\n try {\n await payload.create({\n collection: searchSlug,\n data: {\n ...dataToSave,\n priority: defaultPriority,\n },\n depth: 0,\n locale: syncLocale,\n req,\n })\n } catch (err: unknown) {\n payload.logger.error({ err, msg: `Error creating ${searchSlug} document.` })\n }\n }\n } catch (err: unknown) {\n payload.logger.error({ err, msg: `Error finding ${searchSlug} document.` })\n }\n }\n } catch (err: unknown) {\n payload.logger.error({\n err,\n msg: `Error syncing ${searchSlug} document related to ${collection} with id: '${id}'.`,\n })\n\n if (onSyncError) {\n onSyncError()\n }\n }\n\n return doc\n}\n"],"names":["syncDocAsSearchIndex","collection","doc","locale","onSyncError","operation","pluginConfig","req","payload","id","_status","status","title","beforeSync","defaultPriorities","deleteDrafts","searchOverrides","syncDrafts","searchSlug","slug","syncLocale","dataToSave","relationTo","value","docKeyPrefix","docKey","locales","length","syncedDocsSet","context","Set","has","add","docToSyncWith","config","localization","isTrashDocument","deletedAt","findByID","trash","originalDoc","searchDoc","defaultPriority","priority","err","logger","error","undefined","doSync","create","data","depth","searchDocQuery","find","where","equals","docs","foundDoc","duplicativeDocs","duplicativeDocIDs","map","delete","in","msg","searchDocID","update","docWithPublish","draft","limit","pagination","and"],"mappings":"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"}
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/syncDocAsSearchIndex.ts"],"sourcesContent":["import type { DocToSync, SyncDocArgs } from '../types.js'\n\nexport const syncDocAsSearchIndex = async ({\n collection,\n doc,\n locale,\n onSyncError,\n operation,\n pluginConfig,\n req: { payload },\n req,\n}: SyncDocArgs) => {\n const { id, _status: status, title } = doc || {}\n\n const { beforeSync, defaultPriorities, deleteDrafts, searchOverrides, syncDrafts } = pluginConfig\n\n const searchSlug = searchOverrides?.slug || 'search'\n\n // Determine sync locale\n const syncLocale = locale || req.locale || undefined\n\n if (typeof pluginConfig.skipSync === 'function') {\n try {\n const skipSync = await pluginConfig.skipSync({\n collectionSlug: collection,\n doc,\n locale: syncLocale,\n req,\n })\n\n if (skipSync) {\n return doc\n }\n } catch (err) {\n req.payload.logger.error({\n err,\n msg: 'Search plugin: Error executing skipSync. Proceeding with sync.',\n })\n }\n }\n\n let dataToSave: DocToSync = {\n doc: {\n relationTo: collection,\n value: id,\n },\n title,\n }\n const docKeyPrefix = `${collection}:${id}`\n const docKey = req.payload.config.localization ? `${docKeyPrefix}:${syncLocale}` : docKeyPrefix\n const syncedDocsSet = (req.context?.syncedDocsSet as Set<string>) || new Set<string>()\n\n if (syncedDocsSet.has(docKey)) {\n /*\n * prevents duplicate syncing of documents in the same request\n * this can happen when hooks call `payload.update` within the create lifecycle\n * like the nested-docs plugin does\n */\n return doc\n } else {\n syncedDocsSet.add(docKey)\n }\n\n req.context.syncedDocsSet = syncedDocsSet\n\n if (typeof beforeSync === 'function') {\n let docToSyncWith = doc\n if (payload.config?.localization) {\n // Check if document is trashed (has deletedAt field)\n const isTrashDocument = doc && 'deletedAt' in doc && doc.deletedAt\n\n docToSyncWith = await payload.findByID({\n id,\n collection,\n locale: syncLocale,\n req,\n // Include trashed documents when the document being synced is trashed\n trash: isTrashDocument,\n })\n }\n dataToSave = await beforeSync({\n originalDoc: docToSyncWith,\n payload,\n req,\n searchDoc: dataToSave,\n })\n }\n\n let defaultPriority = 0\n if (defaultPriorities) {\n const { [collection]: priority } = defaultPriorities\n\n if (typeof priority === 'function') {\n try {\n defaultPriority = await priority(doc)\n } catch (err: unknown) {\n payload.logger.error(err)\n payload.logger.error(\n `Error gathering default priority for ${searchSlug} documents related to ${collection}`,\n )\n }\n } else if (priority !== undefined) {\n defaultPriority = priority\n }\n }\n\n const doSync = syncDrafts || (!syncDrafts && status !== 'draft')\n\n try {\n if (operation === 'create' && doSync) {\n await payload.create({\n collection: searchSlug,\n data: {\n ...dataToSave,\n priority: defaultPriority,\n },\n depth: 0,\n locale: syncLocale,\n req,\n })\n }\n\n if (operation === 'update') {\n try {\n // find the correct doc to sync with\n const searchDocQuery = await payload.find({\n collection: searchSlug,\n depth: 0,\n locale: syncLocale,\n req,\n where: {\n 'doc.relationTo': {\n equals: collection,\n },\n 'doc.value': {\n equals: id,\n },\n },\n })\n\n const docs: Array<{\n id: number | string\n priority?: number\n }> = searchDocQuery?.docs || []\n\n const [foundDoc, ...duplicativeDocs] = docs\n\n // delete all duplicative search docs (docs that reference the same page)\n // to ensure the same, out-of-date result does not appear twice (where only syncing the first found doc)\n if (duplicativeDocs.length > 0) {\n try {\n const duplicativeDocIDs = duplicativeDocs.map(({ id }) => id)\n await payload.delete({\n collection: searchSlug,\n depth: 0,\n req,\n where: { id: { in: duplicativeDocIDs } },\n })\n } catch (err: unknown) {\n payload.logger.error({\n err,\n msg: `Error deleting duplicative ${searchSlug} documents.`,\n })\n }\n }\n\n if (foundDoc) {\n const { id: searchDocID } = foundDoc\n\n // Check if document is trashed and delete from search\n const isTrashDocument = doc && 'deletedAt' in doc && doc.deletedAt\n\n if (isTrashDocument) {\n try {\n await payload.delete({\n id: searchDocID,\n collection: searchSlug,\n depth: 0,\n req,\n })\n } catch (err: unknown) {\n payload.logger.error({\n err,\n msg: `Error deleting ${searchSlug} document for trashed doc.`,\n })\n }\n } else {\n if (doSync) {\n // update the doc normally\n try {\n await payload.update({\n id: searchDocID,\n collection: searchSlug,\n data: {\n ...dataToSave,\n priority: foundDoc.priority || defaultPriority,\n },\n depth: 0,\n locale: syncLocale,\n req,\n })\n } catch (err: unknown) {\n payload.logger.error({ err, msg: `Error updating ${searchSlug} document.` })\n }\n }\n\n if (deleteDrafts && status === 'draft') {\n // Check to see if there's a published version of the doc\n // We don't want to remove the search doc if there is a published version but a new draft has been created\n const {\n docs: [docWithPublish],\n } = await payload.find({\n collection,\n depth: 0,\n draft: false,\n limit: 1,\n locale: syncLocale,\n pagination: false,\n req,\n where: {\n and: [\n {\n _status: {\n equals: 'published',\n },\n },\n {\n id: {\n equals: id,\n },\n },\n ],\n },\n })\n\n if (!docWithPublish) {\n // do not include draft docs in search results, so delete the record\n try {\n await payload.delete({\n id: searchDocID,\n collection: searchSlug,\n depth: 0,\n req,\n })\n } catch (err: unknown) {\n payload.logger.error({ err, msg: `Error deleting ${searchSlug} document.` })\n }\n }\n }\n }\n } else if (doSync) {\n try {\n await payload.create({\n collection: searchSlug,\n data: {\n ...dataToSave,\n priority: defaultPriority,\n },\n depth: 0,\n locale: syncLocale,\n req,\n })\n } catch (err: unknown) {\n payload.logger.error({ err, msg: `Error creating ${searchSlug} document.` })\n }\n }\n } catch (err: unknown) {\n payload.logger.error({ err, msg: `Error finding ${searchSlug} document.` })\n }\n }\n } catch (err: unknown) {\n payload.logger.error({\n err,\n msg: `Error syncing ${searchSlug} document related to ${collection} with id: '${id}'.`,\n })\n\n if (onSyncError) {\n onSyncError()\n }\n }\n\n return doc\n}\n"],"names":["syncDocAsSearchIndex","collection","doc","locale","onSyncError","operation","pluginConfig","req","payload","id","_status","status","title","beforeSync","defaultPriorities","deleteDrafts","searchOverrides","syncDrafts","searchSlug","slug","syncLocale","undefined","skipSync","collectionSlug","err","logger","error","msg","dataToSave","relationTo","value","docKeyPrefix","docKey","config","localization","syncedDocsSet","context","Set","has","add","docToSyncWith","isTrashDocument","deletedAt","findByID","trash","originalDoc","searchDoc","defaultPriority","priority","doSync","create","data","depth","searchDocQuery","find","where","equals","docs","foundDoc","duplicativeDocs","length","duplicativeDocIDs","map","delete","in","searchDocID","update","docWithPublish","draft","limit","pagination","and"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@payloadcms/plugin-search",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.71.0-internal.727c7a4",
|
|
4
4
|
"description": "Search plugin for Payload",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"payload",
|
|
@@ -50,19 +50,19 @@
|
|
|
50
50
|
"dist"
|
|
51
51
|
],
|
|
52
52
|
"dependencies": {
|
|
53
|
-
"@payloadcms/next": "3.
|
|
54
|
-
"@payloadcms/ui": "3.
|
|
53
|
+
"@payloadcms/next": "3.71.0-internal.727c7a4",
|
|
54
|
+
"@payloadcms/ui": "3.71.0-internal.727c7a4"
|
|
55
55
|
},
|
|
56
56
|
"devDependencies": {
|
|
57
57
|
"@types/react": "19.2.1",
|
|
58
58
|
"@types/react-dom": "19.2.1",
|
|
59
59
|
"@payloadcms/eslint-config": "3.28.0",
|
|
60
|
-
"payload": "3.
|
|
60
|
+
"payload": "3.71.0-internal.727c7a4"
|
|
61
61
|
},
|
|
62
62
|
"peerDependencies": {
|
|
63
63
|
"react": "^19.0.1 || ^19.1.2 || ^19.2.1",
|
|
64
64
|
"react-dom": "^19.0.1 || ^19.1.2 || ^19.2.1",
|
|
65
|
-
"payload": "3.
|
|
65
|
+
"payload": "3.71.0-internal.727c7a4"
|
|
66
66
|
},
|
|
67
67
|
"publishConfig": {
|
|
68
68
|
"registry": "https://registry.npmjs.org/"
|