@jini-ai/admin 0.3.8 → 0.3.9

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 (169) hide show
  1. package/dist/core/index.d.ts +0 -3
  2. package/dist/core/index.js +0 -1
  3. package/dist/core/ports/index.d.ts +0 -1
  4. package/dist/core/ports/menus.d.ts +0 -43
  5. package/dist/core/ports/menus.js +0 -43
  6. package/dist/react/components/ConfirmDialog/ConfirmDialog.d.ts +2 -1
  7. package/dist/react/components/ConfirmDialog/ConfirmDialog.hooks.d.ts +37 -1
  8. package/dist/react/components/ConfirmDialog/ConfirmDialog.hooks.js +42 -1
  9. package/dist/react/components/ConfirmDialog/ConfirmDialog.js +2 -3
  10. package/dist/react/components/Sidebar.js +2 -90
  11. package/dist/react/index.d.ts +3 -1
  12. package/dist/react/index.js +5 -3
  13. package/package.json +5 -4
  14. package/dist/browser/index.d.ts.map +0 -1
  15. package/dist/browser/index.js.map +0 -1
  16. package/dist/browser/navigation.d.ts.map +0 -1
  17. package/dist/browser/navigation.js.map +0 -1
  18. package/dist/core/data-table/types.d.ts.map +0 -1
  19. package/dist/core/data-table/types.js.map +0 -1
  20. package/dist/core/entities/rules.d.ts +0 -138
  21. package/dist/core/entities/rules.d.ts.map +0 -1
  22. package/dist/core/entities/rules.js +0 -344
  23. package/dist/core/entities/rules.js.map +0 -1
  24. package/dist/core/gated/types.d.ts.map +0 -1
  25. package/dist/core/gated/types.js.map +0 -1
  26. package/dist/core/index.d.ts.map +0 -1
  27. package/dist/core/index.js.map +0 -1
  28. package/dist/core/manifest/rules.d.ts.map +0 -1
  29. package/dist/core/manifest/rules.js.map +0 -1
  30. package/dist/core/manifest/types.d.ts.map +0 -1
  31. package/dist/core/manifest/types.js.map +0 -1
  32. package/dist/core/permissions/rules.d.ts.map +0 -1
  33. package/dist/core/permissions/rules.js.map +0 -1
  34. package/dist/core/ports/analytics.d.ts.map +0 -1
  35. package/dist/core/ports/analytics.js.map +0 -1
  36. package/dist/core/ports/auth.d.ts.map +0 -1
  37. package/dist/core/ports/auth.js.map +0 -1
  38. package/dist/core/ports/comments.d.ts.map +0 -1
  39. package/dist/core/ports/comments.js.map +0 -1
  40. package/dist/core/ports/database.d.ts.map +0 -1
  41. package/dist/core/ports/database.js.map +0 -1
  42. package/dist/core/ports/entities.d.ts +0 -302
  43. package/dist/core/ports/entities.d.ts.map +0 -1
  44. package/dist/core/ports/entities.js +0 -47
  45. package/dist/core/ports/entities.js.map +0 -1
  46. package/dist/core/ports/forms.d.ts.map +0 -1
  47. package/dist/core/ports/forms.js.map +0 -1
  48. package/dist/core/ports/identity.d.ts.map +0 -1
  49. package/dist/core/ports/identity.js.map +0 -1
  50. package/dist/core/ports/index.d.ts.map +0 -1
  51. package/dist/core/ports/index.js.map +0 -1
  52. package/dist/core/ports/integrations.d.ts.map +0 -1
  53. package/dist/core/ports/integrations.js.map +0 -1
  54. package/dist/core/ports/media.d.ts.map +0 -1
  55. package/dist/core/ports/media.js.map +0 -1
  56. package/dist/core/ports/members.d.ts.map +0 -1
  57. package/dist/core/ports/members.js.map +0 -1
  58. package/dist/core/ports/menus.d.ts.map +0 -1
  59. package/dist/core/ports/menus.js.map +0 -1
  60. package/dist/core/ports/plugins.d.ts.map +0 -1
  61. package/dist/core/ports/plugins.js.map +0 -1
  62. package/dist/core/ports/recovery.d.ts.map +0 -1
  63. package/dist/core/ports/recovery.js.map +0 -1
  64. package/dist/core/ports/redirects.d.ts.map +0 -1
  65. package/dist/core/ports/redirects.js.map +0 -1
  66. package/dist/core/ports/seo.d.ts.map +0 -1
  67. package/dist/core/ports/seo.js.map +0 -1
  68. package/dist/core/ports/settings.d.ts.map +0 -1
  69. package/dist/core/ports/settings.js.map +0 -1
  70. package/dist/core/ports/workspace.d.ts.map +0 -1
  71. package/dist/core/ports/workspace.js.map +0 -1
  72. package/dist/core/routing/rules.d.ts.map +0 -1
  73. package/dist/core/routing/rules.js.map +0 -1
  74. package/dist/core/routing/types.d.ts.map +0 -1
  75. package/dist/core/routing/types.js.map +0 -1
  76. package/dist/core/transport/errors.d.ts.map +0 -1
  77. package/dist/core/transport/errors.js.map +0 -1
  78. package/dist/core/transport/http.d.ts.map +0 -1
  79. package/dist/core/transport/http.js.map +0 -1
  80. package/dist/core/transport/index.d.ts.map +0 -1
  81. package/dist/core/transport/index.js.map +0 -1
  82. package/dist/core/transport/types.d.ts.map +0 -1
  83. package/dist/core/transport/types.js.map +0 -1
  84. package/dist/react/components/ConfirmButton/ConfirmButton.d.ts.map +0 -1
  85. package/dist/react/components/ConfirmButton/ConfirmButton.hooks.d.ts.map +0 -1
  86. package/dist/react/components/ConfirmButton/ConfirmButton.hooks.js.map +0 -1
  87. package/dist/react/components/ConfirmButton/ConfirmButton.js.map +0 -1
  88. package/dist/react/components/ConfirmButton.d.ts +0 -39
  89. package/dist/react/components/ConfirmButton.d.ts.map +0 -1
  90. package/dist/react/components/ConfirmButton.js +0 -79
  91. package/dist/react/components/ConfirmButton.js.map +0 -1
  92. package/dist/react/components/ConfirmDialog/ConfirmDialog.d.ts.map +0 -1
  93. package/dist/react/components/ConfirmDialog/ConfirmDialog.hooks.d.ts.map +0 -1
  94. package/dist/react/components/ConfirmDialog/ConfirmDialog.hooks.js.map +0 -1
  95. package/dist/react/components/ConfirmDialog/ConfirmDialog.js.map +0 -1
  96. package/dist/react/components/ConfirmDialog.d.ts +0 -57
  97. package/dist/react/components/ConfirmDialog.d.ts.map +0 -1
  98. package/dist/react/components/ConfirmDialog.js +0 -85
  99. package/dist/react/components/ConfirmDialog.js.map +0 -1
  100. package/dist/react/components/DataTable.d.ts.map +0 -1
  101. package/dist/react/components/DataTable.js.map +0 -1
  102. package/dist/react/components/InteractiveHtmlEditor/InteractiveHtmlEditor.d.ts.map +0 -1
  103. package/dist/react/components/InteractiveHtmlEditor/InteractiveHtmlEditor.js.map +0 -1
  104. package/dist/react/components/RowMenu/RowMenu.d.ts.map +0 -1
  105. package/dist/react/components/RowMenu/RowMenu.hooks.d.ts.map +0 -1
  106. package/dist/react/components/RowMenu/RowMenu.hooks.js.map +0 -1
  107. package/dist/react/components/RowMenu/RowMenu.js.map +0 -1
  108. package/dist/react/components/RowMenu.d.ts +0 -44
  109. package/dist/react/components/RowMenu.d.ts.map +0 -1
  110. package/dist/react/components/RowMenu.js +0 -149
  111. package/dist/react/components/RowMenu.js.map +0 -1
  112. package/dist/react/components/Sidebar.d.ts.map +0 -1
  113. package/dist/react/components/Sidebar.js.map +0 -1
  114. package/dist/react/hooks/use-nav-sections.d.ts.map +0 -1
  115. package/dist/react/hooks/use-nav-sections.js.map +0 -1
  116. package/dist/react/hooks/use-sidebar-rail.d.ts.map +0 -1
  117. package/dist/react/hooks/use-sidebar-rail.js.map +0 -1
  118. package/dist/react/index.d.ts.map +0 -1
  119. package/dist/react/index.js.map +0 -1
  120. package/dist/react/types.d.ts.map +0 -1
  121. package/dist/react/types.js.map +0 -1
  122. package/dist/server/composio/bounded-data.d.ts +0 -36
  123. package/dist/server/composio/bounded-data.d.ts.map +0 -1
  124. package/dist/server/composio/bounded-data.js +0 -181
  125. package/dist/server/composio/bounded-data.js.map +0 -1
  126. package/dist/server/composio/catalog.d.ts +0 -147
  127. package/dist/server/composio/catalog.d.ts.map +0 -1
  128. package/dist/server/composio/catalog.js +0 -126
  129. package/dist/server/composio/catalog.js.map +0 -1
  130. package/dist/server/composio/composio-config.d.ts +0 -42
  131. package/dist/server/composio/composio-config.d.ts.map +0 -1
  132. package/dist/server/composio/composio-config.js +0 -145
  133. package/dist/server/composio/composio-config.js.map +0 -1
  134. package/dist/server/composio/composio-descriptions.d.ts +0 -16
  135. package/dist/server/composio/composio-descriptions.d.ts.map +0 -1
  136. package/dist/server/composio/composio-descriptions.js +0 -766
  137. package/dist/server/composio/composio-descriptions.js.map +0 -1
  138. package/dist/server/composio/composio.d.ts +0 -364
  139. package/dist/server/composio/composio.d.ts.map +0 -1
  140. package/dist/server/composio/composio.js +0 -1902
  141. package/dist/server/composio/composio.js.map +0 -1
  142. package/dist/server/composio/errors.d.ts +0 -15
  143. package/dist/server/composio/errors.d.ts.map +0 -1
  144. package/dist/server/composio/errors.js +0 -16
  145. package/dist/server/composio/errors.js.map +0 -1
  146. package/dist/server/composio/file-lock.d.ts +0 -13
  147. package/dist/server/composio/file-lock.d.ts.map +0 -1
  148. package/dist/server/composio/file-lock.js +0 -92
  149. package/dist/server/composio/file-lock.js.map +0 -1
  150. package/dist/server/composio/index.d.ts +0 -18
  151. package/dist/server/composio/index.d.ts.map +0 -1
  152. package/dist/server/composio/index.js +0 -7
  153. package/dist/server/composio/index.js.map +0 -1
  154. package/dist/server/composio/json-schema.d.ts +0 -93
  155. package/dist/server/composio/json-schema.d.ts.map +0 -1
  156. package/dist/server/composio/json-schema.js +0 -498
  157. package/dist/server/composio/json-schema.js.map +0 -1
  158. package/dist/server/composio/output-protection.d.ts +0 -32
  159. package/dist/server/composio/output-protection.d.ts.map +0 -1
  160. package/dist/server/composio/output-protection.js +0 -105
  161. package/dist/server/composio/output-protection.js.map +0 -1
  162. package/dist/server/composio/service.d.ts +0 -181
  163. package/dist/server/composio/service.d.ts.map +0 -1
  164. package/dist/server/composio/service.js +0 -758
  165. package/dist/server/composio/service.js.map +0 -1
  166. package/dist/server/index.d.ts +0 -15
  167. package/dist/server/index.d.ts.map +0 -1
  168. package/dist/server/index.js +0 -15
  169. package/dist/server/index.js.map +0 -1
