@open-mercato/core 0.4.6-develop-a96241c478 → 0.4.6-develop-7722ab3d39

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 (116) hide show
  1. package/dist/modules/api_docs/frontend/docs/api/page.js +1 -1
  2. package/dist/modules/api_docs/frontend/docs/api/page.js.map +2 -2
  3. package/dist/modules/attachments/api/library/[id]/route.js +0 -1
  4. package/dist/modules/attachments/api/library/[id]/route.js.map +2 -2
  5. package/dist/modules/attachments/components/AttachmentLibrary.js +1 -1
  6. package/dist/modules/attachments/components/AttachmentLibrary.js.map +2 -2
  7. package/dist/modules/attachments/lib/partitionEnv.js +1 -1
  8. package/dist/modules/attachments/lib/partitionEnv.js.map +2 -2
  9. package/dist/modules/auth/backend/users/page.js +1 -1
  10. package/dist/modules/auth/backend/users/page.js.map +2 -2
  11. package/dist/modules/auth/cli.js +1 -1
  12. package/dist/modules/auth/cli.js.map +2 -2
  13. package/dist/modules/auth/commands/users.js +1 -1
  14. package/dist/modules/auth/commands/users.js.map +2 -2
  15. package/dist/modules/business_rules/components/utils/formHelpers.js +1 -1
  16. package/dist/modules/business_rules/components/utils/formHelpers.js.map +2 -2
  17. package/dist/modules/catalog/backend/catalog/products/create/page.js +1 -1
  18. package/dist/modules/catalog/backend/catalog/products/create/page.js.map +2 -2
  19. package/dist/modules/catalog/commands/products.js +1 -1
  20. package/dist/modules/catalog/commands/products.js.map +2 -2
  21. package/dist/modules/catalog/commands/shared.js +1 -1
  22. package/dist/modules/catalog/commands/shared.js.map +2 -2
  23. package/dist/modules/catalog/components/PriceKindSettings.js +1 -1
  24. package/dist/modules/catalog/components/PriceKindSettings.js.map +2 -2
  25. package/dist/modules/catalog/components/products/productForm.js +1 -1
  26. package/dist/modules/catalog/components/products/productForm.js.map +2 -2
  27. package/dist/modules/configs/lib/upgrade-actions.js.map +1 -1
  28. package/dist/modules/currencies/services/providers/raiffeisen.js +1 -1
  29. package/dist/modules/currencies/services/providers/raiffeisen.js.map +2 -2
  30. package/dist/modules/customers/cli.js +2 -2
  31. package/dist/modules/customers/cli.js.map +2 -2
  32. package/dist/modules/customers/lib/detailHelpers.js +1 -1
  33. package/dist/modules/customers/lib/detailHelpers.js.map +2 -2
  34. package/dist/modules/entities/cli.js +1 -1
  35. package/dist/modules/entities/cli.js.map +2 -2
  36. package/dist/modules/entities/lib/field-definitions.js +1 -1
  37. package/dist/modules/entities/lib/field-definitions.js.map +2 -2
  38. package/dist/modules/entities/lib/install-from-ce.js +1 -1
  39. package/dist/modules/entities/lib/install-from-ce.js.map +2 -2
  40. package/dist/modules/inbox_ops/lib/emailParser.js +1 -1
  41. package/dist/modules/inbox_ops/lib/emailParser.js.map +2 -2
  42. package/dist/modules/inbox_ops/widgets/notifications/ProposalCreatedRenderer.js +8 -0
  43. package/dist/modules/inbox_ops/widgets/notifications/ProposalCreatedRenderer.js.map +2 -2
  44. package/dist/modules/perspectives/services/perspectiveService.js +1 -1
  45. package/dist/modules/perspectives/services/perspectiveService.js.map +2 -2
  46. package/dist/modules/query_index/components/QueryIndexesTable.js +7 -7
  47. package/dist/modules/query_index/components/QueryIndexesTable.js.map +2 -2
  48. package/dist/modules/query_index/lib/engine.js +1 -1
  49. package/dist/modules/query_index/lib/engine.js.map +2 -2
  50. package/dist/modules/resources/commands/resources.js +1 -1
  51. package/dist/modules/resources/commands/resources.js.map +2 -2
  52. package/dist/modules/resources/lib/seeds.js +1 -1
  53. package/dist/modules/resources/lib/seeds.js.map +2 -2
  54. package/dist/modules/sales/api/dashboard/widgets/new-orders/route.js +1 -1
  55. package/dist/modules/sales/api/dashboard/widgets/new-orders/route.js.map +2 -2
  56. package/dist/modules/sales/api/dashboard/widgets/new-quotes/route.js +1 -1
  57. package/dist/modules/sales/api/dashboard/widgets/new-quotes/route.js.map +2 -2
  58. package/dist/modules/sales/commands/documents.js +2 -2
  59. package/dist/modules/sales/commands/documents.js.map +2 -2
  60. package/dist/modules/sales/components/documents/SalesDocumentsTable.js +1 -1
  61. package/dist/modules/sales/components/documents/SalesDocumentsTable.js.map +2 -2
  62. package/dist/modules/sales/components/documents/ShipmentDialog.js +1 -1
  63. package/dist/modules/sales/components/documents/ShipmentDialog.js.map +2 -2
  64. package/dist/modules/sales/lib/shipments/snapshots.js.map +1 -1
  65. package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js +8 -0
  66. package/dist/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.js.map +2 -2
  67. package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js +8 -0
  68. package/dist/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.js.map +2 -2
  69. package/dist/modules/workflows/backend/instances/page.js +2 -2
  70. package/dist/modules/workflows/backend/instances/page.js.map +2 -2
  71. package/dist/modules/workflows/backend/tasks/page.js +1 -1
  72. package/dist/modules/workflows/backend/tasks/page.js.map +2 -2
  73. package/dist/modules/workflows/components/DefinitionTriggersEditor.js +1 -1
  74. package/dist/modules/workflows/components/DefinitionTriggersEditor.js.map +2 -2
  75. package/dist/modules/workflows/lib/graph-utils.js +1 -1
  76. package/dist/modules/workflows/lib/graph-utils.js.map +2 -2
  77. package/package.json +2 -2
  78. package/src/modules/api_docs/frontend/docs/api/page.tsx +1 -1
  79. package/src/modules/attachments/api/library/[id]/route.ts +0 -1
  80. package/src/modules/attachments/components/AttachmentLibrary.tsx +1 -1
  81. package/src/modules/attachments/lib/partitionEnv.ts +1 -1
  82. package/src/modules/auth/backend/users/page.tsx +1 -1
  83. package/src/modules/auth/cli.ts +1 -1
  84. package/src/modules/auth/commands/users.ts +1 -1
  85. package/src/modules/business_rules/components/utils/formHelpers.ts +1 -1
  86. package/src/modules/catalog/backend/catalog/products/create/page.tsx +1 -1
  87. package/src/modules/catalog/commands/products.ts +1 -1
  88. package/src/modules/catalog/commands/shared.ts +1 -1
  89. package/src/modules/catalog/components/PriceKindSettings.tsx +1 -1
  90. package/src/modules/catalog/components/products/productForm.ts +1 -1
  91. package/src/modules/configs/lib/upgrade-actions.ts +1 -1
  92. package/src/modules/currencies/services/providers/raiffeisen.ts +1 -1
  93. package/src/modules/customers/cli.ts +2 -2
  94. package/src/modules/customers/lib/detailHelpers.ts +1 -1
  95. package/src/modules/entities/cli.ts +1 -1
  96. package/src/modules/entities/lib/field-definitions.ts +1 -1
  97. package/src/modules/entities/lib/install-from-ce.ts +1 -1
  98. package/src/modules/inbox_ops/lib/emailParser.ts +1 -1
  99. package/src/modules/inbox_ops/widgets/notifications/ProposalCreatedRenderer.tsx +8 -0
  100. package/src/modules/perspectives/services/perspectiveService.ts +1 -1
  101. package/src/modules/query_index/components/QueryIndexesTable.tsx +7 -7
  102. package/src/modules/query_index/lib/engine.ts +1 -1
  103. package/src/modules/resources/commands/resources.ts +1 -1
  104. package/src/modules/resources/lib/seeds.ts +1 -1
  105. package/src/modules/sales/api/dashboard/widgets/new-orders/route.ts +1 -1
  106. package/src/modules/sales/api/dashboard/widgets/new-quotes/route.ts +1 -1
  107. package/src/modules/sales/commands/documents.ts +2 -2
  108. package/src/modules/sales/components/documents/SalesDocumentsTable.tsx +1 -1
  109. package/src/modules/sales/components/documents/ShipmentDialog.tsx +1 -1
  110. package/src/modules/sales/lib/shipments/snapshots.ts +1 -1
  111. package/src/modules/sales/widgets/notifications/SalesOrderCreatedRenderer.tsx +8 -0
  112. package/src/modules/sales/widgets/notifications/SalesQuoteCreatedRenderer.tsx +8 -0
  113. package/src/modules/workflows/backend/instances/page.tsx +2 -2
  114. package/src/modules/workflows/backend/tasks/page.tsx +1 -1
  115. package/src/modules/workflows/components/DefinitionTriggersEditor.tsx +1 -1
  116. package/src/modules/workflows/lib/graph-utils.ts +1 -1
