@open-mercato/core 0.4.5-develop-f4858e0ef3 → 0.4.5-develop-4849712ccb

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.
Files changed (163) hide show
  1. package/dist/generated/entities/catalog_product/index.js +16 -0
  2. package/dist/generated/entities/catalog_product/index.js.map +2 -2
  3. package/dist/generated/entities/catalog_product_unit_conversion/index.js +27 -0
  4. package/dist/generated/entities/catalog_product_unit_conversion/index.js.map +7 -0
  5. package/dist/generated/entities/sales_credit_memo_line/index.js +7 -1
  6. package/dist/generated/entities/sales_credit_memo_line/index.js.map +2 -2
  7. package/dist/generated/entities/sales_invoice_line/index.js +7 -1
  8. package/dist/generated/entities/sales_invoice_line/index.js.map +2 -2
  9. package/dist/generated/entities/sales_order_line/index.js +6 -0
  10. package/dist/generated/entities/sales_order_line/index.js.map +2 -2
  11. package/dist/generated/entities/sales_quote_line/index.js +6 -0
  12. package/dist/generated/entities/sales_quote_line/index.js.map +2 -2
  13. package/dist/generated/entities.ids.generated.js +1 -0
  14. package/dist/generated/entities.ids.generated.js.map +2 -2
  15. package/dist/generated/entity-fields-registry.js +2 -0
  16. package/dist/generated/entity-fields-registry.js.map +2 -2
  17. package/dist/modules/catalog/api/prices/route.js +123 -8
  18. package/dist/modules/catalog/api/prices/route.js.map +2 -2
  19. package/dist/modules/catalog/api/product-unit-conversions/route.js +194 -0
  20. package/dist/modules/catalog/api/product-unit-conversions/route.js.map +7 -0
  21. package/dist/modules/catalog/api/products/route.js +351 -201
  22. package/dist/modules/catalog/api/products/route.js.map +2 -2
  23. package/dist/modules/catalog/backend/catalog/products/[id]/page.js +1267 -497
  24. package/dist/modules/catalog/backend/catalog/products/[id]/page.js.map +2 -2
  25. package/dist/modules/catalog/backend/catalog/products/create/page.js +733 -210
  26. package/dist/modules/catalog/backend/catalog/products/create/page.js.map +2 -2
  27. package/dist/modules/catalog/commands/index.js +1 -0
  28. package/dist/modules/catalog/commands/index.js.map +2 -2
  29. package/dist/modules/catalog/commands/productUnitConversions.js +503 -0
  30. package/dist/modules/catalog/commands/productUnitConversions.js.map +7 -0
  31. package/dist/modules/catalog/commands/products.js +355 -73
  32. package/dist/modules/catalog/commands/products.js.map +2 -2
  33. package/dist/modules/catalog/commands/shared.js +18 -4
  34. package/dist/modules/catalog/commands/shared.js.map +2 -2
  35. package/dist/modules/catalog/components/products/ProductUomSection.js +591 -0
  36. package/dist/modules/catalog/components/products/ProductUomSection.js.map +7 -0
  37. package/dist/modules/catalog/components/products/productForm.js +66 -5
  38. package/dist/modules/catalog/components/products/productForm.js.map +2 -2
  39. package/dist/modules/catalog/components/products/productFormUtils.js +68 -0
  40. package/dist/modules/catalog/components/products/productFormUtils.js.map +7 -0
  41. package/dist/modules/catalog/data/entities.js +86 -0
  42. package/dist/modules/catalog/data/entities.js.map +2 -2
  43. package/dist/modules/catalog/data/validators.js +65 -3
  44. package/dist/modules/catalog/data/validators.js.map +2 -2
  45. package/dist/modules/catalog/events.js +3 -0
  46. package/dist/modules/catalog/events.js.map +2 -2
  47. package/dist/modules/catalog/lib/unitCodes.js +7 -0
  48. package/dist/modules/catalog/lib/unitCodes.js.map +7 -0
  49. package/dist/modules/catalog/lib/unitResolution.js +53 -0
  50. package/dist/modules/catalog/lib/unitResolution.js.map +7 -0
  51. package/dist/modules/catalog/migrations/Migration20260218225422.js +19 -0
  52. package/dist/modules/catalog/migrations/Migration20260218225422.js.map +7 -0
  53. package/dist/modules/catalog/migrations/Migration20260219084500.js +27 -0
  54. package/dist/modules/catalog/migrations/Migration20260219084500.js.map +7 -0
  55. package/dist/modules/catalog/search.js +69 -1
  56. package/dist/modules/catalog/search.js.map +2 -2
  57. package/dist/modules/catalog/seed/examples.js +91 -42
  58. package/dist/modules/catalog/seed/examples.js.map +2 -2
  59. package/dist/modules/dashboards/seed/analytics.js +3 -0
  60. package/dist/modules/dashboards/seed/analytics.js.map +2 -2
  61. package/dist/modules/sales/api/order-lines/route.js +98 -15
  62. package/dist/modules/sales/api/order-lines/route.js.map +2 -2
  63. package/dist/modules/sales/api/quote-lines/route.js +101 -14
  64. package/dist/modules/sales/api/quote-lines/route.js.map +2 -2
  65. package/dist/modules/sales/api/quotes/public/[token]/route.js +87 -12
  66. package/dist/modules/sales/api/quotes/public/[token]/route.js.map +2 -2
  67. package/dist/modules/sales/commands/documents.js +1424 -260
  68. package/dist/modules/sales/commands/documents.js.map +3 -3
  69. package/dist/modules/sales/commands/shared.js +6 -2
  70. package/dist/modules/sales/commands/shared.js.map +2 -2
  71. package/dist/modules/sales/components/documents/ItemsSection.js +216 -86
  72. package/dist/modules/sales/components/documents/ItemsSection.js.map +2 -2
  73. package/dist/modules/sales/components/documents/LineItemDialog.js +913 -241
  74. package/dist/modules/sales/components/documents/LineItemDialog.js.map +3 -3
  75. package/dist/modules/sales/components/documents/ShipmentsSection.js +15 -3
  76. package/dist/modules/sales/components/documents/ShipmentsSection.js.map +2 -2
  77. package/dist/modules/sales/data/entities.js +59 -3
  78. package/dist/modules/sales/data/entities.js.map +2 -2
  79. package/dist/modules/sales/data/validators.js +35 -0
  80. package/dist/modules/sales/data/validators.js.map +2 -2
  81. package/dist/modules/sales/frontend/quote/[token]/page.js +15 -1
  82. package/dist/modules/sales/frontend/quote/[token]/page.js.map +2 -2
  83. package/dist/modules/sales/migrations/Migration20260218225423.js +31 -0
  84. package/dist/modules/sales/migrations/Migration20260218225423.js.map +7 -0
  85. package/dist/modules/sales/migrations/Migration20260219084501.js +71 -0
  86. package/dist/modules/sales/migrations/Migration20260219084501.js.map +7 -0
  87. package/dist/modules/sales/search.js +28 -0
  88. package/dist/modules/sales/search.js.map +2 -2
  89. package/dist/modules/sales/seed/examples.js +14 -1
  90. package/dist/modules/sales/seed/examples.js.map +2 -2
  91. package/dist/modules/sales/widgets/injection/document-history/widget.client.js +1 -1
  92. package/dist/modules/sales/widgets/injection/document-history/widget.client.js.map +2 -2
  93. package/generated/entities/catalog_product/index.ts +8 -0
  94. package/generated/entities/catalog_product_unit_conversion/index.ts +12 -0
  95. package/generated/entities/sales_credit_memo_line/index.ts +3 -0
  96. package/generated/entities/sales_invoice_line/index.ts +3 -0
  97. package/generated/entities/sales_order_line/index.ts +3 -0
  98. package/generated/entities/sales_quote_line/index.ts +3 -0
  99. package/generated/entities.ids.generated.ts +1 -0
  100. package/generated/entity-fields-registry.ts +2 -0
  101. package/package.json +2 -2
  102. package/src/modules/auth/i18n/de.json +1 -1
  103. package/src/modules/auth/i18n/en.json +1 -1
  104. package/src/modules/auth/i18n/es.json +1 -1
  105. package/src/modules/auth/i18n/pl.json +1 -1
  106. package/src/modules/catalog/api/prices/route.ts +213 -81
  107. package/src/modules/catalog/api/product-unit-conversions/route.ts +195 -0
  108. package/src/modules/catalog/api/products/route.ts +638 -402
  109. package/src/modules/catalog/backend/catalog/products/[id]/page.tsx +2085 -1072
  110. package/src/modules/catalog/backend/catalog/products/create/page.tsx +1288 -593
  111. package/src/modules/catalog/commands/index.ts +1 -0
  112. package/src/modules/catalog/commands/productUnitConversions.ts +626 -0
  113. package/src/modules/catalog/commands/products.ts +1151 -693
  114. package/src/modules/catalog/commands/shared.ts +19 -5
  115. package/src/modules/catalog/components/products/ProductUomSection.tsx +745 -0
  116. package/src/modules/catalog/components/products/productForm.ts +369 -256
  117. package/src/modules/catalog/components/products/productFormUtils.ts +82 -0
  118. package/src/modules/catalog/data/entities.ts +82 -1
  119. package/src/modules/catalog/data/validators.ts +118 -34
  120. package/src/modules/catalog/events.ts +3 -0
  121. package/src/modules/catalog/i18n/de.json +56 -0
  122. package/src/modules/catalog/i18n/en.json +56 -0
  123. package/src/modules/catalog/i18n/es.json +56 -0
  124. package/src/modules/catalog/i18n/pl.json +56 -0
  125. package/src/modules/catalog/lib/unitCodes.ts +1 -0
  126. package/src/modules/catalog/lib/unitResolution.ts +62 -0
  127. package/src/modules/catalog/migrations/.snapshot-open-mercato.json +245 -0
  128. package/src/modules/catalog/migrations/Migration20260218225422.ts +21 -0
  129. package/src/modules/catalog/migrations/Migration20260219084500.ts +26 -0
  130. package/src/modules/catalog/search.ts +73 -1
  131. package/src/modules/catalog/seed/examples.ts +552 -479
  132. package/src/modules/dashboards/i18n/de.json +1 -1
  133. package/src/modules/dashboards/i18n/en.json +1 -1
  134. package/src/modules/dashboards/i18n/es.json +1 -1
  135. package/src/modules/dashboards/i18n/pl.json +1 -1
  136. package/src/modules/dashboards/seed/analytics.ts +3 -0
  137. package/src/modules/sales/api/order-lines/route.ts +158 -68
  138. package/src/modules/sales/api/quote-lines/route.ts +161 -67
  139. package/src/modules/sales/api/quotes/public/[token]/route.ts +122 -36
  140. package/src/modules/sales/commands/documents.ts +4250 -2424
  141. package/src/modules/sales/commands/shared.ts +7 -2
  142. package/src/modules/sales/components/documents/ItemsSection.tsx +580 -310
  143. package/src/modules/sales/components/documents/LineItemDialog.tsx +1988 -833
  144. package/src/modules/sales/components/documents/ShipmentsSection.tsx +17 -3
  145. package/src/modules/sales/components/documents/lineItemTypes.ts +6 -0
  146. package/src/modules/sales/data/entities.ts +53 -0
  147. package/src/modules/sales/data/validators.ts +36 -0
  148. package/src/modules/sales/frontend/quote/[token]/page.tsx +25 -1
  149. package/src/modules/sales/i18n/de.json +23 -3
  150. package/src/modules/sales/i18n/en.json +23 -3
  151. package/src/modules/sales/i18n/es.json +23 -3
  152. package/src/modules/sales/i18n/pl.json +23 -3
  153. package/src/modules/sales/lib/types.ts +30 -0
  154. package/src/modules/sales/migrations/.snapshot-open-mercato.json +172 -0
  155. package/src/modules/sales/migrations/Migration20260218225423.ts +37 -0
  156. package/src/modules/sales/migrations/Migration20260219084501.ts +73 -0
  157. package/src/modules/sales/search.ts +28 -0
  158. package/src/modules/sales/seed/examples.ts +20 -1
  159. package/src/modules/sales/widgets/injection/document-history/widget.client.tsx +1 -1
  160. package/src/modules/workflows/i18n/de.json +4 -4
  161. package/src/modules/workflows/i18n/en.json +4 -4
  162. package/src/modules/workflows/i18n/es.json +4 -4
  163. package/src/modules/workflows/i18n/pl.json +4 -4
