@payloadcms/plugin-search 4.0.0-canary.1 → 4.0.0-canary.3

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.
@@ -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,GAChC,cAAc,2BAA2B,KAAG,cAwN5C,CAAA"}
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,GAChC,cAAc,2BAA2B,KAAG,cAyN5C,CAAA"}
@@ -78,6 +78,7 @@ export const generateReindexHandler = (pluginConfig)=>async (req)=>{
78
78
  }
79
79
  const payload = req.payload;
80
80
  const { reindexBatchSize: batchSize, syncDrafts } = pluginConfig;
81
+ const defaultLocale = payload.config.localization ? payload.config.localization.defaultLocale : req.locale;
81
82
  const defaultLocalApiProps = {
82
83
  overrideAccess: false,
83
84
  req,
@@ -92,6 +93,7 @@ export const generateReindexHandler = (pluginConfig)=>async (req)=>{
92
93
  const { totalDocs } = await payload.count({
93
94
  collection,
94
95
  ...defaultLocalApiProps,
96
+ locale: defaultLocale,
95
97
  req: undefined,
96
98
  where: drafts ? undefined : whereStatusPublished
97
99
  });
@@ -120,7 +122,6 @@ export const generateReindexHandler = (pluginConfig)=>async (req)=>{
120
122
  let localErrors = 0;
121
123
  // Loop through batches, then documents, then locales per document
122
124
  for(let i = 0; i < totalBatches; i++){
123
- const defaultLocale = req.payload.config.localization ? req.payload.config.localization.defaultLocale : req.locale;
124
125
  const { docs } = await payload.find({
125
126
  collection,
126
127
  depth: 0,
@@ -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\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 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(\n collection: string,\n ): Promise<{ docs: number; docsWithDrafts: number; errors: number }> {\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 let localErrors = 0\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' && localErrors++,\n operation,\n pluginConfig,\n req,\n })\n }\n }\n }\n\n return { docs: totalDocs, docsWithDrafts: totalDocsWithDrafts, errors: localErrors }\n }\n\n const shouldCommit = await initTransaction(req)\n\n // Collections are processed sequentially to avoid race conditions within the shared transaction.\n // Concurrent writes to the search collection interleave on the same DB connection and can cause\n // locale data to be missing non-deterministically.\n const results: Array<{ docs: number; docsWithDrafts: number; errors: number }> = []\n try {\n for (const collection of collections) {\n try {\n await deleteIndexes(collection)\n results.push(await reindexCollection(collection))\n } catch (err) {\n const message = t('error:unableToReindexCollection', { collection })\n payload.logger.error({ err, msg: message })\n results.push({ docs: 0, docsWithDrafts: 0, errors: 0 })\n }\n }\n } catch (err: unknown) {\n if (shouldCommit) {\n await killTransaction(req)\n }\n return Response.json(\n { message: err instanceof Error ? err.message : String(err) },\n { headers, status: 500 },\n )\n }\n\n const aggregateDocsWithDrafts = results.reduce((sum, r) => sum + r.docsWithDrafts, 0)\n const aggregateDocs = results.reduce((sum, r) => sum + r.docs, 0)\n const aggregateErrors = results.reduce((sum, r) => sum + r.errors, 0)\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","countDocuments","collection","drafts","totalDocs","count","undefined","where","deleteIndexes","depth","select","id","reindexCollection","draftsEnabled","config","versions","totalDocsWithDrafts","totalBatches","Math","ceil","localErrors","i","defaultLocale","localization","locale","docs","find","limit","page","doc","allLocales","localeCodes","firstAllowedLocale","localeToSync","shouldSkip","skipSync","collectionSlug","err","logger","error","msg","operation","data","onSyncError","docsWithDrafts","errors","shouldCommit","results","Error","String","aggregateDocsWithDrafts","reduce","sum","r","aggregateDocs","aggregateErrors","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 defaultLocale = payload.config.localization\n ? payload.config.localization.defaultLocale\n : req.locale\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 async function countDocuments(collection: string, drafts?: boolean): Promise<number> {\n const { totalDocs } = await payload.count({\n collection,\n ...defaultLocalApiProps,\n locale: defaultLocale,\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(\n collection: string,\n ): Promise<{ docs: number; docsWithDrafts: number; errors: number }> {\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 let localErrors = 0\n\n // Loop through batches, then documents, then locales per document\n for (let i = 0; i < totalBatches; i++) {\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' && localErrors++,\n operation,\n pluginConfig,\n req,\n })\n }\n }\n }\n\n return { docs: totalDocs, docsWithDrafts: totalDocsWithDrafts, errors: localErrors }\n }\n\n const shouldCommit = await initTransaction(req)\n\n // Collections are processed sequentially to avoid race conditions within the shared transaction.\n // Concurrent writes to the search collection interleave on the same DB connection and can cause\n // locale data to be missing non-deterministically.\n const results: Array<{ docs: number; docsWithDrafts: number; errors: number }> = []\n try {\n for (const collection of collections) {\n try {\n await deleteIndexes(collection)\n results.push(await reindexCollection(collection))\n } catch (err) {\n const message = t('error:unableToReindexCollection', { collection })\n payload.logger.error({ err, msg: message })\n results.push({ docs: 0, docsWithDrafts: 0, errors: 0 })\n }\n }\n } catch (err: unknown) {\n if (shouldCommit) {\n await killTransaction(req)\n }\n return Response.json(\n { message: err instanceof Error ? err.message : String(err) },\n { headers, status: 500 },\n )\n }\n\n const aggregateDocsWithDrafts = results.reduce((sum, r) => sum + r.docsWithDrafts, 0)\n const aggregateDocs = results.reduce((sum, r) => sum + r.docs, 0)\n const aggregateErrors = results.reduce((sum, r) => sum + r.errors, 0)\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","defaultLocale","config","localization","locale","defaultLocalApiProps","overrideAccess","user","whereStatusPublished","_status","equals","countDocuments","collection","drafts","totalDocs","count","undefined","where","deleteIndexes","depth","select","id","reindexCollection","draftsEnabled","versions","totalDocsWithDrafts","totalBatches","Math","ceil","localErrors","i","docs","find","limit","page","doc","allLocales","localeCodes","firstAllowedLocale","localeToSync","shouldSkip","skipSync","collectionSlug","err","logger","error","msg","operation","data","onSyncError","docsWithDrafts","errors","shouldCommit","results","Error","String","aggregateDocsWithDrafts","reduce","sum","r","aggregateDocs","aggregateErrors","join","skips","total"],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@payloadcms/plugin-search",
3
- "version": "4.0.0-canary.1",
3
+ "version": "4.0.0-canary.3",
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": "4.0.0-canary.1",
54
- "@payloadcms/ui": "4.0.0-canary.1"
53
+ "@payloadcms/ui": "4.0.0-canary.3",
54
+ "@payloadcms/next": "4.0.0-canary.3"
55
55
  },
56
56
  "devDependencies": {
57
57
  "@types/react": "19.2.14",
58
58
  "@types/react-dom": "19.2.3",
59
- "@payloadcms/eslint-config": "3.28.0",
60
- "payload": "4.0.0-canary.1"
59
+ "payload": "4.0.0-canary.3",
60
+ "@payloadcms/eslint-config": "3.28.0"
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": "4.0.0-canary.1"
65
+ "payload": "4.0.0-canary.3"
66
66
  },
67
67
  "publishConfig": {
68
68
  "registry": "https://registry.npmjs.org/"