@@ -39,6 +39,14 @@ function ProposalCreatedRenderer({
39
39
  isUnread && "bg-amber-50/50 dark:bg-amber-950/20"
40
40
  ),
41
41
  onClick: handleReview,
42
+ onKeyDown: (e) => {
43
+ if (e.key === "Enter" || e.key === " ") {
44
+ e.preventDefault();
45
+ handleReview();
46
+ }
47
+ },
48
+ role: "button",
49
+ tabIndex: 0,
42
50
  children: [
43
51
  isUnread && /* @__PURE__ */ jsx("div", { className: "absolute left-1.5 top-1/2 -translate-y-1/2 h-2 w-2 rounded-full bg-primary" }),
44
52
  /* @__PURE__ */ jsxs("div", { className: "flex gap-3", children: [
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../../src/modules/inbox_ops/widgets/notifications/ProposalCreatedRenderer.tsx"],
4
- "sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { Inbox, ExternalLink, Calendar } from 'lucide-react'\nimport { useRouter } from 'next/navigation'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { formatRelativeTime } from '@open-mercato/shared/lib/time'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { NotificationRendererProps } from '@open-mercato/shared/modules/notifications/types'\n\nexport function ProposalCreatedRenderer({\n notification,\n onAction,\n onDismiss,\n actions = [],\n}: NotificationRendererProps) {\n const t = useT()\n const router = useRouter()\n const [executing, setExecuting] = React.useState(false)\n const isUnread = notification.status === 'unread'\n const actionCount = notification.bodyVariables?.actionCount\n\n const reviewAction = actions.find((action) => action.id === 'review') ?? actions[0] ?? null\n\n const handleReview = async () => {\n if (!reviewAction) {\n if (notification.linkHref) router.push(notification.linkHref)\n return\n }\n setExecuting(true)\n try {\n await onAction(reviewAction.id)\n } finally {\n setExecuting(false)\n }\n }\n\n return (\n <div\n className={cn(\n 'group relative px-4 py-3 hover:bg-muted/50 cursor-pointer transition-colors border-l-4 border-l-amber-500',\n isUnread && 'bg-amber-50/50 dark:bg-amber-950/20',\n )}\n onClick={handleReview}\n >\n {isUnread && (\n <div className=\"absolute left-1.5 top-1/2 -translate-y-1/2 h-2 w-2 rounded-full bg-primary\" />\n )}\n\n <div className=\"flex gap-3\">\n <div className=\"flex-shrink-0 mt-0.5\">\n <div className=\"h-10 w-10 rounded-lg bg-amber-100 dark:bg-amber-900/40 flex items-center justify-center\">\n <Inbox className=\"h-5 w-5 text-amber-600 dark:text-amber-400\" />\n </div>\n </div>\n\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-start justify-between gap-2\">\n <h4 className={cn('text-sm font-medium', isUnread && 'font-semibold')}>\n {notification.title}\n </h4>\n <span className=\"flex-shrink-0 text-xs text-muted-foreground flex items-center gap-1\">\n <Calendar className=\"h-3 w-3\" />\n {formatRelativeTime(notification.createdAt, { translate: t }) ?? ''}\n </span>\n </div>\n\n {actionCount && (\n <p className=\"mt-1 text-xs text-muted-foreground\">\n {t('inbox_ops.notifications.renderer.actionCount', '{count} proposed actions', { count: actionCount })}\n </p>\n )}\n\n <div className=\"mt-3 flex gap-2\">\n <Button\n variant=\"default\"\n size=\"sm\"\n onClick={(event) => {\n event.stopPropagation()\n handleReview()\n }}\n disabled={executing || (!reviewAction && !notification.linkHref)}\n className=\"gap-1\"\n >\n <ExternalLink className=\"h-3 w-3\" />\n {t('inbox_ops.action.review', 'Review')}\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={(event) => {\n event.stopPropagation()\n onDismiss()\n }}\n >\n {t('notifications.actions.dismiss', 'Dismiss')}\n </Button>\n </div>\n </div>\n </div>\n </div>\n )\n}\n\nexport default ProposalCreatedRenderer\n"],
5
- "mappings": ";AA+CQ,cAeI,YAfJ;AA7CR,YAAY,WAAW;AACvB,SAAS,OAAO,cAAc,gBAAgB;AAC9C,SAAS,iBAAiB;AAC1B,SAAS,cAAc;AACvB,SAAS,UAAU;AACnB,SAAS,0BAA0B;AACnC,SAAS,YAAY;AAGd,SAAS,wBAAwB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU,CAAC;AACb,GAA8B;AAC5B,QAAM,IAAI,KAAK;AACf,QAAM,SAAS,UAAU;AACzB,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAS,KAAK;AACtD,QAAM,WAAW,aAAa,WAAW;AACzC,QAAM,cAAc,aAAa,eAAe;AAEhD,QAAM,eAAe,QAAQ,KAAK,CAAC,WAAW,OAAO,OAAO,QAAQ,KAAK,QAAQ,CAAC,KAAK;AAEvF,QAAM,eAAe,YAAY;AAC/B,QAAI,CAAC,cAAc;AACjB,UAAI,aAAa,SAAU,QAAO,KAAK,aAAa,QAAQ;AAC5D;AAAA,IACF;AACA,iBAAa,IAAI;AACjB,QAAI;AACF,YAAM,SAAS,aAAa,EAAE;AAAA,IAChC,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA,YAAY;AAAA,MACd;AAAA,MACA,SAAS;AAAA,MAER;AAAA,oBACC,oBAAC,SAAI,WAAU,8EAA6E;AAAA,QAG9F,qBAAC,SAAI,WAAU,cACb;AAAA,8BAAC,SAAI,WAAU,wBACb,8BAAC,SAAI,WAAU,2FACb,8BAAC,SAAM,WAAU,8CAA6C,GAChE,GACF;AAAA,UAEA,qBAAC,SAAI,WAAU,kBACb;AAAA,iCAAC,SAAI,WAAU,0CACb;AAAA,kCAAC,QAAG,WAAW,GAAG,uBAAuB,YAAY,eAAe,GACjE,uBAAa,OAChB;AAAA,cACA,qBAAC,UAAK,WAAU,uEACd;AAAA,oCAAC,YAAS,WAAU,WAAU;AAAA,gBAC7B,mBAAmB,aAAa,WAAW,EAAE,WAAW,EAAE,CAAC,KAAK;AAAA,iBACnE;AAAA,eACF;AAAA,YAEC,eACC,oBAAC,OAAE,WAAU,sCACV,YAAE,gDAAgD,4BAA4B,EAAE,OAAO,YAAY,CAAC,GACvG;AAAA,YAGF,qBAAC,SAAI,WAAU,mBACb;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAQ;AAAA,kBACR,MAAK;AAAA,kBACL,SAAS,CAAC,UAAU;AAClB,0BAAM,gBAAgB;AACtB,iCAAa;AAAA,kBACf;AAAA,kBACA,UAAU,aAAc,CAAC,gBAAgB,CAAC,aAAa;AAAA,kBACvD,WAAU;AAAA,kBAEV;AAAA,wCAAC,gBAAa,WAAU,WAAU;AAAA,oBACjC,EAAE,2BAA2B,QAAQ;AAAA;AAAA;AAAA,cACxC;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAQ;AAAA,kBACR,MAAK;AAAA,kBACL,SAAS,CAAC,UAAU;AAClB,0BAAM,gBAAgB;AACtB,8BAAU;AAAA,kBACZ;AAAA,kBAEC,YAAE,iCAAiC,SAAS;AAAA;AAAA,cAC/C;AAAA,eACF;AAAA,aACF;AAAA,WACF;AAAA;AAAA;AAAA,EACF;AAEJ;AAEA,IAAO,kCAAQ;",
4
+ "sourcesContent": ["'use client'\n\nimport * as React from 'react'\nimport { Inbox, ExternalLink, Calendar } from 'lucide-react'\nimport { useRouter } from 'next/navigation'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { cn } from '@open-mercato/shared/lib/utils'\nimport { formatRelativeTime } from '@open-mercato/shared/lib/time'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport type { NotificationRendererProps } from '@open-mercato/shared/modules/notifications/types'\n\nexport function ProposalCreatedRenderer({\n notification,\n onAction,\n onDismiss,\n actions = [],\n}: NotificationRendererProps) {\n const t = useT()\n const router = useRouter()\n const [executing, setExecuting] = React.useState(false)\n const isUnread = notification.status === 'unread'\n const actionCount = notification.bodyVariables?.actionCount\n\n const reviewAction = actions.find((action) => action.id === 'review') ?? actions[0] ?? null\n\n const handleReview = async () => {\n if (!reviewAction) {\n if (notification.linkHref) router.push(notification.linkHref)\n return\n }\n setExecuting(true)\n try {\n await onAction(reviewAction.id)\n } finally {\n setExecuting(false)\n }\n }\n\n return (\n <div\n className={cn(\n 'group relative px-4 py-3 hover:bg-muted/50 cursor-pointer transition-colors border-l-4 border-l-amber-500',\n isUnread && 'bg-amber-50/50 dark:bg-amber-950/20',\n )}\n onClick={handleReview}\n onKeyDown={(e) => {\n if (e.key === 'Enter' || e.key === ' ') {\n e.preventDefault()\n handleReview()\n }\n }}\n role=\"button\"\n tabIndex={0}\n >\n {isUnread && (\n <div className=\"absolute left-1.5 top-1/2 -translate-y-1/2 h-2 w-2 rounded-full bg-primary\" />\n )}\n\n <div className=\"flex gap-3\">\n <div className=\"flex-shrink-0 mt-0.5\">\n <div className=\"h-10 w-10 rounded-lg bg-amber-100 dark:bg-amber-900/40 flex items-center justify-center\">\n <Inbox className=\"h-5 w-5 text-amber-600 dark:text-amber-400\" />\n </div>\n </div>\n\n <div className=\"flex-1 min-w-0\">\n <div className=\"flex items-start justify-between gap-2\">\n <h4 className={cn('text-sm font-medium', isUnread && 'font-semibold')}>\n {notification.title}\n </h4>\n <span className=\"flex-shrink-0 text-xs text-muted-foreground flex items-center gap-1\">\n <Calendar className=\"h-3 w-3\" />\n {formatRelativeTime(notification.createdAt, { translate: t }) ?? ''}\n </span>\n </div>\n\n {actionCount && (\n <p className=\"mt-1 text-xs text-muted-foreground\">\n {t('inbox_ops.notifications.renderer.actionCount', '{count} proposed actions', { count: actionCount })}\n </p>\n )}\n\n <div className=\"mt-3 flex gap-2\">\n <Button\n variant=\"default\"\n size=\"sm\"\n onClick={(event) => {\n event.stopPropagation()\n handleReview()\n }}\n disabled={executing || (!reviewAction && !notification.linkHref)}\n className=\"gap-1\"\n >\n <ExternalLink className=\"h-3 w-3\" />\n {t('inbox_ops.action.review', 'Review')}\n </Button>\n <Button\n variant=\"ghost\"\n size=\"sm\"\n onClick={(event) => {\n event.stopPropagation()\n onDismiss()\n }}\n >\n {t('notifications.actions.dismiss', 'Dismiss')}\n </Button>\n </div>\n </div>\n </div>\n </div>\n )\n}\n\nexport default ProposalCreatedRenderer\n"],
5
+ "mappings": ";AAuDQ,cAeI,YAfJ;AArDR,YAAY,WAAW;AACvB,SAAS,OAAO,cAAc,gBAAgB;AAC9C,SAAS,iBAAiB;AAC1B,SAAS,cAAc;AACvB,SAAS,UAAU;AACnB,SAAS,0BAA0B;AACnC,SAAS,YAAY;AAGd,SAAS,wBAAwB;AAAA,EACtC;AAAA,EACA;AAAA,EACA;AAAA,EACA,UAAU,CAAC;AACb,GAA8B;AAC5B,QAAM,IAAI,KAAK;AACf,QAAM,SAAS,UAAU;AACzB,QAAM,CAAC,WAAW,YAAY,IAAI,MAAM,SAAS,KAAK;AACtD,QAAM,WAAW,aAAa,WAAW;AACzC,QAAM,cAAc,aAAa,eAAe;AAEhD,QAAM,eAAe,QAAQ,KAAK,CAAC,WAAW,OAAO,OAAO,QAAQ,KAAK,QAAQ,CAAC,KAAK;AAEvF,QAAM,eAAe,YAAY;AAC/B,QAAI,CAAC,cAAc;AACjB,UAAI,aAAa,SAAU,QAAO,KAAK,aAAa,QAAQ;AAC5D;AAAA,IACF;AACA,iBAAa,IAAI;AACjB,QAAI;AACF,YAAM,SAAS,aAAa,EAAE;AAAA,IAChC,UAAE;AACA,mBAAa,KAAK;AAAA,IACpB;AAAA,EACF;AAEA,SACE;AAAA,IAAC;AAAA;AAAA,MACC,WAAW;AAAA,QACT;AAAA,QACA,YAAY;AAAA,MACd;AAAA,MACA,SAAS;AAAA,MACT,WAAW,CAAC,MAAM;AAChB,YAAI,EAAE,QAAQ,WAAW,EAAE,QAAQ,KAAK;AACtC,YAAE,eAAe;AACjB,uBAAa;AAAA,QACf;AAAA,MACF;AAAA,MACA,MAAK;AAAA,MACL,UAAU;AAAA,MAET;AAAA,oBACC,oBAAC,SAAI,WAAU,8EAA6E;AAAA,QAG9F,qBAAC,SAAI,WAAU,cACb;AAAA,8BAAC,SAAI,WAAU,wBACb,8BAAC,SAAI,WAAU,2FACb,8BAAC,SAAM,WAAU,8CAA6C,GAChE,GACF;AAAA,UAEA,qBAAC,SAAI,WAAU,kBACb;AAAA,iCAAC,SAAI,WAAU,0CACb;AAAA,kCAAC,QAAG,WAAW,GAAG,uBAAuB,YAAY,eAAe,GACjE,uBAAa,OAChB;AAAA,cACA,qBAAC,UAAK,WAAU,uEACd;AAAA,oCAAC,YAAS,WAAU,WAAU;AAAA,gBAC7B,mBAAmB,aAAa,WAAW,EAAE,WAAW,EAAE,CAAC,KAAK;AAAA,iBACnE;AAAA,eACF;AAAA,YAEC,eACC,oBAAC,OAAE,WAAU,sCACV,YAAE,gDAAgD,4BAA4B,EAAE,OAAO,YAAY,CAAC,GACvG;AAAA,YAGF,qBAAC,SAAI,WAAU,mBACb;AAAA;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAQ;AAAA,kBACR,MAAK;AAAA,kBACL,SAAS,CAAC,UAAU;AAClB,0BAAM,gBAAgB;AACtB,iCAAa;AAAA,kBACf;AAAA,kBACA,UAAU,aAAc,CAAC,gBAAgB,CAAC,aAAa;AAAA,kBACvD,WAAU;AAAA,kBAEV;AAAA,wCAAC,gBAAa,WAAU,WAAU;AAAA,oBACjC,EAAE,2BAA2B,QAAQ;AAAA;AAAA;AAAA,cACxC;AAAA,cACA;AAAA,gBAAC;AAAA;AAAA,kBACC,SAAQ;AAAA,kBACR,MAAK;AAAA,kBACL,SAAS,CAAC,UAAU;AAClB,0BAAM,gBAAgB;AACtB,8BAAU;AAAA,kBACZ;AAAA,kBAEC,YAAE,iCAAiC,SAAS;AAAA;AAAA,cAC/C;AAAA,eACF;AAAA,aACF;AAAA,WACF;AAAA;AAAA;AAAA,EACF;AAEJ;AAEA,IAAO,kCAAQ;",
6
6
  "names": []
7
7
  }
@@ -2,7 +2,7 @@ import { Perspective, RolePerspective } from "../data/entities.js";
2
2
  const CACHE_TTL_MS = 5 * 60 * 1e3;
3
3
  const nullish = (value) => value == null ? null : value;
4
4
  const scopeKey = (scope) => `${scope.userId}:${scope.tenantId ?? "null"}:${scope.organizationId ?? "null"}`;
5
- const userCacheKey = (scope, tableId, roleIds) => `perspectives:user-state:${scopeKey(scope)}:${tableId}:${roleIds.sort().join(",")}`;
5
+ const userCacheKey = (scope, tableId, roleIds) => `perspectives:user-state:${scopeKey(scope)}:${tableId}:${roleIds.sort((a, b) => a.localeCompare(b)).join(",")}`;
6
6
  const userTag = (scope, tableId) => tableId ? `perspectives:user:${scopeKey(scope)}:${tableId}` : `perspectives:user:${scopeKey(scope)}`;
7
7
  const roleTag = (roleId, tableId, tenantId) => {
8
8
  const tenant = tenantId ?? "null";
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/perspectives/services/perspectiveService.ts"],
4
- "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { CacheStrategy } from '@open-mercato/cache'\nimport { Perspective, RolePerspective } from '../data/entities'\nimport type {\n PerspectiveSettings,\n PerspectiveSaveInput,\n RolePerspectiveSaveInput,\n} from '../data/validators'\n\nexport type PerspectiveScope = {\n userId: string\n tenantId?: string | null\n organizationId?: string | null\n}\n\nexport type ResolvedPerspective = {\n id: string\n name: string\n tableId: string\n settings: PerspectiveSettings\n isDefault: boolean\n createdAt: string\n updatedAt?: string | null\n}\n\nexport type ResolvedRolePerspective = {\n id: string\n roleId: string\n tableId: string\n name: string\n settings: PerspectiveSettings\n isDefault: boolean\n tenantId: string | null\n organizationId: string | null\n createdAt: string\n updatedAt?: string | null\n}\n\nexport type PerspectivesState = {\n tableId: string\n personal: ResolvedPerspective[]\n personalDefaultId: string | null\n rolePerspectives: ResolvedRolePerspective[]\n}\n\nconst CACHE_TTL_MS = 5 * 60 * 1000\n\nconst nullish = <T extends string | null | undefined>(value: T): string | null =>\n value == null ? null : value\n\nconst scopeKey = (scope: PerspectiveScope) =>\n `${scope.userId}:${scope.tenantId ?? 'null'}:${scope.organizationId ?? 'null'}`\n\nconst userCacheKey = (scope: PerspectiveScope, tableId: string, roleIds: string[]) =>\n `perspectives:user-state:${scopeKey(scope)}:${tableId}:${roleIds.sort().join(',')}`\n\nconst userTag = (scope: PerspectiveScope, tableId?: string) =>\n tableId\n ? `perspectives:user:${scopeKey(scope)}:${tableId}`\n : `perspectives:user:${scopeKey(scope)}`\n\nconst roleTag = (roleId: string, tableId?: string, tenantId?: string | null) => {\n const tenant = tenantId ?? 'null'\n return tableId ? `perspectives:role:${roleId}:${tenant}:${tableId}` : `perspectives:role:${roleId}:${tenant}`\n}\n\nfunction isResolvedPerspective(value: unknown): value is ResolvedPerspective {\n if (typeof value !== 'object' || value === null) return false\n const record = value as Partial<ResolvedPerspective>\n return typeof record.id === 'string'\n && typeof record.name === 'string'\n && typeof record.tableId === 'string'\n && typeof record.isDefault === 'boolean'\n && typeof record.createdAt === 'string'\n}\n\nfunction isResolvedRolePerspective(value: unknown): value is ResolvedRolePerspective {\n if (typeof value !== 'object' || value === null) return false\n const record = value as Partial<ResolvedRolePerspective>\n return typeof record.id === 'string'\n && typeof record.roleId === 'string'\n && typeof record.tableId === 'string'\n && typeof record.name === 'string'\n && typeof record.isDefault === 'boolean'\n && typeof record.createdAt === 'string'\n}\n\nfunction isPerspectivesState(value: unknown): value is PerspectivesState {\n if (typeof value !== 'object' || value === null) return false\n const record = value as Partial<PerspectivesState>\n if (typeof record.tableId !== 'string') return false\n if (!Array.isArray(record.personal) || record.personal.some((item) => !isResolvedPerspective(item))) return false\n if (record.personalDefaultId !== null && typeof record.personalDefaultId !== 'string') return false\n if (!Array.isArray(record.rolePerspectives) || record.rolePerspectives.some((item) => !isResolvedRolePerspective(item))) return false\n return true\n}\n\nfunction toResolvedPerspective(entity: Perspective): ResolvedPerspective {\n return {\n id: entity.id,\n name: entity.name,\n tableId: entity.tableId,\n isDefault: !!entity.isDefault,\n settings: (entity.settingsJson ?? {}) as PerspectiveSettings,\n createdAt: entity.createdAt.toISOString(),\n updatedAt: entity.updatedAt ? entity.updatedAt.toISOString() : null,\n }\n}\n\nfunction toResolvedRolePerspective(entity: RolePerspective): ResolvedRolePerspective {\n return {\n id: entity.id,\n roleId: entity.roleId,\n tableId: entity.tableId,\n name: entity.name,\n isDefault: !!entity.isDefault,\n settings: (entity.settingsJson ?? {}) as PerspectiveSettings,\n tenantId: nullish(entity.tenantId),\n organizationId: nullish(entity.organizationId),\n createdAt: entity.createdAt.toISOString(),\n updatedAt: entity.updatedAt ? entity.updatedAt.toISOString() : null,\n }\n}\n\nexport async function loadPerspectivesState(\n em: EntityManager,\n cache: CacheStrategy | null | undefined,\n options: { scope: PerspectiveScope; tableId: string; roleIds?: string[] },\n): Promise<PerspectivesState> {\n const { scope, tableId } = options\n const roleIds = Array.isArray(options.roleIds) ? options.roleIds.filter((id) => id && id.length > 0) : []\n const uniqueRoles = Array.from(new Set(roleIds))\n const cacheKey = cache && uniqueRoles.length <= 16 ? userCacheKey(scope, tableId, uniqueRoles) : null\n\n if (cache && cacheKey) {\n const cached = await cache.get(cacheKey)\n if (cached && isPerspectivesState(cached)) return cached\n }\n\n const tenantId = scope.tenantId ?? null\n const organizationId = scope.organizationId ?? null\n\n const [personal, roleRecords] = await Promise.all([\n em.find(Perspective, {\n userId: scope.userId,\n tenantId,\n organizationId,\n tableId,\n deletedAt: null,\n }, { orderBy: { updatedAt: 'desc' } }),\n uniqueRoles.length\n ? em.find(RolePerspective, {\n roleId: { $in: uniqueRoles as any },\n tableId,\n deletedAt: null,\n $and: [\n { $or: [{ tenantId }, { tenantId: null }] },\n { $or: [{ organizationId }, { organizationId: null }] },\n ],\n } as any, { orderBy: { updatedAt: 'desc' } })\n : [],\n ])\n\n const personalResolved = personal.map(toResolvedPerspective)\n const personalDefaultId = personalResolved.find((p) => p.isDefault)?.id ?? null\n const roleResolved = roleRecords.map(toResolvedRolePerspective)\n\n const state: PerspectivesState = {\n tableId,\n personal: personalResolved,\n personalDefaultId,\n rolePerspectives: roleResolved,\n }\n\n if (cache && cacheKey) {\n await cache.set(cacheKey, state, {\n ttl: CACHE_TTL_MS,\n tags: [\n userTag(scope, tableId),\n ...uniqueRoles.map((roleId) => roleTag(roleId, tableId, tenantId)),\n ],\n })\n }\n\n return state\n}\n\nexport async function saveUserPerspective(\n em: EntityManager,\n cache: CacheStrategy | null | undefined,\n options: { scope: PerspectiveScope; tableId: string; input: PerspectiveSaveInput },\n): Promise<ResolvedPerspective> {\n const { scope, tableId, input } = options\n const tenantId = scope.tenantId ?? null\n const organizationId = scope.organizationId ?? null\n\n let entity: Perspective | null = null\n if (input.perspectiveId) {\n entity = await em.findOne(Perspective, {\n id: input.perspectiveId,\n userId: scope.userId,\n tenantId,\n organizationId,\n tableId,\n deletedAt: null,\n })\n if (!entity) {\n throw Object.assign(new Error('Perspective not found'), { code: 'NOT_FOUND' })\n }\n } else {\n entity = await em.findOne(Perspective, {\n userId: scope.userId,\n tenantId,\n organizationId,\n tableId,\n name: input.name,\n deletedAt: null,\n })\n }\n\n const now = new Date()\n if (!entity) {\n entity = em.create(Perspective, {\n userId: scope.userId,\n tenantId,\n organizationId,\n tableId,\n name: input.name,\n settingsJson: input.settings,\n isDefault: Boolean(input.isDefault),\n createdAt: now,\n updatedAt: now,\n })\n em.persist(entity)\n } else {\n entity.name = input.name\n entity.settingsJson = input.settings\n entity.updatedAt = now\n if (input.isDefault === true) entity.isDefault = true\n if (input.isDefault === false) entity.isDefault = false\n }\n\n if (input.isDefault === true) {\n await em.nativeUpdate(\n Perspective,\n {\n userId: scope.userId,\n tenantId,\n organizationId,\n tableId,\n id: { $ne: entity.id } as any,\n deletedAt: null,\n },\n { isDefault: false, updatedAt: now },\n )\n entity.isDefault = true\n }\n\n await em.flush()\n\n if (cache?.deleteByTags) {\n await cache.deleteByTags([userTag(scope, tableId)])\n }\n\n return toResolvedPerspective(entity)\n}\n\nexport async function deleteUserPerspective(\n em: EntityManager,\n cache: CacheStrategy | null | undefined,\n options: { scope: PerspectiveScope; tableId: string; perspectiveId: string },\n): Promise<void> {\n const { scope, tableId, perspectiveId } = options\n const tenantId = scope.tenantId ?? null\n const organizationId = scope.organizationId ?? null\n\n const existing = await em.findOne(Perspective, {\n id: perspectiveId,\n userId: scope.userId,\n tenantId,\n organizationId,\n tableId,\n deletedAt: null,\n })\n if (!existing) return\n\n existing.deletedAt = new Date()\n existing.isDefault = false\n await em.flush()\n\n if (cache?.deleteByTags) {\n await cache.deleteByTags([userTag(scope, tableId)])\n }\n}\n\nexport async function saveRolePerspectives(\n em: EntityManager,\n cache: CacheStrategy | null | undefined,\n options: {\n tableId: string\n tenantId?: string | null\n organizationId?: string | null\n input: RolePerspectiveSaveInput\n },\n): Promise<ResolvedRolePerspective[]> {\n const { tableId, input } = options\n const tenantId = options.tenantId ?? null\n const organizationId = options.organizationId ?? null\n const now = new Date()\n const touchedRoleIds = new Set<string>()\n\n const results: ResolvedRolePerspective[] = []\n\n for (const roleId of input.roleIds) {\n let record = await em.findOne(RolePerspective, {\n roleId,\n tableId,\n tenantId,\n organizationId,\n name: input.name,\n deletedAt: null,\n })\n if (!record) {\n record = em.create(RolePerspective, {\n roleId,\n tableId,\n tenantId,\n organizationId,\n name: input.name,\n settingsJson: input.settings,\n isDefault: Boolean(input.setDefault),\n createdAt: now,\n updatedAt: now,\n })\n em.persist(record)\n } else {\n record.settingsJson = input.settings\n record.updatedAt = now\n if (input.setDefault === true) record.isDefault = true\n if (input.setDefault === false) record.isDefault = false\n }\n\n if (input.setDefault === true) {\n await em.nativeUpdate(\n RolePerspective,\n {\n roleId,\n tableId,\n tenantId,\n organizationId,\n id: { $ne: record.id } as any,\n deletedAt: null,\n },\n { isDefault: false, updatedAt: now },\n )\n record.isDefault = true\n }\n\n touchedRoleIds.add(roleId)\n results.push(toResolvedRolePerspective(record))\n }\n\n if (input.roleIds.length) {\n await em.flush()\n }\n\n if (cache?.deleteByTags && touchedRoleIds.size > 0) {\n const tags = Array.from(touchedRoleIds).map((roleId) => roleTag(roleId, tableId, tenantId))\n await cache.deleteByTags(tags)\n }\n\n return results\n}\n\nexport async function clearRolePerspectives(\n em: EntityManager,\n cache: CacheStrategy | null | undefined,\n options: {\n tableId: string\n tenantId?: string | null\n organizationId?: string | null\n roleIds: string[]\n },\n): Promise<void> {\n const { tableId, roleIds } = options\n const tenantId = options.tenantId ?? null\n const organizationId = options.organizationId ?? null\n if (!roleIds.length) return\n\n await em.nativeUpdate(\n RolePerspective,\n {\n roleId: { $in: roleIds as any },\n tableId,\n tenantId,\n organizationId,\n deletedAt: null,\n },\n { deletedAt: new Date(), isDefault: false },\n )\n\n if (cache?.deleteByTags) {\n const tags = roleIds.map((roleId) => roleTag(roleId, tableId, tenantId))\n await cache.deleteByTags(tags)\n }\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import type { EntityManager } from '@mikro-orm/postgresql'\nimport type { CacheStrategy } from '@open-mercato/cache'\nimport { Perspective, RolePerspective } from '../data/entities'\nimport type {\n PerspectiveSettings,\n PerspectiveSaveInput,\n RolePerspectiveSaveInput,\n} from '../data/validators'\n\nexport type PerspectiveScope = {\n userId: string\n tenantId?: string | null\n organizationId?: string | null\n}\n\nexport type ResolvedPerspective = {\n id: string\n name: string\n tableId: string\n settings: PerspectiveSettings\n isDefault: boolean\n createdAt: string\n updatedAt?: string | null\n}\n\nexport type ResolvedRolePerspective = {\n id: string\n roleId: string\n tableId: string\n name: string\n settings: PerspectiveSettings\n isDefault: boolean\n tenantId: string | null\n organizationId: string | null\n createdAt: string\n updatedAt?: string | null\n}\n\nexport type PerspectivesState = {\n tableId: string\n personal: ResolvedPerspective[]\n personalDefaultId: string | null\n rolePerspectives: ResolvedRolePerspective[]\n}\n\nconst CACHE_TTL_MS = 5 * 60 * 1000\n\nconst nullish = <T extends string | null | undefined>(value: T): string | null =>\n value == null ? null : value\n\nconst scopeKey = (scope: PerspectiveScope) =>\n `${scope.userId}:${scope.tenantId ?? 'null'}:${scope.organizationId ?? 'null'}`\n\nconst userCacheKey = (scope: PerspectiveScope, tableId: string, roleIds: string[]) =>\n `perspectives:user-state:${scopeKey(scope)}:${tableId}:${roleIds.sort((a, b) => a.localeCompare(b)).join(',')}`\n\nconst userTag = (scope: PerspectiveScope, tableId?: string) =>\n tableId\n ? `perspectives:user:${scopeKey(scope)}:${tableId}`\n : `perspectives:user:${scopeKey(scope)}`\n\nconst roleTag = (roleId: string, tableId?: string, tenantId?: string | null) => {\n const tenant = tenantId ?? 'null'\n return tableId ? `perspectives:role:${roleId}:${tenant}:${tableId}` : `perspectives:role:${roleId}:${tenant}`\n}\n\nfunction isResolvedPerspective(value: unknown): value is ResolvedPerspective {\n if (typeof value !== 'object' || value === null) return false\n const record = value as Partial<ResolvedPerspective>\n return typeof record.id === 'string'\n && typeof record.name === 'string'\n && typeof record.tableId === 'string'\n && typeof record.isDefault === 'boolean'\n && typeof record.createdAt === 'string'\n}\n\nfunction isResolvedRolePerspective(value: unknown): value is ResolvedRolePerspective {\n if (typeof value !== 'object' || value === null) return false\n const record = value as Partial<ResolvedRolePerspective>\n return typeof record.id === 'string'\n && typeof record.roleId === 'string'\n && typeof record.tableId === 'string'\n && typeof record.name === 'string'\n && typeof record.isDefault === 'boolean'\n && typeof record.createdAt === 'string'\n}\n\nfunction isPerspectivesState(value: unknown): value is PerspectivesState {\n if (typeof value !== 'object' || value === null) return false\n const record = value as Partial<PerspectivesState>\n if (typeof record.tableId !== 'string') return false\n if (!Array.isArray(record.personal) || record.personal.some((item) => !isResolvedPerspective(item))) return false\n if (record.personalDefaultId !== null && typeof record.personalDefaultId !== 'string') return false\n if (!Array.isArray(record.rolePerspectives) || record.rolePerspectives.some((item) => !isResolvedRolePerspective(item))) return false\n return true\n}\n\nfunction toResolvedPerspective(entity: Perspective): ResolvedPerspective {\n return {\n id: entity.id,\n name: entity.name,\n tableId: entity.tableId,\n isDefault: !!entity.isDefault,\n settings: (entity.settingsJson ?? {}) as PerspectiveSettings,\n createdAt: entity.createdAt.toISOString(),\n updatedAt: entity.updatedAt ? entity.updatedAt.toISOString() : null,\n }\n}\n\nfunction toResolvedRolePerspective(entity: RolePerspective): ResolvedRolePerspective {\n return {\n id: entity.id,\n roleId: entity.roleId,\n tableId: entity.tableId,\n name: entity.name,\n isDefault: !!entity.isDefault,\n settings: (entity.settingsJson ?? {}) as PerspectiveSettings,\n tenantId: nullish(entity.tenantId),\n organizationId: nullish(entity.organizationId),\n createdAt: entity.createdAt.toISOString(),\n updatedAt: entity.updatedAt ? entity.updatedAt.toISOString() : null,\n }\n}\n\nexport async function loadPerspectivesState(\n em: EntityManager,\n cache: CacheStrategy | null | undefined,\n options: { scope: PerspectiveScope; tableId: string; roleIds?: string[] },\n): Promise<PerspectivesState> {\n const { scope, tableId } = options\n const roleIds = Array.isArray(options.roleIds) ? options.roleIds.filter((id) => id && id.length > 0) : []\n const uniqueRoles = Array.from(new Set(roleIds))\n const cacheKey = cache && uniqueRoles.length <= 16 ? userCacheKey(scope, tableId, uniqueRoles) : null\n\n if (cache && cacheKey) {\n const cached = await cache.get(cacheKey)\n if (cached && isPerspectivesState(cached)) return cached\n }\n\n const tenantId = scope.tenantId ?? null\n const organizationId = scope.organizationId ?? null\n\n const [personal, roleRecords] = await Promise.all([\n em.find(Perspective, {\n userId: scope.userId,\n tenantId,\n organizationId,\n tableId,\n deletedAt: null,\n }, { orderBy: { updatedAt: 'desc' } }),\n uniqueRoles.length\n ? em.find(RolePerspective, {\n roleId: { $in: uniqueRoles as any },\n tableId,\n deletedAt: null,\n $and: [\n { $or: [{ tenantId }, { tenantId: null }] },\n { $or: [{ organizationId }, { organizationId: null }] },\n ],\n } as any, { orderBy: { updatedAt: 'desc' } })\n : [],\n ])\n\n const personalResolved = personal.map(toResolvedPerspective)\n const personalDefaultId = personalResolved.find((p) => p.isDefault)?.id ?? null\n const roleResolved = roleRecords.map(toResolvedRolePerspective)\n\n const state: PerspectivesState = {\n tableId,\n personal: personalResolved,\n personalDefaultId,\n rolePerspectives: roleResolved,\n }\n\n if (cache && cacheKey) {\n await cache.set(cacheKey, state, {\n ttl: CACHE_TTL_MS,\n tags: [\n userTag(scope, tableId),\n ...uniqueRoles.map((roleId) => roleTag(roleId, tableId, tenantId)),\n ],\n })\n }\n\n return state\n}\n\nexport async function saveUserPerspective(\n em: EntityManager,\n cache: CacheStrategy | null | undefined,\n options: { scope: PerspectiveScope; tableId: string; input: PerspectiveSaveInput },\n): Promise<ResolvedPerspective> {\n const { scope, tableId, input } = options\n const tenantId = scope.tenantId ?? null\n const organizationId = scope.organizationId ?? null\n\n let entity: Perspective | null = null\n if (input.perspectiveId) {\n entity = await em.findOne(Perspective, {\n id: input.perspectiveId,\n userId: scope.userId,\n tenantId,\n organizationId,\n tableId,\n deletedAt: null,\n })\n if (!entity) {\n throw Object.assign(new Error('Perspective not found'), { code: 'NOT_FOUND' })\n }\n } else {\n entity = await em.findOne(Perspective, {\n userId: scope.userId,\n tenantId,\n organizationId,\n tableId,\n name: input.name,\n deletedAt: null,\n })\n }\n\n const now = new Date()\n if (!entity) {\n entity = em.create(Perspective, {\n userId: scope.userId,\n tenantId,\n organizationId,\n tableId,\n name: input.name,\n settingsJson: input.settings,\n isDefault: Boolean(input.isDefault),\n createdAt: now,\n updatedAt: now,\n })\n em.persist(entity)\n } else {\n entity.name = input.name\n entity.settingsJson = input.settings\n entity.updatedAt = now\n if (input.isDefault === true) entity.isDefault = true\n if (input.isDefault === false) entity.isDefault = false\n }\n\n if (input.isDefault === true) {\n await em.nativeUpdate(\n Perspective,\n {\n userId: scope.userId,\n tenantId,\n organizationId,\n tableId,\n id: { $ne: entity.id } as any,\n deletedAt: null,\n },\n { isDefault: false, updatedAt: now },\n )\n entity.isDefault = true\n }\n\n await em.flush()\n\n if (cache?.deleteByTags) {\n await cache.deleteByTags([userTag(scope, tableId)])\n }\n\n return toResolvedPerspective(entity)\n}\n\nexport async function deleteUserPerspective(\n em: EntityManager,\n cache: CacheStrategy | null | undefined,\n options: { scope: PerspectiveScope; tableId: string; perspectiveId: string },\n): Promise<void> {\n const { scope, tableId, perspectiveId } = options\n const tenantId = scope.tenantId ?? null\n const organizationId = scope.organizationId ?? null\n\n const existing = await em.findOne(Perspective, {\n id: perspectiveId,\n userId: scope.userId,\n tenantId,\n organizationId,\n tableId,\n deletedAt: null,\n })\n if (!existing) return\n\n existing.deletedAt = new Date()\n existing.isDefault = false\n await em.flush()\n\n if (cache?.deleteByTags) {\n await cache.deleteByTags([userTag(scope, tableId)])\n }\n}\n\nexport async function saveRolePerspectives(\n em: EntityManager,\n cache: CacheStrategy | null | undefined,\n options: {\n tableId: string\n tenantId?: string | null\n organizationId?: string | null\n input: RolePerspectiveSaveInput\n },\n): Promise<ResolvedRolePerspective[]> {\n const { tableId, input } = options\n const tenantId = options.tenantId ?? null\n const organizationId = options.organizationId ?? null\n const now = new Date()\n const touchedRoleIds = new Set<string>()\n\n const results: ResolvedRolePerspective[] = []\n\n for (const roleId of input.roleIds) {\n let record = await em.findOne(RolePerspective, {\n roleId,\n tableId,\n tenantId,\n organizationId,\n name: input.name,\n deletedAt: null,\n })\n if (!record) {\n record = em.create(RolePerspective, {\n roleId,\n tableId,\n tenantId,\n organizationId,\n name: input.name,\n settingsJson: input.settings,\n isDefault: Boolean(input.setDefault),\n createdAt: now,\n updatedAt: now,\n })\n em.persist(record)\n } else {\n record.settingsJson = input.settings\n record.updatedAt = now\n if (input.setDefault === true) record.isDefault = true\n if (input.setDefault === false) record.isDefault = false\n }\n\n if (input.setDefault === true) {\n await em.nativeUpdate(\n RolePerspective,\n {\n roleId,\n tableId,\n tenantId,\n organizationId,\n id: { $ne: record.id } as any,\n deletedAt: null,\n },\n { isDefault: false, updatedAt: now },\n )\n record.isDefault = true\n }\n\n touchedRoleIds.add(roleId)\n results.push(toResolvedRolePerspective(record))\n }\n\n if (input.roleIds.length) {\n await em.flush()\n }\n\n if (cache?.deleteByTags && touchedRoleIds.size > 0) {\n const tags = Array.from(touchedRoleIds).map((roleId) => roleTag(roleId, tableId, tenantId))\n await cache.deleteByTags(tags)\n }\n\n return results\n}\n\nexport async function clearRolePerspectives(\n em: EntityManager,\n cache: CacheStrategy | null | undefined,\n options: {\n tableId: string\n tenantId?: string | null\n organizationId?: string | null\n roleIds: string[]\n },\n): Promise<void> {\n const { tableId, roleIds } = options\n const tenantId = options.tenantId ?? null\n const organizationId = options.organizationId ?? null\n if (!roleIds.length) return\n\n await em.nativeUpdate(\n RolePerspective,\n {\n roleId: { $in: roleIds as any },\n tableId,\n tenantId,\n organizationId,\n deletedAt: null,\n },\n { deletedAt: new Date(), isDefault: false },\n )\n\n if (cache?.deleteByTags) {\n const tags = roleIds.map((roleId) => roleTag(roleId, tableId, tenantId))\n await cache.deleteByTags(tags)\n }\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -274,17 +274,17 @@ function QueryIndexesTable() {
274
274
  perspective: { tableId: "query_index.status.list" },
275
275
  rowActions: (row) => {
276
276
  const items = [
277
- { id: "reindex", label: t("query_index.table.actions.reindex"), onSelect: () => trigger("reindex", row.entityId) },
277
+ { id: "reindex", label: t("query_index.table.actions.reindex"), onSelect: () => void trigger("reindex", row.entityId) },
278
278
  {
279
279
  id: "reindex-force",
280
280
  label: t("query_index.table.actions.reindexForce"),
281
- onSelect: () => trigger("reindex", row.entityId, { force: true })
281
+ onSelect: () => void trigger("reindex", row.entityId, { force: true })
282
282
  },
283
283
  {
284
284
  id: "purge",
285
285
  label: t("query_index.table.actions.purge"),
286
286
  destructive: true,
287
- onSelect: () => trigger("purge", row.entityId)
287
+ onSelect: () => void trigger("purge", row.entityId)
288
288
  }
289
289
  ];
290
290
  if (row.vectorEnabled) {
@@ -292,13 +292,13 @@ function QueryIndexesTable() {
292
292
  {
293
293
  id: "vector-reindex",
294
294
  label: t("query_index.table.actions.vectorReindex"),
295
- onSelect: () => triggerVector("reindex", row.entityId)
295
+ onSelect: () => void triggerVector("reindex", row.entityId)
296
296
  },
297
297
  {
298
298
  id: "vector-purge",
299
299
  label: t("query_index.table.actions.vectorPurge"),
300
300
  destructive: true,
301
- onSelect: () => triggerVector("purge", row.entityId)
301
+ onSelect: () => void triggerVector("purge", row.entityId)
302
302
  }
303
303
  );
304
304
  }
@@ -307,13 +307,13 @@ function QueryIndexesTable() {
307
307
  {
308
308
  id: "fulltext-reindex",
309
309
  label: t("query_index.table.actions.fulltextReindex"),
310
- onSelect: () => triggerFulltext("reindex", row.entityId)
310
+ onSelect: () => void triggerFulltext("reindex", row.entityId)
311
311
  },
312
312
  {
313
313
  id: "fulltext-purge",
314
314
  label: t("query_index.table.actions.fulltextPurge"),
315
315
  destructive: true,
316
- onSelect: () => triggerFulltext("purge", row.entityId)
316
+ onSelect: () => void triggerFulltext("purge", row.entityId)
317
317
  }
318
318
  );
319
319
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../../../src/modules/query_index/components/QueryIndexesTable.tsx"],
4
- "sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { apiCallOrThrow, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\n\ntype Translator = (key: string, params?: Record<string, string | number>) => string\n\ntype PartitionStatus = {\n partitionIndex: number | null\n partitionCount: number | null\n status: 'reindexing' | 'purging' | 'stalled' | 'completed'\n processedCount?: number | null\n totalCount?: number | null\n heartbeatAt?: string | null\n startedAt?: string | null\n finishedAt?: string | null\n}\n\ntype JobStatus = {\n status: 'idle' | 'reindexing' | 'purging' | 'stalled'\n startedAt?: string | null\n finishedAt?: string | null\n heartbeatAt?: string | null\n processedCount?: number | null\n totalCount?: number | null\n partitions?: PartitionStatus[]\n scope?: {\n status?: 'reindexing' | 'purging' | 'stalled' | 'completed' | null\n processedCount?: number | null\n totalCount?: number | null\n } | null\n}\n\ntype Row = {\n entityId: string\n label: string\n baseCount: number | null\n indexCount: number | null\n vectorCount: number | null\n vectorEnabled: boolean\n fulltextCount: number | null\n fulltextEnabled: boolean\n ok: boolean\n job?: JobStatus\n}\n\ntype Resp = { items: Row[] }\n\nfunction formatCount(value: number | null): string {\n if (value == null) return '\u2014'\n return value.toLocaleString()\n}\n\nfunction formatNumeric(value: number | null | undefined): string | null {\n if (value == null) return null\n return Number(value).toLocaleString()\n}\n\nfunction formatProgressLabel(\n processed: number | null | undefined,\n total: number | null | undefined,\n t: Translator,\n): string | null {\n const processedText = formatNumeric(processed)\n if (!processedText) return null\n const totalText = formatNumeric(total)\n if (totalText) return t('query_index.table.status.progress', { processed: processedText, total: totalText })\n return t('query_index.table.status.progressSingle', { processed: processedText })\n}\n\nfunction translateJobStatus(t: Translator, status: JobStatus['status'] | undefined, ok: boolean): string {\n if (!status || status === 'idle') {\n return ok ? t('query_index.table.status.in_sync') : t('query_index.table.status.out_of_sync')\n }\n if (status === 'reindexing') return t('query_index.table.status.reindexing')\n if (status === 'purging') return t('query_index.table.status.purging')\n if (status === 'stalled') return t('query_index.table.status.stalled')\n return ok ? t('query_index.table.status.in_sync') : t('query_index.table.status.out_of_sync')\n}\n\nfunction translateScopeStatus(\n t: Translator,\n status: PartitionStatus['status'] | JobStatus['status'] | undefined | null,\n): string {\n if (status === 'reindexing') return t('query_index.table.status.scope.reindexing')\n if (status === 'purging') return t('query_index.table.status.scope.purging')\n if (status === 'stalled') return t('query_index.table.status.scope.stalled')\n return t('query_index.table.status.scope.completed')\n}\n\n\nfunction createColumns(t: Translator): ColumnDef<Row>[] {\n return [\n { id: 'entityId', header: () => t('query_index.table.columns.entity'), accessorKey: 'entityId', meta: { priority: 1 } },\n { id: 'label', header: () => t('query_index.table.columns.label'), accessorKey: 'label', meta: { priority: 2 } },\n {\n id: 'baseCount',\n header: () => t('query_index.table.columns.records'),\n accessorFn: (row) => row.baseCount ?? 0,\n cell: ({ row }) => <span>{formatCount(row.original.baseCount)}</span>,\n meta: { priority: 2 },\n },\n {\n id: 'indexCount',\n header: () => t('query_index.table.columns.indexed'),\n accessorFn: (row) => row.indexCount ?? 0,\n cell: ({ row }) => <span>{formatCount(row.original.indexCount)}</span>,\n meta: { priority: 2 },\n },\n {\n id: 'vectorCount',\n header: () => t('query_index.table.columns.vector'),\n accessorFn: (row) => (row.vectorEnabled ? row.vectorCount ?? 0 : -1),\n cell: ({ row }) => {\n const record = row.original\n if (!record.vectorEnabled) return <span>\u2014</span>\n const ok = record.vectorCount != null && record.baseCount != null && record.vectorCount === record.baseCount\n const display = formatCount(record.vectorCount)\n const className = ok ? 'text-green-600' : 'text-orange-600'\n return <span className={className}>{display}</span>\n },\n meta: { priority: 2 },\n },\n {\n id: 'fulltextCount',\n header: () => t('query_index.table.columns.fulltext'),\n accessorFn: (row) => (row.fulltextEnabled ? row.fulltextCount ?? 0 : -1),\n cell: ({ row }) => {\n const record = row.original\n if (!record.fulltextEnabled) return <span>\u2014</span>\n const ok = record.fulltextCount != null && record.baseCount != null && record.fulltextCount === record.baseCount\n const display = formatCount(record.fulltextCount)\n const className = ok ? 'text-green-600' : 'text-orange-600'\n return <span className={className}>{display}</span>\n },\n meta: { priority: 2 },\n },\n {\n id: 'status',\n header: () => t('query_index.table.columns.status'),\n cell: ({ row }) => {\n const record = row.original\n const job = record.job\n const partitions = job?.partitions ?? []\n const ok = record.ok && (!job || job.status === 'idle')\n const statusText = translateJobStatus(t, job?.status, ok)\n const jobProgress = job ? formatProgressLabel(job.processedCount ?? null, job.totalCount ?? null, t) : null\n const label = jobProgress\n ? t('query_index.table.status.withProgress', { status: statusText, progress: jobProgress })\n : statusText\n const className = job\n ? job.status === 'stalled'\n ? 'text-red-600'\n : job.status === 'reindexing' || job.status === 'purging'\n ? 'text-orange-600'\n : ok\n ? 'text-green-600'\n : 'text-muted-foreground'\n : ok\n ? 'text-green-600'\n : 'text-muted-foreground'\n\n const lines: string[] = []\n\n if (job?.scope && partitions.length <= 1) {\n const scopeStatus = translateScopeStatus(t, job.scope.status ?? null)\n const scopeProgress = formatProgressLabel(job.scope.processedCount ?? null, job.scope.totalCount ?? null, t)\n const scopeLabel = t('query_index.table.status.scopeLabel')\n lines.push(`${scopeLabel}: ${scopeStatus}${scopeProgress ? ` (${scopeProgress})` : ''}`)\n }\n\n if (partitions.length > 1) {\n for (const part of partitions) {\n const partitionLabel =\n part.partitionIndex != null\n ? t('query_index.table.status.partitionLabel', { index: Number(part.partitionIndex) + 1 })\n : t('query_index.table.status.scopeLabel')\n const partitionStatus = translateScopeStatus(t, part.status)\n const partitionProgress = formatProgressLabel(part.processedCount ?? null, part.totalCount ?? null, t)\n lines.push(`${partitionLabel}: ${partitionStatus}${partitionProgress ? ` (${partitionProgress})` : ''}`)\n }\n }\n\n if (record.vectorEnabled) {\n const vectorLabel = t('query_index.table.status.vectorLabel')\n const vectorCount = formatCount(record.vectorCount)\n const vectorTotal = record.baseCount != null ? formatCount(record.baseCount) : null\n const vectorValue = vectorTotal\n ? t('query_index.table.status.vectorValue', { count: vectorCount, total: vectorTotal })\n : vectorCount\n lines.push(`${vectorLabel}: ${vectorValue}`)\n }\n\n return (\n <div className=\"space-y-1\">\n <span className={className}>{label}</span>\n {lines.length > 0 && (\n <div className=\"text-xs text-muted-foreground\">\n {lines.map((line, idx) => (\n <div key={idx}>{line}</div>\n ))}\n </div>\n )}\n </div>\n )\n },\n meta: { priority: 1 },\n },\n ]\n}\n\nexport default function QueryIndexesTable() {\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'entityId', desc: false }])\n const [page, setPage] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const qc = useQueryClient()\n const scopeVersion = useOrganizationScopeVersion()\n const [refreshSeq, setRefreshSeq] = React.useState(0)\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const columns = React.useMemo(() => createColumns(t), [t])\n\n const { data, isLoading } = useQuery<Resp>({\n queryKey: ['query-index-status', scopeVersion, refreshSeq],\n queryFn: async () => {\n const baseUrl = '/api/query_index/status'\n const url = refreshSeq > 0 ? `${baseUrl}?refresh=${refreshSeq}` : baseUrl\n return readApiResultOrThrow<Resp>(\n url,\n undefined,\n { errorMessage: t('query_index.table.errors.loadFailed') },\n )\n },\n refetchInterval: 4000,\n })\n\n const rowsAll = data?.items || []\n const rows = React.useMemo(() => {\n if (!search) return rowsAll\n const q = search.toLowerCase()\n return rowsAll.filter((r) => r.entityId.toLowerCase().includes(q) || r.label.toLowerCase().includes(q))\n }, [rowsAll, search])\n\n const trigger = React.useCallback(\n async (action: 'reindex' | 'purge', entityId: string, opts?: { force?: boolean }) => {\n const body: Record<string, unknown> = { entityType: entityId }\n if (opts?.force) body.force = true\n const actionLabel =\n action === 'purge' ? t('query_index.table.actions.purge') : t('query_index.table.actions.reindex')\n const errorMessage = t('query_index.table.errors.actionFailed', { action: actionLabel })\n try {\n await apiCallOrThrow(`/api/query_index/${action}`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n }, { errorMessage })\n } catch (err) {\n console.error('query_index.table.trigger', err)\n if (typeof window !== 'undefined') {\n const message = err instanceof Error ? err.message : errorMessage\n window.alert(message)\n }\n }\n qc.invalidateQueries({ queryKey: ['query-index-status'] })\n },\n [qc, t],\n )\n\n const triggerVector = React.useCallback(\n async (action: 'reindex' | 'purge', entityId: string) => {\n if (action === 'purge') {\n const confirmed = await confirm({\n title: t('query_index.table.confirm.vectorPurge'),\n variant: 'destructive',\n })\n if (!confirmed) return\n }\n\n const actionLabel = action === 'purge'\n ? t('query_index.table.actions.vectorPurge')\n : t('query_index.table.actions.vectorReindex')\n const errorMessage = t('query_index.table.errors.actionFailed', { action: actionLabel })\n try {\n if (action === 'reindex') {\n await apiCallOrThrow('/api/vector/reindex', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ entityId }),\n }, { errorMessage })\n } else {\n const url = `/api/vector/index?entityId=${encodeURIComponent(entityId)}`\n await apiCallOrThrow(url, { method: 'DELETE' }, { errorMessage })\n }\n } catch (err) {\n console.error('query_index.table.vectorAction', err)\n if (typeof window !== 'undefined') {\n const message = err instanceof Error ? err.message : errorMessage\n window.alert(message)\n }\n }\n qc.invalidateQueries({ queryKey: ['query-index-status'] })\n },\n [confirm, qc, t],\n )\n\n const triggerFulltext = React.useCallback(\n async (action: 'reindex' | 'purge', entityId: string) => {\n if (action === 'purge') {\n const confirmed = await confirm({\n title: t('query_index.table.confirm.fulltextPurge'),\n variant: 'destructive',\n })\n if (!confirmed) return\n }\n\n const actionLabel = action === 'purge'\n ? t('query_index.table.actions.fulltextPurge')\n : t('query_index.table.actions.fulltextReindex')\n const errorMessage = t('query_index.table.errors.actionFailed', { action: actionLabel })\n try {\n await apiCallOrThrow('/api/search/reindex', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n action: action === 'purge' ? 'clear' : 'reindex',\n entityId,\n }),\n }, { errorMessage })\n } catch (err) {\n console.error('query_index.table.fulltextAction', err)\n if (typeof window !== 'undefined') {\n const message = err instanceof Error ? err.message : errorMessage\n window.alert(message)\n }\n }\n qc.invalidateQueries({ queryKey: ['query-index-status'] })\n },\n [confirm, qc, t],\n )\n\n return (\n <>\n <DataTable\n title={t('query_index.nav.queryIndexes')}\n actions={(\n <>\n <Button\n variant=\"outline\"\n onClick={() => {\n setRefreshSeq((v) => v + 1)\n qc.invalidateQueries({ queryKey: ['query-index-status'] })\n }}\n >\n {t('query_index.table.refresh')}\n </Button>\n </>\n )}\n columns={columns}\n data={rows}\n searchValue={search}\n searchPlaceholder={t('query_index.table.searchPlaceholder')}\n onSearchChange={(value) => {\n setSearch(value)\n setPage(1)\n }}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n perspective={{ tableId: 'query_index.status.list' }}\n rowActions={(row) => {\n const items: Array<{ id: string; label: string; onSelect: () => void; destructive?: boolean }> = [\n { id: 'reindex', label: t('query_index.table.actions.reindex'), onSelect: () => trigger('reindex', row.entityId) },\n {\n id: 'reindex-force',\n label: t('query_index.table.actions.reindexForce'),\n onSelect: () => trigger('reindex', row.entityId, { force: true }),\n },\n {\n id: 'purge',\n label: t('query_index.table.actions.purge'),\n destructive: true,\n onSelect: () => trigger('purge', row.entityId),\n },\n ]\n\n if (row.vectorEnabled) {\n items.push(\n {\n id: 'vector-reindex',\n label: t('query_index.table.actions.vectorReindex'),\n onSelect: () => triggerVector('reindex', row.entityId),\n },\n {\n id: 'vector-purge',\n label: t('query_index.table.actions.vectorPurge'),\n destructive: true,\n onSelect: () => triggerVector('purge', row.entityId),\n },\n )\n }\n\n if (row.fulltextEnabled) {\n items.push(\n {\n id: 'fulltext-reindex',\n label: t('query_index.table.actions.fulltextReindex'),\n onSelect: () => triggerFulltext('reindex', row.entityId),\n },\n {\n id: 'fulltext-purge',\n label: t('query_index.table.actions.fulltextPurge'),\n destructive: true,\n onSelect: () => triggerFulltext('purge', row.entityId),\n },\n )\n }\n\n return <RowActions items={items} />\n }}\n pagination={{ page, pageSize: 50, total: rows.length, totalPages: 1, onPageChange: setPage }}\n isLoading={isLoading}\n />\n {ConfirmDialogElement}\n </>\n )\n}\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["\"use client\"\nimport * as React from 'react'\nimport { useQuery, useQueryClient } from '@tanstack/react-query'\nimport type { ColumnDef, SortingState } from '@tanstack/react-table'\nimport { DataTable } from '@open-mercato/ui/backend/DataTable'\nimport { RowActions } from '@open-mercato/ui/backend/RowActions'\nimport { Button } from '@open-mercato/ui/primitives/button'\nimport { apiCallOrThrow, readApiResultOrThrow } from '@open-mercato/ui/backend/utils/apiCall'\nimport { useOrganizationScopeVersion } from '@open-mercato/shared/lib/frontend/useOrganizationScope'\nimport { useT } from '@open-mercato/shared/lib/i18n/context'\nimport { useConfirmDialog } from '@open-mercato/ui/backend/confirm-dialog'\n\ntype Translator = (key: string, params?: Record<string, string | number>) => string\n\ntype PartitionStatus = {\n partitionIndex: number | null\n partitionCount: number | null\n status: 'reindexing' | 'purging' | 'stalled' | 'completed'\n processedCount?: number | null\n totalCount?: number | null\n heartbeatAt?: string | null\n startedAt?: string | null\n finishedAt?: string | null\n}\n\ntype JobStatus = {\n status: 'idle' | 'reindexing' | 'purging' | 'stalled'\n startedAt?: string | null\n finishedAt?: string | null\n heartbeatAt?: string | null\n processedCount?: number | null\n totalCount?: number | null\n partitions?: PartitionStatus[]\n scope?: {\n status?: 'reindexing' | 'purging' | 'stalled' | 'completed' | null\n processedCount?: number | null\n totalCount?: number | null\n } | null\n}\n\ntype Row = {\n entityId: string\n label: string\n baseCount: number | null\n indexCount: number | null\n vectorCount: number | null\n vectorEnabled: boolean\n fulltextCount: number | null\n fulltextEnabled: boolean\n ok: boolean\n job?: JobStatus\n}\n\ntype Resp = { items: Row[] }\n\nfunction formatCount(value: number | null): string {\n if (value == null) return '\u2014'\n return value.toLocaleString()\n}\n\nfunction formatNumeric(value: number | null | undefined): string | null {\n if (value == null) return null\n return Number(value).toLocaleString()\n}\n\nfunction formatProgressLabel(\n processed: number | null | undefined,\n total: number | null | undefined,\n t: Translator,\n): string | null {\n const processedText = formatNumeric(processed)\n if (!processedText) return null\n const totalText = formatNumeric(total)\n if (totalText) return t('query_index.table.status.progress', { processed: processedText, total: totalText })\n return t('query_index.table.status.progressSingle', { processed: processedText })\n}\n\nfunction translateJobStatus(t: Translator, status: JobStatus['status'] | undefined, ok: boolean): string {\n if (!status || status === 'idle') {\n return ok ? t('query_index.table.status.in_sync') : t('query_index.table.status.out_of_sync')\n }\n if (status === 'reindexing') return t('query_index.table.status.reindexing')\n if (status === 'purging') return t('query_index.table.status.purging')\n if (status === 'stalled') return t('query_index.table.status.stalled')\n return ok ? t('query_index.table.status.in_sync') : t('query_index.table.status.out_of_sync')\n}\n\nfunction translateScopeStatus(\n t: Translator,\n status: PartitionStatus['status'] | JobStatus['status'] | undefined | null,\n): string {\n if (status === 'reindexing') return t('query_index.table.status.scope.reindexing')\n if (status === 'purging') return t('query_index.table.status.scope.purging')\n if (status === 'stalled') return t('query_index.table.status.scope.stalled')\n return t('query_index.table.status.scope.completed')\n}\n\n\nfunction createColumns(t: Translator): ColumnDef<Row>[] {\n return [\n { id: 'entityId', header: () => t('query_index.table.columns.entity'), accessorKey: 'entityId', meta: { priority: 1 } },\n { id: 'label', header: () => t('query_index.table.columns.label'), accessorKey: 'label', meta: { priority: 2 } },\n {\n id: 'baseCount',\n header: () => t('query_index.table.columns.records'),\n accessorFn: (row) => row.baseCount ?? 0,\n cell: ({ row }) => <span>{formatCount(row.original.baseCount)}</span>,\n meta: { priority: 2 },\n },\n {\n id: 'indexCount',\n header: () => t('query_index.table.columns.indexed'),\n accessorFn: (row) => row.indexCount ?? 0,\n cell: ({ row }) => <span>{formatCount(row.original.indexCount)}</span>,\n meta: { priority: 2 },\n },\n {\n id: 'vectorCount',\n header: () => t('query_index.table.columns.vector'),\n accessorFn: (row) => (row.vectorEnabled ? row.vectorCount ?? 0 : -1),\n cell: ({ row }) => {\n const record = row.original\n if (!record.vectorEnabled) return <span>\u2014</span>\n const ok = record.vectorCount != null && record.baseCount != null && record.vectorCount === record.baseCount\n const display = formatCount(record.vectorCount)\n const className = ok ? 'text-green-600' : 'text-orange-600'\n return <span className={className}>{display}</span>\n },\n meta: { priority: 2 },\n },\n {\n id: 'fulltextCount',\n header: () => t('query_index.table.columns.fulltext'),\n accessorFn: (row) => (row.fulltextEnabled ? row.fulltextCount ?? 0 : -1),\n cell: ({ row }) => {\n const record = row.original\n if (!record.fulltextEnabled) return <span>\u2014</span>\n const ok = record.fulltextCount != null && record.baseCount != null && record.fulltextCount === record.baseCount\n const display = formatCount(record.fulltextCount)\n const className = ok ? 'text-green-600' : 'text-orange-600'\n return <span className={className}>{display}</span>\n },\n meta: { priority: 2 },\n },\n {\n id: 'status',\n header: () => t('query_index.table.columns.status'),\n cell: ({ row }) => {\n const record = row.original\n const job = record.job\n const partitions = job?.partitions ?? []\n const ok = record.ok && (!job || job.status === 'idle')\n const statusText = translateJobStatus(t, job?.status, ok)\n const jobProgress = job ? formatProgressLabel(job.processedCount ?? null, job.totalCount ?? null, t) : null\n const label = jobProgress\n ? t('query_index.table.status.withProgress', { status: statusText, progress: jobProgress })\n : statusText\n const className = job\n ? job.status === 'stalled'\n ? 'text-red-600'\n : job.status === 'reindexing' || job.status === 'purging'\n ? 'text-orange-600'\n : ok\n ? 'text-green-600'\n : 'text-muted-foreground'\n : ok\n ? 'text-green-600'\n : 'text-muted-foreground'\n\n const lines: string[] = []\n\n if (job?.scope && partitions.length <= 1) {\n const scopeStatus = translateScopeStatus(t, job.scope.status ?? null)\n const scopeProgress = formatProgressLabel(job.scope.processedCount ?? null, job.scope.totalCount ?? null, t)\n const scopeLabel = t('query_index.table.status.scopeLabel')\n lines.push(`${scopeLabel}: ${scopeStatus}${scopeProgress ? ` (${scopeProgress})` : ''}`)\n }\n\n if (partitions.length > 1) {\n for (const part of partitions) {\n const partitionLabel =\n part.partitionIndex != null\n ? t('query_index.table.status.partitionLabel', { index: Number(part.partitionIndex) + 1 })\n : t('query_index.table.status.scopeLabel')\n const partitionStatus = translateScopeStatus(t, part.status)\n const partitionProgress = formatProgressLabel(part.processedCount ?? null, part.totalCount ?? null, t)\n lines.push(`${partitionLabel}: ${partitionStatus}${partitionProgress ? ` (${partitionProgress})` : ''}`)\n }\n }\n\n if (record.vectorEnabled) {\n const vectorLabel = t('query_index.table.status.vectorLabel')\n const vectorCount = formatCount(record.vectorCount)\n const vectorTotal = record.baseCount != null ? formatCount(record.baseCount) : null\n const vectorValue = vectorTotal\n ? t('query_index.table.status.vectorValue', { count: vectorCount, total: vectorTotal })\n : vectorCount\n lines.push(`${vectorLabel}: ${vectorValue}`)\n }\n\n return (\n <div className=\"space-y-1\">\n <span className={className}>{label}</span>\n {lines.length > 0 && (\n <div className=\"text-xs text-muted-foreground\">\n {lines.map((line, idx) => (\n <div key={idx}>{line}</div>\n ))}\n </div>\n )}\n </div>\n )\n },\n meta: { priority: 1 },\n },\n ]\n}\n\nexport default function QueryIndexesTable() {\n const [sorting, setSorting] = React.useState<SortingState>([{ id: 'entityId', desc: false }])\n const [page, setPage] = React.useState(1)\n const [search, setSearch] = React.useState('')\n const qc = useQueryClient()\n const scopeVersion = useOrganizationScopeVersion()\n const [refreshSeq, setRefreshSeq] = React.useState(0)\n const t = useT()\n const { confirm, ConfirmDialogElement } = useConfirmDialog()\n const columns = React.useMemo(() => createColumns(t), [t])\n\n const { data, isLoading } = useQuery<Resp>({\n queryKey: ['query-index-status', scopeVersion, refreshSeq],\n queryFn: async () => {\n const baseUrl = '/api/query_index/status'\n const url = refreshSeq > 0 ? `${baseUrl}?refresh=${refreshSeq}` : baseUrl\n return readApiResultOrThrow<Resp>(\n url,\n undefined,\n { errorMessage: t('query_index.table.errors.loadFailed') },\n )\n },\n refetchInterval: 4000,\n })\n\n const rowsAll = data?.items || []\n const rows = React.useMemo(() => {\n if (!search) return rowsAll\n const q = search.toLowerCase()\n return rowsAll.filter((r) => r.entityId.toLowerCase().includes(q) || r.label.toLowerCase().includes(q))\n }, [rowsAll, search])\n\n const trigger = React.useCallback(\n async (action: 'reindex' | 'purge', entityId: string, opts?: { force?: boolean }) => {\n const body: Record<string, unknown> = { entityType: entityId }\n if (opts?.force) body.force = true\n const actionLabel =\n action === 'purge' ? t('query_index.table.actions.purge') : t('query_index.table.actions.reindex')\n const errorMessage = t('query_index.table.errors.actionFailed', { action: actionLabel })\n try {\n await apiCallOrThrow(`/api/query_index/${action}`, {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(body),\n }, { errorMessage })\n } catch (err) {\n console.error('query_index.table.trigger', err)\n if (typeof window !== 'undefined') {\n const message = err instanceof Error ? err.message : errorMessage\n window.alert(message)\n }\n }\n qc.invalidateQueries({ queryKey: ['query-index-status'] })\n },\n [qc, t],\n )\n\n const triggerVector = React.useCallback(\n async (action: 'reindex' | 'purge', entityId: string) => {\n if (action === 'purge') {\n const confirmed = await confirm({\n title: t('query_index.table.confirm.vectorPurge'),\n variant: 'destructive',\n })\n if (!confirmed) return\n }\n\n const actionLabel = action === 'purge'\n ? t('query_index.table.actions.vectorPurge')\n : t('query_index.table.actions.vectorReindex')\n const errorMessage = t('query_index.table.errors.actionFailed', { action: actionLabel })\n try {\n if (action === 'reindex') {\n await apiCallOrThrow('/api/vector/reindex', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({ entityId }),\n }, { errorMessage })\n } else {\n const url = `/api/vector/index?entityId=${encodeURIComponent(entityId)}`\n await apiCallOrThrow(url, { method: 'DELETE' }, { errorMessage })\n }\n } catch (err) {\n console.error('query_index.table.vectorAction', err)\n if (typeof window !== 'undefined') {\n const message = err instanceof Error ? err.message : errorMessage\n window.alert(message)\n }\n }\n qc.invalidateQueries({ queryKey: ['query-index-status'] })\n },\n [confirm, qc, t],\n )\n\n const triggerFulltext = React.useCallback(\n async (action: 'reindex' | 'purge', entityId: string) => {\n if (action === 'purge') {\n const confirmed = await confirm({\n title: t('query_index.table.confirm.fulltextPurge'),\n variant: 'destructive',\n })\n if (!confirmed) return\n }\n\n const actionLabel = action === 'purge'\n ? t('query_index.table.actions.fulltextPurge')\n : t('query_index.table.actions.fulltextReindex')\n const errorMessage = t('query_index.table.errors.actionFailed', { action: actionLabel })\n try {\n await apiCallOrThrow('/api/search/reindex', {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify({\n action: action === 'purge' ? 'clear' : 'reindex',\n entityId,\n }),\n }, { errorMessage })\n } catch (err) {\n console.error('query_index.table.fulltextAction', err)\n if (typeof window !== 'undefined') {\n const message = err instanceof Error ? err.message : errorMessage\n window.alert(message)\n }\n }\n qc.invalidateQueries({ queryKey: ['query-index-status'] })\n },\n [confirm, qc, t],\n )\n\n return (\n <>\n <DataTable\n title={t('query_index.nav.queryIndexes')}\n actions={(\n <>\n <Button\n variant=\"outline\"\n onClick={() => {\n setRefreshSeq((v) => v + 1)\n qc.invalidateQueries({ queryKey: ['query-index-status'] })\n }}\n >\n {t('query_index.table.refresh')}\n </Button>\n </>\n )}\n columns={columns}\n data={rows}\n searchValue={search}\n searchPlaceholder={t('query_index.table.searchPlaceholder')}\n onSearchChange={(value) => {\n setSearch(value)\n setPage(1)\n }}\n sortable\n sorting={sorting}\n onSortingChange={setSorting}\n perspective={{ tableId: 'query_index.status.list' }}\n rowActions={(row) => {\n const items: Array<{ id: string; label: string; onSelect: () => void; destructive?: boolean }> = [\n { id: 'reindex', label: t('query_index.table.actions.reindex'), onSelect: () => void trigger('reindex', row.entityId) },\n {\n id: 'reindex-force',\n label: t('query_index.table.actions.reindexForce'),\n onSelect: () => void trigger('reindex', row.entityId, { force: true }),\n },\n {\n id: 'purge',\n label: t('query_index.table.actions.purge'),\n destructive: true,\n onSelect: () => void trigger('purge', row.entityId),\n },\n ]\n\n if (row.vectorEnabled) {\n items.push(\n {\n id: 'vector-reindex',\n label: t('query_index.table.actions.vectorReindex'),\n onSelect: () => void triggerVector('reindex', row.entityId),\n },\n {\n id: 'vector-purge',\n label: t('query_index.table.actions.vectorPurge'),\n destructive: true,\n onSelect: () => void triggerVector('purge', row.entityId),\n },\n )\n }\n\n if (row.fulltextEnabled) {\n items.push(\n {\n id: 'fulltext-reindex',\n label: t('query_index.table.actions.fulltextReindex'),\n onSelect: () => void triggerFulltext('reindex', row.entityId),\n },\n {\n id: 'fulltext-purge',\n label: t('query_index.table.actions.fulltextPurge'),\n destructive: true,\n onSelect: () => void triggerFulltext('purge', row.entityId),\n },\n )\n }\n\n return <RowActions items={items} />\n }}\n pagination={{ page, pageSize: 50, total: rows.length, totalPages: 1, onPageChange: setPage }}\n isLoading={isLoading}\n />\n {ConfirmDialogElement}\n </>\n )\n}\n"],
5
+ "mappings": "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",
6
6
  "names": []
7
7
  }
@@ -1132,7 +1132,7 @@ class HybridQueryEngine {
1132
1132
  }
1133
1133
  }
1134
1134
  customFieldKeysCacheKey(entityIds, tenantId) {
1135
- const sorted = entityIds.slice().sort().join(",");
1135
+ const sorted = entityIds.slice().sort((a, b) => a.localeCompare(b)).join(",");
1136
1136
  return `${tenantId ?? "__none__"}|${sorted}`;
1137
1137
  }
1138
1138
  resolveVectorService() {