@@ -0,0 +1,27 @@
1
+ import { Migration } from "@mikro-orm/migrations";
2
+ class Migration20260219084500 extends Migration {
3
+ async up() {
4
+ this.addSql(
5
+ `update "catalog_products" set "default_unit" = 'pc' where lower(btrim(coalesce("default_unit", ''))) = 'qty';`
6
+ );
7
+ this.addSql(
8
+ `update "catalog_products" set "default_sales_unit" = 'pc' where lower(btrim(coalesce("default_sales_unit", ''))) = 'qty';`
9
+ );
10
+ this.addSql(
11
+ `update "catalog_products" set "unit_price_reference_unit" = 'pc' where lower(btrim(coalesce("unit_price_reference_unit", ''))) = 'qty';`
12
+ );
13
+ this.addSql(
14
+ `delete from "catalog_product_unit_conversions" as legacy where lower(btrim(coalesce(legacy."unit_code", ''))) = 'qty' and exists (select 1 from "catalog_product_unit_conversions" as canonical where canonical."product_id" = legacy."product_id" and canonical."id" <> legacy."id" and lower(btrim(coalesce(canonical."unit_code", ''))) = 'pc');`
15
+ );
16
+ this.addSql(
17
+ `update "catalog_product_unit_conversions" set "unit_code" = 'pc' where lower(btrim(coalesce("unit_code", ''))) = 'qty';`
18
+ );
19
+ }
20
+ // Irreversible: cannot reconstruct original 'qty' values
21
+ async down() {
22
+ }
23
+ }
24
+ export {
25
+ Migration20260219084500
26
+ };
27
+ //# sourceMappingURL=Migration20260219084500.js.map
@@ -0,0 +1,7 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../../../../src/modules/catalog/migrations/Migration20260219084500.ts"],
4
+ "sourcesContent": ["import { Migration } from \"@mikro-orm/migrations\";\n\n// Data migration: normalize legacy 'qty' unit codes to 'pc'\nexport class Migration20260219084500 extends Migration {\n override async up(): Promise<void> {\n this.addSql(\n `update \"catalog_products\" set \"default_unit\" = 'pc' where lower(btrim(coalesce(\"default_unit\", ''))) = 'qty';`,\n );\n this.addSql(\n `update \"catalog_products\" set \"default_sales_unit\" = 'pc' where lower(btrim(coalesce(\"default_sales_unit\", ''))) = 'qty';`,\n );\n this.addSql(\n `update \"catalog_products\" set \"unit_price_reference_unit\" = 'pc' where lower(btrim(coalesce(\"unit_price_reference_unit\", ''))) = 'qty';`,\n );\n\n this.addSql(\n `delete from \"catalog_product_unit_conversions\" as legacy where lower(btrim(coalesce(legacy.\"unit_code\", ''))) = 'qty' and exists (select 1 from \"catalog_product_unit_conversions\" as canonical where canonical.\"product_id\" = legacy.\"product_id\" and canonical.\"id\" <> legacy.\"id\" and lower(btrim(coalesce(canonical.\"unit_code\", ''))) = 'pc');`,\n );\n this.addSql(\n `update \"catalog_product_unit_conversions\" set \"unit_code\" = 'pc' where lower(btrim(coalesce(\"unit_code\", ''))) = 'qty';`,\n );\n }\n\n // Irreversible: cannot reconstruct original 'qty' values\n override async down(): Promise<void> {}\n}\n"],
5
+ "mappings": "AAAA,SAAS,iBAAiB;AAGnB,MAAM,gCAAgC,UAAU;AAAA,EACrD,MAAe,KAAoB;AACjC,SAAK;AAAA,MACH;AAAA,IACF;AACA,SAAK;AAAA,MACH;AAAA,IACF;AACA,SAAK;AAAA,MACH;AAAA,IACF;AAEA,SAAK;AAAA,MACH;AAAA,IACF;AACA,SAAK;AAAA,MACH;AAAA,IACF;AAAA,EACF;AAAA;AAAA,EAGA,MAAe,OAAsB;AAAA,EAAC;AACxC;",
6
+ "names": []
7
+ }
@@ -179,6 +179,16 @@ function buildPriceKindPresenter(translate, record) {
179
179
  );
180
180
  return { title, subtitle, icon: "dollar-sign", badge: label };
181
181
  }
