@vicacha-devs/strapi-plugin-global-search 0.0.0-stage → 2.0.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.
- package/LICENSE +21 -0
- package/README.md +136 -2
- package/dist/admin/index.d.ts +2 -0
- package/dist/admin/index.js +2310 -0
- package/dist/admin/index.js.map +7 -0
- package/dist/admin/index.mjs +2310 -0
- package/dist/admin/index.mjs.map +7 -0
- package/dist/admin/translations/ar.json +89 -0
- package/dist/admin/translations/en.json +89 -0
- package/dist/admin/translations/es.json +89 -0
- package/dist/admin/translations/fr.json +89 -0
- package/dist/admin/translations/tr.json +89 -0
- package/dist/server/bootstrap.d.ts +6 -0
- package/dist/server/bootstrap.d.ts.map +1 -0
- package/dist/server/config/index.d.ts +15 -0
- package/dist/server/config/index.d.ts.map +1 -0
- package/dist/server/controllers/index.d.ts +94 -0
- package/dist/server/controllers/index.d.ts.map +1 -0
- package/dist/server/controllers/schema.d.ts +24 -0
- package/dist/server/controllers/schema.d.ts.map +1 -0
- package/dist/server/controllers/search.d.ts +21 -0
- package/dist/server/controllers/search.d.ts.map +1 -0
- package/dist/server/controllers/settings.d.ts +23 -0
- package/dist/server/controllers/settings.d.ts.map +1 -0
- package/dist/server/index.d.ts +212 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +1186 -0
- package/dist/server/index.js.map +7 -0
- package/dist/server/index.mjs +1186 -0
- package/dist/server/index.mjs.map +7 -0
- package/dist/server/register.d.ts +6 -0
- package/dist/server/register.d.ts.map +1 -0
- package/dist/server/routes/index.d.ts +20 -0
- package/dist/server/routes/index.d.ts.map +1 -0
- package/dist/server/services/index.d.ts +89 -0
- package/dist/server/services/index.d.ts.map +1 -0
- package/dist/server/services/permissions.d.ts +13 -0
- package/dist/server/services/permissions.d.ts.map +1 -0
- package/dist/server/services/query.d.ts +25 -0
- package/dist/server/services/query.d.ts.map +1 -0
- package/dist/server/services/ranking.d.ts +27 -0
- package/dist/server/services/ranking.d.ts.map +1 -0
- package/dist/server/services/schema.d.ts +70 -0
- package/dist/server/services/schema.d.ts.map +1 -0
- package/dist/server/services/search.d.ts +36 -0
- package/dist/server/services/search.d.ts.map +1 -0
- package/dist/server/services/settings.d.ts +15 -0
- package/dist/server/services/settings.d.ts.map +1 -0
- package/dist/server/types.d.ts +195 -0
- package/dist/server/types.d.ts.map +1 -0
- package/dist/server/utils/async.d.ts +8 -0
- package/dist/server/utils/async.d.ts.map +1 -0
- package/dist/server/utils/constants.d.ts +42 -0
- package/dist/server/utils/constants.d.ts.map +1 -0
- package/dist/server/utils/text.d.ts +20 -0
- package/dist/server/utils/text.d.ts.map +1 -0
- package/package.json +79 -3
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../server/utils/constants.ts", "../../server/bootstrap.ts", "../../server/config/index.ts", "../../server/controllers/schema.ts", "../../server/controllers/search.ts", "../../server/controllers/settings.ts", "../../server/controllers/index.ts", "../../server/register.ts", "../../server/routes/index.ts", "../../server/services/permissions.ts", "../../server/services/query.ts", "../../server/utils/text.ts", "../../server/services/ranking.ts", "../../server/services/schema.ts", "../../server/utils/async.ts", "../../server/services/search.ts", "../../server/services/settings.ts", "../../server/services/index.ts", "../../server/index.ts"],
|
|
4
|
+
"sourcesContent": ["export const PLUGIN_ID = \"global-search\";\n\n/**\n * Attribute types whose stored value is a plain string, i.e. the ones the query\n * engine can match with `$containsi`.\n */\nexport const SEARCHABLE_SCALAR_TYPES = [\n \"string\",\n \"text\",\n \"richtext\",\n \"customField\",\n \"uid\",\n \"email\",\n \"enumeration\",\n];\n\n/**\n * Internal Strapi system/infrastructure plugin UID prefixes that should not be\n * indexed as user-facing Content-Manager content types by default.\n */\nexport const SYSTEM_PLUGIN_PREFIXES = [\n \"plugin::upload.\",\n \"plugin::i18n.\",\n \"plugin::users-permissions.\",\n \"plugin::content-releases.\",\n \"plugin::review-workflows.\",\n \"plugin::navigation.\",\n \"plugin::config-sync.\",\n \"plugin::email-designer-5.\",\n \"plugin::publisher.\",\n \"plugin::seo.\",\n \"plugin::tiptap-editor.\",\n \"plugin::global-search.\",\n];\n\n/**\n * Attribute types we deliberately never walk into.\n * - dynamiczone / blocks: the query engine cannot filter polymorphic JSON.\n * - relation / media: would explode the join graph; relations are shown, not searched.\n */\nexport const SKIPPED_ATTRIBUTE_TYPES = [\n \"dynamiczone\",\n \"blocks\",\n \"json\",\n \"relation\",\n \"media\",\n \"password\",\n];\n\n/** Attribute names that must never leave the server, whatever their type. */\nexport const BLOCKLISTED_ATTRIBUTE_NAMES = [\n \"password\",\n \"resetPasswordToken\",\n \"registrationToken\",\n \"confirmationToken\",\n];\n\n/**\n * String attributes that identify an entry. `id` is numeric and handled\n * separately. `documentId` is always queried in Strapi 5 even when it is not\n * declared on the schema.\n */\nexport const IDENTIFIER_FIELDS = [\n \"uid\",\n \"slug\",\n \"code\",\n \"key\",\n \"referenceCode\",\n \"bookingCode\",\n \"certificateNumber\",\n \"transactionReference\",\n];\n\n/** Used when the Content-Manager configuration has no mainField for a type. */\nexport const MAIN_FIELD_FALLBACKS = [\n \"name\",\n \"title\",\n \"label\",\n \"displayName\",\n \"heading\",\n \"heroTitle\",\n \"question\",\n \"term\",\n \"subject\",\n \"fullName\",\n \"applicantName\",\n \"customerName\",\n \"donorName\",\n \"referenceCode\",\n \"bookingCode\",\n \"certificateNumber\",\n \"slug\",\n];\n\n/** Ranking tiers \u2014 lower wins. Mirrors the documented ordering rule. */\nexport const TIER = {\n ID_EXACT: 0,\n ID_CONTAINS: 1,\n MAIN_EXACT: 2,\n MAIN_STARTS_WITH: 3,\n MAIN_CONTAINS: 4,\n FIELD_CONTAINS: 5,\n NESTED_CONTAINS: 6,\n UNKNOWN: 7,\n};\n\nexport const TIER_LABELS: Record<number, string> = {\n 0: \"id:exact\",\n 1: \"id:partial\",\n 2: \"name:exact\",\n 3: \"name:starts-with\",\n 4: \"name:partial\",\n 5: \"field\",\n 6: \"nested-field\",\n 7: \"other\",\n};\n\nexport const MAX_QUERY_LENGTH = 200;\nexport const SNIPPET_RADIUS = 45;\n", "import type { ContentTypeDescriptor, StrapiLike } from \"./types\";\nimport { PLUGIN_ID } from \"./utils/constants\";\n\nexport default async ({ strapi }: { strapi: StrapiLike }) => {\n // Warm the schema cache so the first keystroke does not pay for introspection,\n // and surface a misconfigured install in the boot logs rather than at search time.\n try {\n const types = (await strapi\n .plugin(PLUGIN_ID)\n .service(\"schema\")\n .getSearchableContentTypes()) as ContentTypeDescriptor[];\n\n const uidList = types.map((type) => type.uid).join(\", \");\n strapi.log.debug(\n `[${PLUGIN_ID}] indexed ${types.length} content type(s): ${uidList}`\n );\n } catch (error) {\n const msg = (error as Error).message;\n strapi.log.error(\n `[${PLUGIN_ID}] failed to introspect content types: ${msg}`\n );\n }\n};\n", "import type { PluginSettings } from \"../types\";\n\n/**\n * Every value here has a working default: the plugin must run on a fresh app\n * with no `config/plugins.js` entry at all.\n */\nexport const defaults: PluginSettings = {\n /** Minimum number of characters before a search is executed. */\n minChars: 2,\n /** Client-side debounce, in ms. Served to the admin so both UIs stay in sync. */\n debounce: 250,\n /** Maximum rows fetched per content type, per search. */\n perTypeLimit: 20,\n /** Hard cap on the merged, ranked result set. */\n maxResults: 100,\n /** Search inside nested component fields. */\n deep: true,\n /** How many component levels to walk when collecting searchable paths. */\n maxDepth: 3,\n /** Include unpublished entries (draft & publish types). */\n includeDrafts: true,\n /** Include Content-Manager-visible content types registered by plugins (plugin::*). */\n includePluginContentTypes: true,\n /** Per-content-type query timeout, in ms. */\n queryTimeout: 4000,\n /** Maximum number of content types queried in parallel. */\n concurrency: 8,\n /** Content type UIDs never searched. */\n excludedContentTypes: [],\n /** Field paths never searched, as `uid:path` (e.g. `api::article.article:body`). */\n excludedFields: [],\n /** Up to two extra fields shown next to the main field, keyed by content type UID. */\n displayFields: {},\n};\n\nexport const isPlainObject = (\n value: unknown\n): value is Record<string, unknown> =>\n typeof value === \"object\" && value !== null && !Array.isArray(value);\n\nconst isStringArray = (value: unknown): value is string[] =>\n Array.isArray(value) && value.every((item) => typeof item === \"string\");\n\nexport const validator = (config: Partial<PluginSettings> = {}) => {\n if (!isPlainObject(config)) {\n throw new Error(\"[global-search] config must be a plain object\");\n }\n\n const numbers: Record<string, [number, number]> = {\n minChars: [1, 10],\n debounce: [0, 5000],\n perTypeLimit: [1, 200],\n maxResults: [1, 1000],\n maxDepth: [1, 6],\n queryTimeout: [500, 60000],\n concurrency: [1, 32],\n };\n\n Object.entries(numbers).forEach(([key, [min, max]]) => {\n if ((config as Record<string, unknown>)[key] === undefined) return;\n const value = (config as Record<string, unknown>)[key];\n if (\n typeof value !== \"number\" ||\n !Number.isInteger(value) ||\n value < min ||\n value > max\n ) {\n throw new Error(\n `[global-search] config.${key} must be an integer ` +\n `between ${min} and ${max}`\n );\n }\n });\n\n ([\"deep\", \"includeDrafts\", \"includePluginContentTypes\"] as const).forEach(\n (key) => {\n if (config[key] !== undefined && typeof config[key] !== \"boolean\") {\n throw new Error(`[global-search] config.${key} must be a boolean`);\n }\n }\n );\n\n ([\"excludedContentTypes\", \"excludedFields\"] as const).forEach((key) => {\n if (config[key] !== undefined && !isStringArray(config[key])) {\n throw new Error(\n `[global-search] config.${key} must be an array of strings`\n );\n }\n });\n\n if (config.displayFields !== undefined) {\n const validMap =\n isPlainObject(config.displayFields) &&\n Object.values(config.displayFields).every(isStringArray);\n if (!validMap) {\n throw new Error(\n \"[global-search] config.displayFields must map content type UIDs \" +\n \"to string arrays\"\n );\n }\n }\n};\n\nconst config = {\n default: defaults,\n validator,\n defaults,\n};\n\nexport default config;\n", "import type { ContentTypeDescriptor, StrapiLike } from \"../types\";\nimport { PLUGIN_ID } from \"../utils/constants\";\n\ntype Ctx = {\n request: { query: Record<string, unknown>; body?: Record<string, unknown> };\n state: {\n userAbility?: { can: (action: string, subject: string) => boolean } | null;\n };\n body?: unknown;\n throw: (code: number, msg: string) => void;\n};\n\nconst collectAllFields = (type: ContentTypeDescriptor): string[] => {\n const main =\n type.mainField &&\n type.mainField !== \"id\" &&\n type.mainFieldSearchable !== false\n ? [type.mainField]\n : [];\n return Array.from(\n new Set([\n ...type.idFields,\n ...main,\n ...type.topLevelFields,\n ...type.nestedFields,\n ])\n );\n};\n\n/** Field paths are internal detail; the admin only needs counts and labels. */\nconst toSummary = (type: ContentTypeDescriptor) => ({\n uid: type.uid,\n kind: type.kind,\n displayName: type.displayName,\n mainField: type.mainField,\n localized: type.localized,\n draftAndPublish: type.draftAndPublish,\n fieldCount: collectAllFields(type).length,\n searchable: type.searchable,\n});\n\nexport default ({ strapi }: { strapi: StrapiLike }) => ({\n /** Powers the content-type filter chips on the search page. */\n async find(ctx: Ctx) {\n const types = await strapi\n .plugin(PLUGIN_ID)\n .service(\"schema\")\n .getSearchableContentTypes();\n const readable = strapi\n .plugin(PLUGIN_ID)\n .service(\"permissions\")\n .filterReadableTypes(types, ctx.state.userAbility);\n\n const settings = await strapi.plugin(PLUGIN_ID).service(\"settings\").get();\n\n ctx.body = {\n contentTypes: readable.map(toSummary),\n settings: { minChars: settings.minChars, debounce: settings.debounce },\n };\n },\n\n /** Full picture, including excluded and unsearchable types, for Settings. */\n async findAll(ctx: Ctx) {\n const types = await strapi\n .plugin(PLUGIN_ID)\n .service(\"schema\")\n .getAllContentTypes();\n const settings = await strapi.plugin(PLUGIN_ID).service(\"settings\").get();\n\n ctx.body = {\n contentTypes: types.map((type: ContentTypeDescriptor) => ({\n ...toSummary(type),\n excluded: (settings.excludedContentTypes || []).includes(type.uid),\n fields: collectAllFields(type),\n })),\n };\n },\n});\n", "import type { StrapiLike } from \"../types\";\nimport { PLUGIN_ID } from \"../utils/constants\";\n\ntype Ctx = {\n request: { query: Record<string, unknown>; body?: Record<string, unknown> };\n state: {\n userAbility?: { can: (action: string, subject: string) => boolean } | null;\n };\n body?: unknown;\n throw: (code: number, msg: string) => void;\n};\n\n/** `?types[]=a&types[]=b`, `?types[0]=a`, and `?types=a,b` are all accepted. */\nconst toArray = (value: unknown): string[] => {\n if (!value) return [];\n if (Array.isArray(value)) {\n return value\n .flatMap((item) => String(item).split(\",\"))\n .map((item) => item.trim())\n .filter(Boolean);\n }\n if (typeof value === \"object\") {\n return Object.values(value as Record<string, unknown>)\n .flatMap((item) => String(item).split(\",\"))\n .map((item) => item.trim())\n .filter(Boolean);\n }\n\n return String(value)\n .split(\",\")\n .map((item) => item.trim())\n .filter(Boolean);\n};\n\nexport default ({ strapi }: { strapi: StrapiLike }) => ({\n async find(ctx: Ctx) {\n const { q, locale, page, pageSize } = ctx.request.query;\n const rawTypes = ctx.request.query.types ?? ctx.request.query[\"types[]\"];\n\n try {\n ctx.body = await strapi\n .plugin(PLUGIN_ID)\n .service(\"search\")\n .search({\n query: typeof q === \"string\" ? q : undefined,\n types: toArray(rawTypes),\n locale: typeof locale === \"string\" ? locale : undefined,\n page: page !== undefined ? Number(page) : undefined,\n pageSize: pageSize !== undefined ? Number(pageSize) : undefined,\n userAbility: ctx.state.userAbility,\n });\n } catch (error) {\n const detail = (error as Error).stack || (error as Error).message;\n strapi.log.error(`[${PLUGIN_ID}] search request failed: ${detail}`);\n ctx.throw(\n 500,\n \"Global search failed. Check the server logs for details.\"\n );\n }\n },\n});\n", "import type { PluginSettings, StrapiLike } from \"../types\";\nimport { PLUGIN_ID } from \"../utils/constants\";\n\ntype Ctx = {\n request: { query: Record<string, unknown>; body?: Partial<PluginSettings> };\n state: {\n userAbility?: { can: (action: string, subject: string) => boolean } | null;\n };\n body?: unknown;\n throw: (code: number, msg: string) => void;\n};\n\nexport default ({ strapi }: { strapi: StrapiLike }) => ({\n async find(ctx: Ctx) {\n ctx.body = await strapi.plugin(PLUGIN_ID).service(\"settings\").get();\n },\n\n async update(ctx: Ctx) {\n try {\n ctx.body = await strapi\n .plugin(PLUGIN_ID)\n .service(\"settings\")\n .set(ctx.request.body || {});\n } catch (error) {\n ctx.throw(400, (error as Error).message);\n }\n },\n\n async reset(ctx: Ctx) {\n ctx.body = await strapi.plugin(PLUGIN_ID).service(\"settings\").reset();\n },\n});\n", "import schema from \"./schema\";\nimport search from \"./search\";\nimport settings from \"./settings\";\n\nexport default {\n search,\n schema,\n settings,\n};\n", "import type { StrapiLike } from \"./types\";\nimport { PLUGIN_ID } from \"./utils/constants\";\n\nconst RBAC_ACTIONS = [\n {\n section: \"plugins\",\n displayName: \"Search content\",\n uid: \"read\",\n pluginName: PLUGIN_ID,\n },\n {\n section: \"settings\",\n category: \"global search\",\n subCategory: \"general\",\n displayName: \"Configure global search\",\n uid: \"settings\",\n pluginName: PLUGIN_ID,\n },\n];\n\nexport default ({ strapi }: { strapi: StrapiLike }) => {\n strapi.admin?.services?.permission?.actionProvider?.registerMany(\n RBAC_ACTIONS\n );\n};\n", "import { PLUGIN_ID } from \"../utils/constants\";\n\nconst withPermission = (action: string) => ({\n policies: [\n {\n name: \"admin::hasPermissions\",\n config: { actions: [`plugin::${PLUGIN_ID}.${action}`] },\n },\n ],\n});\n\nexport default {\n admin: {\n type: \"admin\",\n routes: [\n {\n method: \"GET\",\n path: \"/search\",\n handler: \"search.find\",\n config: withPermission(\"read\"),\n },\n {\n method: \"GET\",\n path: \"/schema\",\n handler: \"schema.find\",\n config: withPermission(\"read\"),\n },\n {\n method: \"GET\",\n path: \"/schema/all\",\n handler: \"schema.findAll\",\n config: withPermission(\"settings\"),\n },\n {\n method: \"GET\",\n path: \"/settings\",\n handler: \"settings.find\",\n config: withPermission(\"settings\"),\n },\n {\n method: \"PUT\",\n path: \"/settings\",\n handler: \"settings.update\",\n config: withPermission(\"settings\"),\n },\n {\n method: \"POST\",\n path: \"/settings/reset\",\n handler: \"settings.reset\",\n config: withPermission(\"settings\"),\n },\n ],\n },\n};\n", "import type { ContentTypeDescriptor } from \"../types\";\n\nconst CM_READ_ACTION = \"plugin::content-manager.explorer.read\";\n\nexport default () => ({\n /**\n * An editor restricted to Articles must not discover Orders through search, so\n * candidate types are intersected with what the caller can read in the Content\n * Manager before any query runs.\n */\n filterReadableTypes(\n types: ContentTypeDescriptor[],\n userAbility?: { can: (action: string, subject: string) => boolean } | null\n ): ContentTypeDescriptor[] {\n if (!userAbility || typeof userAbility.can !== \"function\") return types;\n\n return types.filter((type) => {\n try {\n return userAbility.can(CM_READ_ACTION, type.uid);\n } catch {\n return false;\n }\n });\n },\n});\n", "import type { ContentTypeDescriptor } from \"../types\";\n\n/** `seo.metaTitle` + condition -> `{ seo: { metaTitle: condition } }` */\nconst nest = (\n path: string,\n condition: Record<string, unknown>\n): Record<string, unknown> =>\n path\n .split(\".\")\n .reduceRight(\n (acc, segment) => ({ [segment]: acc }),\n condition as Record<string, unknown>\n );\n\n/**\n * Turns the component segments of the nested paths into a Document Service\n * populate tree, so the matched value is present on the returned entry and can\n * be ranked and excerpted. Only the components actually searched are populated.\n */\nconst buildPopulate = (\n paths: string[]\n): Record<string, unknown> | undefined => {\n const tree: Record<string, Record<string, unknown>> = {};\n\n paths.forEach((path) => {\n const segments = path.split(\".\");\n segments.pop(); // drop the scalar field itself\n\n let node: Record<string, unknown> = tree;\n segments.forEach((segment) => {\n node[segment] = (node[segment] as Record<string, unknown>) || {};\n node = node[segment] as Record<string, unknown>;\n });\n });\n\n const toPopulate = (node: Record<string, unknown>): Record<string, unknown> =>\n Object.entries(node).reduce(\n (acc: Record<string, unknown>, [key, child]) => {\n const childObj = child as Record<string, unknown>;\n acc[key] = Object.keys(childObj).length\n ? { populate: toPopulate(childObj) }\n : true;\n return acc;\n },\n {}\n );\n\n return Object.keys(tree).length ? toPopulate(tree) : undefined;\n};\n\nconst MAX_PG_INT32 = 2_147_483_647;\n\nexport default () => ({\n nest,\n buildPopulate,\n\n /** All field paths a hit could have matched, in ranking order. */\n searchablePaths(descriptor: ContentTypeDescriptor): string[] {\n const main =\n descriptor.mainField &&\n descriptor.mainField !== \"id\" &&\n descriptor.mainFieldSearchable !== false\n ? [descriptor.mainField]\n : [];\n return Array.from(\n new Set([\n ...descriptor.idFields,\n ...main,\n ...descriptor.topLevelFields,\n ...descriptor.nestedFields,\n ])\n );\n },\n\n /**\n * One `$or` over every searchable path. `id` is numeric, so it is only added \u2014\n * as an equality \u2014 when the query is a plain integer within 32-bit Postgres INT\n * bounds; `$containsi` on an integer column is rejected by Postgres.\n * `documentId` is matched as a string unless excluded.\n */\n buildFilters(\n descriptor: ContentTypeDescriptor,\n query: string\n ): { $or: unknown[] } | null {\n const paths = this.searchablePaths(descriptor);\n const conditions: unknown[] = [];\n\n if (paths.includes(\"documentId\")) {\n conditions.push({ documentId: { $containsi: query } });\n }\n\n if (/^\\d+$/.test(query)) {\n const numericId = Number(query);\n if (\n Number.isSafeInteger(numericId) &&\n numericId >= 1 &&\n numericId <= MAX_PG_INT32\n ) {\n conditions.push({ id: { $eq: numericId } });\n }\n }\n\n paths.forEach((path) => {\n if (path === \"documentId\") return;\n conditions.push(nest(path, { $containsi: query }));\n });\n\n return conditions.length ? { $or: conditions } : null;\n },\n\n /** Bounded projection \u2014 never `populate: '*'`, never a full row. */\n buildParams(\n descriptor: ContentTypeDescriptor,\n {\n query,\n locale,\n limit,\n includeDrafts,\n }: { query: string; locale?: string; limit: number; includeDrafts: boolean }\n ): Record<string, unknown> | null {\n const filters = this.buildFilters(descriptor, query);\n if (!filters) return null;\n\n const fields = Array.from(\n new Set(\n [\n \"documentId\",\n ...descriptor.idFields,\n descriptor.mainField,\n ...descriptor.topLevelFields,\n ...(descriptor.displayFields || []),\n \"createdAt\",\n \"updatedAt\",\n ...(descriptor.draftAndPublish ? [\"publishedAt\"] : []),\n ...(descriptor.localized ? [\"locale\"] : []),\n ].filter((field) => field && field !== \"id\")\n )\n );\n\n const params: Record<string, unknown> = {\n filters,\n fields,\n sort: { updatedAt: \"desc\" },\n limit,\n start: 0,\n };\n\n const populate = buildPopulate(descriptor.nestedFields);\n if (populate) params.populate = populate;\n\n if (descriptor.draftAndPublish) {\n params.status = includeDrafts ? \"draft\" : \"published\";\n }\n\n if (descriptor.localized) {\n params.locale = locale && locale !== \"all\" ? locale : \"*\";\n }\n\n return params;\n },\n});\n", "import { MAX_QUERY_LENGTH, SNIPPET_RADIUS } from \"./constants\";\n\n/**\n * `$containsi` is compiled to `LIKE %value%` with the value bound as a parameter,\n * so there is no injection surface \u2014 but `%` is still a wildcard inside the bound\n * value and a lone `%` would match every row. Strip it and cap the length.\n */\nconst MAX_DOC_DEPTH = 32;\nconst MAX_STRUCTURED_CHARS = 500_000;\n\nexport const sanitizeQuery = (raw: unknown): string => {\n if (typeof raw !== \"string\") return \"\";\n const cleaned = raw.replace(/%/g, \"\").trim().slice(0, MAX_QUERY_LENGTH);\n return /^[_\\s]+$/.test(cleaned) ? \"\" : cleaned;\n};\n\nconst isProseMirrorRoot = (\n value: unknown\n): value is Record<string, unknown> => {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) return false;\n const obj = value as Record<string, unknown>;\n if (obj.type === \"doc\" && Array.isArray(obj.content)) return true;\n if (obj.doc && typeof obj.doc === \"object\" && !Array.isArray(obj.doc)) {\n const inner = obj.doc as Record<string, unknown>;\n return inner.type === \"doc\" && Array.isArray(inner.content);\n }\n return false;\n};\n\nconst walkDocNodes = (\n node: unknown,\n chunks: string[],\n depth = 0,\n visited = new WeakSet<object>()\n): void => {\n if (!node || depth > MAX_DOC_DEPTH) return;\n if (Array.isArray(node)) {\n if (visited.has(node)) return;\n visited.add(node);\n node.forEach((child) => walkDocNodes(child, chunks, depth + 1, visited));\n return;\n }\n if (typeof node !== \"object\") return;\n if (visited.has(node)) return;\n visited.add(node);\n\n const obj = node as Record<string, unknown>;\n if (typeof obj.text === \"string\" && obj.text.trim()) {\n chunks.push(obj.text);\n }\n if (obj.doc && typeof obj.doc === \"object\") {\n walkDocNodes(obj.doc, chunks, depth + 1, visited);\n }\n if (Array.isArray(obj.content)) {\n walkDocNodes(obj.content, chunks, depth + 1, visited);\n }\n if (Array.isArray(obj.children)) {\n walkDocNodes(obj.children, chunks, depth + 1, visited);\n }\n};\n\n/**\n * Extracts human-readable text from ProseMirror / Tiptap JSON documents\n * (`{ type: 'doc', content: [...] }` or `{ doc: { type: 'doc', content: [...] } }`),\n * whether passed as an object or a serialized JSON string. Returns `null` if\n * `value` is not a structured rich-text document.\n */\nexport const extractStructuredText = (value: unknown): string | null => {\n let candidate: unknown = value;\n\n if (typeof value === \"string\") {\n const trimmed = value.trim();\n if (!trimmed.startsWith(\"{\") || trimmed.length > MAX_STRUCTURED_CHARS) {\n return null;\n }\n try {\n candidate = JSON.parse(trimmed);\n } catch {\n return null;\n }\n }\n\n if (!isProseMirrorRoot(candidate)) return null;\n\n const chunks: string[] = [];\n walkDocNodes(candidate, chunks);\n return chunks.join(\" \").replace(/\\s+/g, \" \").trim();\n};\n\n/**\n * Linear O(N) HTML/XML tag stripper without regex backtracking.\n * Unclosed `<` characters are preserved without re-scanning the remainder.\n */\nconst stripHtmlTags = (input: string): string => {\n let out = \"\";\n let tagStart = -1;\n\n for (let i = 0; i < input.length; i += 1) {\n const ch = input[i];\n if (ch === \"<\") {\n if (tagStart !== -1) {\n out += input.slice(tagStart, i);\n }\n tagStart = i;\n } else if (ch === \">\" && tagStart !== -1) {\n out += \" \";\n tagStart = -1;\n } else if (tagStart === -1) {\n out += ch;\n }\n }\n\n if (tagStart !== -1) {\n out += input.slice(tagStart);\n }\n\n return out;\n};\n\n/** Plain-text projection of richtext/HTML/Markdown/ProseMirror JSON, used for snippets. */\nexport const toPlainText = (value: unknown): string => {\n if (value === null || value === undefined) return \"\";\n\n const structured = extractStructuredText(value);\n if (structured !== null) return structured;\n\n return stripHtmlTags(String(value))\n .replace(/[#*_>`~]+/g, \" \")\n .replace(/\\s+/g, \" \")\n .trim();\n};\n\n/**\n * Walks a dotted path, transparently flattening arrays so repeatable components\n * yield every one of their values.\n */\nexport const collectValues = (node: unknown, parts: string[]): string[] => {\n if (node === null || node === undefined) return [];\n if (Array.isArray(node))\n return node.flatMap((item) => collectValues(item, parts));\n if (parts.length === 0) {\n const structured = extractStructuredText(node);\n if (structured !== null) return structured ? [structured] : [];\n if (typeof node === \"string\") return [node];\n if (typeof node === \"number\") return [String(node)];\n return [];\n }\n if (typeof node !== \"object\") return [];\n return collectValues(\n (node as Record<string, unknown>)[parts[0]],\n parts.slice(1)\n );\n};\n\nexport const getValuesAtPath = (entry: unknown, path: string): string[] =>\n collectValues(entry, path.split(\".\"));\n\n/** Extracts a short excerpt centred on the match, for highlighting in the UI. */\nexport const buildSnippet = (value: unknown, query: string): string => {\n const text = toPlainText(value);\n const index = text.toLowerCase().indexOf(query.toLowerCase());\n\n if (index === -1) {\n return text.length > SNIPPET_RADIUS * 2\n ? `${text.slice(0, SNIPPET_RADIUS * 2)}\u2026`\n : text;\n }\n\n const start = Math.max(0, index - SNIPPET_RADIUS);\n const end = Math.min(text.length, index + query.length + SNIPPET_RADIUS);\n\n const prefix = start > 0 ? \"\u2026\" : \"\";\n const suffix = end < text.length ? \"\u2026\" : \"\";\n return `${prefix}${text.slice(start, end)}${suffix}`;\n};\n\nexport const humanizeFieldPath = (path: string): string =>\n path\n .split(\".\")\n .map((segment) =>\n segment\n .replace(/[_-]+/g, \" \")\n .replace(/([a-z0-9])([A-Z])/g, \"$1 $2\")\n .replace(/^./, (c) => c.toUpperCase())\n )\n .join(\" \u203A \");\n", "import type { ContentTypeDescriptor, RankedHit } from \"../types\";\nimport { TIER, TIER_LABELS } from \"../utils/constants\";\nimport {\n getValuesAtPath,\n buildSnippet,\n humanizeFieldPath,\n toPlainText,\n} from \"../utils/text\";\n\ntype ScoreResult = Pick<\n RankedHit,\n | \"tier\"\n | \"tierLabel\"\n | \"matchedField\"\n | \"matchedFieldLabel\"\n | \"matchedSnippet\"\n | \"exactCase\"\n | \"valueLength\"\n>;\n\n/**\n * Ordering rule, highest priority first:\n * 0 id / documentId exact\n * 1 id / documentId partial\n * 2 name (main field) exact\n * 3 name starts with\n * 4 name contains\n * 5 any other top-level field\n * 6 any nested component field (\"from inside\")\n * Ties are broken by an exact-case bonus, then the shortest matching value\n * (a hit in a 10-character title beats one in a 5,000-character body), then\n * the most recently updated entry.\n */\nexport default () => ({\n /** First path whose value satisfies `test`, searched in the given order. */\n findMatch(\n entry: unknown,\n paths: string[],\n test: (value: string) => boolean,\n normalize = false\n ): { path: string; value: string } | null {\n for (const path of paths) {\n const values = getValuesAtPath(entry, path);\n\n for (const rawValue of values) {\n const value = normalize ? toPlainText(rawValue) || rawValue : rawValue;\n if (test(value)) return { path, value };\n }\n }\n\n return null;\n },\n\n score(\n entry: unknown,\n descriptor: ContentTypeDescriptor,\n query: string\n ): ScoreResult {\n const lowered = query.toLowerCase();\n const idSet = new Set([\"id\", ...descriptor.idFields]);\n const idPaths = Array.from(idSet);\n const mainPaths =\n descriptor.mainField &&\n descriptor.mainField !== \"id\" &&\n descriptor.mainFieldSearchable !== false\n ? [descriptor.mainField]\n : [];\n\n const attempts: Array<\n [number, string[], (value: string) => boolean, boolean]\n > = [\n [TIER.ID_EXACT, idPaths, (val) => val.toLowerCase() === lowered, false],\n [\n TIER.ID_CONTAINS,\n idPaths,\n (val) => val.toLowerCase().includes(lowered),\n false,\n ],\n [\n TIER.MAIN_EXACT,\n mainPaths,\n (val) => val.toLowerCase() === lowered,\n true,\n ],\n [\n TIER.MAIN_STARTS_WITH,\n mainPaths,\n (val) => val.toLowerCase().startsWith(lowered),\n true,\n ],\n [\n TIER.MAIN_CONTAINS,\n mainPaths,\n (val) => val.toLowerCase().includes(lowered),\n true,\n ],\n [\n TIER.FIELD_CONTAINS,\n descriptor.topLevelFields,\n (val) => val.toLowerCase().includes(lowered),\n true,\n ],\n [\n TIER.NESTED_CONTAINS,\n descriptor.nestedFields,\n (val) => val.toLowerCase().includes(lowered),\n true,\n ],\n ];\n\n for (const [tier, paths, test, normalize] of attempts) {\n const match = this.findMatch(entry, paths, test, normalize);\n\n if (match) {\n return {\n tier,\n tierLabel: TIER_LABELS[tier],\n matchedField: match.path,\n matchedFieldLabel: humanizeFieldPath(match.path),\n matchedSnippet: buildSnippet(match.value, query),\n exactCase: match.value.includes(query),\n valueLength: match.value.length,\n };\n }\n }\n\n // The database matched something we cannot re-locate \u2014 a value behind an\n // unpopulated relation, say. Keep the hit, rank it last.\n return {\n tier: TIER.UNKNOWN,\n tierLabel: TIER_LABELS[TIER.UNKNOWN],\n matchedField: null,\n matchedFieldLabel: null,\n matchedSnippet: null,\n exactCase: false,\n valueLength: Number.MAX_SAFE_INTEGER,\n };\n },\n\n compare(a: RankedHit, b: RankedHit): number {\n if (a.tier !== b.tier) return a.tier - b.tier;\n if (a.exactCase !== b.exactCase) return a.exactCase ? -1 : 1;\n if (a.valueLength !== b.valueLength) return a.valueLength - b.valueLength;\n\n return (\n new Date(b.updatedAt || 0).getTime() -\n new Date(a.updatedAt || 0).getTime()\n );\n },\n\n sort(hits: RankedHit[]): RankedHit[] {\n return [...hits].sort((a, b) => this.compare(a, b));\n },\n});\n", "import type {\n ContentTypeDescriptor,\n PluginSettings,\n StrapiLike,\n} from \"../types\";\nimport {\n PLUGIN_ID,\n SEARCHABLE_SCALAR_TYPES,\n SYSTEM_PLUGIN_PREFIXES,\n SKIPPED_ATTRIBUTE_TYPES,\n BLOCKLISTED_ATTRIBUTE_NAMES,\n IDENTIFIER_FIELDS,\n MAIN_FIELD_FALLBACKS,\n} from \"../utils/constants\";\n\nexport interface AttributeLike {\n type?: string;\n private?: boolean;\n searchable?: boolean;\n component?: string;\n customField?: string;\n}\n\nexport interface ContentTypeLike {\n uid: string;\n kind?: string;\n apiName?: string;\n attributes?: Record<string, AttributeLike>;\n info?: { displayName?: string; singularName?: string };\n pluginOptions?: {\n \"i18n\"?: { localized?: boolean };\n \"content-manager\"?: { visible?: boolean };\n };\n options?: { draftAndPublish?: boolean };\n}\n\ninterface SchemaCache {\n signature: string;\n types: ContentTypeDescriptor[];\n}\n\nexport default ({ strapi }: { strapi: StrapiLike }) => {\n let cache: SchemaCache | null = null;\n\n const computeSignature = (settings: PluginSettings): string =>\n JSON.stringify({\n settings,\n uids: Object.keys(strapi.contentTypes).sort(),\n });\n\n return {\n /**\n * Content types the plugin is allowed to look at: the app's own `api::` types\n * plus user-facing `plugin::` types (excluding internal Strapi system plugins\n * and types explicitly hidden from the Content Manager).\n */\n listCandidateUids(includePluginContentTypes = true): string[] {\n return Object.keys(strapi.contentTypes).filter((uid) => {\n if (uid.startsWith(\"api::\")) return true;\n if (!includePluginContentTypes || !uid.startsWith(\"plugin::\"))\n return false;\n if (SYSTEM_PLUGIN_PREFIXES.some((prefix) => uid.startsWith(prefix)))\n return false;\n\n const contentType = strapi.contentTypes[uid] as\n | ContentTypeLike\n | undefined;\n if (contentType?.pluginOptions?.[\"content-manager\"]?.visible === false)\n return false;\n\n return true;\n });\n },\n\n isSearchableAttribute(\n name: string,\n attribute: AttributeLike | undefined\n ): boolean {\n if (!attribute || BLOCKLISTED_ATTRIBUTE_NAMES.includes(name))\n return false;\n if (attribute.private === true) return false;\n if (attribute.searchable === false) return false;\n if (attribute.type && SKIPPED_ATTRIBUTE_TYPES.includes(attribute.type))\n return false;\n\n return Boolean(\n attribute.type && SEARCHABLE_SCALAR_TYPES.includes(attribute.type)\n );\n },\n\n isSafeDisplayAttribute(\n name: string,\n attribute: AttributeLike | undefined\n ): boolean {\n if (!name || typeof name !== \"string\") return false;\n if (BLOCKLISTED_ATTRIBUTE_NAMES.includes(name)) return false;\n if (!attribute || attribute.private === true) return false;\n if (attribute.type && SKIPPED_ATTRIBUTE_TYPES.includes(attribute.type))\n return false;\n return true;\n },\n\n /**\n * Flattens an attribute map into dotted, searchable field paths, walking into\n * components up to `maxDepth`. `visited` breaks component cycles (a component\n * that, directly or not, contains itself).\n */\n collectFieldPaths(\n attributes: Record<string, AttributeLike> = {},\n {\n maxDepth,\n depth = 0,\n prefix = \"\",\n visited = new Set<string>(),\n }: {\n maxDepth: number;\n depth?: number;\n prefix?: string;\n visited?: Set<string>;\n } = {\n maxDepth: 0,\n }\n ): string[] {\n const paths: string[] = [];\n\n Object.entries(attributes).forEach(([name, attribute]) => {\n const path = prefix ? `${prefix}.${name}` : name;\n\n if (this.isSearchableAttribute(name, attribute)) {\n paths.push(path);\n return;\n }\n\n if (attribute.type !== \"component\" || depth >= maxDepth) return;\n\n const component = strapi.components[attribute.component as string];\n if (\n !component ||\n !attribute.component ||\n visited.has(attribute.component)\n )\n return;\n\n paths.push(\n ...this.collectFieldPaths(component.attributes, {\n maxDepth,\n depth: depth + 1,\n prefix: path,\n visited: new Set([...visited, attribute.component]),\n })\n );\n });\n\n return paths;\n },\n\n /** Resolves the field the Content Manager uses to label an entry. */\n async resolveMainField(contentType: ContentTypeLike): Promise<string> {\n try {\n const configuration = await strapi\n .plugin(\"content-manager\")\n .service(\"content-types\")\n .findConfiguration(contentType);\n\n const mainField =\n configuration &&\n configuration.settings &&\n configuration.settings.mainField;\n\n if (\n mainField &&\n mainField !== \"id\" &&\n this.isSafeDisplayAttribute(\n mainField,\n contentType.attributes?.[mainField]\n )\n ) {\n return mainField;\n }\n } catch (error) {\n const msg = (error as Error).message;\n strapi.log.debug(\n `[${PLUGIN_ID}] CM config read failed (${contentType.uid}): ${msg}`\n );\n }\n\n const fallback = MAIN_FIELD_FALLBACKS.find((name) =>\n this.isSearchableAttribute(name, contentType.attributes?.[name])\n );\n\n return fallback || \"id\";\n },\n\n extractExcludedFields(uid: string, excludedFields?: string[]): Set<string> {\n return new Set(\n (excludedFields || [])\n .filter(\n (entry): entry is string =>\n typeof entry === \"string\" &&\n (entry.startsWith(`${uid}:`) || entry.startsWith(`${uid}.`))\n )\n .map((entry) => entry.slice(uid.length + 1))\n );\n },\n\n resolveDisplayName(uid: string, info?: ContentTypeLike[\"info\"]): string {\n return info?.displayName || info?.singularName || uid;\n },\n\n hasAnySearchableField(\n fields: {\n idFields: string[];\n topLevelFields: string[];\n nestedFields: string[];\n },\n isMainSearchable: boolean\n ): boolean {\n if (fields.idFields.length > 0 || fields.topLevelFields.length > 0)\n return true;\n return fields.nestedFields.length > 0 || isMainSearchable;\n },\n\n async describeContentType(\n uid: string,\n settings: PluginSettings\n ): Promise<ContentTypeDescriptor | null> {\n const contentType = strapi.contentTypes[uid] as\n | ContentTypeLike\n | undefined;\n if (!contentType) return null;\n\n const attributes = contentType.attributes || {};\n const excludedForType = this.extractExcludedFields(\n uid,\n settings.excludedFields\n );\n const allPaths = this.collectFieldPaths(attributes, {\n maxDepth: settings.maxDepth,\n }).filter((path) => !excludedForType.has(path));\n const mainField = await this.resolveMainField(contentType);\n const mainFieldSearchable =\n !excludedForType.has(mainField) &&\n this.isSearchableAttribute(mainField, attributes[mainField]);\n\n const idFields = [\n \"documentId\",\n ...IDENTIFIER_FIELDS.filter((name) =>\n this.isSearchableAttribute(name, attributes[name])\n ),\n ].filter((name) => !excludedForType.has(name));\n\n const topLevelFields = allPaths.filter(\n (path) =>\n !path.includes(\".\") && path !== mainField && !idFields.includes(path)\n );\n const nestedFields = settings.deep\n ? allPaths.filter((path) => path.includes(\".\"))\n : [];\n\n const rawDisplay = settings.displayFields?.[uid];\n const displayFields = Array.isArray(rawDisplay)\n ? rawDisplay\n .filter((name) =>\n this.isSafeDisplayAttribute(name, attributes[name])\n )\n .slice(0, 2)\n : [];\n\n return {\n uid,\n kind: contentType.kind || \"collectionType\",\n displayName: this.resolveDisplayName(uid, contentType.info),\n apiName: contentType.apiName,\n mainField,\n mainFieldSearchable,\n idFields,\n topLevelFields,\n nestedFields,\n displayFields,\n localized: Boolean(contentType.pluginOptions?.i18n?.localized),\n draftAndPublish: Boolean(contentType.options?.draftAndPublish),\n /** Nothing to match against \u2014 the type is listed but never queried. */\n searchable: this.hasAnySearchableField(\n { idFields, topLevelFields, nestedFields },\n mainFieldSearchable\n ),\n };\n },\n\n async getSearchableContentTypes({\n force = false,\n }: { force?: boolean } = {}): Promise<ContentTypeDescriptor[]> {\n const settings = (await strapi\n .plugin(PLUGIN_ID)\n .service(\"settings\")\n .get()) as PluginSettings;\n const signature = computeSignature(settings);\n\n if (cache && !force && cache.signature === signature) {\n return cache.types;\n }\n\n const excluded = new Set(settings.excludedContentTypes || []);\n const includePlugins = settings.includePluginContentTypes !== false;\n\n const described = await Promise.all(\n this.listCandidateUids(includePlugins)\n .filter((uid) => !excluded.has(uid))\n .map((uid) => this.describeContentType(uid, settings))\n );\n\n const types = described\n .filter((type): type is ContentTypeDescriptor =>\n Boolean(type && type.searchable)\n )\n .sort((a, b) => a.displayName.localeCompare(b.displayName));\n\n cache = { signature, types };\n\n return types;\n },\n\n /** Every candidate type, searchable or not \u2014 the Settings page needs the full list. */\n async getAllContentTypes(): Promise<ContentTypeDescriptor[]> {\n const settings = (await strapi\n .plugin(PLUGIN_ID)\n .service(\"settings\")\n .get()) as PluginSettings;\n const includePlugins = settings.includePluginContentTypes !== false;\n const described = await Promise.all(\n this.listCandidateUids(includePlugins).map((uid) =>\n this.describeContentType(uid, settings)\n )\n );\n\n return described\n .filter((type): type is ContentTypeDescriptor => Boolean(type))\n .sort((a, b) => a.displayName.localeCompare(b.displayName));\n },\n\n clearCache() {\n cache = null;\n },\n };\n};\n", "/** Rejects if `factory()` has not settled within `ms`. Always clears its timer. */\nexport const withTimeout = <T>(\n factory: () => T | Promise<T>,\n ms: number,\n label: string\n): Promise<T> => {\n let timer: ReturnType<typeof setTimeout>;\n\n return Promise.race([\n Promise.resolve()\n .then(factory)\n .finally(() => clearTimeout(timer)),\n new Promise<never>((_, reject) => {\n timer = setTimeout(\n () => reject(new Error(`GLOBAL_SEARCH_TIMEOUT:${label}`)),\n ms\n );\n }),\n ]);\n};\n\n/**\n * Runs `worker` over `items` with at most `concurrency` in flight, so an app with\n * 60 content types cannot exhaust the database pool on a single keystroke.\n */\nexport const mapWithConcurrency = async <T, R>(\n items: T[],\n concurrency: number,\n worker: (item: T, index: number) => Promise<R>\n): Promise<R[]> => {\n const results = Array.from<R>({ length: items.length });\n let cursor = 0;\n\n const safeConcurrency = Math.max(1, Math.floor(Number(concurrency) || 1));\n const runners = Array.from(\n { length: Math.min(safeConcurrency, items.length) },\n async () => {\n while (cursor < items.length) {\n const index = cursor;\n cursor += 1;\n results[index] = await worker(items[index], index);\n }\n }\n );\n\n await Promise.all(runners);\n\n return results;\n};\n", "import type {\n ContentTypeDescriptor,\n PluginSettings,\n RankedHit,\n SearchParams,\n SearchResult,\n StrapiLike,\n} from \"../types\";\nimport { withTimeout, mapWithConcurrency } from \"../utils/async\";\nimport { BLOCKLISTED_ATTRIBUTE_NAMES, PLUGIN_ID } from \"../utils/constants\";\nimport { sanitizeQuery } from \"../utils/text\";\n\nconst service = (strapi: StrapiLike, name: string) =>\n strapi.plugin(PLUGIN_ID).service(name);\n\nexport interface EntryLike {\n id: string | number;\n documentId?: string;\n locale?: string;\n publishedAt?: string | null;\n updatedAt?: string | null;\n name?: string;\n title?: string;\n [key: string]: unknown;\n}\n\nexport default ({ strapi }: { strapi: StrapiLike }) => ({\n /** Content Manager deep-link for a hit. */\n buildAdminUrl(descriptor: ContentTypeDescriptor, entry: EntryLike): string {\n const localeQuery = entry.locale\n ? `?locale=${encodeURIComponent(entry.locale)}`\n : \"\";\n\n if (descriptor.kind === \"singleType\") {\n return `/content-manager/single-types/${descriptor.uid}${localeQuery}`;\n }\n\n const documentId = encodeURIComponent(String(entry.documentId || entry.id));\n const base = `/content-manager/collection-types/${descriptor.uid}`;\n\n return `${base}/${documentId}${localeQuery}`;\n },\n\n async queryContentType(\n descriptor: ContentTypeDescriptor,\n {\n query,\n locale,\n settings,\n }: { query: string; locale?: string; settings: PluginSettings }\n ): Promise<EntryLike[]> {\n const params = service(strapi, \"query\").buildParams(descriptor, {\n query,\n locale,\n limit: settings.perTypeLimit,\n includeDrafts: settings.includeDrafts,\n });\n\n if (!params) return [];\n\n const result = await strapi.documents(descriptor.uid).findMany(params);\n\n return (\n Array.isArray(result) ? result : [result].filter(Boolean)\n ) as EntryLike[];\n },\n\n resolveEntryTitle(\n descriptor: ContentTypeDescriptor,\n entry: EntryLike\n ): string {\n const mainVal = descriptor.mainField\n ? (entry[descriptor.mainField] as string)\n : \"\";\n if (mainVal) return String(mainVal);\n return String(\n entry.name || entry.title || `#${entry.documentId || entry.id}`\n );\n },\n\n resolveEntryStatus(\n descriptor: ContentTypeDescriptor,\n entry: EntryLike\n ): \"published\" | \"draft\" | null {\n if (!descriptor.draftAndPublish) return null;\n return entry.publishedAt ? \"published\" : \"draft\";\n },\n\n toHit(\n descriptor: ContentTypeDescriptor,\n entry: EntryLike,\n query: string,\n settings: PluginSettings\n ): RankedHit {\n const scored = service(strapi, \"ranking\").score(entry, descriptor, query);\n const rawExtra =\n descriptor.displayFields ??\n (Array.isArray(settings.displayFields?.[descriptor.uid])\n ? settings.displayFields[descriptor.uid]\n : []);\n const extraFields = rawExtra\n .filter(\n (field): field is string =>\n typeof field === \"string\" &&\n Boolean(field) &&\n !BLOCKLISTED_ATTRIBUTE_NAMES.includes(field)\n )\n .slice(0, 2);\n\n return {\n ...scored,\n contentTypeUid: descriptor.uid,\n contentTypeLabel: descriptor.displayName,\n kind: descriptor.kind,\n id: entry.id,\n documentId: entry.documentId || null,\n title: this.resolveEntryTitle(descriptor, entry),\n mainField: descriptor.mainField,\n extra: extraFields.map((field) => ({\n field,\n value: entry[field] ?? null,\n })),\n locale: entry.locale || null,\n status: this.resolveEntryStatus(descriptor, entry),\n updatedAt: entry.updatedAt || null,\n adminUrl: this.buildAdminUrl(descriptor, entry),\n };\n },\n\n /**\n * Fans out across every permitted content type, ranks the merged set, then\n * paginates in memory.\n *\n * `total` is the size of the *capped* merged set (`perTypeLimit` rows per type,\n * `maxResults` overall), not a database count \u2014 searching for a common word in a\n * 100k-row table must not turn into a full-table `COUNT`.\n */\n async search({\n query: rawQuery,\n types,\n locale,\n page = 1,\n pageSize = 20,\n userAbility,\n }: SearchParams = {}): Promise<SearchResult> {\n const settings = (await service(\n strapi,\n \"settings\"\n ).get()) as PluginSettings;\n const query = sanitizeQuery(rawQuery);\n const safePageSize = Math.min(\n Math.max(Math.floor(Number(pageSize)) || 20, 1),\n 100\n );\n\n const empty: SearchResult = {\n query,\n results: [],\n groups: [],\n pagination: { page: 1, pageSize: safePageSize, total: 0, pageCount: 0 },\n meta: {\n searchedTypes: 0,\n truncatedTypes: [],\n failedTypes: [],\n minChars: settings.minChars,\n },\n };\n\n if (query.length < settings.minChars) return empty;\n\n const searchable = (await service(\n strapi,\n \"schema\"\n ).getSearchableContentTypes()) as ContentTypeDescriptor[];\n const requested =\n Array.isArray(types) && types.length ? new Set(types) : null;\n\n const candidates = service(strapi, \"permissions\")\n .filterReadableTypes(searchable, userAbility)\n .filter(\n (descriptor: ContentTypeDescriptor) =>\n !requested || requested.has(descriptor.uid)\n );\n\n if (!candidates.length) return { ...empty, query };\n\n const truncatedTypes: string[] = [];\n const failedTypes: Array<{ uid: string; message: string }> = [];\n\n const perType = await mapWithConcurrency(\n candidates,\n settings.concurrency,\n async (descriptor: ContentTypeDescriptor) => {\n try {\n const entries = await withTimeout(\n () =>\n this.queryContentType(descriptor, { query, locale, settings }),\n settings.queryTimeout,\n descriptor.uid\n );\n\n if (entries.length >= settings.perTypeLimit)\n truncatedTypes.push(descriptor.uid);\n\n return entries.map((entry) =>\n this.toHit(descriptor, entry, query, settings)\n );\n } catch (error) {\n // One broken or slow content type must never fail the whole search.\n const msg = (error as Error).message;\n failedTypes.push({ uid: descriptor.uid, message: msg });\n strapi.log.warn(\n `[${PLUGIN_ID}] search failed for ${descriptor.uid}: ${msg}`\n );\n\n return [];\n }\n }\n );\n\n const allHits = perType.flat();\n const ranked = service(strapi, \"ranking\")\n .sort(allHits)\n .slice(0, settings.maxResults) as RankedHit[];\n\n const total = ranked.length;\n const pageCount = Math.ceil(total / safePageSize) || 0;\n const safePage = Math.min(\n Math.max(Math.floor(Number(page)) || 1, 1),\n pageCount || 1\n );\n const start = (safePage - 1) * safePageSize;\n const results = ranked.slice(start, start + safePageSize);\n\n // Group headers are built from the full ranked set, not the current page, so\n // the counts stay stable while paging.\n const groups = candidates\n .map((descriptor: ContentTypeDescriptor) => ({\n uid: descriptor.uid,\n label: descriptor.displayName,\n kind: descriptor.kind,\n count: ranked.filter((hit) => hit.contentTypeUid === descriptor.uid)\n .length,\n truncated: truncatedTypes.includes(descriptor.uid),\n }))\n .filter((group: { count: number }) => group.count > 0)\n .sort((a: { count: number }, b: { count: number }) => b.count - a.count);\n\n return {\n query,\n results,\n groups,\n pagination: { page: safePage, pageSize: safePageSize, total, pageCount },\n meta: {\n searchedTypes: candidates.length,\n truncatedTypes,\n failedTypes,\n minChars: settings.minChars,\n capped:\n allHits.length > settings.maxResults ||\n total >= settings.maxResults ||\n truncatedTypes.length > 0,\n },\n };\n },\n});\n", "import { defaults, isPlainObject, validator } from \"../config\";\nimport type { PluginSettings, StrapiLike } from \"../types\";\nimport { PLUGIN_ID } from \"../utils/constants\";\n\nconst STORE_KEY = \"settings\";\nconst ALLOWED_KEYS = Object.keys(defaults);\n\nconst getStore = (strapi: StrapiLike) =>\n strapi.store({ type: \"plugin\", name: PLUGIN_ID });\n\nconst pickAllowed = (source: unknown): Partial<PluginSettings> => {\n if (!isPlainObject(source)) return {};\n return Object.entries(source).reduce((acc, [key, value]) => {\n if (ALLOWED_KEYS.includes(key) && value !== undefined) {\n (acc as Record<string, unknown>)[key] = value;\n }\n return acc;\n }, {} as Partial<PluginSettings>);\n};\n\nexport default ({ strapi }: { strapi: StrapiLike }) => ({\n /**\n * Resolution order: values saved from the Settings page, then `config/plugins.js`,\n * then the built-in defaults. Every key always resolves to something usable.\n */\n async get(): Promise<PluginSettings> {\n const fromFile = pickAllowed(strapi.config.get(`plugin::${PLUGIN_ID}`, {}));\n const fromStore = pickAllowed(\n await getStore(strapi).get({ key: STORE_KEY })\n );\n\n return { ...defaults, ...fromFile, ...fromStore };\n },\n\n async set(patch: Partial<PluginSettings> = {}): Promise<PluginSettings> {\n if (!isPlainObject(patch)) {\n throw new Error(\"[global-search] settings payload must be an object\");\n }\n const sanitized = pickAllowed(patch);\n\n validator(sanitized);\n\n const current = pickAllowed(await getStore(strapi).get({ key: STORE_KEY }));\n const next = { ...current, ...sanitized };\n\n await getStore(strapi).set({ key: STORE_KEY, value: next });\n\n // Field lists and depth feed the introspection cache \u2014 rebuild it.\n strapi.plugin(PLUGIN_ID).service(\"schema\").clearCache();\n\n return this.get();\n },\n\n async reset(): Promise<PluginSettings> {\n await getStore(strapi).set({ key: STORE_KEY, value: {} });\n strapi.plugin(PLUGIN_ID).service(\"schema\").clearCache();\n\n return this.get();\n },\n\n defaults,\n});\n", "import permissions from \"./permissions\";\nimport query from \"./query\";\nimport ranking from \"./ranking\";\nimport schema from \"./schema\";\nimport search from \"./search\";\nimport settings from \"./settings\";\n\nexport default {\n schema,\n query,\n ranking,\n permissions,\n settings,\n search,\n};\n", "import bootstrap from \"./bootstrap\";\nimport config from \"./config\";\nimport controllers from \"./controllers\";\nimport register from \"./register\";\nimport routes from \"./routes\";\nimport services from \"./services\";\n\nexport default {\n register,\n bootstrap,\n config,\n controllers,\n routes,\n services,\n};\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["config", "schema_default", "search_default", "settings_default", "schema_default", "settings_default", "search_default"]
|
|
7
|
+
}
|