@@ -18,7 +18,4 @@ export type { GatedConfirmResult, GatedOperation, GatedPlanResult } from './gate
18
18
  export type { DataTableSortDirection, DataTableSortState } from './data-table/types.js';
19
19
  export type { AdminAnalyticsHit, AdminAnalyticsPort, AdminAuthPort, AdminAuthUser, AdminComment, AdminCommentsPort, AdminCommentsQueuePage, AdminDatabasePort, AdminDegradedBanner, AdminDisclosureResult, AdminExtensionEnabledResult, AdminExtensionsPort, AdminIdentityPort, AdminIdentityUser, AdminIntegrationDelivery, AdminIntegrationDeliverySummary, AdminIntegrationSubscription, AdminIntegrationsPort, AdminLedgerRow, AdminMedia, AdminMediaPort, AdminMember, AdminMembersPort, AdminPlugin, AdminPolicy, AdminRecoveryDeepLinkResult, AdminRecoveryPort, AdminRecoveryStatus, AdminRestorePoint, AdminRestorePointSummary, AdminRole, AdminSettingsPort, AdminWorkspace, AdminWorkspacePort, CategoryCount, CommentModerationAction, CommentsSettings, CommentStatus, DatabaseContextEnvelope, DegradedBannerActionKind, DegradedBannerKind, MigrateForwardResult, RestoreConfirmInput, RestoreExecuteInput, RestoreExecuteResult, RestorePointCostClass, SettingResolvedValue, SettingResetResponse, SettingScope, SettingValueResponse, } from './ports/index.js';
20
20
  export type { AdminAssignMenuLocationResult, AdminDeleteMenuResult, AdminFormCreateInput, AdminFormDefinition, AdminFormField, AdminFormNotifyConfig, AdminFormsPort, AdminFormSubmission, AdminFormSubmissionPage, AdminFormUpdatePatch, AdminMenu, AdminMenuBinding, AdminMenuCreateInput, AdminMenuCustomTarget, AdminMenuEntryTarget, AdminMenuItem, AdminMenuItemAttrs, AdminMenuRouteTarget, AdminMenusPort, AdminMenuTarget, AdminMenuTermTarget, AdminMenuUpdateTreeInput, AdminMenuUrlTarget, AdminRedirect, AdminRedirectCreateInput, AdminRedirectHitStats, AdminRedirectImportFailure, AdminRedirectImportResult, AdminRedirectListFilter, AdminRedirectsPort, AdminRedirectUpdatePatch, AdminSeoAnalysis, AdminSeoIssue, AdminSeoMeta, AdminSeoOpenGraph, AdminSeoOverrides, AdminSeoPort, AdminSeoRobotsDirective, AdminSeoRobotsRule, AdminSeoSettings, AdminSeoTwitterCard, FormDefinitionStatus, FormFieldType, MenuStatus, NavTargetKind, RedirectMatchType, RedirectSource, RedirectStatus, RedirectStatusCode, SeoIssueSeverity, SeoOpenGraphType, SeoTwitterCardKind, } from './ports/index.js';
