@payloadcms/plugin-search 3.1.1 → 3.2.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/dist/Search/hooks/syncWithSearch.d.ts.map +1 -1
- package/dist/Search/hooks/syncWithSearch.js +3 -167
- package/dist/Search/hooks/syncWithSearch.js.map +1 -1
- package/dist/Search/index.d.ts +2 -2
- package/dist/Search/index.d.ts.map +1 -1
- package/dist/Search/index.js +30 -2
- package/dist/Search/index.js.map +1 -1
- package/dist/Search/ui/LinkToDoc/index.client.d.ts.map +1 -0
- package/dist/Search/ui/LinkToDoc/index.client.js.map +1 -0
- package/dist/Search/ui/LinkToDoc/index.d.ts.map +1 -0
- package/dist/Search/ui/LinkToDoc/index.js.map +1 -0
- package/dist/Search/ui/ReindexButton/ReindexButtonLabel/index.d.ts +2 -0
- package/dist/Search/ui/ReindexButton/ReindexButtonLabel/index.d.ts.map +1 -0
- package/dist/Search/ui/ReindexButton/ReindexButtonLabel/index.js +13 -0
- package/dist/Search/ui/ReindexButton/ReindexButtonLabel/index.js.map +1 -0
- package/dist/Search/ui/ReindexButton/ReindexConfirmModal/index.d.ts +11 -0
- package/dist/Search/ui/ReindexButton/ReindexConfirmModal/index.d.ts.map +1 -0
- package/dist/Search/ui/ReindexButton/ReindexConfirmModal/index.js +45 -0
- package/dist/Search/ui/ReindexButton/ReindexConfirmModal/index.js.map +1 -0
- package/dist/Search/ui/ReindexButton/index.client.d.ts +4 -0
- package/dist/Search/ui/ReindexButton/index.client.d.ts.map +1 -0
- package/dist/Search/ui/ReindexButton/index.client.js +138 -0
- package/dist/Search/ui/ReindexButton/index.client.js.map +1 -0
- package/dist/Search/ui/ReindexButton/index.d.ts +3 -0
- package/dist/Search/ui/ReindexButton/index.d.ts.map +1 -0
- package/dist/Search/ui/ReindexButton/index.js +36 -0
- package/dist/Search/ui/ReindexButton/index.js.map +1 -0
- package/dist/Search/ui/ReindexButton/types.d.ts +14 -0
- package/dist/Search/ui/ReindexButton/types.d.ts.map +1 -0
- package/dist/Search/ui/ReindexButton/types.js +3 -0
- package/dist/Search/ui/ReindexButton/types.js.map +1 -0
- package/dist/exports/client.d.ts +2 -1
- package/dist/exports/client.d.ts.map +1 -1
- package/dist/exports/client.js +2 -1
- package/dist/exports/client.js.map +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +8 -0
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +19 -3
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utilities/generateReindexHandler.d.ts +4 -0
- package/dist/utilities/generateReindexHandler.d.ts.map +1 -0
- package/dist/utilities/generateReindexHandler.js +172 -0
- package/dist/utilities/generateReindexHandler.js.map +1 -0
- package/dist/utilities/syncDocAsSearchIndex.d.ts +3 -0
- package/dist/utilities/syncDocAsSearchIndex.d.ts.map +1 -0
- package/dist/utilities/syncDocAsSearchIndex.js +173 -0
- package/dist/utilities/syncDocAsSearchIndex.js.map +1 -0
- package/package.json +6 -5
- package/dist/Search/ui/index.client.d.ts.map +0 -1
- package/dist/Search/ui/index.client.js.map +0 -1
- package/dist/Search/ui/index.d.ts.map +0 -1
- package/dist/Search/ui/index.js.map +0 -1
- /package/dist/Search/ui/{index.client.d.ts → LinkToDoc/index.client.d.ts} +0 -0
- /package/dist/Search/ui/{index.client.js → LinkToDoc/index.client.js} +0 -0
- /package/dist/Search/ui/{index.d.ts → LinkToDoc/index.d.ts} +0 -0
- /package/dist/Search/ui/{index.js → LinkToDoc/index.js} +0 -0
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { ReindexButtonClient } from './index.client.js';
|
|
3
|
+
export const ReindexButton = (props)=>{
|
|
4
|
+
const { collectionLabels, i18n, searchCollections, searchSlug } = props;
|
|
5
|
+
const getStaticLocalizedPluralLabels = ()=>{
|
|
6
|
+
return Object.fromEntries(searchCollections.map((collection)=>{
|
|
7
|
+
const labels = collectionLabels[collection];
|
|
8
|
+
const pluralLabel = labels?.plural;
|
|
9
|
+
if (typeof pluralLabel === 'function') {
|
|
10
|
+
return [
|
|
11
|
+
collection,
|
|
12
|
+
pluralLabel({
|
|
13
|
+
t: i18n.t
|
|
14
|
+
})
|
|
15
|
+
];
|
|
16
|
+
}
|
|
17
|
+
if (pluralLabel) {
|
|
18
|
+
return [
|
|
19
|
+
collection,
|
|
20
|
+
pluralLabel
|
|
21
|
+
];
|
|
22
|
+
}
|
|
23
|
+
return [
|
|
24
|
+
collection,
|
|
25
|
+
collection
|
|
26
|
+
];
|
|
27
|
+
}));
|
|
28
|
+
};
|
|
29
|
+
return /*#__PURE__*/ _jsx(ReindexButtonClient, {
|
|
30
|
+
collectionLabels: getStaticLocalizedPluralLabels(),
|
|
31
|
+
searchCollections: searchCollections,
|
|
32
|
+
searchSlug: searchSlug
|
|
33
|
+
});
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/Search/ui/ReindexButton/index.tsx"],"sourcesContent":["import type { SearchReindexButtonServerComponent } from './types.js'\n\nimport { ReindexButtonClient } from './index.client.js'\n\nexport const ReindexButton: SearchReindexButtonServerComponent = (props) => {\n const { collectionLabels, i18n, searchCollections, searchSlug } = props\n\n const getStaticLocalizedPluralLabels = () => {\n return Object.fromEntries(\n searchCollections.map((collection) => {\n const labels = collectionLabels[collection]\n const pluralLabel = labels?.plural\n\n if (typeof pluralLabel === 'function') {\n return [collection, pluralLabel({ t: i18n.t })]\n }\n\n if (pluralLabel) {\n return [collection, pluralLabel]\n }\n\n return [collection, collection]\n }),\n )\n }\n\n return (\n <ReindexButtonClient\n collectionLabels={getStaticLocalizedPluralLabels()}\n searchCollections={searchCollections}\n searchSlug={searchSlug}\n />\n )\n}\n"],"names":["ReindexButtonClient","ReindexButton","props","collectionLabels","i18n","searchCollections","searchSlug","getStaticLocalizedPluralLabels","Object","fromEntries","map","collection","labels","pluralLabel","plural","t"],"mappings":";AAEA,SAASA,mBAAmB,QAAQ,oBAAmB;AAEvD,OAAO,MAAMC,gBAAoD,CAACC;IAChE,MAAM,EAAEC,gBAAgB,EAAEC,IAAI,EAAEC,iBAAiB,EAAEC,UAAU,EAAE,GAAGJ;IAElE,MAAMK,iCAAiC;QACrC,OAAOC,OAAOC,WAAW,CACvBJ,kBAAkBK,GAAG,CAAC,CAACC;YACrB,MAAMC,SAAST,gBAAgB,CAACQ,WAAW;YAC3C,MAAME,cAAcD,QAAQE;YAE5B,IAAI,OAAOD,gBAAgB,YAAY;gBACrC,OAAO;oBAACF;oBAAYE,YAAY;wBAAEE,GAAGX,KAAKW,CAAC;oBAAC;iBAAG;YACjD;YAEA,IAAIF,aAAa;gBACf,OAAO;oBAACF;oBAAYE;iBAAY;YAClC;YAEA,OAAO;gBAACF;gBAAYA;aAAW;QACjC;IAEJ;IAEA,qBACE,KAACX;QACCG,kBAAkBI;QAClBF,mBAAmBA;QACnBC,YAAYA;;AAGlB,EAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import type { CustomComponent, PayloadServerReactComponent, StaticLabel } from 'payload';
|
|
2
|
+
import type { CollectionLabels } from '../../../types.js';
|
|
3
|
+
export type ReindexButtonProps = {
|
|
4
|
+
collectionLabels: Record<string, StaticLabel>;
|
|
5
|
+
searchCollections: string[];
|
|
6
|
+
searchSlug: string;
|
|
7
|
+
};
|
|
8
|
+
type ReindexButtonServerProps = {
|
|
9
|
+
collectionLabels: CollectionLabels;
|
|
10
|
+
} & ReindexButtonProps;
|
|
11
|
+
export type SearchReindexButtonClientComponent = ReindexButtonProps;
|
|
12
|
+
export type SearchReindexButtonServerComponent = PayloadServerReactComponent<CustomComponent<ReindexButtonServerProps>>;
|
|
13
|
+
export {};
|
|
14
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../../src/Search/ui/ReindexButton/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,2BAA2B,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AAExF,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAA;AAEzD,MAAM,MAAM,kBAAkB,GAAG;IAC/B,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAA;IAC7C,iBAAiB,EAAE,MAAM,EAAE,CAAA;IAC3B,UAAU,EAAE,MAAM,CAAA;CACnB,CAAA;AAED,KAAK,wBAAwB,GAAG;IAC9B,gBAAgB,EAAE,gBAAgB,CAAA;CACnC,GAAG,kBAAkB,CAAA;AAEtB,MAAM,MAAM,kCAAkC,GAAG,kBAAkB,CAAA;AACnE,MAAM,MAAM,kCAAkC,GAAG,2BAA2B,CAC1E,eAAe,CAAC,wBAAwB,CAAC,CAC1C,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../../../src/Search/ui/ReindexButton/types.ts"],"sourcesContent":["import type { CustomComponent, PayloadServerReactComponent, StaticLabel } from 'payload'\n\nimport type { CollectionLabels } from '../../../types.js'\n\nexport type ReindexButtonProps = {\n collectionLabels: Record<string, StaticLabel>\n searchCollections: string[]\n searchSlug: string\n}\n\ntype ReindexButtonServerProps = {\n collectionLabels: CollectionLabels\n} & ReindexButtonProps\n\nexport type SearchReindexButtonClientComponent = ReindexButtonProps\nexport type SearchReindexButtonServerComponent = PayloadServerReactComponent<\n CustomComponent<ReindexButtonServerProps>\n>\n"],"names":[],"mappings":"AAeA,WAEC"}
|
package/dist/exports/client.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/exports/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/exports/client.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,iCAAiC,CAAA;AAC3D,OAAO,EAAE,aAAa,EAAE,MAAM,qCAAqC,CAAA"}
|
package/dist/exports/client.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/exports/client.ts"],"sourcesContent":["export { LinkToDoc } from '../Search/ui/index.js'\n"],"names":["LinkToDoc"],"mappings":"AAAA,SAASA,SAAS,QAAQ,
|
|
1
|
+
{"version":3,"sources":["../../src/exports/client.ts"],"sourcesContent":["export { LinkToDoc } from '../Search/ui/LinkToDoc/index.js'\nexport { ReindexButton } from '../Search/ui/ReindexButton/index.js'\n"],"names":["LinkToDoc","ReindexButton"],"mappings":"AAAA,SAASA,SAAS,QAAQ,kCAAiC;AAC3D,SAASC,aAAa,QAAQ,sCAAqC"}
|
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,EAAwD,MAAM,EAAE,MAAM,SAAS,CAAA;AAE3F,OAAO,KAAK,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAwD,MAAM,EAAE,MAAM,SAAS,CAAA;AAE3F,OAAO,KAAK,EAAE,kBAAkB,EAAiC,MAAM,YAAY,CAAA;AASnF,eAAO,MAAM,YAAY,yBACA,kBAAkB,cAChC,MAAM,KAAG,MAmFjB,CAAA"}
|
package/dist/index.js
CHANGED
|
@@ -8,9 +8,17 @@ 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
|
+
const labels = Object.fromEntries(collections.filter(({ slug })=>incomingPluginConfig.collections?.includes(slug)).map((collection)=>[
|
|
13
|
+
collection.slug,
|
|
14
|
+
collection.labels
|
|
15
|
+
]));
|
|
11
16
|
const pluginConfig = {
|
|
12
17
|
// write any config defaults here
|
|
13
18
|
deleteDrafts: true,
|
|
19
|
+
labels,
|
|
20
|
+
locales,
|
|
21
|
+
reindexBatchSize: incomingPluginConfig?.reindexBatchSize || 50,
|
|
14
22
|
syncDrafts: false,
|
|
15
23
|
...incomingPluginConfig
|
|
16
24
|
};
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { CollectionAfterChangeHook, CollectionAfterDeleteHook, Config } from 'payload'\n\nimport type { 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]\ntype CollectionAfterDeleteHookArgs = Parameters<CollectionAfterDeleteHook>[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 pluginConfig:
|
|
1
|
+
{"version":3,"sources":["../src/index.ts"],"sourcesContent":["import type { CollectionAfterChangeHook, CollectionAfterDeleteHook, Config } from 'payload'\n\nimport type { SearchPluginConfig, SearchPluginConfigWithLocales } 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]\ntype CollectionAfterDeleteHookArgs = Parameters<CollectionAfterDeleteHook>[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 locales = config.localization\n ? config.localization.locales.map((localeConfig) =>\n typeof localeConfig === 'string' ? localeConfig : localeConfig.code,\n )\n : []\n\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: SearchPluginConfigWithLocales = {\n // write any config defaults here\n deleteDrafts: true,\n labels,\n locales,\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 afterDelete: [\n ...(existingHooks?.afterDelete || []),\n async (args: CollectionAfterDeleteHookArgs) => {\n await deleteFromSearch({\n ...args,\n pluginConfig,\n })\n },\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","locales","map","localeConfig","code","labels","Object","fromEntries","filter","slug","includes","collection","pluginConfig","deleteDrafts","reindexBatchSize","syncDrafts","collectionsWithSearchHooks","hooks","existingHooks","enabledCollections","isEnabled","indexOf","afterChange","args","afterDelete"],"mappings":"AAIA,SAASA,gBAAgB,QAAQ,qCAAoC;AACrE,SAASC,cAAc,QAAQ,mCAAkC;AACjE,SAASC,wBAAwB,QAAQ,oBAAmB;AAK5D,OAAO,MAAMC,eACX,CAACC,uBACD,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,UAAUN,OAAOK,YAAY,GAC/BL,OAAOK,YAAY,CAACC,OAAO,CAACC,GAAG,CAAC,CAACC,eAC/B,OAAOA,iBAAiB,WAAWA,eAAeA,aAAaC,IAAI,IAErE,EAAE;YAEN,MAAMC,SAASC,OAAOC,WAAW,CAC/BX,YACGY,MAAM,CAAC,CAAC,EAAEC,IAAI,EAAE,GAAKf,qBAAqBE,WAAW,EAAEc,SAASD,OAChEP,GAAG,CAAC,CAACS,aAAe;oBAACA,WAAWF,IAAI;oBAAEE,WAAWN,MAAM;iBAAC;YAG7D,MAAMO,eAA8C;gBAClD,iCAAiC;gBACjCC,cAAc;gBACdR;gBACAJ;gBACAa,kBAAkBpB,sBAAsBoB,oBAAoB;gBAC5DC,YAAY;gBACZ,GAAGrB,oBAAoB;YACzB;YAEA,2EAA2E;YAC3E,MAAMsB,6BAA6BrB,QAAQC,aACvCM,IAAI,CAACS;gBACL,MAAM,EAAEM,OAAOC,aAAa,EAAE,GAAGP;gBAEjC,MAAMQ,qBAAqBP,aAAahB,WAAW,IAAI,EAAE;gBACzD,MAAMwB,YAAYD,mBAAmBE,OAAO,CAACV,WAAWF,IAAI,IAAI,CAAC;gBACjE,IAAIW,WAAW;oBACb,OAAO;wBACL,GAAGT,UAAU;wBACbM,OAAO;4BACL,GAAGN,WAAWM,KAAK;4BACnBK,aAAa;mCACPJ,eAAeI,eAAe,EAAE;gCACpC,OAAOC;oCACL,MAAMhC,eAAe;wCACnB,GAAGgC,IAAI;wCACPZ,YAAYA,WAAWF,IAAI;wCAC3BG;oCACF;gCACF;6BACD;4BACDY,aAAa;mCACPN,eAAeM,eAAe,EAAE;gCACpC,OAAOD;oCACL,MAAMjC,iBAAiB;wCACrB,GAAGiC,IAAI;wCACPX;oCACF;gCACF;6BACD;wBACH;oBACF;gBACF;gBAEA,OAAOD;YACT,GACCH,OAAOT;YAEV,OAAO;gBACL,GAAGJ,MAAM;gBACTC,aAAa;uBACPoB,8BAA8B,EAAE;oBACpCxB,yBAAyBoB;iBAC1B;YACH;QACF;QAEA,OAAOjB;IACT,EAAC"}
|
package/dist/types.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { CollectionAfterChangeHook, CollectionAfterDeleteHook, CollectionConfig, Field, Payload, PayloadRequest } from 'payload';
|
|
1
|
+
import type { CollectionAfterChangeHook, CollectionAfterDeleteHook, CollectionConfig, Field, LabelFunction, Payload, PayloadRequest, StaticLabel } from 'payload';
|
|
2
2
|
export type DocToSync = {
|
|
3
3
|
[key: string]: any;
|
|
4
4
|
doc: {
|
|
@@ -26,15 +26,31 @@ export type SearchPluginConfig = {
|
|
|
26
26
|
};
|
|
27
27
|
deleteDrafts?: boolean;
|
|
28
28
|
localize?: boolean;
|
|
29
|
+
reindexBatchSize?: number;
|
|
29
30
|
searchOverrides?: {
|
|
30
31
|
fields?: FieldsOverride;
|
|
31
32
|
} & Partial<Omit<CollectionConfig, 'fields'>>;
|
|
32
33
|
syncDrafts?: boolean;
|
|
33
34
|
};
|
|
34
|
-
export type
|
|
35
|
+
export type CollectionLabels = {
|
|
36
|
+
[collection: string]: {
|
|
37
|
+
plural?: LabelFunction | StaticLabel;
|
|
38
|
+
singular?: LabelFunction | StaticLabel;
|
|
39
|
+
};
|
|
40
|
+
};
|
|
41
|
+
export type SearchPluginConfigWithLocales = {
|
|
42
|
+
labels?: CollectionLabels;
|
|
43
|
+
locales?: string[];
|
|
44
|
+
} & SearchPluginConfig;
|
|
45
|
+
export type SyncWithSearchArgs = {
|
|
35
46
|
collection: string;
|
|
36
47
|
pluginConfig: SearchPluginConfig;
|
|
37
|
-
} & Omit<Parameters<CollectionAfterChangeHook>[0], 'collection'
|
|
48
|
+
} & Omit<Parameters<CollectionAfterChangeHook>[0], 'collection'>;
|
|
49
|
+
export type SyncDocArgs = {
|
|
50
|
+
locale?: string;
|
|
51
|
+
onSyncError?: () => void;
|
|
52
|
+
} & Omit<SyncWithSearchArgs, 'context' | 'previousDoc'>;
|
|
53
|
+
export type SyncWithSearch = (Args: SyncWithSearchArgs) => ReturnType<CollectionAfterChangeHook>;
|
|
38
54
|
export type DeleteFromSearch = (Args: {
|
|
39
55
|
pluginConfig: SearchPluginConfig;
|
|
40
56
|
} & Omit<Parameters<CollectionAfterDeleteHook>[0], 'collection'>) => ReturnType<CollectionAfterDeleteHook>;
|
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,yBAAyB,EACzB,gBAAgB,EAChB,KAAK,EACL,OAAO,EACP,cAAc,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,yBAAyB,EACzB,yBAAyB,EACzB,gBAAgB,EAChB,KAAK,EACL,aAAa,EAEb,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;IAC/B,UAAU,CAAC,EAAE,UAAU,CAAA;IACvB,WAAW,CAAC,EAAE,MAAM,EAAE,CAAA;IACtB,iBAAiB,CAAC,EAAE;QAClB,CAAC,UAAU,EAAE,MAAM,GAAG,CAAC,CAAC,GAAG,EAAE,GAAG,KAAK,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,MAAM,CAAA;KACxE,CAAA;IACD,YAAY,CAAC,EAAE,OAAO,CAAA;IACtB,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,gBAAgB,CAAC,EAAE,MAAM,CAAA;IACzB,eAAe,CAAC,EAAE;QAAE,MAAM,CAAC,EAAE,cAAc,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,gBAAgB,EAAE,QAAQ,CAAC,CAAC,CAAA;IACzF,UAAU,CAAC,EAAE,OAAO,CAAA;CACrB,CAAA;AAED,MAAM,MAAM,gBAAgB,GAAG;IAC7B,CAAC,UAAU,EAAE,MAAM,GAAG;QACpB,MAAM,CAAC,EAAE,aAAa,GAAG,WAAW,CAAA;QACpC,QAAQ,CAAC,EAAE,aAAa,GAAG,WAAW,CAAA;KACvC,CAAA;CACF,CAAA;AAED,MAAM,MAAM,6BAA6B,GAAG;IAC1C,MAAM,CAAC,EAAE,gBAAgB,CAAA;IACzB,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;CACnB,GAAG,kBAAkB,CAAA;AAEtB,MAAM,MAAM,kBAAkB,GAAG;IAC/B,UAAU,EAAE,MAAM,CAAA;IAClB,YAAY,EAAE,kBAAkB,CAAA;CACjC,GAAG,IAAI,CAAC,UAAU,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,CAAA;AAEhE,MAAM,MAAM,WAAW,GAAG;IACxB,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,WAAW,CAAC,EAAE,MAAM,IAAI,CAAA;CACzB,GAAG,IAAI,CAAC,kBAAkB,EAAE,SAAS,GAAG,aAAa,CAAC,CAAA;AAIvD,MAAM,MAAM,cAAc,GAAG,CAAC,IAAI,EAAE,kBAAkB,KAAK,UAAU,CAAC,yBAAyB,CAAC,CAAA;AAEhG,MAAM,MAAM,gBAAgB,GAAG,CAC7B,IAAI,EAAE;IACJ,YAAY,EAAE,kBAAkB,CAAA;CACjC,GAAG,IAAI,CAAC,UAAU,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,EAAE,YAAY,CAAC,KAC7D,UAAU,CAAC,yBAAyB,CAAC,CAAA"}
|
package/dist/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type {\n CollectionAfterChangeHook,\n CollectionAfterDeleteHook,\n CollectionConfig,\n Field,\n Payload,\n PayloadRequest,\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 beforeSync?: BeforeSync\n collections?: string[]\n defaultPriorities?: {\n [collection: string]: ((doc: any) => number | Promise<number>) | number\n }\n deleteDrafts?: boolean\n localize?: boolean\n searchOverrides?: { fields?: FieldsOverride } & Partial<Omit<CollectionConfig, 'fields'>>\n syncDrafts?: boolean\n}\n\
|
|
1
|
+
{"version":3,"sources":["../src/types.ts"],"sourcesContent":["import type {\n CollectionAfterChangeHook,\n CollectionAfterDeleteHook,\n CollectionConfig,\n Field,\n LabelFunction,\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 beforeSync?: BeforeSync\n collections?: string[]\n defaultPriorities?: {\n [collection: string]: ((doc: any) => number | Promise<number>) | number\n }\n deleteDrafts?: boolean\n localize?: boolean\n reindexBatchSize?: number\n searchOverrides?: { fields?: FieldsOverride } & Partial<Omit<CollectionConfig, 'fields'>>\n syncDrafts?: boolean\n}\n\nexport type CollectionLabels = {\n [collection: string]: {\n plural?: LabelFunction | StaticLabel\n singular?: LabelFunction | StaticLabel\n }\n}\n\nexport type SearchPluginConfigWithLocales = {\n labels?: CollectionLabels\n locales?: string[]\n} & SearchPluginConfig\n\nexport type SyncWithSearchArgs = {\n collection: string\n pluginConfig: SearchPluginConfig\n} & Omit<Parameters<CollectionAfterChangeHook>[0], 'collection'>\n\nexport type SyncDocArgs = {\n locale?: string\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 = (\n Args: {\n pluginConfig: SearchPluginConfig\n } & Omit<Parameters<CollectionAfterDeleteHook>[0], 'collection'>,\n) => ReturnType<CollectionAfterDeleteHook>\n"],"names":[],"mappings":"AAuEA,WAI0C"}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { PayloadHandler } from 'payload';
|
|
2
|
+
import type { SearchPluginConfigWithLocales } from '../types.js';
|
|
3
|
+
export declare const generateReindexHandler: (pluginConfig: SearchPluginConfigWithLocales) => PayloadHandler;
|
|
4
|
+
//# sourceMappingURL=generateReindexHandler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"generateReindexHandler.d.ts","sourceRoot":"","sources":["../../src/utilities/generateReindexHandler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,SAAS,CAAA;AAK7C,OAAO,KAAK,EAAE,6BAA6B,EAAE,MAAM,aAAa,CAAA;AAShE,eAAO,MAAM,sBAAsB,iBAClB,6BAA6B,KAAG,cAiJ9C,CAAA"}
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
import { addLocalesToRequestFromData, headersWithCors } from '@payloadcms/next/utilities';
|
|
2
|
+
import { commitTransaction, getAccessResults, initTransaction, killTransaction } from 'payload';
|
|
3
|
+
import { syncDocAsSearchIndex } from './syncDocAsSearchIndex.js';
|
|
4
|
+
export const generateReindexHandler = (pluginConfig)=>async (req)=>{
|
|
5
|
+
addLocalesToRequestFromData(req);
|
|
6
|
+
const { collections = [] } = await req.json();
|
|
7
|
+
const t = req.t;
|
|
8
|
+
const searchSlug = pluginConfig?.searchOverrides?.slug || 'search';
|
|
9
|
+
const searchCollections = pluginConfig?.collections || [];
|
|
10
|
+
const reindexLocales = pluginConfig?.locales?.length ? pluginConfig.locales : [
|
|
11
|
+
req.locale
|
|
12
|
+
];
|
|
13
|
+
const validatePermissions = async ()=>{
|
|
14
|
+
const accessResults = await getAccessResults({
|
|
15
|
+
req
|
|
16
|
+
});
|
|
17
|
+
const searchAccessResults = accessResults.collections[searchSlug];
|
|
18
|
+
const permissions = [
|
|
19
|
+
searchAccessResults.delete,
|
|
20
|
+
searchAccessResults.update
|
|
21
|
+
];
|
|
22
|
+
// plugin doesn't allow create by default:
|
|
23
|
+
// if user provided, then add it to check
|
|
24
|
+
if (pluginConfig.searchOverrides?.access?.create) {
|
|
25
|
+
permissions.push(searchAccessResults.create);
|
|
26
|
+
}
|
|
27
|
+
// plugin allows reads by anyone by default:
|
|
28
|
+
// so if user provided, then add to check
|
|
29
|
+
if (pluginConfig.searchOverrides?.access?.read) {
|
|
30
|
+
permissions.push(searchAccessResults.read);
|
|
31
|
+
}
|
|
32
|
+
return permissions.every(Boolean) ? {
|
|
33
|
+
isValid: true
|
|
34
|
+
} : {
|
|
35
|
+
isValid: false,
|
|
36
|
+
message: t('error:notAllowedToPerformAction')
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
const validateCollections = ()=>{
|
|
40
|
+
const collectionsAreValid = collections.every((col)=>searchCollections.includes(col));
|
|
41
|
+
return collections.length && collectionsAreValid ? {
|
|
42
|
+
isValid: true
|
|
43
|
+
} : {
|
|
44
|
+
isValid: false,
|
|
45
|
+
message: t('error:invalidRequestArgs', {
|
|
46
|
+
args: `'collections'`
|
|
47
|
+
})
|
|
48
|
+
};
|
|
49
|
+
};
|
|
50
|
+
const headers = headersWithCors({
|
|
51
|
+
headers: new Headers(),
|
|
52
|
+
req
|
|
53
|
+
});
|
|
54
|
+
const { isValid: hasPermissions, message: permissionError } = await validatePermissions();
|
|
55
|
+
if (!hasPermissions) {
|
|
56
|
+
return Response.json({
|
|
57
|
+
message: permissionError
|
|
58
|
+
}, {
|
|
59
|
+
headers,
|
|
60
|
+
status: 401
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
const { isValid: validCollections, message: collectionError } = validateCollections();
|
|
64
|
+
if (!validCollections) {
|
|
65
|
+
return Response.json({
|
|
66
|
+
message: collectionError
|
|
67
|
+
}, {
|
|
68
|
+
headers,
|
|
69
|
+
status: 400
|
|
70
|
+
});
|
|
71
|
+
}
|
|
72
|
+
const payload = req.payload;
|
|
73
|
+
const batchSize = pluginConfig.reindexBatchSize;
|
|
74
|
+
const defaultLocalApiProps = {
|
|
75
|
+
overrideAccess: false,
|
|
76
|
+
req,
|
|
77
|
+
user: req.user
|
|
78
|
+
};
|
|
79
|
+
let aggregateErrors = 0;
|
|
80
|
+
let aggregateDocs = 0;
|
|
81
|
+
const countDocuments = async (collection)=>{
|
|
82
|
+
const { totalDocs } = await payload.count({
|
|
83
|
+
collection,
|
|
84
|
+
...defaultLocalApiProps,
|
|
85
|
+
req: undefined
|
|
86
|
+
});
|
|
87
|
+
return totalDocs;
|
|
88
|
+
};
|
|
89
|
+
const deleteIndexes = async (collection)=>{
|
|
90
|
+
await payload.delete({
|
|
91
|
+
collection: searchSlug,
|
|
92
|
+
depth: 0,
|
|
93
|
+
select: {
|
|
94
|
+
id: true
|
|
95
|
+
},
|
|
96
|
+
where: {
|
|
97
|
+
'doc.relationTo': {
|
|
98
|
+
equals: collection
|
|
99
|
+
}
|
|
100
|
+
},
|
|
101
|
+
...defaultLocalApiProps
|
|
102
|
+
});
|
|
103
|
+
};
|
|
104
|
+
const reindexCollection = async (collection)=>{
|
|
105
|
+
const totalDocs = await countDocuments(collection);
|
|
106
|
+
const totalBatches = Math.ceil(totalDocs / batchSize);
|
|
107
|
+
aggregateDocs += totalDocs;
|
|
108
|
+
for(let j = 0; j < reindexLocales.length; j++){
|
|
109
|
+
// create first index, then we update with other locales accordingly
|
|
110
|
+
const operation = j === 0 ? 'create' : 'update';
|
|
111
|
+
const localeToSync = reindexLocales[j];
|
|
112
|
+
for(let i = 0; i < totalBatches; i++){
|
|
113
|
+
const { docs } = await payload.find({
|
|
114
|
+
collection,
|
|
115
|
+
limit: batchSize,
|
|
116
|
+
locale: localeToSync,
|
|
117
|
+
page: i + 1,
|
|
118
|
+
...defaultLocalApiProps
|
|
119
|
+
});
|
|
120
|
+
const promises = docs.map((doc)=>syncDocAsSearchIndex({
|
|
121
|
+
collection,
|
|
122
|
+
doc,
|
|
123
|
+
locale: localeToSync,
|
|
124
|
+
onSyncError: ()=>operation === 'create' && aggregateErrors++,
|
|
125
|
+
operation,
|
|
126
|
+
pluginConfig,
|
|
127
|
+
req
|
|
128
|
+
}));
|
|
129
|
+
// Sequentially await promises to avoid transaction issues
|
|
130
|
+
for (const promise of promises){
|
|
131
|
+
await promise;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
await initTransaction(req);
|
|
137
|
+
for (const collection of collections){
|
|
138
|
+
try {
|
|
139
|
+
await deleteIndexes(collection);
|
|
140
|
+
await reindexCollection(collection);
|
|
141
|
+
} catch (err) {
|
|
142
|
+
const message = t('error:unableToReindexCollection', {
|
|
143
|
+
collection
|
|
144
|
+
});
|
|
145
|
+
payload.logger.error({
|
|
146
|
+
err,
|
|
147
|
+
msg: message
|
|
148
|
+
});
|
|
149
|
+
await killTransaction(req);
|
|
150
|
+
return Response.json({
|
|
151
|
+
message
|
|
152
|
+
}, {
|
|
153
|
+
headers,
|
|
154
|
+
status: 500
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
const message = t('general:successfullyReindexed', {
|
|
159
|
+
collections: collections.join(', '),
|
|
160
|
+
count: aggregateDocs - aggregateErrors,
|
|
161
|
+
total: aggregateDocs
|
|
162
|
+
});
|
|
163
|
+
await commitTransaction(req);
|
|
164
|
+
return Response.json({
|
|
165
|
+
message
|
|
166
|
+
}, {
|
|
167
|
+
headers,
|
|
168
|
+
status: 200
|
|
169
|
+
});
|
|
170
|
+
};
|
|
171
|
+
|
|
172
|
+
//# sourceMappingURL=generateReindexHandler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/utilities/generateReindexHandler.ts"],"sourcesContent":["import type { PayloadHandler } from 'payload'\n\nimport { addLocalesToRequestFromData, headersWithCors } from '@payloadcms/next/utilities'\nimport { commitTransaction, getAccessResults, initTransaction, killTransaction } from 'payload'\n\nimport type { SearchPluginConfigWithLocales } 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: SearchPluginConfigWithLocales): PayloadHandler =>\n async (req) => {\n addLocalesToRequestFromData(req)\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 ? pluginConfig.locales : [req.locale]\n\n const validatePermissions = async (): Promise<ValidationResult> => {\n const accessResults = await getAccessResults({ req })\n const searchAccessResults = accessResults.collections[searchSlug]\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 batchSize = pluginConfig.reindexBatchSize\n\n const defaultLocalApiProps = {\n overrideAccess: false,\n req,\n user: req.user,\n }\n let aggregateErrors = 0\n let aggregateDocs = 0\n\n const countDocuments = async (collection: string): Promise<number> => {\n const { totalDocs } = await payload.count({\n collection,\n ...defaultLocalApiProps,\n req: undefined,\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 totalDocs = await countDocuments(collection)\n const totalBatches = Math.ceil(totalDocs / batchSize)\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 limit: batchSize,\n locale: localeToSync,\n page: i + 1,\n ...defaultLocalApiProps,\n })\n\n const promises = docs.map((doc) =>\n syncDocAsSearchIndex({\n collection,\n doc,\n locale: localeToSync,\n onSyncError: () => operation === 'create' && aggregateErrors++,\n operation,\n pluginConfig,\n req,\n }),\n )\n\n // Sequentially await promises to avoid transaction issues\n for (const promise of promises) {\n await promise\n }\n }\n }\n }\n\n await initTransaction(req)\n\n for (const collection of collections) {\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 await killTransaction(req)\n return Response.json({ message }, { headers, status: 500 })\n }\n }\n\n const message = t('general:successfullyReindexed', {\n collections: collections.join(', '),\n count: aggregateDocs - aggregateErrors,\n total: aggregateDocs,\n })\n\n await commitTransaction(req)\n\n return Response.json({ message }, { headers, status: 200 })\n }\n"],"names":["addLocalesToRequestFromData","headersWithCors","commitTransaction","getAccessResults","initTransaction","killTransaction","syncDocAsSearchIndex","generateReindexHandler","pluginConfig","req","collections","json","t","searchSlug","searchOverrides","slug","searchCollections","reindexLocales","locales","length","locale","validatePermissions","accessResults","searchAccessResults","permissions","delete","update","access","create","push","read","every","Boolean","isValid","message","validateCollections","collectionsAreValid","col","includes","args","headers","Headers","hasPermissions","permissionError","Response","status","validCollections","collectionError","payload","batchSize","reindexBatchSize","defaultLocalApiProps","overrideAccess","user","aggregateErrors","aggregateDocs","countDocuments","collection","totalDocs","count","undefined","deleteIndexes","depth","select","id","where","equals","reindexCollection","totalBatches","Math","ceil","j","operation","localeToSync","i","docs","find","limit","page","promises","map","doc","onSyncError","promise","err","logger","error","msg","join","total"],"mappings":"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"}
|
|
@@ -0,0 +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,iBA+Kb,CAAA"}
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
export const syncDocAsSearchIndex = async ({ collection, doc, locale, onSyncError, operation, pluginConfig, req: { payload }, req })=>{
|
|
2
|
+
const { id, _status: status, title } = doc || {};
|
|
3
|
+
const { beforeSync, defaultPriorities, deleteDrafts, searchOverrides, syncDrafts } = pluginConfig;
|
|
4
|
+
const searchSlug = searchOverrides?.slug || 'search';
|
|
5
|
+
const syncLocale = locale || req.locale;
|
|
6
|
+
let dataToSave = {
|
|
7
|
+
doc: {
|
|
8
|
+
relationTo: collection,
|
|
9
|
+
value: id
|
|
10
|
+
},
|
|
11
|
+
title
|
|
12
|
+
};
|
|
13
|
+
if (typeof beforeSync === 'function') {
|
|
14
|
+
let docToSyncWith = doc;
|
|
15
|
+
if (payload.config?.localization) {
|
|
16
|
+
docToSyncWith = await payload.findByID({
|
|
17
|
+
id,
|
|
18
|
+
collection,
|
|
19
|
+
locale: syncLocale,
|
|
20
|
+
req
|
|
21
|
+
});
|
|
22
|
+
}
|
|
23
|
+
dataToSave = await beforeSync({
|
|
24
|
+
originalDoc: docToSyncWith,
|
|
25
|
+
payload,
|
|
26
|
+
req,
|
|
27
|
+
searchDoc: dataToSave
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
let defaultPriority = 0;
|
|
31
|
+
if (defaultPriorities) {
|
|
32
|
+
const { [collection]: priority } = defaultPriorities;
|
|
33
|
+
if (typeof priority === 'function') {
|
|
34
|
+
try {
|
|
35
|
+
defaultPriority = await priority(doc);
|
|
36
|
+
} catch (err) {
|
|
37
|
+
payload.logger.error(err);
|
|
38
|
+
payload.logger.error(`Error gathering default priority for ${searchSlug} documents related to ${collection}`);
|
|
39
|
+
}
|
|
40
|
+
} else {
|
|
41
|
+
defaultPriority = priority;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const doSync = syncDrafts || !syncDrafts && status !== 'draft';
|
|
45
|
+
try {
|
|
46
|
+
if (operation === 'create') {
|
|
47
|
+
if (doSync) {
|
|
48
|
+
await payload.create({
|
|
49
|
+
collection: searchSlug,
|
|
50
|
+
data: {
|
|
51
|
+
...dataToSave,
|
|
52
|
+
priority: defaultPriority
|
|
53
|
+
},
|
|
54
|
+
locale: syncLocale,
|
|
55
|
+
req
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
if (operation === 'update') {
|
|
60
|
+
try {
|
|
61
|
+
// find the correct doc to sync with
|
|
62
|
+
const searchDocQuery = await payload.find({
|
|
63
|
+
collection: searchSlug,
|
|
64
|
+
depth: 0,
|
|
65
|
+
locale: syncLocale,
|
|
66
|
+
req,
|
|
67
|
+
where: {
|
|
68
|
+
'doc.relationTo': {
|
|
69
|
+
equals: collection
|
|
70
|
+
},
|
|
71
|
+
'doc.value': {
|
|
72
|
+
equals: id
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
const docs = searchDocQuery?.docs || [];
|
|
77
|
+
const [foundDoc, ...duplicativeDocs] = docs;
|
|
78
|
+
// delete all duplicative search docs (docs that reference the same page)
|
|
79
|
+
// to ensure the same, out-of-date result does not appear twice (where only syncing the first found doc)
|
|
80
|
+
if (duplicativeDocs.length > 0) {
|
|
81
|
+
try {
|
|
82
|
+
const duplicativeDocIDs = duplicativeDocs.map(({ id })=>id);
|
|
83
|
+
await payload.delete({
|
|
84
|
+
collection: searchSlug,
|
|
85
|
+
req,
|
|
86
|
+
where: {
|
|
87
|
+
id: {
|
|
88
|
+
in: duplicativeDocIDs
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
});
|
|
92
|
+
} catch (err) {
|
|
93
|
+
payload.logger.error({
|
|
94
|
+
err,
|
|
95
|
+
msg: `Error deleting duplicative ${searchSlug} documents.`
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
if (foundDoc) {
|
|
100
|
+
const { id: searchDocID } = foundDoc;
|
|
101
|
+
if (doSync) {
|
|
102
|
+
// update the doc normally
|
|
103
|
+
try {
|
|
104
|
+
await payload.update({
|
|
105
|
+
id: searchDocID,
|
|
106
|
+
collection: searchSlug,
|
|
107
|
+
data: {
|
|
108
|
+
...dataToSave,
|
|
109
|
+
priority: foundDoc.priority || defaultPriority
|
|
110
|
+
},
|
|
111
|
+
locale: syncLocale,
|
|
112
|
+
req
|
|
113
|
+
});
|
|
114
|
+
} catch (err) {
|
|
115
|
+
payload.logger.error({
|
|
116
|
+
err,
|
|
117
|
+
msg: `Error updating ${searchSlug} document.`
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
if (deleteDrafts && status === 'draft') {
|
|
122
|
+
// do not include draft docs in search results, so delete the record
|
|
123
|
+
try {
|
|
124
|
+
await payload.delete({
|
|
125
|
+
id: searchDocID,
|
|
126
|
+
collection: searchSlug,
|
|
127
|
+
req
|
|
128
|
+
});
|
|
129
|
+
} catch (err) {
|
|
130
|
+
payload.logger.error({
|
|
131
|
+
err,
|
|
132
|
+
msg: `Error deleting ${searchSlug} document.`
|
|
133
|
+
});
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
} else if (doSync) {
|
|
137
|
+
try {
|
|
138
|
+
await payload.create({
|
|
139
|
+
collection: searchSlug,
|
|
140
|
+
data: {
|
|
141
|
+
...dataToSave,
|
|
142
|
+
priority: defaultPriority
|
|
143
|
+
},
|
|
144
|
+
locale: syncLocale,
|
|
145
|
+
req
|
|
146
|
+
});
|
|
147
|
+
} catch (err) {
|
|
148
|
+
payload.logger.error({
|
|
149
|
+
err,
|
|
150
|
+
msg: `Error creating ${searchSlug} document.`
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
} catch (err) {
|
|
155
|
+
payload.logger.error({
|
|
156
|
+
err,
|
|
157
|
+
msg: `Error finding ${searchSlug} document.`
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
} catch (err) {
|
|
162
|
+
payload.logger.error({
|
|
163
|
+
err,
|
|
164
|
+
msg: `Error syncing ${searchSlug} document related to ${collection} with id: '${id}'.`
|
|
165
|
+
});
|
|
166
|
+
if (onSyncError) {
|
|
167
|
+
onSyncError();
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
return doc;
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
//# sourceMappingURL=syncDocAsSearchIndex.js.map
|
|
@@ -0,0 +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\n if (typeof beforeSync === 'function') {\n let docToSyncWith = doc\n if (payload.config?.localization) {\n docToSyncWith = await payload.findByID({\n id,\n collection,\n locale: syncLocale,\n req,\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 {\n defaultPriority = priority\n }\n }\n\n const doSync = syncDrafts || (!syncDrafts && status !== 'draft')\n\n try {\n if (operation === 'create') {\n if (doSync) {\n await payload.create({\n collection: searchSlug,\n data: {\n ...dataToSave,\n priority: defaultPriority,\n },\n locale: syncLocale,\n req,\n })\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 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 locale: syncLocale,\n req,\n })\n } catch (err: unknown) {\n payload.logger.error({ err, msg: `Error updating ${searchSlug} document.` })\n }\n }\n if (deleteDrafts && status === 'draft') {\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 req,\n })\n } catch (err: unknown) {\n payload.logger.error({ err, msg: `Error deleting ${searchSlug} document.` })\n }\n }\n } else if (doSync) {\n try {\n await payload.create({\n collection: searchSlug,\n data: {\n ...dataToSave,\n priority: defaultPriority,\n },\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","docToSyncWith","config","localization","findByID","originalDoc","searchDoc","defaultPriority","priority","err","logger","error","doSync","create","data","searchDocQuery","find","depth","where","equals","docs","foundDoc","duplicativeDocs","length","duplicativeDocIDs","map","delete","in","msg","searchDocID","update"],"mappings":"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"}
|