182
+ function buildUnitConversionPresenter(translate, record) {
183
+ const label = translate("catalog.search.badge.unitConversion", "Unit Conversion");
184
+ const unitCode = readRecordText(record, "unit_code", "unitCode");
185
+ const factor = readRecordText(record, "to_base_factor", "toBaseFactor");
186
+ const title = unitCode ? `${unitCode} (\xD7${factor ?? "?"})` : label;
187
+ const isActive = record.is_active ?? record.isActive;
188
+ const statusText = isActive === false ? translate("catalog.search.status.inactive", "Inactive") : null;
189
+ const subtitle = formatSubtitle(unitCode, statusText);
190
+ return { title, subtitle, icon: "ruler", badge: label };
191
+ }
182
192
  function buildOptionSchemaPresenter(translate, record) {
183
193
  const label = translate("catalog.search.badge.optionSchema", "Option Schema");
184
194
  const title = pickText(
@@ -210,6 +220,26 @@ const searchConfig = {
210
220
  appendLine(lines, "SKU", record.sku);
211
221
  appendLine(lines, "Handle", record.handle);
212
222
  appendLine(lines, "Product type", record.product_type ?? record.productType);
223
+ appendLine(lines, "Base unit", record.default_unit ?? record.defaultUnit);
224
+ appendLine(lines, "Default sales unit", record.default_sales_unit ?? record.defaultSalesUnit);
225
+ appendLine(
226
+ lines,
227
+ "Default sales quantity",
228
+ record.default_sales_unit_quantity ?? record.defaultSalesUnitQuantity
229
+ );
230
+ appendLine(lines, "UoM rounding mode", record.uom_rounding_mode ?? record.uomRoundingMode);
231
+ appendLine(lines, "UoM rounding scale", record.uom_rounding_scale ?? record.uomRoundingScale);
232
+ appendLine(lines, "Unit price enabled", record.unit_price_enabled ?? record.unitPriceEnabled);
233
+ appendLine(
234
+ lines,
235
+ "Unit price reference unit",
236
+ record.unit_price_reference_unit ?? record.unitPriceReferenceUnit
237
+ );
238
+ appendLine(
239
+ lines,
240
+ "Unit price base quantity",
241
+ record.unit_price_base_quantity ?? record.unitPriceBaseQuantity
242
+ );
213
243
  return buildIndexSource(ctx, buildProductPresenter(translate, record), lines);
214
244
  },
215
245
  formatResult: async (ctx) => {
@@ -218,7 +248,17 @@ const searchConfig = {
218
248
  },
219
249
  resolveUrl: async (ctx) => buildProductUrl(readRecordText(ctx.record, "id")),
220
250
  fieldPolicy: {
221
- searchable: ["title", "subtitle", "description", "sku", "handle", "product_type"],
251
+ searchable: [
252
+ "title",
253
+ "subtitle",
254
+ "description",
255
+ "sku",
256
+ "handle",
257
+ "product_type",
258
+ "default_unit",
259
+ "default_sales_unit",
260
+ "unit_price_reference_unit"
261
+ ],
222
262
  excluded: ["metadata", "dimensions", "tax_rate_id"]
223
263
  }
224
264
  },
@@ -344,6 +384,34 @@ const searchConfig = {
344
384
  searchable: ["title", "code"]
345
385
  }
346
386
  },
387
+ {
388
+ entityId: "catalog:catalog_product_unit_conversion",
389
+ enabled: true,
390
+ priority: 3,
391
+ buildSource: async (ctx) => {
392
+ const { t: translate } = await resolveTranslations();
393
+ const record = ctx.record;
394
+ const lines = [];
395
+ appendLine(lines, "Unit code", record.unit_code ?? record.unitCode);
396
+ appendLine(lines, "To base factor", record.to_base_factor ?? record.toBaseFactor);
397
+ appendLine(lines, "Sort order", record.sort_order ?? record.sortOrder);
398
+ const isActive = record.is_active ?? record.isActive;
399
+ appendLine(lines, "Active", isActive);
400
+ return buildIndexSource(ctx, buildUnitConversionPresenter(translate, record), lines);
401
+ },
402
+ formatResult: async (ctx) => {
403
+ const { t: translate } = await resolveTranslations();
404
+ return buildUnitConversionPresenter(translate, ctx.record);
405
+ },
406
+ resolveUrl: async (ctx) => {
407
+ const productId = resolveProductId(ctx.record);
408
+ return buildProductUrl(productId);
409
+ },
410
+ fieldPolicy: {
411
+ searchable: ["unit_code"],
412
+ excluded: ["metadata"]
413
+ }
414
+ },
347
415
  {
348
416
  entityId: "catalog:catalog_option_schema_template",
349
417
  enabled: true,
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../src/modules/catalog/search.ts"],
4
- "sourcesContent": ["import type { SearchBuildContext, SearchIndexSource, SearchModuleConfig, SearchResultPresenter } from '@open-mercato/shared/modules/search'\nimport type { TranslateFn } from '@open-mercato/shared/lib/i18n/context'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\n\nconst CATALOG_PRODUCTS_URL = '/backend/catalog/products'\nconst CATALOG_CATEGORIES_URL = '/backend/catalog/categories'\nconst CATALOG_CONFIG_URL = '/backend/config/catalog'\n\nfunction normalizeText(value: unknown): string | null {\n if (value === null || value === undefined) return null\n if (typeof value === 'string') {\n const trimmed = value.trim()\n return trimmed.length > 0 ? trimmed : null\n }\n if (value instanceof Date) return value.toISOString()\n if (typeof value === 'number' || typeof value === 'boolean') return String(value)\n return null\n}\n\nfunction pickText(...candidates: Array<unknown>): string | null {\n for (const candidate of candidates) {\n const text = normalizeText(candidate)\n if (text) return text\n }\n return null\n}\n\nfunction readRecordText(record: Record<string, unknown>, ...keys: string[]): string | null {\n for (const key of keys) {\n const text = normalizeText(record[key])\n if (text) return text\n }\n return null\n}\n\nfunction formatSubtitle(...parts: Array<unknown>): string | undefined {\n const text = parts\n .map((part) => normalizeText(part))\n .filter((value): value is string => Boolean(value))\n if (!text.length) return undefined\n return text.join(' \u00B7 ')\n}\n\nfunction snippet(value: unknown, maxLength = 140): string | undefined {\n const text = normalizeText(value)\n if (!text) return undefined\n if (text.length <= maxLength) return text\n return `${text.slice(0, maxLength - 3)}...`\n}\n\nfunction appendLine(lines: string[], label: string, value: unknown) {\n if (value === null || value === undefined) return\n const text = Array.isArray(value)\n ? value.map((item) => normalizeText(item)).filter(Boolean).join(', ')\n : typeof value === 'object'\n ? JSON.stringify(value)\n : String(value)\n if (!text.trim()) return\n lines.push(`${label}: ${text}`)\n}\n\nfunction friendlyLabel(input: string): string {\n return input\n .replace(/^cf:/, '')\n .replace(/_/g, ' ')\n .replace(/([a-z])([A-Z])/g, (_match, firstChar, secondChar) => `${firstChar} ${secondChar}`)\n .replace(/\\b\\w/g, (character) => character.toUpperCase())\n}\n\nfunction appendCustomFieldLines(lines: string[], customFields: Record<string, unknown>) {\n for (const [key, value] of Object.entries(customFields)) {\n if (value === null || value === undefined) continue\n appendLine(lines, friendlyLabel(key), value)\n }\n}\n\nfunction buildIndexSource(\n ctx: SearchBuildContext,\n presenter: SearchResultPresenter,\n lines: string[],\n): SearchIndexSource | null {\n appendCustomFieldLines(lines, ctx.customFields)\n if (!lines.length) return null\n return {\n text: lines,\n presenter,\n checksumSource: { record: ctx.record, customFields: ctx.customFields },\n }\n}\n\nfunction buildProductUrl(productId: string | null): string | null {\n if (!productId) return null\n return `${CATALOG_PRODUCTS_URL}/${encodeURIComponent(productId)}`\n}\n\nfunction buildVariantUrl(productId: string | null, variantId: string | null): string | null {\n if (!productId || !variantId) return null\n return `${CATALOG_PRODUCTS_URL}/${encodeURIComponent(productId)}/variants/${encodeURIComponent(variantId)}`\n}\n\nfunction buildCategoryUrl(categoryId: string | null): string | null {\n if (!categoryId) return null\n return `${CATALOG_CATEGORIES_URL}/${encodeURIComponent(categoryId)}/edit`\n}\n\nfunction resolveProductId(record: Record<string, unknown>): string | null {\n // Check direct FK fields first\n const directId = readRecordText(record, 'product_id', 'productId')\n if (directId) return directId\n // Check if product is a string (FK value)\n const product = record.product\n if (typeof product === 'string') return product\n // Check if product is an object with id\n if (product && typeof product === 'object') {\n const productObj = product as Record<string, unknown>\n return readRecordText(productObj, 'id')\n }\n return null\n}\n\nfunction buildProductPresenter(\n translate: TranslateFn,\n record: Record<string, unknown>,\n): SearchResultPresenter {\n const label = translate('catalog.search.badge.product', 'Product')\n const title = pickText(\n readRecordText(record, 'title'),\n readRecordText(record, 'sku'),\n readRecordText(record, 'handle'),\n readRecordText(record, 'id'),\n ) ?? label\n const isActive = record.is_active ?? record.isActive\n const statusText = isActive === false ? translate('catalog.search.status.inactive', 'Inactive') : null\n const subtitle = formatSubtitle(\n readRecordText(record, 'subtitle'),\n readRecordText(record, 'sku'),\n readRecordText(record, 'product_type', 'productType'),\n statusText,\n ) ?? snippet(readRecordText(record, 'description'))\n return { title, subtitle, icon: 'package', badge: label }\n}\n\nfunction buildVariantPresenter(\n translate: TranslateFn,\n record: Record<string, unknown>,\n): SearchResultPresenter {\n const label = translate('catalog.search.badge.variant', 'Variant')\n const isDefault = record.is_default ?? record.isDefault\n const defaultLabel = isDefault ? translate('catalog.search.variant.default', 'Default') : null\n const title = pickText(\n readRecordText(record, 'name'),\n readRecordText(record, 'sku'),\n defaultLabel,\n readRecordText(record, 'id'),\n ) ?? label\n const isActive = record.is_active ?? record.isActive\n const statusText = isActive === false ? translate('catalog.search.status.inactive', 'Inactive') : null\n const subtitle = formatSubtitle(\n readRecordText(record, 'sku'),\n readRecordText(record, 'barcode'),\n defaultLabel,\n statusText,\n )\n return { title, subtitle, icon: 'box', badge: label }\n}\n\nfunction buildCategoryPresenter(\n translate: TranslateFn,\n record: Record<string, unknown>,\n): SearchResultPresenter {\n const label = translate('catalog.search.badge.category', 'Category')\n const title = pickText(\n readRecordText(record, 'name'),\n readRecordText(record, 'slug'),\n readRecordText(record, 'id'),\n ) ?? label\n const isActive = record.is_active ?? record.isActive\n const statusText = isActive === false ? translate('catalog.search.status.inactive', 'Inactive') : null\n const subtitle = formatSubtitle(\n readRecordText(record, 'tree_path', 'treePath'),\n readRecordText(record, 'slug'),\n statusText,\n ) ?? snippet(readRecordText(record, 'description'))\n return { title, subtitle, icon: 'folder-tree', badge: label }\n}\n\nfunction buildOfferPresenter(\n translate: TranslateFn,\n record: Record<string, unknown>,\n channelName?: string | null,\n): SearchResultPresenter {\n const label = translate('catalog.search.badge.offer', 'Channel Offer')\n const channelLabel = channelName ?? readRecordText(record, 'channel_name', 'channelName')\n const title = pickText(\n readRecordText(record, 'title'),\n readRecordText(record, 'id'),\n ) ?? label\n const titleWithChannel = channelLabel ? `${title} \u00B7 ${channelLabel}` : title\n const isActive = record.is_active ?? record.isActive\n const statusText = isActive === false ? translate('catalog.search.status.inactive', 'Inactive') : null\n const subtitle = formatSubtitle(statusText) ?? snippet(readRecordText(record, 'description'))\n return { title: titleWithChannel, subtitle, icon: 'store', badge: label }\n}\n\nfunction buildTagPresenter(\n translate: TranslateFn,\n record: Record<string, unknown>,\n): SearchResultPresenter {\n const label = translate('catalog.search.badge.tag', 'Tag')\n const title = pickText(\n readRecordText(record, 'label'),\n readRecordText(record, 'slug'),\n readRecordText(record, 'id'),\n ) ?? label\n const subtitle = formatSubtitle(readRecordText(record, 'slug'))\n return { title, subtitle, icon: 'tag', badge: label }\n}\n\nfunction buildPriceKindPresenter(\n translate: TranslateFn,\n record: Record<string, unknown>,\n): SearchResultPresenter {\n const label = translate('catalog.search.badge.priceKind', 'Price Kind')\n const title = pickText(\n readRecordText(record, 'title'),\n readRecordText(record, 'code'),\n readRecordText(record, 'id'),\n ) ?? label\n const displayMode = readRecordText(record, 'display_mode', 'displayMode')\n const isPromotion = record.is_promotion ?? record.isPromotion\n const promotionLabel = isPromotion ? translate('catalog.search.priceKind.promotion', 'Promotion') : null\n const displayModeLabel = displayMode === 'including-tax'\n ? translate('catalog.search.priceKind.includingTax', 'Incl. tax')\n : displayMode === 'excluding-tax'\n ? translate('catalog.search.priceKind.excludingTax', 'Excl. tax')\n : null\n const subtitle = formatSubtitle(\n readRecordText(record, 'code'),\n displayModeLabel,\n promotionLabel,\n )\n return { title, subtitle, icon: 'dollar-sign', badge: label }\n}\n\nfunction buildOptionSchemaPresenter(\n translate: TranslateFn,\n record: Record<string, unknown>,\n): SearchResultPresenter {\n const label = translate('catalog.search.badge.optionSchema', 'Option Schema')\n const title = pickText(\n readRecordText(record, 'name'),\n readRecordText(record, 'code'),\n readRecordText(record, 'id'),\n ) ?? label\n const isActive = record.is_active ?? record.isActive\n const statusText = isActive === false ? translate('catalog.search.status.inactive', 'Inactive') : null\n const subtitle = formatSubtitle(\n readRecordText(record, 'code'),\n statusText,\n ) ?? snippet(readRecordText(record, 'description'))\n return { title, subtitle, icon: 'settings', badge: label }\n}\n\nexport const searchConfig: SearchModuleConfig = {\n entities: [\n {\n entityId: 'catalog:catalog_product',\n enabled: true,\n priority: 10,\n buildSource: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Title', record.title)\n appendLine(lines, 'Subtitle', record.subtitle)\n appendLine(lines, 'Description', record.description)\n appendLine(lines, 'SKU', record.sku)\n appendLine(lines, 'Handle', record.handle)\n appendLine(lines, 'Product type', record.product_type ?? record.productType)\n return buildIndexSource(ctx, buildProductPresenter(translate, record), lines)\n },\n formatResult: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n return buildProductPresenter(translate, ctx.record)\n },\n resolveUrl: async (ctx) => buildProductUrl(readRecordText(ctx.record, 'id')),\n fieldPolicy: {\n searchable: ['title', 'subtitle', 'description', 'sku', 'handle', 'product_type'],\n excluded: ['metadata', 'dimensions', 'tax_rate_id'],\n },\n },\n {\n entityId: 'catalog:catalog_product_variant',\n enabled: true,\n priority: 8,\n buildSource: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Name', record.name)\n appendLine(lines, 'SKU', record.sku)\n appendLine(lines, 'Barcode', record.barcode)\n appendLine(lines, 'Option values', record.option_values ?? record.optionValues)\n return buildIndexSource(ctx, buildVariantPresenter(translate, record), lines)\n },\n formatResult: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n return buildVariantPresenter(translate, ctx.record)\n },\n resolveUrl: async (ctx) => {\n const productId = resolveProductId(ctx.record)\n const variantId = readRecordText(ctx.record, 'id')\n return buildVariantUrl(productId, variantId)\n },\n fieldPolicy: {\n searchable: ['name', 'sku', 'barcode'],\n excluded: ['metadata', 'dimensions', 'option_values', 'tax_rate_id'],\n },\n },\n {\n entityId: 'catalog:catalog_product_category',\n enabled: true,\n priority: 7,\n buildSource: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Name', record.name)\n appendLine(lines, 'Slug', record.slug)\n appendLine(lines, 'Description', record.description)\n appendLine(lines, 'Path', record.tree_path ?? record.treePath)\n return buildIndexSource(ctx, buildCategoryPresenter(translate, record), lines)\n },\n formatResult: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n return buildCategoryPresenter(translate, ctx.record)\n },\n resolveUrl: async (ctx) => buildCategoryUrl(readRecordText(ctx.record, 'id')),\n fieldPolicy: {\n searchable: ['name', 'slug', 'description', 'tree_path'],\n excluded: ['metadata', 'ancestor_ids', 'child_ids', 'descendant_ids'],\n },\n },\n {\n entityId: 'catalog:catalog_offer',\n enabled: true,\n priority: 7,\n buildSource: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Title', record.title)\n appendLine(lines, 'Description', record.description)\n appendLine(lines, 'Channel', record.channel_id ?? record.channelId)\n return buildIndexSource(ctx, buildOfferPresenter(translate, record), lines)\n },\n formatResult: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n return buildOfferPresenter(translate, ctx.record)\n },\n resolveUrl: async (ctx) => {\n const productId = resolveProductId(ctx.record)\n return buildProductUrl(productId)\n },\n fieldPolicy: {\n searchable: ['title', 'description'],\n excluded: ['metadata'],\n },\n },\n {\n entityId: 'catalog:catalog_product_tag',\n enabled: true,\n priority: 5,\n buildSource: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Label', record.label)\n appendLine(lines, 'Slug', record.slug)\n return buildIndexSource(ctx, buildTagPresenter(translate, record), lines)\n },\n formatResult: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n return buildTagPresenter(translate, ctx.record)\n },\n resolveUrl: async () => CATALOG_PRODUCTS_URL,\n fieldPolicy: {\n searchable: ['label', 'slug'],\n },\n },\n {\n entityId: 'catalog:catalog_price_kind',\n enabled: true,\n priority: 4,\n buildSource: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Title', record.title)\n appendLine(lines, 'Code', record.code)\n appendLine(lines, 'Display mode', record.display_mode ?? record.displayMode)\n appendLine(lines, 'Currency', record.currency_code ?? record.currencyCode)\n return buildIndexSource(ctx, buildPriceKindPresenter(translate, record), lines)\n },\n formatResult: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n return buildPriceKindPresenter(translate, ctx.record)\n },\n resolveUrl: async () => CATALOG_CONFIG_URL,\n fieldPolicy: {\n searchable: ['title', 'code'],\n },\n },\n {\n entityId: 'catalog:catalog_option_schema_template',\n enabled: true,\n priority: 4,\n buildSource: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Name', record.name)\n appendLine(lines, 'Code', record.code)\n appendLine(lines, 'Description', record.description)\n return buildIndexSource(ctx, buildOptionSchemaPresenter(translate, record), lines)\n },\n formatResult: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n return buildOptionSchemaPresenter(translate, ctx.record)\n },\n resolveUrl: async () => CATALOG_CONFIG_URL,\n fieldPolicy: {\n searchable: ['name', 'code', 'description'],\n excluded: ['schema', 'metadata'],\n },\n },\n ],\n}\n\nexport default searchConfig\nexport const config = searchConfig\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { SearchBuildContext, SearchIndexSource, SearchModuleConfig, SearchResultPresenter } from '@open-mercato/shared/modules/search'\nimport type { TranslateFn } from '@open-mercato/shared/lib/i18n/context'\nimport { resolveTranslations } from '@open-mercato/shared/lib/i18n/server'\n\nconst CATALOG_PRODUCTS_URL = '/backend/catalog/products'\nconst CATALOG_CATEGORIES_URL = '/backend/catalog/categories'\nconst CATALOG_CONFIG_URL = '/backend/config/catalog'\n\nfunction normalizeText(value: unknown): string | null {\n if (value === null || value === undefined) return null\n if (typeof value === 'string') {\n const trimmed = value.trim()\n return trimmed.length > 0 ? trimmed : null\n }\n if (value instanceof Date) return value.toISOString()\n if (typeof value === 'number' || typeof value === 'boolean') return String(value)\n return null\n}\n\nfunction pickText(...candidates: Array<unknown>): string | null {\n for (const candidate of candidates) {\n const text = normalizeText(candidate)\n if (text) return text\n }\n return null\n}\n\nfunction readRecordText(record: Record<string, unknown>, ...keys: string[]): string | null {\n for (const key of keys) {\n const text = normalizeText(record[key])\n if (text) return text\n }\n return null\n}\n\nfunction formatSubtitle(...parts: Array<unknown>): string | undefined {\n const text = parts\n .map((part) => normalizeText(part))\n .filter((value): value is string => Boolean(value))\n if (!text.length) return undefined\n return text.join(' \u00B7 ')\n}\n\nfunction snippet(value: unknown, maxLength = 140): string | undefined {\n const text = normalizeText(value)\n if (!text) return undefined\n if (text.length <= maxLength) return text\n return `${text.slice(0, maxLength - 3)}...`\n}\n\nfunction appendLine(lines: string[], label: string, value: unknown) {\n if (value === null || value === undefined) return\n const text = Array.isArray(value)\n ? value.map((item) => normalizeText(item)).filter(Boolean).join(', ')\n : typeof value === 'object'\n ? JSON.stringify(value)\n : String(value)\n if (!text.trim()) return\n lines.push(`${label}: ${text}`)\n}\n\nfunction friendlyLabel(input: string): string {\n return input\n .replace(/^cf:/, '')\n .replace(/_/g, ' ')\n .replace(/([a-z])([A-Z])/g, (_match, firstChar, secondChar) => `${firstChar} ${secondChar}`)\n .replace(/\\b\\w/g, (character) => character.toUpperCase())\n}\n\nfunction appendCustomFieldLines(lines: string[], customFields: Record<string, unknown>) {\n for (const [key, value] of Object.entries(customFields)) {\n if (value === null || value === undefined) continue\n appendLine(lines, friendlyLabel(key), value)\n }\n}\n\nfunction buildIndexSource(\n ctx: SearchBuildContext,\n presenter: SearchResultPresenter,\n lines: string[],\n): SearchIndexSource | null {\n appendCustomFieldLines(lines, ctx.customFields)\n if (!lines.length) return null\n return {\n text: lines,\n presenter,\n checksumSource: { record: ctx.record, customFields: ctx.customFields },\n }\n}\n\nfunction buildProductUrl(productId: string | null): string | null {\n if (!productId) return null\n return `${CATALOG_PRODUCTS_URL}/${encodeURIComponent(productId)}`\n}\n\nfunction buildVariantUrl(productId: string | null, variantId: string | null): string | null {\n if (!productId || !variantId) return null\n return `${CATALOG_PRODUCTS_URL}/${encodeURIComponent(productId)}/variants/${encodeURIComponent(variantId)}`\n}\n\nfunction buildCategoryUrl(categoryId: string | null): string | null {\n if (!categoryId) return null\n return `${CATALOG_CATEGORIES_URL}/${encodeURIComponent(categoryId)}/edit`\n}\n\nfunction resolveProductId(record: Record<string, unknown>): string | null {\n // Check direct FK fields first\n const directId = readRecordText(record, 'product_id', 'productId')\n if (directId) return directId\n // Check if product is a string (FK value)\n const product = record.product\n if (typeof product === 'string') return product\n // Check if product is an object with id\n if (product && typeof product === 'object') {\n const productObj = product as Record<string, unknown>\n return readRecordText(productObj, 'id')\n }\n return null\n}\n\nfunction buildProductPresenter(\n translate: TranslateFn,\n record: Record<string, unknown>,\n): SearchResultPresenter {\n const label = translate('catalog.search.badge.product', 'Product')\n const title = pickText(\n readRecordText(record, 'title'),\n readRecordText(record, 'sku'),\n readRecordText(record, 'handle'),\n readRecordText(record, 'id'),\n ) ?? label\n const isActive = record.is_active ?? record.isActive\n const statusText = isActive === false ? translate('catalog.search.status.inactive', 'Inactive') : null\n const subtitle = formatSubtitle(\n readRecordText(record, 'subtitle'),\n readRecordText(record, 'sku'),\n readRecordText(record, 'product_type', 'productType'),\n statusText,\n ) ?? snippet(readRecordText(record, 'description'))\n return { title, subtitle, icon: 'package', badge: label }\n}\n\nfunction buildVariantPresenter(\n translate: TranslateFn,\n record: Record<string, unknown>,\n): SearchResultPresenter {\n const label = translate('catalog.search.badge.variant', 'Variant')\n const isDefault = record.is_default ?? record.isDefault\n const defaultLabel = isDefault ? translate('catalog.search.variant.default', 'Default') : null\n const title = pickText(\n readRecordText(record, 'name'),\n readRecordText(record, 'sku'),\n defaultLabel,\n readRecordText(record, 'id'),\n ) ?? label\n const isActive = record.is_active ?? record.isActive\n const statusText = isActive === false ? translate('catalog.search.status.inactive', 'Inactive') : null\n const subtitle = formatSubtitle(\n readRecordText(record, 'sku'),\n readRecordText(record, 'barcode'),\n defaultLabel,\n statusText,\n )\n return { title, subtitle, icon: 'box', badge: label }\n}\n\nfunction buildCategoryPresenter(\n translate: TranslateFn,\n record: Record<string, unknown>,\n): SearchResultPresenter {\n const label = translate('catalog.search.badge.category', 'Category')\n const title = pickText(\n readRecordText(record, 'name'),\n readRecordText(record, 'slug'),\n readRecordText(record, 'id'),\n ) ?? label\n const isActive = record.is_active ?? record.isActive\n const statusText = isActive === false ? translate('catalog.search.status.inactive', 'Inactive') : null\n const subtitle = formatSubtitle(\n readRecordText(record, 'tree_path', 'treePath'),\n readRecordText(record, 'slug'),\n statusText,\n ) ?? snippet(readRecordText(record, 'description'))\n return { title, subtitle, icon: 'folder-tree', badge: label }\n}\n\nfunction buildOfferPresenter(\n translate: TranslateFn,\n record: Record<string, unknown>,\n channelName?: string | null,\n): SearchResultPresenter {\n const label = translate('catalog.search.badge.offer', 'Channel Offer')\n const channelLabel = channelName ?? readRecordText(record, 'channel_name', 'channelName')\n const title = pickText(\n readRecordText(record, 'title'),\n readRecordText(record, 'id'),\n ) ?? label\n const titleWithChannel = channelLabel ? `${title} \u00B7 ${channelLabel}` : title\n const isActive = record.is_active ?? record.isActive\n const statusText = isActive === false ? translate('catalog.search.status.inactive', 'Inactive') : null\n const subtitle = formatSubtitle(statusText) ?? snippet(readRecordText(record, 'description'))\n return { title: titleWithChannel, subtitle, icon: 'store', badge: label }\n}\n\nfunction buildTagPresenter(\n translate: TranslateFn,\n record: Record<string, unknown>,\n): SearchResultPresenter {\n const label = translate('catalog.search.badge.tag', 'Tag')\n const title = pickText(\n readRecordText(record, 'label'),\n readRecordText(record, 'slug'),\n readRecordText(record, 'id'),\n ) ?? label\n const subtitle = formatSubtitle(readRecordText(record, 'slug'))\n return { title, subtitle, icon: 'tag', badge: label }\n}\n\nfunction buildPriceKindPresenter(\n translate: TranslateFn,\n record: Record<string, unknown>,\n): SearchResultPresenter {\n const label = translate('catalog.search.badge.priceKind', 'Price Kind')\n const title = pickText(\n readRecordText(record, 'title'),\n readRecordText(record, 'code'),\n readRecordText(record, 'id'),\n ) ?? label\n const displayMode = readRecordText(record, 'display_mode', 'displayMode')\n const isPromotion = record.is_promotion ?? record.isPromotion\n const promotionLabel = isPromotion ? translate('catalog.search.priceKind.promotion', 'Promotion') : null\n const displayModeLabel = displayMode === 'including-tax'\n ? translate('catalog.search.priceKind.includingTax', 'Incl. tax')\n : displayMode === 'excluding-tax'\n ? translate('catalog.search.priceKind.excludingTax', 'Excl. tax')\n : null\n const subtitle = formatSubtitle(\n readRecordText(record, 'code'),\n displayModeLabel,\n promotionLabel,\n )\n return { title, subtitle, icon: 'dollar-sign', badge: label }\n}\n\nfunction buildUnitConversionPresenter(\n translate: TranslateFn,\n record: Record<string, unknown>,\n): SearchResultPresenter {\n const label = translate('catalog.search.badge.unitConversion', 'Unit Conversion')\n const unitCode = readRecordText(record, 'unit_code', 'unitCode')\n const factor = readRecordText(record, 'to_base_factor', 'toBaseFactor')\n const title = unitCode ? `${unitCode} (\u00D7${factor ?? '?'})` : label\n const isActive = record.is_active ?? record.isActive\n const statusText = isActive === false ? translate('catalog.search.status.inactive', 'Inactive') : null\n const subtitle = formatSubtitle(unitCode, statusText)\n return { title, subtitle, icon: 'ruler', badge: label }\n}\n\nfunction buildOptionSchemaPresenter(\n translate: TranslateFn,\n record: Record<string, unknown>,\n): SearchResultPresenter {\n const label = translate('catalog.search.badge.optionSchema', 'Option Schema')\n const title = pickText(\n readRecordText(record, 'name'),\n readRecordText(record, 'code'),\n readRecordText(record, 'id'),\n ) ?? label\n const isActive = record.is_active ?? record.isActive\n const statusText = isActive === false ? translate('catalog.search.status.inactive', 'Inactive') : null\n const subtitle = formatSubtitle(\n readRecordText(record, 'code'),\n statusText,\n ) ?? snippet(readRecordText(record, 'description'))\n return { title, subtitle, icon: 'settings', badge: label }\n}\n\nexport const searchConfig: SearchModuleConfig = {\n entities: [\n {\n entityId: 'catalog:catalog_product',\n enabled: true,\n priority: 10,\n buildSource: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Title', record.title)\n appendLine(lines, 'Subtitle', record.subtitle)\n appendLine(lines, 'Description', record.description)\n appendLine(lines, 'SKU', record.sku)\n appendLine(lines, 'Handle', record.handle)\n appendLine(lines, 'Product type', record.product_type ?? record.productType)\n appendLine(lines, 'Base unit', record.default_unit ?? record.defaultUnit)\n appendLine(lines, 'Default sales unit', record.default_sales_unit ?? record.defaultSalesUnit)\n appendLine(\n lines,\n 'Default sales quantity',\n record.default_sales_unit_quantity ?? record.defaultSalesUnitQuantity,\n )\n appendLine(lines, 'UoM rounding mode', record.uom_rounding_mode ?? record.uomRoundingMode)\n appendLine(lines, 'UoM rounding scale', record.uom_rounding_scale ?? record.uomRoundingScale)\n appendLine(lines, 'Unit price enabled', record.unit_price_enabled ?? record.unitPriceEnabled)\n appendLine(\n lines,\n 'Unit price reference unit',\n record.unit_price_reference_unit ?? record.unitPriceReferenceUnit,\n )\n appendLine(\n lines,\n 'Unit price base quantity',\n record.unit_price_base_quantity ?? record.unitPriceBaseQuantity,\n )\n return buildIndexSource(ctx, buildProductPresenter(translate, record), lines)\n },\n formatResult: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n return buildProductPresenter(translate, ctx.record)\n },\n resolveUrl: async (ctx) => buildProductUrl(readRecordText(ctx.record, 'id')),\n fieldPolicy: {\n searchable: [\n 'title',\n 'subtitle',\n 'description',\n 'sku',\n 'handle',\n 'product_type',\n 'default_unit',\n 'default_sales_unit',\n 'unit_price_reference_unit',\n ],\n excluded: ['metadata', 'dimensions', 'tax_rate_id'],\n },\n },\n {\n entityId: 'catalog:catalog_product_variant',\n enabled: true,\n priority: 8,\n buildSource: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Name', record.name)\n appendLine(lines, 'SKU', record.sku)\n appendLine(lines, 'Barcode', record.barcode)\n appendLine(lines, 'Option values', record.option_values ?? record.optionValues)\n return buildIndexSource(ctx, buildVariantPresenter(translate, record), lines)\n },\n formatResult: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n return buildVariantPresenter(translate, ctx.record)\n },\n resolveUrl: async (ctx) => {\n const productId = resolveProductId(ctx.record)\n const variantId = readRecordText(ctx.record, 'id')\n return buildVariantUrl(productId, variantId)\n },\n fieldPolicy: {\n searchable: ['name', 'sku', 'barcode'],\n excluded: ['metadata', 'dimensions', 'option_values', 'tax_rate_id'],\n },\n },\n {\n entityId: 'catalog:catalog_product_category',\n enabled: true,\n priority: 7,\n buildSource: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Name', record.name)\n appendLine(lines, 'Slug', record.slug)\n appendLine(lines, 'Description', record.description)\n appendLine(lines, 'Path', record.tree_path ?? record.treePath)\n return buildIndexSource(ctx, buildCategoryPresenter(translate, record), lines)\n },\n formatResult: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n return buildCategoryPresenter(translate, ctx.record)\n },\n resolveUrl: async (ctx) => buildCategoryUrl(readRecordText(ctx.record, 'id')),\n fieldPolicy: {\n searchable: ['name', 'slug', 'description', 'tree_path'],\n excluded: ['metadata', 'ancestor_ids', 'child_ids', 'descendant_ids'],\n },\n },\n {\n entityId: 'catalog:catalog_offer',\n enabled: true,\n priority: 7,\n buildSource: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Title', record.title)\n appendLine(lines, 'Description', record.description)\n appendLine(lines, 'Channel', record.channel_id ?? record.channelId)\n return buildIndexSource(ctx, buildOfferPresenter(translate, record), lines)\n },\n formatResult: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n return buildOfferPresenter(translate, ctx.record)\n },\n resolveUrl: async (ctx) => {\n const productId = resolveProductId(ctx.record)\n return buildProductUrl(productId)\n },\n fieldPolicy: {\n searchable: ['title', 'description'],\n excluded: ['metadata'],\n },\n },\n {\n entityId: 'catalog:catalog_product_tag',\n enabled: true,\n priority: 5,\n buildSource: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Label', record.label)\n appendLine(lines, 'Slug', record.slug)\n return buildIndexSource(ctx, buildTagPresenter(translate, record), lines)\n },\n formatResult: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n return buildTagPresenter(translate, ctx.record)\n },\n resolveUrl: async () => CATALOG_PRODUCTS_URL,\n fieldPolicy: {\n searchable: ['label', 'slug'],\n },\n },\n {\n entityId: 'catalog:catalog_price_kind',\n enabled: true,\n priority: 4,\n buildSource: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Title', record.title)\n appendLine(lines, 'Code', record.code)\n appendLine(lines, 'Display mode', record.display_mode ?? record.displayMode)\n appendLine(lines, 'Currency', record.currency_code ?? record.currencyCode)\n return buildIndexSource(ctx, buildPriceKindPresenter(translate, record), lines)\n },\n formatResult: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n return buildPriceKindPresenter(translate, ctx.record)\n },\n resolveUrl: async () => CATALOG_CONFIG_URL,\n fieldPolicy: {\n searchable: ['title', 'code'],\n },\n },\n {\n entityId: 'catalog:catalog_product_unit_conversion',\n enabled: true,\n priority: 3,\n buildSource: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Unit code', record.unit_code ?? record.unitCode)\n appendLine(lines, 'To base factor', record.to_base_factor ?? record.toBaseFactor)\n appendLine(lines, 'Sort order', record.sort_order ?? record.sortOrder)\n const isActive = record.is_active ?? record.isActive\n appendLine(lines, 'Active', isActive)\n return buildIndexSource(ctx, buildUnitConversionPresenter(translate, record), lines)\n },\n formatResult: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n return buildUnitConversionPresenter(translate, ctx.record)\n },\n resolveUrl: async (ctx) => {\n const productId = resolveProductId(ctx.record)\n return buildProductUrl(productId)\n },\n fieldPolicy: {\n searchable: ['unit_code'],\n excluded: ['metadata'],\n },\n },\n {\n entityId: 'catalog:catalog_option_schema_template',\n enabled: true,\n priority: 4,\n buildSource: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n const record = ctx.record\n const lines: string[] = []\n appendLine(lines, 'Name', record.name)\n appendLine(lines, 'Code', record.code)\n appendLine(lines, 'Description', record.description)\n return buildIndexSource(ctx, buildOptionSchemaPresenter(translate, record), lines)\n },\n formatResult: async (ctx) => {\n const { t: translate } = await resolveTranslations()\n return buildOptionSchemaPresenter(translate, ctx.record)\n },\n resolveUrl: async () => CATALOG_CONFIG_URL,\n fieldPolicy: {\n searchable: ['name', 'code', 'description'],\n excluded: ['schema', 'metadata'],\n },\n },\n ],\n}\n\nexport default searchConfig\nexport const config = searchConfig\n"],
5
+ "mappings": "AAEA,SAAS,2BAA2B;AAEpC,MAAM,uBAAuB;AAC7B,MAAM,yBAAyB;AAC/B,MAAM,qBAAqB;AAE3B,SAAS,cAAc,OAA+B;AACpD,MAAI,UAAU,QAAQ,UAAU,OAAW,QAAO;AAClD,MAAI,OAAO,UAAU,UAAU;AAC7B,UAAM,UAAU,MAAM,KAAK;AAC3B,WAAO,QAAQ,SAAS,IAAI,UAAU;AAAA,EACxC;AACA,MAAI,iBAAiB,KAAM,QAAO,MAAM,YAAY;AACpD,MAAI,OAAO,UAAU,YAAY,OAAO,UAAU,UAAW,QAAO,OAAO,KAAK;AAChF,SAAO;AACT;AAEA,SAAS,YAAY,YAA2C;AAC9D,aAAW,aAAa,YAAY;AAClC,UAAM,OAAO,cAAc,SAAS;AACpC,QAAI,KAAM,QAAO;AAAA,EACnB;AACA,SAAO;AACT;AAEA,SAAS,eAAe,WAAoC,MAA+B;AACzF,aAAW,OAAO,MAAM;AACtB,UAAM,OAAO,cAAc,OAAO,GAAG,CAAC;AACtC,QAAI,KAAM,QAAO;AAAA,EACnB;AACA,SAAO;AACT;AAEA,SAAS,kBAAkB,OAA2C;AACpE,QAAM,OAAO,MACV,IAAI,CAAC,SAAS,cAAc,IAAI,CAAC,EACjC,OAAO,CAAC,UAA2B,QAAQ,KAAK,CAAC;AACpD,MAAI,CAAC,KAAK,OAAQ,QAAO;AACzB,SAAO,KAAK,KAAK,QAAK;AACxB;AAEA,SAAS,QAAQ,OAAgB,YAAY,KAAyB;AACpE,QAAM,OAAO,cAAc,KAAK;AAChC,MAAI,CAAC,KAAM,QAAO;AAClB,MAAI,KAAK,UAAU,UAAW,QAAO;AACrC,SAAO,GAAG,KAAK,MAAM,GAAG,YAAY,CAAC,CAAC;AACxC;AAEA,SAAS,WAAW,OAAiB,OAAe,OAAgB;AAClE,MAAI,UAAU,QAAQ,UAAU,OAAW;AAC3C,QAAM,OAAO,MAAM,QAAQ,KAAK,IAC5B,MAAM,IAAI,CAAC,SAAS,cAAc,IAAI,CAAC,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI,IAClE,OAAO,UAAU,WACf,KAAK,UAAU,KAAK,IACpB,OAAO,KAAK;AAClB,MAAI,CAAC,KAAK,KAAK,EAAG;AAClB,QAAM,KAAK,GAAG,KAAK,KAAK,IAAI,EAAE;AAChC;AAEA,SAAS,cAAc,OAAuB;AAC5C,SAAO,MACJ,QAAQ,QAAQ,EAAE,EAClB,QAAQ,MAAM,GAAG,EACjB,QAAQ,mBAAmB,CAAC,QAAQ,WAAW,eAAe,GAAG,SAAS,IAAI,UAAU,EAAE,EAC1F,QAAQ,SAAS,CAAC,cAAc,UAAU,YAAY,CAAC;AAC5D;AAEA,SAAS,uBAAuB,OAAiB,cAAuC;AACtF,aAAW,CAAC,KAAK,KAAK,KAAK,OAAO,QAAQ,YAAY,GAAG;AACvD,QAAI,UAAU,QAAQ,UAAU,OAAW;AAC3C,eAAW,OAAO,cAAc,GAAG,GAAG,KAAK;AAAA,EAC7C;AACF;AAEA,SAAS,iBACP,KACA,WACA,OAC0B;AAC1B,yBAAuB,OAAO,IAAI,YAAY;AAC9C,MAAI,CAAC,MAAM,OAAQ,QAAO;AAC1B,SAAO;AAAA,IACL,MAAM;AAAA,IACN;AAAA,IACA,gBAAgB,EAAE,QAAQ,IAAI,QAAQ,cAAc,IAAI,aAAa;AAAA,EACvE;AACF;AAEA,SAAS,gBAAgB,WAAyC;AAChE,MAAI,CAAC,UAAW,QAAO;AACvB,SAAO,GAAG,oBAAoB,IAAI,mBAAmB,SAAS,CAAC;AACjE;AAEA,SAAS,gBAAgB,WAA0B,WAAyC;AAC1F,MAAI,CAAC,aAAa,CAAC,UAAW,QAAO;AACrC,SAAO,GAAG,oBAAoB,IAAI,mBAAmB,SAAS,CAAC,aAAa,mBAAmB,SAAS,CAAC;AAC3G;AAEA,SAAS,iBAAiB,YAA0C;AAClE,MAAI,CAAC,WAAY,QAAO;AACxB,SAAO,GAAG,sBAAsB,IAAI,mBAAmB,UAAU,CAAC;AACpE;AAEA,SAAS,iBAAiB,QAAgD;AAExE,QAAM,WAAW,eAAe,QAAQ,cAAc,WAAW;AACjE,MAAI,SAAU,QAAO;AAErB,QAAM,UAAU,OAAO;AACvB,MAAI,OAAO,YAAY,SAAU,QAAO;AAExC,MAAI,WAAW,OAAO,YAAY,UAAU;AAC1C,UAAM,aAAa;AACnB,WAAO,eAAe,YAAY,IAAI;AAAA,EACxC;AACA,SAAO;AACT;AAEA,SAAS,sBACP,WACA,QACuB;AACvB,QAAM,QAAQ,UAAU,gCAAgC,SAAS;AACjE,QAAM,QAAQ;AAAA,IACZ,eAAe,QAAQ,OAAO;AAAA,IAC9B,eAAe,QAAQ,KAAK;AAAA,IAC5B,eAAe,QAAQ,QAAQ;AAAA,IAC/B,eAAe,QAAQ,IAAI;AAAA,EAC7B,KAAK;AACL,QAAM,WAAW,OAAO,aAAa,OAAO;AAC5C,QAAM,aAAa,aAAa,QAAQ,UAAU,kCAAkC,UAAU,IAAI;AAClG,QAAM,WAAW;AAAA,IACf,eAAe,QAAQ,UAAU;AAAA,IACjC,eAAe,QAAQ,KAAK;AAAA,IAC5B,eAAe,QAAQ,gBAAgB,aAAa;AAAA,IACpD;AAAA,EACF,KAAK,QAAQ,eAAe,QAAQ,aAAa,CAAC;AAClD,SAAO,EAAE,OAAO,UAAU,MAAM,WAAW,OAAO,MAAM;AAC1D;AAEA,SAAS,sBACP,WACA,QACuB;AACvB,QAAM,QAAQ,UAAU,gCAAgC,SAAS;AACjE,QAAM,YAAY,OAAO,cAAc,OAAO;AAC9C,QAAM,eAAe,YAAY,UAAU,kCAAkC,SAAS,IAAI;AAC1F,QAAM,QAAQ;AAAA,IACZ,eAAe,QAAQ,MAAM;AAAA,IAC7B,eAAe,QAAQ,KAAK;AAAA,IAC5B;AAAA,IACA,eAAe,QAAQ,IAAI;AAAA,EAC7B,KAAK;AACL,QAAM,WAAW,OAAO,aAAa,OAAO;AAC5C,QAAM,aAAa,aAAa,QAAQ,UAAU,kCAAkC,UAAU,IAAI;AAClG,QAAM,WAAW;AAAA,IACf,eAAe,QAAQ,KAAK;AAAA,IAC5B,eAAe,QAAQ,SAAS;AAAA,IAChC;AAAA,IACA;AAAA,EACF;AACA,SAAO,EAAE,OAAO,UAAU,MAAM,OAAO,OAAO,MAAM;AACtD;AAEA,SAAS,uBACP,WACA,QACuB;AACvB,QAAM,QAAQ,UAAU,iCAAiC,UAAU;AACnE,QAAM,QAAQ;AAAA,IACZ,eAAe,QAAQ,MAAM;AAAA,IAC7B,eAAe,QAAQ,MAAM;AAAA,IAC7B,eAAe,QAAQ,IAAI;AAAA,EAC7B,KAAK;AACL,QAAM,WAAW,OAAO,aAAa,OAAO;AAC5C,QAAM,aAAa,aAAa,QAAQ,UAAU,kCAAkC,UAAU,IAAI;AAClG,QAAM,WAAW;AAAA,IACf,eAAe,QAAQ,aAAa,UAAU;AAAA,IAC9C,eAAe,QAAQ,MAAM;AAAA,IAC7B;AAAA,EACF,KAAK,QAAQ,eAAe,QAAQ,aAAa,CAAC;AAClD,SAAO,EAAE,OAAO,UAAU,MAAM,eAAe,OAAO,MAAM;AAC9D;AAEA,SAAS,oBACP,WACA,QACA,aACuB;AACvB,QAAM,QAAQ,UAAU,8BAA8B,eAAe;AACrE,QAAM,eAAe,eAAe,eAAe,QAAQ,gBAAgB,aAAa;AACxF,QAAM,QAAQ;AAAA,IACZ,eAAe,QAAQ,OAAO;AAAA,IAC9B,eAAe,QAAQ,IAAI;AAAA,EAC7B,KAAK;AACL,QAAM,mBAAmB,eAAe,GAAG,KAAK,SAAM,YAAY,KAAK;AACvE,QAAM,WAAW,OAAO,aAAa,OAAO;AAC5C,QAAM,aAAa,aAAa,QAAQ,UAAU,kCAAkC,UAAU,IAAI;AAClG,QAAM,WAAW,eAAe,UAAU,KAAK,QAAQ,eAAe,QAAQ,aAAa,CAAC;AAC5F,SAAO,EAAE,OAAO,kBAAkB,UAAU,MAAM,SAAS,OAAO,MAAM;AAC1E;AAEA,SAAS,kBACP,WACA,QACuB;AACvB,QAAM,QAAQ,UAAU,4BAA4B,KAAK;AACzD,QAAM,QAAQ;AAAA,IACZ,eAAe,QAAQ,OAAO;AAAA,IAC9B,eAAe,QAAQ,MAAM;AAAA,IAC7B,eAAe,QAAQ,IAAI;AAAA,EAC7B,KAAK;AACL,QAAM,WAAW,eAAe,eAAe,QAAQ,MAAM,CAAC;AAC9D,SAAO,EAAE,OAAO,UAAU,MAAM,OAAO,OAAO,MAAM;AACtD;AAEA,SAAS,wBACP,WACA,QACuB;AACvB,QAAM,QAAQ,UAAU,kCAAkC,YAAY;AACtE,QAAM,QAAQ;AAAA,IACZ,eAAe,QAAQ,OAAO;AAAA,IAC9B,eAAe,QAAQ,MAAM;AAAA,IAC7B,eAAe,QAAQ,IAAI;AAAA,EAC7B,KAAK;AACL,QAAM,cAAc,eAAe,QAAQ,gBAAgB,aAAa;AACxE,QAAM,cAAc,OAAO,gBAAgB,OAAO;AAClD,QAAM,iBAAiB,cAAc,UAAU,sCAAsC,WAAW,IAAI;AACpG,QAAM,mBAAmB,gBAAgB,kBACrC,UAAU,yCAAyC,WAAW,IAC9D,gBAAgB,kBACd,UAAU,yCAAyC,WAAW,IAC9D;AACN,QAAM,WAAW;AAAA,IACf,eAAe,QAAQ,MAAM;AAAA,IAC7B;AAAA,IACA;AAAA,EACF;AACA,SAAO,EAAE,OAAO,UAAU,MAAM,eAAe,OAAO,MAAM;AAC9D;AAEA,SAAS,6BACP,WACA,QACuB;AACvB,QAAM,QAAQ,UAAU,uCAAuC,iBAAiB;AAChF,QAAM,WAAW,eAAe,QAAQ,aAAa,UAAU;AAC/D,QAAM,SAAS,eAAe,QAAQ,kBAAkB,cAAc;AACtE,QAAM,QAAQ,WAAW,GAAG,QAAQ,SAAM,UAAU,GAAG,MAAM;AAC7D,QAAM,WAAW,OAAO,aAAa,OAAO;AAC5C,QAAM,aAAa,aAAa,QAAQ,UAAU,kCAAkC,UAAU,IAAI;AAClG,QAAM,WAAW,eAAe,UAAU,UAAU;AACpD,SAAO,EAAE,OAAO,UAAU,MAAM,SAAS,OAAO,MAAM;AACxD;AAEA,SAAS,2BACP,WACA,QACuB;AACvB,QAAM,QAAQ,UAAU,qCAAqC,eAAe;AAC5E,QAAM,QAAQ;AAAA,IACZ,eAAe,QAAQ,MAAM;AAAA,IAC7B,eAAe,QAAQ,MAAM;AAAA,IAC7B,eAAe,QAAQ,IAAI;AAAA,EAC7B,KAAK;AACL,QAAM,WAAW,OAAO,aAAa,OAAO;AAC5C,QAAM,aAAa,aAAa,QAAQ,UAAU,kCAAkC,UAAU,IAAI;AAClG,QAAM,WAAW;AAAA,IACf,eAAe,QAAQ,MAAM;AAAA,IAC7B;AAAA,EACF,KAAK,QAAQ,eAAe,QAAQ,aAAa,CAAC;AAClD,SAAO,EAAE,OAAO,UAAU,MAAM,YAAY,OAAO,MAAM;AAC3D;AAEO,MAAM,eAAmC;AAAA,EAC9C,UAAU;AAAA,IACR;AAAA,MACE,UAAU;AAAA,MACV,SAAS;AAAA,MACT,UAAU;AAAA,MACV,aAAa,OAAO,QAAQ;AAC1B,cAAM,EAAE,GAAG,UAAU,IAAI,MAAM,oBAAoB;AACnD,cAAM,SAAS,IAAI;AACnB,cAAM,QAAkB,CAAC;AACzB,mBAAW,OAAO,SAAS,OAAO,KAAK;AACvC,mBAAW,OAAO,YAAY,OAAO,QAAQ;AAC7C,mBAAW,OAAO,eAAe,OAAO,WAAW;AACnD,mBAAW,OAAO,OAAO,OAAO,GAAG;AACnC,mBAAW,OAAO,UAAU,OAAO,MAAM;AACzC,mBAAW,OAAO,gBAAgB,OAAO,gBAAgB,OAAO,WAAW;AAC3E,mBAAW,OAAO,aAAa,OAAO,gBAAgB,OAAO,WAAW;AACxE,mBAAW,OAAO,sBAAsB,OAAO,sBAAsB,OAAO,gBAAgB;AAC5F;AAAA,UACE;AAAA,UACA;AAAA,UACA,OAAO,+BAA+B,OAAO;AAAA,QAC/C;AACA,mBAAW,OAAO,qBAAqB,OAAO,qBAAqB,OAAO,eAAe;AACzF,mBAAW,OAAO,sBAAsB,OAAO,sBAAsB,OAAO,gBAAgB;AAC5F,mBAAW,OAAO,sBAAsB,OAAO,sBAAsB,OAAO,gBAAgB;AAC5F;AAAA,UACE;AAAA,UACA;AAAA,UACA,OAAO,6BAA6B,OAAO;AAAA,QAC7C;AACA;AAAA,UACE;AAAA,UACA;AAAA,UACA,OAAO,4BAA4B,OAAO;AAAA,QAC5C;AACA,eAAO,iBAAiB,KAAK,sBAAsB,WAAW,MAAM,GAAG,KAAK;AAAA,MAC9E;AAAA,MACA,cAAc,OAAO,QAAQ;AAC3B,cAAM,EAAE,GAAG,UAAU,IAAI,MAAM,oBAAoB;AACnD,eAAO,sBAAsB,WAAW,IAAI,MAAM;AAAA,MACpD;AAAA,MACA,YAAY,OAAO,QAAQ,gBAAgB,eAAe,IAAI,QAAQ,IAAI,CAAC;AAAA,MAC3E,aAAa;AAAA,QACX,YAAY;AAAA,UACV;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,UACA;AAAA,QACF;AAAA,QACA,UAAU,CAAC,YAAY,cAAc,aAAa;AAAA,MACpD;AAAA,IACF;AAAA,IACA;AAAA,MACE,UAAU;AAAA,MACV,SAAS;AAAA,MACT,UAAU;AAAA,MACV,aAAa,OAAO,QAAQ;AAC1B,cAAM,EAAE,GAAG,UAAU,IAAI,MAAM,oBAAoB;AACnD,cAAM,SAAS,IAAI;AACnB,cAAM,QAAkB,CAAC;AACzB,mBAAW,OAAO,QAAQ,OAAO,IAAI;AACrC,mBAAW,OAAO,OAAO,OAAO,GAAG;AACnC,mBAAW,OAAO,WAAW,OAAO,OAAO;AAC3C,mBAAW,OAAO,iBAAiB,OAAO,iBAAiB,OAAO,YAAY;AAC9E,eAAO,iBAAiB,KAAK,sBAAsB,WAAW,MAAM,GAAG,KAAK;AAAA,MAC9E;AAAA,MACA,cAAc,OAAO,QAAQ;AAC3B,cAAM,EAAE,GAAG,UAAU,IAAI,MAAM,oBAAoB;AACnD,eAAO,sBAAsB,WAAW,IAAI,MAAM;AAAA,MACpD;AAAA,MACA,YAAY,OAAO,QAAQ;AACzB,cAAM,YAAY,iBAAiB,IAAI,MAAM;AAC7C,cAAM,YAAY,eAAe,IAAI,QAAQ,IAAI;AACjD,eAAO,gBAAgB,WAAW,SAAS;AAAA,MAC7C;AAAA,MACA,aAAa;AAAA,QACX,YAAY,CAAC,QAAQ,OAAO,SAAS;AAAA,QACrC,UAAU,CAAC,YAAY,cAAc,iBAAiB,aAAa;AAAA,MACrE;AAAA,IACF;AAAA,IACA;AAAA,MACE,UAAU;AAAA,MACV,SAAS;AAAA,MACT,UAAU;AAAA,MACV,aAAa,OAAO,QAAQ;AAC1B,cAAM,EAAE,GAAG,UAAU,IAAI,MAAM,oBAAoB;AACnD,cAAM,SAAS,IAAI;AACnB,cAAM,QAAkB,CAAC;AACzB,mBAAW,OAAO,QAAQ,OAAO,IAAI;AACrC,mBAAW,OAAO,QAAQ,OAAO,IAAI;AACrC,mBAAW,OAAO,eAAe,OAAO,WAAW;AACnD,mBAAW,OAAO,QAAQ,OAAO,aAAa,OAAO,QAAQ;AAC7D,eAAO,iBAAiB,KAAK,uBAAuB,WAAW,MAAM,GAAG,KAAK;AAAA,MAC/E;AAAA,MACA,cAAc,OAAO,QAAQ;AAC3B,cAAM,EAAE,GAAG,UAAU,IAAI,MAAM,oBAAoB;AACnD,eAAO,uBAAuB,WAAW,IAAI,MAAM;AAAA,MACrD;AAAA,MACA,YAAY,OAAO,QAAQ,iBAAiB,eAAe,IAAI,QAAQ,IAAI,CAAC;AAAA,MAC5E,aAAa;AAAA,QACX,YAAY,CAAC,QAAQ,QAAQ,eAAe,WAAW;AAAA,QACvD,UAAU,CAAC,YAAY,gBAAgB,aAAa,gBAAgB;AAAA,MACtE;AAAA,IACF;AAAA,IACA;AAAA,MACE,UAAU;AAAA,MACV,SAAS;AAAA,MACT,UAAU;AAAA,MACV,aAAa,OAAO,QAAQ;AAC1B,cAAM,EAAE,GAAG,UAAU,IAAI,MAAM,oBAAoB;AACnD,cAAM,SAAS,IAAI;AACnB,cAAM,QAAkB,CAAC;AACzB,mBAAW,OAAO,SAAS,OAAO,KAAK;AACvC,mBAAW,OAAO,eAAe,OAAO,WAAW;AACnD,mBAAW,OAAO,WAAW,OAAO,cAAc,OAAO,SAAS;AAClE,eAAO,iBAAiB,KAAK,oBAAoB,WAAW,MAAM,GAAG,KAAK;AAAA,MAC5E;AAAA,MACA,cAAc,OAAO,QAAQ;AAC3B,cAAM,EAAE,GAAG,UAAU,IAAI,MAAM,oBAAoB;AACnD,eAAO,oBAAoB,WAAW,IAAI,MAAM;AAAA,MAClD;AAAA,MACA,YAAY,OAAO,QAAQ;AACzB,cAAM,YAAY,iBAAiB,IAAI,MAAM;AAC7C,eAAO,gBAAgB,SAAS;AAAA,MAClC;AAAA,MACA,aAAa;AAAA,QACX,YAAY,CAAC,SAAS,aAAa;AAAA,QACnC,UAAU,CAAC,UAAU;AAAA,MACvB;AAAA,IACF;AAAA,IACA;AAAA,MACE,UAAU;AAAA,MACV,SAAS;AAAA,MACT,UAAU;AAAA,MACV,aAAa,OAAO,QAAQ;AAC1B,cAAM,EAAE,GAAG,UAAU,IAAI,MAAM,oBAAoB;AACnD,cAAM,SAAS,IAAI;AACnB,cAAM,QAAkB,CAAC;AACzB,mBAAW,OAAO,SAAS,OAAO,KAAK;AACvC,mBAAW,OAAO,QAAQ,OAAO,IAAI;AACrC,eAAO,iBAAiB,KAAK,kBAAkB,WAAW,MAAM,GAAG,KAAK;AAAA,MAC1E;AAAA,MACA,cAAc,OAAO,QAAQ;AAC3B,cAAM,EAAE,GAAG,UAAU,IAAI,MAAM,oBAAoB;AACnD,eAAO,kBAAkB,WAAW,IAAI,MAAM;AAAA,MAChD;AAAA,MACA,YAAY,YAAY;AAAA,MACxB,aAAa;AAAA,QACX,YAAY,CAAC,SAAS,MAAM;AAAA,MAC9B;AAAA,IACF;AAAA,IACA;AAAA,MACE,UAAU;AAAA,MACV,SAAS;AAAA,MACT,UAAU;AAAA,MACV,aAAa,OAAO,QAAQ;AAC1B,cAAM,EAAE,GAAG,UAAU,IAAI,MAAM,oBAAoB;AACnD,cAAM,SAAS,IAAI;AACnB,cAAM,QAAkB,CAAC;AACzB,mBAAW,OAAO,SAAS,OAAO,KAAK;AACvC,mBAAW,OAAO,QAAQ,OAAO,IAAI;AACrC,mBAAW,OAAO,gBAAgB,OAAO,gBAAgB,OAAO,WAAW;AAC3E,mBAAW,OAAO,YAAY,OAAO,iBAAiB,OAAO,YAAY;AACzE,eAAO,iBAAiB,KAAK,wBAAwB,WAAW,MAAM,GAAG,KAAK;AAAA,MAChF;AAAA,MACA,cAAc,OAAO,QAAQ;AAC3B,cAAM,EAAE,GAAG,UAAU,IAAI,MAAM,oBAAoB;AACnD,eAAO,wBAAwB,WAAW,IAAI,MAAM;AAAA,MACtD;AAAA,MACA,YAAY,YAAY;AAAA,MACxB,aAAa;AAAA,QACX,YAAY,CAAC,SAAS,MAAM;AAAA,MAC9B;AAAA,IACF;AAAA,IACA;AAAA,MACE,UAAU;AAAA,MACV,SAAS;AAAA,MACT,UAAU;AAAA,MACV,aAAa,OAAO,QAAQ;AAC1B,cAAM,EAAE,GAAG,UAAU,IAAI,MAAM,oBAAoB;AACnD,cAAM,SAAS,IAAI;AACnB,cAAM,QAAkB,CAAC;AACzB,mBAAW,OAAO,aAAa,OAAO,aAAa,OAAO,QAAQ;AAClE,mBAAW,OAAO,kBAAkB,OAAO,kBAAkB,OAAO,YAAY;AAChF,mBAAW,OAAO,cAAc,OAAO,cAAc,OAAO,SAAS;AACrE,cAAM,WAAW,OAAO,aAAa,OAAO;AAC5C,mBAAW,OAAO,UAAU,QAAQ;AACpC,eAAO,iBAAiB,KAAK,6BAA6B,WAAW,MAAM,GAAG,KAAK;AAAA,MACrF;AAAA,MACA,cAAc,OAAO,QAAQ;AAC3B,cAAM,EAAE,GAAG,UAAU,IAAI,MAAM,oBAAoB;AACnD,eAAO,6BAA6B,WAAW,IAAI,MAAM;AAAA,MAC3D;AAAA,MACA,YAAY,OAAO,QAAQ;AACzB,cAAM,YAAY,iBAAiB,IAAI,MAAM;AAC7C,eAAO,gBAAgB,SAAS;AAAA,MAClC;AAAA,MACA,aAAa;AAAA,QACX,YAAY,CAAC,WAAW;AAAA,QACxB,UAAU,CAAC,UAAU;AAAA,MACvB;AAAA,IACF;AAAA,IACA;AAAA,MACE,UAAU;AAAA,MACV,SAAS;AAAA,MACT,UAAU;AAAA,MACV,aAAa,OAAO,QAAQ;AAC1B,cAAM,EAAE,GAAG,UAAU,IAAI,MAAM,oBAAoB;AACnD,cAAM,SAAS,IAAI;AACnB,cAAM,QAAkB,CAAC;AACzB,mBAAW,OAAO,QAAQ,OAAO,IAAI;AACrC,mBAAW,OAAO,QAAQ,OAAO,IAAI;AACrC,mBAAW,OAAO,eAAe,OAAO,WAAW;AACnD,eAAO,iBAAiB,KAAK,2BAA2B,WAAW,MAAM,GAAG,KAAK;AAAA,MACnF;AAAA,MACA,cAAc,OAAO,QAAQ;AAC3B,cAAM,EAAE,GAAG,UAAU,IAAI,MAAM,oBAAoB;AACnD,eAAO,2BAA2B,WAAW,IAAI,MAAM;AAAA,MACzD;AAAA,MACA,YAAY,YAAY;AAAA,MACxB,aAAa;AAAA,QACX,YAAY,CAAC,QAAQ,QAAQ,aAAa;AAAA,QAC1C,UAAU,CAAC,UAAU,UAAU;AAAA,MACjC;AAAA,IACF;AAAA,EACF;AACF;AAEA,IAAO,iBAAQ;AACR,MAAM,SAAS;",
6
6
  "names": []
7
7
  }
@@ -12,17 +12,30 @@ import {
12
12
  CatalogProductVariant
13
13
  } from "../data/entities.js";
14
14
  import { DefaultDataEngine } from "@open-mercato/shared/lib/data/engine";
15
- import { ensureCustomFieldDefinitions } from "@open-mercato/core/modules/entities/lib/field-definitions";
15
+ import {
16
+ ensureCustomFieldDefinitions
17
+ } from "@open-mercato/core/modules/entities/lib/field-definitions";
16
18
  import { CustomFieldEntityConfig } from "@open-mercato/core/modules/entities/data/entities";
17
19
  import { rebuildCategoryHierarchyForOrganization } from "../lib/categoryHierarchy.js";
18
20
  import { defineFields, cf } from "@open-mercato/shared/modules/dsl";
19
21
  import { E } from "../../../generated/entities.ids.generated.js";
20
22
  import { SalesTaxRate } from "@open-mercato/core/modules/sales/data/entities";
21
- import { Attachment, AttachmentPartition } from "@open-mercato/core/modules/attachments/data/entities";
22
- import { ensureDefaultPartitions, resolveDefaultPartitionCode } from "@open-mercato/core/modules/attachments/lib/partitions";
23
+ import {
24
+ Attachment,
25
+ AttachmentPartition
26
+ } from "@open-mercato/core/modules/attachments/data/entities";
27
+ import {
28
+ ensureDefaultPartitions,
29
+ resolveDefaultPartitionCode
30
+ } from "@open-mercato/core/modules/attachments/lib/partitions";
23
31
  import { storePartitionFile } from "@open-mercato/core/modules/attachments/lib/storage";
24
32
  import { mergeAttachmentMetadata } from "@open-mercato/core/modules/attachments/lib/metadata";
25
- import { buildAttachmentFileUrl, buildAttachmentImageUrl, slugifyAttachmentFileName } from "@open-mercato/core/modules/attachments/lib/imageUrls";
33
+ import {
34
+ buildAttachmentFileUrl,
35
+ buildAttachmentImageUrl,
36
+ slugifyAttachmentFileName
37
+ } from "@open-mercato/core/modules/attachments/lib/imageUrls";
38
+ import { canonicalizeUnitCode } from "../lib/unitCodes.js";
26
39
  const EXAMPLES_MEDIA_ROOT = path.join(process.cwd(), "public", "examples");
27
40
  function detectMimeType(fileName) {
28
41
  const ext = fileName.toLowerCase().split(".").pop() || "";
@@ -168,12 +181,16 @@ const CUSTOM_FIELD_SETS = [
168
181
  fieldset: "fashion_mens_footwear",
169
182
  group: { code: "identity" }
170
183
  }),
171
- cf.select("upper_material", ["engineered_knit", "full_grain_leather", "recycled_mesh"], {
172
- label: "Upper material",
173
- fieldset: "fashion_mens_footwear",
174
- group: { code: "materials" },
175
- filterable: true
176
- }),
184
+ cf.select(
185
+ "upper_material",
186
+ ["engineered_knit", "full_grain_leather", "recycled_mesh"],
187
+ {
188
+ label: "Upper material",
189
+ fieldset: "fashion_mens_footwear",
190
+ group: { code: "materials" },
191
+ filterable: true
192
+ }
193
+ ),
177
194
  cf.select("cushioning_profile", ["responsive", "plush", "stability"], {
178
195
  label: "Cushioning profile",
179
196
  fieldset: "fashion_mens_footwear",
@@ -266,13 +283,17 @@ const CUSTOM_FIELD_SETS = [
266
283
  fieldset: "service_schedule",
267
284
  group: { code: "identity" }
268
285
  }),
269
- cf.select("service_resources", ["stylist", "therapist", "treatment_room", "wash_station", "steam_room"], {
270
- label: "Required resources",
271
- description: "Staff or rooms required to perform the service.",
272
- fieldset: "service_schedule",
273
- group: { code: "resources" },
274
- multi: true
275
- }),
286
+ cf.select(
287
+ "service_resources",
288
+ ["stylist", "therapist", "treatment_room", "wash_station", "steam_room"],
289
+ {
290
+ label: "Required resources",
291
+ description: "Staff or rooms required to perform the service.",
292
+ fieldset: "service_schedule",
293
+ group: { code: "resources" },
294
+ multi: true
295
+ }
296
+ ),
276
297
  cf.boolean("service_remote_available", {
277
298
  label: "Remote session available",
278
299
  description: "Indicates whether the service can be performed remotely or virtually.",
@@ -368,9 +389,7 @@ const PRODUCT_SEEDS = [
368
389
  cushioning_profile: "responsive",
369
390
  care_notes: "Spot clean after each run and air dry. Avoid machine drying."
370
391
  },
371
- media: [
372
- { file: "atlas-runner-midnight-1.png" }
373
- ],
392
+ media: [{ file: "atlas-runner-midnight-1.png" }],
374
393
  variants: [
375
394
  {
376
395
  name: "Midnight Navy \xB7 US 8",
@@ -378,7 +397,11 @@ const PRODUCT_SEEDS = [
378
397
  isDefault: true,
379
398
  optionValues: { color: "Midnight Navy", size: "US 8" },
380
399
  prices: { regular: 168, sale: 148 },
381
- customFields: { shoe_size: 8, shoe_width: "D", colorway: "Midnight Navy" },
400
+ customFields: {
401
+ shoe_size: 8,
402
+ shoe_width: "D",
403
+ colorway: "Midnight Navy"
404
+ },
382
405
  media: [
383
406
  { file: "atlas-runner-midnight-1.png" },
384
407
  { file: "atlas-runner-midnight-2.png" }
@@ -389,7 +412,11 @@ const PRODUCT_SEEDS = [
389
412
  sku: "ATLAS-RUN-GLACIER-10",
390
413
  optionValues: { color: "Glacier Grey", size: "US 10" },
391
414
  prices: { regular: 168, sale: 138 },
392
- customFields: { shoe_size: 10, shoe_width: "EE", colorway: "Glacier Grey" },
415
+ customFields: {
416
+ shoe_size: 10,
417
+ shoe_width: "EE",
418
+ colorway: "Glacier Grey"
419
+ },
393
420
  media: [
394
421
  { file: "atlas-runner-glacier-1.png" },
395
422
  { file: "atlas-runner-glacier-2.png" }
@@ -413,9 +440,7 @@ const PRODUCT_SEEDS = [
413
440
  occasion_ready: "evening",
414
441
  finishing_details: "Hand-finished hem with subtle tonal beading along the wrap edge."
415
442
  },
416
- media: [
417
- { file: "aurora-wrap-rosewood.png" }
418
- ],
443
+ media: [{ file: "aurora-wrap-rosewood.png" }],
419
444
  variants: [
420
445
  {
421
446
  name: "Rosewood \xB7 Medium",
@@ -423,20 +448,24 @@ const PRODUCT_SEEDS = [
423
448
  isDefault: true,
424
449
  optionValues: { color: "Rosewood", size: "Medium" },
425
450
  prices: { regular: 248, sale: 212 },
426
- customFields: { numeric_size: 6, length_profile: "midi", color_story: "Rosewood" },
427
- media: [
428
- { file: "aurora-wrap-rosewood.png" }
429
- ]
451
+ customFields: {
452
+ numeric_size: 6,
453
+ length_profile: "midi",
454
+ color_story: "Rosewood"
455
+ },
456
+ media: [{ file: "aurora-wrap-rosewood.png" }]
430
457
  },
431
458
  {
432
459
  name: "Celestial \xB7 Large",
433
460
  sku: "AURORA-CELESTIAL-L",
434
461
  optionValues: { color: "Celestial", size: "Large" },
435
462
  prices: { regular: 248, sale: 198 },
436
- customFields: { numeric_size: 8, length_profile: "maxi", color_story: "Celestial blue" },
437
- media: [
438
- { file: "aurora-wrap-celestial.png" }
439
- ]
463
+ customFields: {
464
+ numeric_size: 8,
465
+ length_profile: "maxi",
466
+ color_story: "Celestial blue"
467
+ },
468
+ media: [{ file: "aurora-wrap-celestial.png" }]
440
469
  }
441
470
  ]
442
471
  },
@@ -566,8 +595,18 @@ async function ensureFieldsetConfig(em, scope, entityId, fieldsets) {
566
595
  em.persist(config);
567
596
  }
568
597
  async function ensureFieldsetsAndDefinitions(em, scope) {
569
- await ensureFieldsetConfig(em, scope, E.catalog.catalog_product, PRODUCT_FIELDSETS);
570
- await ensureFieldsetConfig(em, scope, E.catalog.catalog_product_variant, VARIANT_FIELDSETS);
598
+ await ensureFieldsetConfig(
599
+ em,
600
+ scope,
601
+ E.catalog.catalog_product,
602
+ PRODUCT_FIELDSETS
603
+ );
604
+ await ensureFieldsetConfig(
605
+ em,
606
+ scope,
607
+ E.catalog.catalog_product_variant,
608
+ VARIANT_FIELDSETS
609
+ );
571
610
  await ensureCustomFieldDefinitions(em, CUSTOM_FIELD_SETS, {
572
611
  organizationId: scope.organizationId,
573
612
  tenantId: scope.tenantId
@@ -622,7 +661,11 @@ async function ensureCategories(em, scope) {
622
661
  await upsert(seed, null);
623
662
  }
624
663
  await em.flush();
625
- await rebuildCategoryHierarchyForOrganization(em, scope.organizationId, scope.tenantId);
664
+ await rebuildCategoryHierarchyForOrganization(
665
+ em,
666
+ scope.organizationId,
667
+ scope.tenantId
668
+ );
626
669
  return map;
627
670
  }
628
671
  async function ensureChannel(em, scope) {
@@ -673,9 +716,11 @@ async function seedCatalogExamples(em, container, scope) {
673
716
  const existingProducts = await em.find(CatalogProduct, {
674
717
  tenantId: scope.tenantId,
675
718
  organizationId: scope.organizationId,
676
- handle: { $in: handles }
719
+ handle: { $in: [...handles] }
677
720
  });
678
- const existingByHandle = new Map(existingProducts.map((product) => [product.handle?.toLowerCase(), product]));
721
+ const existingByHandle = new Map(
722
+ existingProducts.map((product) => [product.handle?.toLowerCase(), product])
723
+ );
679
724
  const categoryMap = await ensureCategories(em, scope);
680
725
  const channel = await ensureChannel(em, scope);
681
726
  const priceKinds = await loadPriceKinds(em, scope);
@@ -685,7 +730,9 @@ async function seedCatalogExamples(em, container, scope) {
685
730
  const defaultTaxRateId = defaultTaxRate?.id ?? null;
686
731
  const defaultTaxRateValue = defaultTaxRate?.rate ?? null;
687
732
  if (!regularKind || !saleKind) {
688
- throw new Error("Missing catalog price kinds; run `mercato catalog seed-price-kinds` first.");
733
+ throw new Error(
734
+ "Missing catalog price kinds; run `mercato catalog seed-price-kinds` first."
735
+ );
689
736
  }
690
737
  const dataEngine = new DefaultDataEngine(em, container);
691
738
  const customFieldAssignments = [];
@@ -706,7 +753,7 @@ async function seedCatalogExamples(em, container, scope) {
706
753
  handle: productSeed.handle,
707
754
  productType: "configurable",
708
755
  primaryCurrencyCode: "USD",
709
- defaultUnit: productSeed.unit,
756
+ defaultUnit: canonicalizeUnitCode(productSeed.unit) ?? productSeed.unit,
710
757
  customFieldsetCode: productSeed.customFieldsetCode,
711
758
  metadata: productSeed.metadata ?? null,
712
759
  taxRateId: defaultTaxRateId,
@@ -797,7 +844,6 @@ async function seedCatalogExamples(em, container, scope) {
797
844
  variant.id,
798
845
  variantSeed.media
799
846
  );
800
- const variantCover = variantMedia[0] ?? productMedia[0];
801
847
  const regularPrice = em.create(CatalogProductPrice, {
802
848
  id: randomUUID(),
803
849
  organizationId: scope.organizationId,
@@ -860,7 +906,10 @@ async function seedCatalogExamples(em, container, scope) {
860
906
  try {
861
907
  await assign();
862
908
  } catch (err) {
863
- console.warn("[catalog.seed] Failed to set example custom field values", err);
909
+ console.warn(
910
+ "[catalog.seed] Failed to set example custom field values",
911
+ err
912
+ );
864
913
  }
865
914
  }
866
915
  return true;