21
- export type { AdminEntityDescriptor, AdminEntityField, AdminEntityFieldKind, AdminEntityFilter, AdminEntityJsonField, AdminEntityListQuery, AdminEntityPage, AdminEntityPort, AdminEntityRegistry, AdminEntityRelationField, AdminEntityRow, AdminEntityRowData, AdminEntityScalarField, AdminErasedEntityPort, } from './ports/index.js';
22
- export { createAdminEntityRegistry, describeAdminEntityFieldMismatch, eraseEntityPort, getErasedEntityPort, listErasedEntityPorts, } from './entities/rules.js';
23
- export type { AdminEntityErasureOptions, AdminEntityRowViolation } from './entities/rules.js';
24
21
  //# sourceMappingURL=index.d.ts.map
@@ -12,5 +12,4 @@ export { DEFAULT_ADMIN_BASE, adminHref, currentRoutePath, matchRoute, stripTrail
12
12
  export { hasPermission } from './permissions/rules.js';
13
13
  // Transport — the seam every route group is built on.
14
14
  export { AdminApiError, createAdminClient, createHttpTransport, describeApiError, } from './transport/index.js';
15
- export { createAdminEntityRegistry, describeAdminEntityFieldMismatch, eraseEntityPort, getErasedEntityPort, listErasedEntityPorts, } from './entities/rules.js';
16
15
  //# sourceMappingURL=index.js.map
@@ -18,5 +18,4 @@ export type { AdminSeoAnalysis, AdminSeoIssue, AdminSeoMeta, AdminSeoOpenGraph,
18
18
  export type { AdminRedirect, AdminRedirectCreateInput, AdminRedirectHitStats, AdminRedirectImportFailure, AdminRedirectImportResult, AdminRedirectListFilter, AdminRedirectsPort, AdminRedirectUpdatePatch, RedirectMatchType, RedirectSource, RedirectStatus, RedirectStatusCode, } from './redirects.js';
19
19
  export type { AdminAssignMenuLocationResult, AdminDeleteMenuResult, AdminMenu, AdminMenuBinding, AdminMenuCreateInput, AdminMenuCustomTarget, AdminMenuEntryTarget, AdminMenuItem, AdminMenuItemAttrs, AdminMenuRouteTarget, AdminMenusPort, AdminMenuTarget, AdminMenuTermTarget, AdminMenuUpdateTreeInput, AdminMenuUrlTarget, MenuStatus, NavTargetKind, } from './menus.js';
20
20
  export type { AdminFormCreateInput, AdminFormDefinition, AdminFormField, AdminFormNotifyConfig, AdminFormsPort, AdminFormSubmission, AdminFormSubmissionPage, AdminFormUpdatePatch, FormDefinitionStatus, FormFieldType, } from './forms.js';
21
- export type { AdminEntityDescriptor, AdminEntityField, AdminEntityFieldKind, AdminEntityFilter, AdminEntityJsonField, AdminEntityListQuery, AdminEntityPage, AdminEntityPort, AdminEntityRegistry, AdminEntityRelationField, AdminEntityRow, AdminEntityRowData, AdminEntityScalarField, AdminErasedEntityPort, } from './entities.js';
22
21
  //# sourceMappingURL=index.d.ts.map
@@ -25,20 +25,6 @@
25
25
  * `kind` values (with `AdminMenuCustomTarget` as the `default` arm) is the straightforward way to
26
26
  * stay correct.
27
27
  *
28
- * **Migration hazard, measured 2026-09-05.** This is not merely a style preference — it means an
29
- * exhaustive `switch` with NO `default` arm cannot compile against `AdminMenuTarget` at all, and
30
- * that is exactly the shape a host arrives with. Both existing admin apps' `targetForKind`
31
- * (`apps/admin/src/features/menus/MenuEditor.tsx`) switch over their own local CLOSED four-member
32
- * union with no `default`, and rely on exhaustiveness for the return type. Compiling that function
33
- * against this port's union emits `TS2366` (lacks ending return statement) plus a `TS2339` per
34
- * field access. Confirmed by compiling the real function against this union directly.
35
- *
36
- * The hazard is pre-existing and belongs to `AdminMenuCustomTarget`, not to any later change: the
37
- * identical probe run against the union with and without an extra member emits a character-for-
38
- * character identical error set. Recorded here because it will surface the first time anyone wires
39
- * a host onto this port, and the natural instinct will be to blame whatever change is in flight at
40
- * that moment. The fix is a `default` arm in the host, not a change to this file.
41
- *
42
28
  * **This is a deliberately deferred decision, not a settled one — record it as such.** `entryRef`/
43
29
  * `termRef` encode a host content model (an "entry" and a "taxonomy term" are the reference
44
30
  * implementation's own vocabulary for its content system, not a vendor-neutral abstraction this
@@ -53,35 +39,6 @@
53
39
  * instead of one, and a genuine vendor-neutral reference shape (rather than another bespoke
54
40
  * `kind`-per-host member) becomes the right call.
55
41
  *
56
- * ### Status of that trigger, re-checked 2026-09-05 — NOT fired
57
- *
58
- * A second host now exists in this workspace, and that is NOT the trigger. The trigger is a second
59
- * host needing a fifth KIND. Recording the difference here because a promotion was very nearly
60
- * approved on the weaker reading. Four findings, all verified against source rather than assumed:
61
- *
62
- * 1. **Zero importers.** Nothing anywhere imports `AdminMenuTarget`, `NavTargetKind`, or any target
63
- * variant from this package. In this repo they are re-exported by `core/index.ts` and
64
- * `core/ports/index.ts` and consumed by nothing.
65
- * 2. **Both admin apps declare their own.** Each ships a local, *closed*
66
- * `{ kind: "entryRef" | "termRef" | "url" | "route" }` in its own `src/lib/api.ts` — an HTTP
67
- * DTO, not this port. The two are byte-identical to each other: the second is a fork of the
68
- * first, so they are one data point, not two.
69
- * 3. **The other `NavTargetKind` is a different type.** `@jini-ai/cms/navigation` exports its own
70
- * `NavTargetKind` (closed, plus a separate `ReservedNavTargetKind`). A host importing that one
71
- * is not exercising this port.
72
- * 4. **The union is already open.** `AdminMenuCustomTarget`'s `kind: string & {}` already lets any
73
- * host express any kind today. Nothing is blocked while the decision stays deferred.
74
- *
75
- * So no fifth kind has been needed, and adding a named generic variant now would be designing from
76
- * zero validating examples — the exact failure the paragraph above exists to prevent. Considered
77
- * and rejected on 2026-09-05 for that reason. Re-check this section, not the prose above it,
78
- * before concluding the trigger has fired.
79
- *
80
- * Note for whoever revisits: wiring `AdminMenusPort` into a host is the experiment that ANSWERS the
81
- * type question, and it is not blocked by it. A host that wires the port and finds
82
- * `entryRef`/`termRef` fit vindicates the deferral; one that needs a product/collection kind fires
83
- * the trigger with a real second example to design from.
84
- *
85
42
  * ## `deleteMenu` is a two-rung ladder driven by call count, not by `force` alone
86
43
  *
87
44
  * A single method models a two-step deletion flow: the FIRST call against a non-trashed menu
@@ -25,20 +25,6 @@
25
25
  * `kind` values (with `AdminMenuCustomTarget` as the `default` arm) is the straightforward way to
26
26
  * stay correct.
27
27
  *
28
- * **Migration hazard, measured 2026-09-05.** This is not merely a style preference — it means an
29
- * exhaustive `switch` with NO `default` arm cannot compile against `AdminMenuTarget` at all, and
30
- * that is exactly the shape a host arrives with. Both existing admin apps' `targetForKind`
31
- * (`apps/admin/src/features/menus/MenuEditor.tsx`) switch over their own local CLOSED four-member
32
- * union with no `default`, and rely on exhaustiveness for the return type. Compiling that function
33
- * against this port's union emits `TS2366` (lacks ending return statement) plus a `TS2339` per
34
- * field access. Confirmed by compiling the real function against this union directly.
35
- *
36
- * The hazard is pre-existing and belongs to `AdminMenuCustomTarget`, not to any later change: the
37
- * identical probe run against the union with and without an extra member emits a character-for-
38
- * character identical error set. Recorded here because it will surface the first time anyone wires
39
- * a host onto this port, and the natural instinct will be to blame whatever change is in flight at
40
- * that moment. The fix is a `default` arm in the host, not a change to this file.
41
- *
42
28
  * **This is a deliberately deferred decision, not a settled one — record it as such.** `entryRef`/
43
29
  * `termRef` encode a host content model (an "entry" and a "taxonomy term" are the reference
44
30
  * implementation's own vocabulary for its content system, not a vendor-neutral abstraction this
@@ -53,35 +39,6 @@
53
39
  * instead of one, and a genuine vendor-neutral reference shape (rather than another bespoke
54
40
  * `kind`-per-host member) becomes the right call.
55
41
  *
56
- * ### Status of that trigger, re-checked 2026-09-05 — NOT fired
57
- *
58
- * A second host now exists in this workspace, and that is NOT the trigger. The trigger is a second
59
- * host needing a fifth KIND. Recording the difference here because a promotion was very nearly
60
- * approved on the weaker reading. Four findings, all verified against source rather than assumed:
61
- *
62
- * 1. **Zero importers.** Nothing anywhere imports `AdminMenuTarget`, `NavTargetKind`, or any target
63
- * variant from this package. In this repo they are re-exported by `core/index.ts` and
64
- * `core/ports/index.ts` and consumed by nothing.
65
- * 2. **Both admin apps declare their own.** Each ships a local, *closed*
66
- * `{ kind: "entryRef" | "termRef" | "url" | "route" }` in its own `src/lib/api.ts` — an HTTP
67
- * DTO, not this port. The two are byte-identical to each other: the second is a fork of the
68
- * first, so they are one data point, not two.
69
- * 3. **The other `NavTargetKind` is a different type.** `@jini-ai/cms/navigation` exports its own
70
- * `NavTargetKind` (closed, plus a separate `ReservedNavTargetKind`). A host importing that one
71
- * is not exercising this port.
72
- * 4. **The union is already open.** `AdminMenuCustomTarget`'s `kind: string & {}` already lets any
73
- * host express any kind today. Nothing is blocked while the decision stays deferred.
74
- *
75
- * So no fifth kind has been needed, and adding a named generic variant now would be designing from
76
- * zero validating examples — the exact failure the paragraph above exists to prevent. Considered
77
- * and rejected on 2026-09-05 for that reason. Re-check this section, not the prose above it,
78
- * before concluding the trigger has fired.
79
- *
80
- * Note for whoever revisits: wiring `AdminMenusPort` into a host is the experiment that ANSWERS the
81
- * type question, and it is not blocked by it. A host that wires the port and finds
82
- * `entryRef`/`termRef` fit vindicates the deferral; one that needs a product/collection kind fires
83
- * the trigger with a real second example to design from.
84
- *
85
42
  * ## `deleteMenu` is a two-rung ladder driven by call count, not by `force` alone
86
43
  *
87
44
  * A single method models a two-step deletion flow: the FIRST call against a non-trashed menu
@@ -51,7 +51,8 @@ export interface ConfirmDialogProps {
51
51
  title: string;
52
52
  body: ReactNode;
53
53
  confirmLabel: string;
54
- /** @default "Cancel" */
54
+ /** @default the enclosing `ConfirmDialogDefaultsProvider`'s `cancelLabel`, or "Cancel" with
55
+ * none mounted. */
55
56
  cancelLabel?: string;
56
57
  /** Applies `.btn-warning`/`.btn-danger` to the confirm action. Defaults to `"default"` (no class,
57
58
  * the plain primary button). Wins over `destructive` below when both are passed. */
@@ -1,4 +1,4 @@
1
- import { type MouseEvent, type RefObject, type SyntheticEvent } from 'react';
1
+ import { type MouseEvent, type ReactNode, type RefObject, type SyntheticEvent } from 'react';
2
2
  /**
3
3
  * @file `ConfirmDialog`'s open/close and focus-management state, split out of the component so it
4
4
  * can be swapped for a fake via the `useDialog` prop on `ConfirmDialogProps` — see that prop's doc
@@ -33,6 +33,42 @@ export interface ConfirmDialogController {
33
33
  /** The signature `ConfirmDialogProps.useDialog` accepts. Any hook matching this can drive the
34
34
  * component; it does not have to be {@link useConfirmDialog}, or even use React state at all. */
35
35
  export type UseConfirmDialog = (open: boolean, pending: boolean | undefined, onCancel: () => void) => ConfirmDialogController;
36
+ /**
37
+ * Host-wide defaults every `ConfirmDialog` beneath a {@link ConfirmDialogDefaultsProvider} falls
38
+ * back to when the matching prop is not passed explicitly. Today this is only `cancelLabel` — see
39
+ * that provider's doc comment for why it exists.
40
+ */
41
+ export interface ConfirmDialogDefaults {
42
+ cancelLabel?: string | undefined;
43
+ }
44
+ export interface ConfirmDialogDefaultsProviderProps extends ConfirmDialogDefaults {
45
+ children: ReactNode;
46
+ }
47
+ /**
48
+ * Publishes host-wide `ConfirmDialog` defaults — today just a translated `cancelLabel` — to every
49
+ * `ConfirmDialog` mounted beneath it. Exists so a host with its own localized "Cancel" copy can
50
+ * set it once at its app root instead of passing `cancelLabel` at every call site (and remembering
51
+ * to add it to every new one it writes later).
52
+ *
53
+ * An explicit `cancelLabel` prop on a given `ConfirmDialog` still wins over this (see
54
+ * {@link useConfirmDialogCancelLabel}). A `ConfirmDialog` mounted with no enclosing provider at
55
+ * all is unaffected — it falls back to the component's own built-in `"Cancel"`, exactly as before
56
+ * this provider existed.
57
+ *
58
+ * Optional by design, unlike `Sidebar`'s `useSidebar` context: a caller with no localization need
59
+ * should never be forced to wrap anything just to render one dialog.
60
+ */
61
+ export declare function ConfirmDialogDefaultsProvider({ children, cancelLabel }: ConfirmDialogDefaultsProviderProps): import("react").JSX.Element;
62
+ /**
63
+ * Resolves `ConfirmDialog`'s Cancel button text: the explicit `cancelLabel` prop first, then the
64
+ * enclosing {@link ConfirmDialogDefaultsProvider}'s default, then the built-in `"Cancel"`. No
65
+ * provider is a normal, fully-supported state (unlike `useSidebar`, this never throws).
66
+ *
67
+ * @param explicit - The dialog's own `cancelLabel` prop, or `undefined` when the caller passed none.
68
+ * @returns The label to render.
69
+ * @complexity O(1).
70
+ */
71
+ export declare function useConfirmDialogCancelLabel(explicit: string | undefined): string;
36
72
  /**
37
73
  * Owns the `<dialog>` element's open/close lifecycle and focus management for `ConfirmDialog`.
38
74
  *
@@ -1,4 +1,45 @@
1
- import { useEffect, useId, useRef } from 'react';
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { createContext, useContext, useEffect, useId, useMemo, useRef, } from 'react';
3
+ /** Empty object, not `undefined` — {@link useConfirmDialogCancelLabel} can always read `cancelLabel`
4
+ * off it without an extra null check, whether or not a provider is mounted. */
5
+ const ConfirmDialogDefaultsContext = createContext({});
6
+ /** The built-in last resort for {@link useConfirmDialogCancelLabel}, used when neither the prop nor
7
+ * an enclosing provider supplies a label. */
8
+ const DEFAULT_CANCEL_LABEL = 'Cancel';
9
+ /**
10
+ * Publishes host-wide `ConfirmDialog` defaults — today just a translated `cancelLabel` — to every
11
+ * `ConfirmDialog` mounted beneath it. Exists so a host with its own localized "Cancel" copy can
12
+ * set it once at its app root instead of passing `cancelLabel` at every call site (and remembering
13
+ * to add it to every new one it writes later).
14
+ *
15
+ * An explicit `cancelLabel` prop on a given `ConfirmDialog` still wins over this (see
16
+ * {@link useConfirmDialogCancelLabel}). A `ConfirmDialog` mounted with no enclosing provider at
17
+ * all is unaffected — it falls back to the component's own built-in `"Cancel"`, exactly as before
18
+ * this provider existed.
19
+ *
20
+ * Optional by design, unlike `Sidebar`'s `useSidebar` context: a caller with no localization need
21
+ * should never be forced to wrap anything just to render one dialog.
22
+ */
23
+ export function ConfirmDialogDefaultsProvider({ children, cancelLabel }) {
24
+ // Memoized so a host re-render that leaves `cancelLabel` unchanged does not publish a new context
25
+ // value — a fresh object would re-render every `ConfirmDialog` beneath it, even under a memoized
26
+ // parent that otherwise bailed out.
27
+ const defaults = useMemo(() => ({ cancelLabel }), [cancelLabel]);
28
+ return _jsx(ConfirmDialogDefaultsContext.Provider, { value: defaults, children: children });
29
+ }
30
+ /**
31
+ * Resolves `ConfirmDialog`'s Cancel button text: the explicit `cancelLabel` prop first, then the
32
+ * enclosing {@link ConfirmDialogDefaultsProvider}'s default, then the built-in `"Cancel"`. No
33
+ * provider is a normal, fully-supported state (unlike `useSidebar`, this never throws).
34
+ *
35
+ * @param explicit - The dialog's own `cancelLabel` prop, or `undefined` when the caller passed none.
36
+ * @returns The label to render.
37
+ * @complexity O(1).
38
+ */
39
+ export function useConfirmDialogCancelLabel(explicit) {
40
+ const { cancelLabel } = useContext(ConfirmDialogDefaultsContext);
41
+ return explicit ?? cancelLabel ?? DEFAULT_CANCEL_LABEL;
42
+ }
2
43
  /**
3
44
  * Owns the `<dialog>` element's open/close lifecycle and focus management for `ConfirmDialog`.
4
45
  *
@@ -2,8 +2,7 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
2
2
  import {} from 'react';
3
3
  import { agentHandle } from '@jini-ai/agentic';
4
4
  import { resolveTone, toneClassName } from '../../types.js';
5
- import { useConfirmDialog } from './ConfirmDialog.hooks.js';
6
- const DEFAULT_CANCEL_LABEL = 'Cancel';
5
+ import { useConfirmDialog, useConfirmDialogCancelLabel } from './ConfirmDialog.hooks.js';
7
6
  /** Sub-handle segments appended to the caller's base — literals this component chooses itself,
8
7
  * never host data (see this file's "Agent handles" doc comment for why that means neither needs
9
8
  * sanitizing, unlike `RowMenu`'s per-item keys). */
@@ -80,7 +79,7 @@ function confirmDialogAgentProps(base, action, options) {
80
79
  export function ConfirmDialog({ useDialog = useConfirmDialog, agentHandle: baseHandle, ...props }) {
81
80
  const { titleId, dialogRef, cancelRef, handleNativeCancel, handleBackdropClick } = useDialog(props.open, props.pending, props.onCancel);
82
81
  const tone = resolveTone(props);
83
- const cancelLabel = props.cancelLabel ?? DEFAULT_CANCEL_LABEL;
82
+ const cancelLabel = useConfirmDialogCancelLabel(props.cancelLabel);
84
83
  return (_jsxs("dialog", { ref: dialogRef, className: "confirm-dialog", "aria-labelledby": titleId, onCancel: handleNativeCancel, onClick: handleBackdropClick, children: [_jsx("h2", { id: titleId, children: props.title }), _jsx("div", { className: "confirm-dialog-body", children: props.body }), _jsxs("div", { className: "confirm-dialog-actions", children: [_jsx("button", { ref: cancelRef, type: "button", className: "btn-secondary", disabled: props.pending, onClick: props.onCancel, ...confirmDialogAgentProps(baseHandle, CANCEL_HANDLE_ACTION, {
85
84
  role: 'button',
86
85
  label: confirmDialogCancelLabel(cancelLabel, props.title),
@@ -1,5 +1,5 @@
1
1
  import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
- import { Fragment, createContext, createElement, useContext, useEffect, useMemo, useRef, useState, } from 'react';
2
+ import { Fragment, createContext, useContext, useEffect, useMemo, useRef, useState, } from 'react';
3
3
  import { createPortal } from 'react-dom';
4
4
  import { DEFAULT_ADMIN_BASE, adminHref } from '../../core/routing/rules.js';
5
5
  import { useNavSections } from '../hooks/use-nav-sections.js';
@@ -18,96 +18,8 @@ export function useSidebar() {
18
18
  }
19
19
  return value;
20
20
  }
21
- /**
22
- * Shape elements `AdminNavEntry.icon` markup may use. A host draws its own glyphs as raw inner
23
- * SVG (see that field's doc comment in `core/manifest/types.ts`), so this can't be a fixed set of
24
- * named icons — but it also means the string reaching {@link Icon} was written by whoever owns the
25
- * nav entry, which soon enough will be a descriptor rather than code. `g` is included so multi-path
26
- * icons can group and transform their pieces together.
27
- */
28
- const ICON_ALLOWED_TAGS = new Set(['path', 'circle', 'rect', 'line', 'polygon', 'polyline', 'ellipse', 'g']);
29
- /**
30
- * Presentation attributes let through on an icon shape, mapped from their SVG/XML spelling to the
31
- * camelCase prop name React expects. Anything not listed here — `style`, `href`/`xlink:href`, every
32
- * `on*` handler — is dropped by {@link sanitizeIconNode} rather than passed through, so there is no
33
- * allowlist gap to keep in sync with a separate denylist.
34
- */
35
- const ICON_ALLOWED_ATTRS = {
36
- d: 'd',
37
- cx: 'cx',
38
- cy: 'cy',
39
- r: 'r',
40
- rx: 'rx',
41
- ry: 'ry',
42
- x: 'x',
43
- y: 'y',
44
- width: 'width',
45
- height: 'height',
46
- x1: 'x1',
47
- y1: 'y1',
48
- x2: 'x2',
49
- y2: 'y2',
50
- points: 'points',
51
- transform: 'transform',
52
- fill: 'fill',
53
- 'fill-rule': 'fillRule',
54
- opacity: 'opacity',
55
- 'stroke-width': 'strokeWidth',
56
- 'stroke-linecap': 'strokeLinecap',
57
- 'stroke-linejoin': 'strokeLinejoin',
58
- 'clip-rule': 'clipRule',
59
- };
60
- /**
61
- * Rebuilds one parsed element as a React element, keeping only {@link ICON_ALLOWED_TAGS} /
62
- * {@link ICON_ALLOWED_ATTRS}. This is what stands in for `dangerouslySetInnerHTML`: the browser's
63
- * own parser does the tokenizing (far less error-prone than a hand-rolled regex over SVG/XML), and
64
- * this function decides what survives the trip into React's tree — a `<script>`, a `<foreignObject>`
65
- * carrying arbitrary HTML, an `<image>`/`<use>` reference, or an `onload=` attribute all fail to
66
- * match anything on either allowlist and are simply not there afterward, whatever they contained.
67
- */
68
- function sanitizeIconNode(node, key) {
69
- const tag = node.tagName.toLowerCase();
70
- if (!ICON_ALLOWED_TAGS.has(tag))
71
- return null;
72
- // `key` goes straight into the props object — `createElement` pulls it out as the element's
73
- // reserved key rather than forwarding it to the DOM, the same as writing `key={key}` in JSX.
74
- const props = { key };
75
- for (const attr of Array.from(node.attributes)) {
76
- const propName = ICON_ALLOWED_ATTRS[attr.name.toLowerCase()];
77
- if (propName)
78
- props[propName] = attr.value;
79
- }
80
- const children = Array.from(node.children)
81
- .map((child, i) => sanitizeIconNode(child, i))
82
- .filter((child) => child !== null);
83
- return createElement(tag, props, children.length ? children : undefined);
84
- }
85
- // Reused across parses rather than constructed per render — `DOMParser` instances are stateless
86
- // and this runs once per icon render, but there is no reason to pay allocation cost for it twice.
87
- let iconMarkupParser;
88
- /**
89
- * Parses one `AdminNavEntry.icon` string into a sanitized element list. Wrapping in a throwaway
90
- * `<svg>` document (never attached to the page — this is markup parsing, not rendering) lets the
91
- * browser's own XML parser validate structure for free: malformed markup surfaces as a
92
- * `parsererror` node, which is treated the same as empty input — the row loses its icon, not its
93
- * label or link.
94
- */
95
- function parseIconMarkup(markup) {
96
- if (!markup)
97
- return [];
98
- iconMarkupParser ??= new DOMParser();
99
- const doc = iconMarkupParser.parseFromString(`<svg xmlns="http://www.w3.org/2000/svg">${markup}</svg>`, 'image/svg+xml');
100
- if (doc.getElementsByTagName('parsererror').length > 0)
101
- return [];
102
- return Array.from(doc.documentElement.children)
103
- .map((child, i) => sanitizeIconNode(child, i))
104
- .filter((child) => child !== null);
105
- }
106
21
  function Icon(props) {
107
- // Re-parsing on every keystroke of an unrelated state update would be wasted work for a string
108
- // that, in practice, never changes after the nav manifest is built.
109
- const children = useMemo(() => parseIconMarkup(props.markup), [props.markup]);
110
- return (_jsx("svg", { viewBox: "0 0 18 18", fill: "none", stroke: "currentColor", strokeWidth: 1.5, children: children }));
22
+ return (_jsx("svg", { viewBox: "0 0 18 18", fill: "none", stroke: "currentColor", strokeWidth: 1.5, dangerouslySetInnerHTML: { __html: props.markup } }));
111
23
  }
112
24
  /**
113
25
  * Rail-mode tooltip, portaled to `document.body`.
@@ -38,8 +38,10 @@ export type { ConfirmButtonProps } from './components/ConfirmButton/ConfirmButto
38
38
  export { ConfirmDialog } from './components/ConfirmDialog/ConfirmDialog.js';
39
39
  export type { ConfirmDialogProps } from './components/ConfirmDialog/ConfirmDialog.js';
40
40
  export type { ConfirmDialogController, UseConfirmDialog } from './components/ConfirmDialog/ConfirmDialog.hooks.js';
41
+ export { ConfirmDialogDefaultsProvider } from './components/ConfirmDialog/ConfirmDialog.hooks.js';
42
+ export type { ConfirmDialogDefaults, ConfirmDialogDefaultsProviderProps, } from './components/ConfirmDialog/ConfirmDialog.hooks.js';
41
43
  export { DataTable } from './components/DataTable.js';
42
- export type { DataTableColumn, DataTableColumnSort, DataTableProps, DataTableSortDirection, DataTableSortState, } from './components/DataTable.js';
44
+ export type { DataTableColumn, DataTableProps } from './components/DataTable.js';
43
45
  export { InteractiveHtmlEditor } from './components/InteractiveHtmlEditor/InteractiveHtmlEditor.js';
44
46
  export type { InteractiveHtmlEditorProps } from './components/InteractiveHtmlEditor/InteractiveHtmlEditor.js';
45
47
  export { RowMenu } from './components/RowMenu/RowMenu.js';
@@ -36,9 +36,11 @@
36
36
  export { resolveTone, toneClassName } from './types.js';
37
37
  export { ConfirmButton } from './components/ConfirmButton/ConfirmButton.js';
38
38
  export { ConfirmDialog } from './components/ConfirmDialog/ConfirmDialog.js';
39
- // The list table. Sorting is opt-in per column (`DataTableColumn.sort`); pagination and row
40
- // selection are still deliberately absent — see its file header for the corpus evidence behind
41
- // every one of these decisions.
39
+ // Host-wide `ConfirmDialog` defaults (today just a translated `cancelLabel`), set once at an app
40
+ // root rather than passed at every call site — see `ConfirmDialogDefaultsProvider`'s doc comment.
41
+ export { ConfirmDialogDefaultsProvider } from './components/ConfirmDialog/ConfirmDialog.hooks.js';
42
+ // The list table. Deliberately has no sorting, pagination or row selection — see its file header
43
+ // for the corpus evidence behind each omission.
42
44
  export { DataTable } from './components/DataTable.js';
43
45
  // Visual click-into-text editing surface for a bespoke HTML document, built on GrapesJS. See its
44
46
  // own file header for the styling-contract exception it carries (vendor CSS import) and the
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jini-ai/admin",
3
- "version": "0.3.8",
3
+ "version": "0.3.9",
4
4
  "description": "Composable admin surface for Jini-hosted products: framework-free contracts, panel registry, and route model in `/core`; React shell and panels in `/react`. Import only the layers you need.",
5
5
  "license": "Apache-2.0",
6
6
  "repository": {
@@ -51,7 +51,8 @@
51
51
  "!dist/**/*.test.d.ts",
52
52
  "!dist/**/*.test.js.map",
53
53
  "!dist/**/*.test.d.ts.map",
54
- "!dist/**/__tests__/**"
54
+ "!dist/**/__tests__/**",
55
+ "!dist/**/*.map"
55
56
  ],
56
57
  "publishConfig": {
57
58
  "access": "public",
@@ -80,8 +81,8 @@
80
81
  "react-dom": "^19.2.0"
81
82
  },
82
83
  "dependencies": {
83
- "@jini-ai/agentic": "0.3.6",
84
- "@jini-ai/ui": "0.3.8"
84
+ "@jini-ai/agentic": "0.3.0",
85
+ "@jini-ai/ui": "0.3.9"
85
86
  },
86
87
  "scripts": {
87
88
  "build": "tsc -p tsconfig.json",
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,gBAAgB,EAChB,8BAA8B,EAC9B,QAAQ,EACR,aAAa,EACb,gBAAgB,GACjB,MAAM,iBAAiB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/browser/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EACL,gBAAgB,EAChB,8BAA8B,EAC9B,QAAQ,EACR,aAAa,EACb,gBAAgB,GACjB,MAAM,iBAAiB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"navigation.d.ts","sourceRoot":"","sources":["../../src/browser/navigation.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,iGAAiG;AACjG,eAAO,MAAM,gBAAgB,wBAAwB,CAAC;AAEtD,yDAAyD;AACzD,wBAAgB,aAAa,CAAC,IAAI,GAAE,MAA2B,GAAG,MAAM,CAEvE;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CACtB,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE;IAAE,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,GACnE,IAAI,CA8BN;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,8BAA8B,CAAC,IAAI,GAAE,MAA2B,GAAG,MAAM,IAAI,CAiC5F;AAED,sFAAsF;AACtF,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,IAAI,GAAG,MAAM,IAAI,CAOjE"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"navigation.js","sourceRoot":"","sources":["../../src/browser/navigation.ts"],"names":[],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/data-table/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,MAAM,sBAAsB,GAAG,KAAK,GAAG,MAAM,CAAC;AAEpD;oFACoF;AACpF,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,sBAAsB,CAAC;CACnC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/data-table/types.ts"],"names":[],"mappings":"AAAA;;;;;GAKG"}
@@ -1,138 +0,0 @@
1
- /**
2
- * @file The runtime half of `AdminEntityPort`: registration, descriptor validation, and the one
3
- * erasure a screen generic over all entities needs.
4
- *
5
- * `core/ports/entities.ts` is types only, like every other port. Everything here is the code those
6
- * types cannot be: checks that a descriptor is internally consistent, and the single cast that
7
- * turns a descriptor-generic port into the shape a screen can hold.
8
- *
9
- * ## Why any of this is runtime rather than type-level
10
- *
11
- * Two of the descriptor's own promises are not expressible in the type system:
12
- *
13
- * - `titleField` names a `text` field on this same descriptor. Encoding that needs a conditional
14
- * type heavy enough to make every descriptor's error message unreadable — and a typo here is not
15
- * cosmetic: it makes every relation picker pointing at this entity render `undefined` for every
16
- * row, which looks like missing data rather than a typo.
17
- * - `relation.target` names another *registered* entity. A descriptor cannot know what it will be
18
- * registered beside, so this can only be checked once the registry is assembled.
19
- *
20
- * Both are therefore checked at composition time, where they fail once, at startup, naming the
21
- * problem — rather than at render time, silently, as blank cells.
22
- */
23
- import type { AdminEntityDescriptor, AdminEntityField, AdminEntityPort, AdminEntityRegistry, AdminErasedEntityPort } from '../ports/entities.js';
24
- /**
25
- * A row that does not match the descriptor its port advertises.
26
- *
27
- * This is the failure `eraseEntityPort`'s cast makes possible: the cast is sound in the direction
28
- * that matters (a typed row *is* a bag of unknowns), and unsound only if an adapter lies about its
29
- * own descriptor. Nothing in the type system catches that, so this is what does — as a report, not
30
- * an exception: a mistyped field is a fidelity problem, and throwing on a read would take a
31
- * mostly-working screen down over one bad cell.
32
- */
33
- export interface AdminEntityRowViolation {
34
- /** `descriptor.name` of the port that produced the row. */
35
- readonly entity: string;
36
- readonly operation: 'list' | 'get' | 'create' | 'update';
37
- /** The offending row's `id`, or `'<no id>'` when that is itself what is wrong. */
38
- readonly rowId: string;
39
- /** Declared field name, `'id'`, or the undeclared key that appeared. */
40
- readonly field: string;
41
- readonly problem: 'missing-required' | 'wrong-type' | 'undeclared-field';
42
- /** One sentence naming what was expected and what arrived. Safe to log verbatim. */
43
- readonly detail: string;
44
- }
45
- export interface AdminEntityErasureOptions {
46
- /**
47
- * Where descriptor-conformance violations are reported.
48
- *
49
- * **Omit it and no row checking runs at all** — that is the zero-cost default, and it is why this
50
- * package emits no diagnostics of its own (nothing here writes to `console`; a host owns its
51
- * reporting the same way it owns its transport). A host wires this under its own development
52
- * flag and gets adapter drift surfaced the moment it happens; production pays nothing.
53
- */
54
- readonly onViolation?: (violation: AdminEntityRowViolation) => void;
55
- }
56
- /**
57
- * Whether `value` is a legal runtime value for `field`.
58
- *
59
- * Exported because an EDITOR needs exactly this judgement and must not re-derive it. A generic form
60
- * that decides for itself what an `integer` accepts will drift from what the conformance walk
61
- * below rejects, and the two disagreeing is worse than either being wrong alone: the form saves a
62
- * value the port then reports as a violation, so the write succeeds and the diagnostic blames the
63
- * adapter. `1.5` in an `integer` and `Infinity` in a `real` are both reachable from a plain
64
- * `<input type="number">` — `step` constrains the spinner, not the parsed value — so this is not a
65
- * theoretical seam. One function, both callers.
66
- *
67
- * @param field The declared field the value is destined for.
68
- * @param value The candidate value, typically a form draft entry or an adapter-returned cell.
69
- * @returns `null` when it conforms, otherwise a one-phrase reason naming what arrived instead.
70
- * Phrased to complete the sentence "declared `<kind>`; ...".
71
- * @complexity Time O(1) for every kind but `json`; see {@link describeNonJsonValue} for that one.
72
- * @overallScore 100
73
- */
74
- export declare function describeAdminEntityFieldMismatch(field: AdminEntityField, value: unknown): string | null;
75
- /**
76
- * Erases a port's descriptor generic so a screen can hold ports for different entities in one
77
- * collection.
78
- *
79
- * The `as unknown as` below is unavoidable and is the only one in this port. `create` and `update`
80
- * take the row type as a *parameter*, so `AdminEntityPort<SpecificDescriptor>` is contravariant in
81
- * it and is genuinely not assignable to any common supertype. The cast is sound in the direction
82
- * that gets exercised — a typed row is a bag of unknowns — and unsound only if the adapter's rows
83
- * do not match the descriptor it advertises, which is precisely what `options.onViolation` is here
84
- * to surface.
85
- *
86
- * @param port A port whose rows are typed by its own descriptor.
87
- * @param options Wire `onViolation` to have every row checked against the descriptor on the way
88
- * out; omit it for zero added cost.
89
- * @returns The same port, typed as {@link AdminErasedEntityPort}; a fresh wrapper object when
90
- * `onViolation` is set, and the original object when it is not.
91
- * @complexity Time O(1) to erase; O(rows × fields) per call when checking is on.
92
- * @overallScore 100
93
- */
94
- export declare function eraseEntityPort<D extends AdminEntityDescriptor>(port: AdminEntityPort<D>, options?: AdminEntityErasureOptions): AdminErasedEntityPort;
95
- /**
96
- * Assembles entity ports into a registry, validating every descriptor first.
97
- *
98
- * Same ergonomics as `createAdminClient`: one object literal, `TPorts` inferred, host-owned and
99
- * Jini-shipped entries indistinguishable. Registering an entity is one line.
100
- *
101
- * **No key is reserved.** `createAdminClient` reserves `'transport'` because it merges the
102
- * transport into the same object it returns; this returns nothing but the ports, so there is
103
- * nothing an entity named `transport` could shadow. The returned object has a `null` prototype, so
104
- * a lookup by an attacker- or URL-supplied name (`'constructor'`, `'__proto__'`) resolves to
105
- * `undefined` rather than walking to `Object.prototype` and yielding a truthy non-port.
106
- *
107
- * Deliberately takes no erasure options: a registry holds ports with their row types intact, and
108
- * checking only becomes possible once those types are erased. `onViolation` therefore belongs to
109
- * {@link getErasedEntityPort}/{@link listErasedEntityPorts}, at the point the guarantee is dropped.
110
- *
111
- * @param ports Entity name -> port. Each key must equal that port's `descriptor.name`.
112
- * @returns A frozen, null-prototype registry preserving each port's own type.
113
- * @throws {Error} listing *every* problem found, not just the first — a descriptor with three
114
- * typos should take one round trip to fix, not three.
115
- * @complexity Time O(entities × fields); space O(entities).
116
- * @overallScore 100
117
- */
118
- export declare function createAdminEntityRegistry<TPorts extends Record<string, AdminEntityPort<AdminEntityDescriptor>>>(ports: TPorts): AdminEntityRegistry<TPorts>;
119
- /**
120
- * Every registered port, erased, in registration order — what a screen that renders any entity
121
- * iterates.
122
- *
123
- * @complexity Time O(entities); space O(entities).
124
- * @overallScore 100
125
- */
126
- export declare function listErasedEntityPorts(registry: Readonly<Record<string, AdminEntityPort<AdminEntityDescriptor>>>, options?: AdminEntityErasureOptions): readonly AdminErasedEntityPort[];
127
- /**
128
- * The erased port registered under `name`, or `null`.
129
- *
130
- * `name` is routinely a URL segment, so this never trusts a bare property read: the registry's null
131
- * prototype already stops `'constructor'` resolving to something truthy, and `Object.hasOwn` holds
132
- * that guarantee even for a caller that hands in a plain object literal instead.
133
- *
134
- * @complexity Time O(1) for the lookup, O(1) for the erasure.
135
- * @overallScore 100
136
- */
137
- export declare function getErasedEntityPort(registry: Readonly<Record<string, AdminEntityPort<AdminEntityDescriptor>>>, name: string, options?: AdminEntityErasureOptions): AdminErasedEntityPort | null;
138
- //# sourceMappingURL=rules.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"rules.d.ts","sourceRoot":"","sources":["../../../src/core/entities/rules.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,OAAO,KAAK,EACV,qBAAqB,EACrB,gBAAgB,EAGhB,eAAe,EACf,mBAAmB,EAEnB,qBAAqB,EACtB,MAAM,sBAAsB,CAAC;AAW9B;;;;;;;;GAQG;AACH,MAAM,WAAW,uBAAuB;IACtC,2DAA2D;IAC3D,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;IACzD,kFAAkF;IAClF,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,wEAAwE;IACxE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,kBAAkB,GAAG,YAAY,GAAG,kBAAkB,CAAC;IACzE,oFAAoF;IACpF,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,yBAAyB;IACxC;;;;;;;OAOG;IACH,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC,SAAS,EAAE,uBAAuB,KAAK,IAAI,CAAC;CACrE;AA8CD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,gBAAgB,EACvB,KAAK,EAAE,OAAO,GACb,MAAM,GAAG,IAAI,CAuBf;AAyED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,eAAe,CAAC,CAAC,SAAS,qBAAqB,EAC7D,IAAI,EAAE,eAAe,CAAC,CAAC,CAAC,EACxB,OAAO,GAAE,yBAA8B,GACtC,qBAAqB,CAgCvB;AA4DD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,yBAAyB,CACvC,MAAM,SAAS,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,qBAAqB,CAAC,CAAC,EACrE,KAAK,EAAE,MAAM,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAc5C;AAED;;;;;;GAMG;AACH,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,qBAAqB,CAAC,CAAC,CAAC,EAC1E,OAAO,GAAE,yBAA8B,GACtC,SAAS,qBAAqB,EAAE,CAElC;AAED;;;;;;;;;GASG;AACH,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,qBAAqB,CAAC,CAAC,CAAC,EAC1E,IAAI,EAAE,MAAM,EACZ,OAAO,GAAE,yBAA8B,GACtC,qBAAqB,GAAG,IAAI,CAI9B"}