@cosmicdrift/kumiko-types 0.327.0 → 0.328.1

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 (174) hide show
  1. package/dist/action-icon.d.ts +3 -0
  2. package/dist/action-icon.js +51 -0
  3. package/{src/agent-exposure.ts → dist/agent-exposure.d.ts} +8 -15
  4. package/dist/agent-exposure.js +16 -0
  5. package/dist/concurrency-mode.d.ts +1 -0
  6. package/dist/config-scope.d.ts +1 -0
  7. package/dist/config-scope.js +1 -0
  8. package/dist/config.d.ts +234 -0
  9. package/dist/config.js +1 -0
  10. package/dist/cursor-types.d.ts +16 -0
  11. package/dist/cursor-types.js +1 -0
  12. package/dist/db-connection.d.ts +14 -0
  13. package/dist/db-connection.js +1 -0
  14. package/dist/define-handler.d.ts +58 -0
  15. package/dist/define-handler.js +1 -0
  16. package/dist/derivatives-types.d.ts +53 -0
  17. package/dist/derivatives-types.js +3 -0
  18. package/dist/entity-cache.d.ts +16 -0
  19. package/dist/entity-cache.js +1 -0
  20. package/dist/entity-handlers.d.ts +54 -0
  21. package/dist/entity-handlers.js +1 -0
  22. package/dist/entity-table-meta-types.d.ts +44 -0
  23. package/dist/entity-table-meta-types.js +6 -0
  24. package/dist/envelope-cipher-types.d.ts +5 -0
  25. package/dist/envelope-cipher-types.js +1 -0
  26. package/dist/event-store-executor-types.d.ts +86 -0
  27. package/dist/event-store-executor-types.js +1 -0
  28. package/dist/event-store-types.d.ts +37 -0
  29. package/dist/event-store-types.js +7 -0
  30. package/dist/event-type-map.d.ts +8 -0
  31. package/{src/event-type-map.ts → dist/event-type-map.js} +1 -16
  32. package/dist/executor-brand.d.ts +8 -0
  33. package/dist/executor-brand.js +1 -0
  34. package/dist/extension-options-map.d.ts +9 -0
  35. package/dist/extension-options-map.js +4 -0
  36. package/dist/feature.d.ts +518 -0
  37. package/dist/feature.js +1 -0
  38. package/dist/field-icon.d.ts +1 -0
  39. package/dist/field-icon.js +1 -0
  40. package/dist/fields.d.ts +729 -0
  41. package/dist/fields.js +50 -0
  42. package/dist/file-handle-types.d.ts +12 -0
  43. package/dist/file-handle-types.js +1 -0
  44. package/dist/file-provider-resolver-types.d.ts +3 -0
  45. package/dist/file-provider-resolver-types.js +1 -0
  46. package/dist/file-storage-provider-types.d.ts +17 -0
  47. package/dist/file-storage-provider-types.js +1 -0
  48. package/dist/geo-tz.d.ts +17 -0
  49. package/{src/geo-tz.ts → dist/geo-tz.js} +1 -20
  50. package/dist/handlers.d.ts +493 -0
  51. package/dist/handlers.js +49 -0
  52. package/dist/hook-phase.d.ts +1 -0
  53. package/dist/hook-phase.js +1 -0
  54. package/dist/hooks.d.ts +75 -0
  55. package/dist/hooks.js +1 -0
  56. package/dist/http-route.d.ts +52 -0
  57. package/dist/http-route.js +13 -0
  58. package/dist/identifiers.d.ts +8 -0
  59. package/{src/identifiers.ts → dist/identifiers.js} +7 -24
  60. package/dist/index.d.ts +1 -0
  61. package/dist/index.js +1 -0
  62. package/dist/kms-adapter-types.d.ts +68 -0
  63. package/dist/kms-adapter-types.js +49 -0
  64. package/dist/logger.d.ts +7 -0
  65. package/dist/logger.js +1 -0
  66. package/dist/multi-stream-apply-context-types.d.ts +18 -0
  67. package/dist/multi-stream-apply-context-types.js +1 -0
  68. package/dist/nav-icon.d.ts +3 -0
  69. package/dist/nav-icon.js +100 -0
  70. package/dist/nav.d.ts +39 -0
  71. package/dist/nav.js +1 -0
  72. package/dist/observability/index.d.ts +3 -0
  73. package/dist/observability/index.js +2 -0
  74. package/dist/observability/metric.d.ts +34 -0
  75. package/dist/observability/metric.js +3 -0
  76. package/dist/observability/provider.d.ts +24 -0
  77. package/dist/observability/provider.js +4 -0
  78. package/dist/observability/span.d.ts +32 -0
  79. package/dist/observability/span.js +4 -0
  80. package/dist/ownership.d.ts +33 -0
  81. package/dist/ownership.js +5 -0
  82. package/dist/projection.d.ts +38 -0
  83. package/dist/projection.js +1 -0
  84. package/dist/rate-limit-types.d.ts +19 -0
  85. package/dist/rate-limit-types.js +1 -0
  86. package/dist/relations.d.ts +25 -0
  87. package/dist/relations.js +1 -0
  88. package/dist/schema-table-types.d.ts +15 -0
  89. package/{src/schema-table-types.ts → dist/schema-table-types.js} +0 -20
  90. package/dist/screen.d.ts +1265 -0
  91. package/dist/screen.js +3 -0
  92. package/dist/search-adapter.d.ts +32 -0
  93. package/dist/search-adapter.js +1 -0
  94. package/dist/secrets-types.d.ts +52 -0
  95. package/dist/secrets-types.js +30 -0
  96. package/dist/snapshot-types.d.ts +13 -0
  97. package/dist/snapshot-types.js +1 -0
  98. package/dist/step.d.ts +304 -0
  99. package/dist/step.js +11 -0
  100. package/dist/target-ref.d.ts +5 -0
  101. package/{src/target-ref.ts → dist/target-ref.js} +1 -6
  102. package/dist/tenancy-brand.d.ts +6 -0
  103. package/dist/tenancy-brand.js +1 -0
  104. package/dist/tenant-db-types.d.ts +67 -0
  105. package/dist/tenant-db-types.js +5 -0
  106. package/dist/tree-node.d.ts +26 -0
  107. package/dist/tree-node.js +22 -0
  108. package/dist/tz-context.d.ts +48 -0
  109. package/dist/tz-context.js +6 -0
  110. package/dist/websocket-route.d.ts +46 -0
  111. package/dist/websocket-route.js +10 -0
  112. package/dist/where-clause-types.d.ts +20 -0
  113. package/dist/where-clause-types.js +1 -0
  114. package/dist/workspace.d.ts +10 -0
  115. package/dist/workspace.js +1 -0
  116. package/dist/write-error-info-types.d.ts +12 -0
  117. package/dist/write-error-info-types.js +1 -0
  118. package/package.json +372 -124
  119. package/src/changes.json +18 -0
  120. package/src/__tests__/handlers.test.ts +0 -40
  121. package/src/__tests__/plural-forms.test.ts +0 -18
  122. package/src/action-icon.ts +0 -57
  123. package/src/concurrency-mode.ts +0 -5
  124. package/src/config-scope.ts +0 -5
  125. package/src/config.ts +0 -563
  126. package/src/cursor-types.ts +0 -18
  127. package/src/db-connection.ts +0 -25
  128. package/src/define-handler.ts +0 -138
  129. package/src/derivatives-types.ts +0 -106
  130. package/src/entity-cache.ts +0 -35
  131. package/src/entity-handlers.ts +0 -68
  132. package/src/entity-table-meta-types.ts +0 -101
  133. package/src/envelope-cipher-types.ts +0 -6
  134. package/src/event-store-executor-types.ts +0 -163
  135. package/src/event-store-types.ts +0 -85
  136. package/src/executor-brand.ts +0 -19
  137. package/src/extension-options-map.ts +0 -21
  138. package/src/feature.ts +0 -1141
  139. package/src/field-icon.ts +0 -23
  140. package/src/fields.ts +0 -1114
  141. package/src/file-handle-types.ts +0 -20
  142. package/src/file-provider-resolver-types.ts +0 -7
  143. package/src/file-storage-provider-types.ts +0 -54
  144. package/src/handlers.ts +0 -1246
  145. package/src/hook-phase.ts +0 -2
  146. package/src/hooks.ts +0 -170
  147. package/src/http-route.ts +0 -78
  148. package/src/kms-adapter-types.ts +0 -128
  149. package/src/logger.ts +0 -7
  150. package/src/multi-stream-apply-context-types.ts +0 -52
  151. package/src/nav-icon.ts +0 -105
  152. package/src/nav.ts +0 -139
  153. package/src/observability/index.ts +0 -28
  154. package/src/observability/metric.ts +0 -56
  155. package/src/observability/provider.ts +0 -32
  156. package/src/observability/span.ts +0 -58
  157. package/src/ownership.ts +0 -83
  158. package/src/projection.ts +0 -170
  159. package/src/rate-limit-types.ts +0 -32
  160. package/src/relations.ts +0 -52
  161. package/src/screen.ts +0 -1593
  162. package/src/search-adapter.ts +0 -45
  163. package/src/secrets-types.ts +0 -182
  164. package/src/snapshot-types.ts +0 -36
  165. package/src/step.ts +0 -390
  166. package/src/tenancy-brand.ts +0 -9
  167. package/src/tenant-db-types.ts +0 -116
  168. package/src/tree-node.ts +0 -134
  169. package/src/tz-context.ts +0 -63
  170. package/src/websocket-route.ts +0 -68
  171. package/src/where-clause-types.ts +0 -31
  172. package/src/workspace.ts +0 -42
  173. package/src/write-error-info-types.ts +0 -20
  174. /package/{src/index.ts → dist/concurrency-mode.js} +0 -0
@@ -1,116 +0,0 @@
1
- import type { DbRunner } from "./db-connection";
2
- import type { EntityTableMeta } from "./entity-table-meta-types";
3
- import type { ExecutorOnly, NotExecutorOnly } from "./executor-brand";
4
- import type { TenantId } from "./identifiers";
5
- import type { SchemaTable } from "./schema-table-types";
6
- import type { TenancyBrand } from "./tenancy-brand";
7
- import type { SelectOptions, WhereObject } from "./where-clause-types";
8
-
9
- // Method-form writes reject the executor-only brand exactly like the free-function
10
- // helpers (#742): a managed EntityTable is a rebuildable projection, so writing it
11
- // directly — free-function OR method-form — drifts the row past its event stream and
12
- // a rebuild wipes it. The permissive base stays (raw pgTables AND unmanaged entity
13
- // metas are not projections → writable); `& NotExecutorOnly` strips only branded
14
- // EntityTables (its `[EXECUTOR_ONLY]: true` violates the optional-never). Reads keep
15
- // the plain `SchemaTable` param.
16
- type WritableTable = (SchemaTable | EntityTableMeta) & NotExecutorOnly;
17
-
18
- // db.global(table)'s surface: reads are unrestricted; writes require the managed
19
- // EntityTable's executor-only brand to be absent (mirrors WritableTable above).
20
- type GlobalReads = {
21
- selectMany<T = Record<string, unknown>>(
22
- where?: WhereObject,
23
- options?: SelectOptions,
24
- ): Promise<readonly T[]>;
25
- fetchOne<T = Record<string, unknown>>(where: WhereObject): Promise<T | undefined>;
26
- };
27
- type GlobalWrites = {
28
- insertOne<T = Record<string, unknown>>(values: Record<string, unknown>): Promise<T | undefined>;
29
- updateMany<T = Record<string, unknown>>(
30
- set: Record<string, unknown>,
31
- where: WhereObject,
32
- ): Promise<readonly T[]>;
33
- deleteMany(where: WhereObject): Promise<void>;
34
- };
35
- // Checks `extends ExecutorOnly`, not `NotExecutorOnly` — the latter's optional-never
36
- // property is a TS "weak type" that would silently collapse every TTable to GlobalReads.
37
- export type GlobalTableDb<TTable> = GlobalReads &
38
- (TTable extends ExecutorOnly ? unknown : GlobalWrites);
39
-
40
- /**
41
- * TenantDb scope modes:
42
- *
43
- * - "tenant" (default): SELECT/UPDATE/DELETE filtered by tenantId + reference data (tenantId=SYSTEM_TENANT_ID).
44
- * INSERT forces tenantId — handler cannot override.
45
- *
46
- * - "system" (r.systemScope()): No tenant filter on reads/updates/deletes.
47
- * INSERT uses tenantId as default but handler can override.
48
- *
49
- * Tables without a tenantId column are always unfiltered regardless of mode.
50
- */
51
- export type TenantDbMode = "tenant" | "system";
52
-
53
- export type TenantDb = {
54
- readonly tenantId: TenantId;
55
- readonly mode: TenantDbMode;
56
- /**
57
- * Unfiltered DbRunner escape hatch for handlers/hooks that declare `escapeHatch: { reason }`.
58
- * Throws `AccessDeniedError` when ungranted, or `Error` when `reason` is empty.
59
- */
60
- unsafeRaw(reason: string): DbRunner;
61
- /**
62
- * Reach a "global" table with the tenant filter lifted — reads always work; writes
63
- * reject unless the write handler declared `escapeHatch: { reason }`. "tenant"-tenancy is a compile error here.
64
- */
65
- global<TTable extends (SchemaTable | EntityTableMeta) & TenancyBrand<"global">>(
66
- table: TTable,
67
- ): GlobalTableDb<TTable>;
68
- selectMany<T = Record<string, unknown>>(
69
- table: SchemaTable | EntityTableMeta,
70
- where?: WhereObject,
71
- options?: SelectOptions,
72
- ): Promise<readonly T[]>;
73
- fetchOne<T = Record<string, unknown>>(
74
- table: SchemaTable | EntityTableMeta,
75
- where: WhereObject,
76
- ): Promise<T | undefined>;
77
- count(table: SchemaTable | EntityTableMeta, where?: WhereObject): Promise<number>;
78
- insertOne<T = Record<string, unknown>>(
79
- table: WritableTable,
80
- values: Record<string, unknown>,
81
- ): Promise<T | undefined>;
82
- updateMany<T = Record<string, unknown>>(
83
- table: WritableTable,
84
- set: Record<string, unknown>,
85
- where: WhereObject,
86
- ): Promise<readonly T[]>;
87
- deleteMany(table: WritableTable, where: WhereObject): Promise<void>;
88
- };
89
-
90
- // Symbol.for (global registry) so the brand identity matches even if kumiko-types
91
- // resolves to two independent copies (workspace symlink vs. published npm) — a plain
92
- // `Symbol()` per copy would make each resolution's `UncheckedSystemDb` structurally
93
- // incompatible with the other, per the kumiko.secret precedent in secrets-types.ts.
94
- export const SYSTEM_SCOPE_CHECK_BRAND: unique symbol = Symbol.for("kumiko.system-scope-check");
95
-
96
- export type UncheckedSystemDb = {
97
- readonly [SYSTEM_SCOPE_CHECK_BRAND]: true;
98
- assertTenantMatch(tenantId: TenantId): TenantDb;
99
- assertRowsTenant<T>(rows: readonly T[], tenantField: keyof T): readonly T[];
100
- acknowledgeCrossTenant(reason: string): TenantDb;
101
- /**
102
- * Raw unfiltered DbRunner, gated behind a mandatory non-empty `reason` for auditability.
103
- * Throws on an empty (or whitespace-only) reason.
104
- */
105
- unsafeRaw(reason: string): DbRunner;
106
- // Same self-check pair as above, but hands back the caller's
107
- // ctx.dbOutsideTransaction TenantDb instead of the in-tx one — for
108
- // durability writes that must survive a rollback of the handler's own
109
- // transaction. Throws if the dispatch has no outside-transaction source
110
- // configured (e.g. a hand-built UncheckedSystemDb that only ever passed
111
- // the in-tx db, as createSystemDbView callers do).
112
- readonly outsideTransaction: {
113
- assertTenantMatch(tenantId: TenantId): TenantDb;
114
- acknowledgeCrossTenant(reason: string): TenantDb;
115
- };
116
- };
package/src/tree-node.ts DELETED
@@ -1,134 +0,0 @@
1
- // TreeNode — single Knoten im Client-navProvider-Tree. Provider liefern
2
- // entweder statische readonly TreeNode[] oder dynamische TreeChildrenSubscribe.
3
- //
4
- // **Mental-Modell** (VS-Code-Explorer):
5
- // [icon] [label] [...hover-actions]
6
- // optional ein target zum Klicken (öffnet Editor-Maske via
7
- // Target-Resolver) und optional children als nested tree.
8
- //
9
- // **State** markiert Visual-Modus für Skeleton-Pattern:
10
- // - "filled" (default) — schwarz, Knoten hat Inhalt
11
- // - "stub" — hellgrau, existing aber leer (Designer-Stub-File)
12
- // - "empty" — Platzhalter für "+ create"-Affordance
13
- // - "loading" — Children werden gerade aufgelöst
14
- // - "error" — Provider hat Fehler emittiert
15
- // Provider die kein Skeleton-Pattern brauchen müssen state nicht setzen.
16
- //
17
- // **Subscribe-Form** für dynamic Children: Provider erhält emit(),
18
- // gibt unsubscribe() zurück. Initial-Emit synchron oder async, weitere
19
- // Emits beliebig oft (z.B. wenn Entity-Row neu erscheint via SSE).
20
- // Spielt natürlich mit existing SSE-Frame: ein Provider kann intern
21
- // auf Entity-Update-Events abonnieren und bei Änderung emit() aufrufen.
22
-
23
- import type { TargetRef } from "./target-ref";
24
-
25
- export type TreeNodeState = "filled" | "stub" | "empty" | "loading" | "error";
26
-
27
- export type TreeAction = {
28
- // Icon-Key — vom Renderer-Icon-Registry interpretiert. Konvention
29
- // matched NavDefinition.icon: unbekannte Icons surface als missing-icon
30
- // im UI, nicht als Boot-Failure.
31
- readonly icon: string;
32
- // i18n-Translation-Key oder roher String. Vom Renderer aufgelöst, Engine
33
- // behandelt opak (mirrors NavDefinition.label, WorkspaceDefinition.label).
34
- readonly label: string;
35
- // Qualified screen name ("<feature>:screen:<id>") — renders as a route
36
- // link. Exactly one of `screen`/`target` must be set; an action with
37
- // neither is a Hover-Icon that does nothing, the boot validator rejects
38
- // it.
39
- readonly screen?: string;
40
- // EditorPanel dispatch target — renders as a click-dispatch button.
41
- // Exactly one of `screen`/`target` must be set.
42
- readonly target?: TargetRef;
43
- };
44
-
45
- export type TreeNode = {
46
- // i18n-Translation-Key oder roher String. Vom Renderer beim Rendern
47
- // aufgelöst (siehe TreeAction.label).
48
- readonly label: string;
49
- // Optional. Icon links neben dem Label. Selbe Konvention wie
50
- // TreeAction.icon — Renderer-Icon-Registry-Lookup.
51
- readonly icon?: string;
52
- // Visueller State für Skeleton-Pattern. Default "filled" (kein Eintrag
53
- // ⇒ schwarz/normal). Wert-Semantik im Header-Comment dieser Datei.
54
- readonly state?: TreeNodeState;
55
- // Optional Klick-Ziel. Fehlt → reiner Container-Knoten (nur ausklappbar,
56
- // nicht klickbar). Vorhanden → Klick öffnet die Editor-Maske via
57
- // Target-Resolver in renderer-web.
58
- readonly target?: TargetRef;
59
- // Hover-Actions rechts (Add/Refresh/Delete/etc.). Werden in der
60
- // Sidebar-Row erst bei Hover sichtbar — VS-Code-Pattern. Engine
61
- // ordnet die Actions in der Reihenfolge an, in der sie hier stehen.
62
- readonly actions?: readonly TreeAction[];
63
- // Statische Children oder dynamic Subscribe-Function. Subscribe wird
64
- // erst beim Ausklappen aufgerufen (lazy); die Function-Form erlaubt
65
- // SSE-gefütterte Live-Updates wenn neue Entity-Rows reinkommen.
66
- readonly children?: readonly TreeNode[] | TreeChildrenSubscribe;
67
- // Provider-declared "+ create" action for nodes with `state: "empty"`.
68
- // The tree component automatically shows a "+" icon; click navigates to
69
- // `createAction.screen` or dispatches `createAction.target` — the
70
- // provider knows what "create empty" means for it (e.g. "new page slug"
71
- // vs. "new entity row"), convention couldn't guess that. Consistent with
72
- // `state` (also provider-explicit). See visual-tree.md V.1.1 Decision D3.
73
- readonly createAction?: TreeAction;
74
- };
75
-
76
- // Subscribe<T> — Provider implementiert: emit(initial); ...emit(updated);
77
- // und gibt unsubscribe-Function zurück. Caller (Tree-Component) ruft
78
- // unsubscribe auf wenn Knoten unmounted/eingeklappt wird.
79
- //
80
- // **V.1.4 emitError**: optional callback für async-error-Pfade (fetch-
81
- // fail, SSE-disconnect). Provider die explizit Errors signalisieren
82
- // wollen rufen `emitError(e)` statt empty-emit; VisualTree zeigt
83
- // Error-Banner mit Retry-Button. Sync-Throws im Provider-Body werden
84
- // vom useEffect-try/catch abgefangen — emitError ist nur für async.
85
- export type Subscribe<T> = (
86
- emit: (value: T) => void,
87
- emitError?: (error: Error) => void,
88
- ) => () => void;
89
-
90
- // TreeChildrenSubscribe — Lazy-Variante für dynamic Children. Wird
91
- // erst aufgerufen wenn der Knoten im UI ausgeklappt wird. Kein ctx-
92
- // Argument: Provider sind session-bound; Backend liest tenantId aus
93
- // session bei jedem fetch/dispatch. V.1.1 hatte ein ctx mit tenantId,
94
- // das aber im Browser nie echten Tenant trug (war auf SYSTEM_TENANT_ID
95
- // gepinnt) und vom einzigen V.1.2-Consumer (text-content) ignoriert
96
- // wurde. SR2-Rip 2026-05-18: Dead-API entfernt; wenn später ein
97
- // Provider tenant-aware-rendern muss (z.B. cross-tenant-Dashboards
98
- // für SystemAdmin), wird ctx mit echtem Tenant-Source aus dem Auth-
99
- // Layer re-introduziert. YAGNI bis dahin.
100
- export type TreeChildrenSubscribe = () => Subscribe<readonly TreeNode[]>;
101
-
102
- // TreeActionDef — Schema-Eintrag pro Action in der treeActions-Map
103
- // eines Features. Phase 0: Args sind ein optionales Type-Sample
104
- // (kein Validator zur Laufzeit — Validation passiert compile-time
105
- // via buildTarget-Generic, runtime via Editor-Panel-Schema).
106
- //
107
- // Lebt hier (nicht in build-target.ts) weil es konzeptuell zur
108
- // Visual-Tree-Domäne gehört, nicht zum Builder. build-target.ts
109
- // importiert den Type von hier.
110
- export type TreeActionDef<TArgs = Record<string, unknown>> = {
111
- readonly args?: TArgs;
112
- };
113
-
114
- // TreeActionsHandle<T> — Return-Type von r.treeActions(...). Trägt
115
- // den literal-typed Action-Map durch das Feature-Export-System
116
- // (siehe FeatureDefinition.exports + Memory `[EventDef-Exports-
117
- // Pattern]`). Das ist die compile-time Bridge zu buildTarget:
118
- //
119
- // const handle = r.treeActions({ edit: { args: { slug: "" as string } } });
120
- // // handle.id → TFeature (literal feature name)
121
- // // handle.treeActions → { edit: { args: { slug: string } } } (literal-typed)
122
- // buildTarget({ target: handle, action: "edit", args: { slug: "x" } });
123
- // // ^^^^^^^^^^^^^^ ^^^^^^^^
124
- // // literal-validated typed-validated
125
- //
126
- // Runtime-Lookup geht über FeatureDefinition.treeActions (erased Map),
127
- // Compile-Time-Validation über diesen Handle.
128
- export type TreeActionsHandle<
129
- TFeature extends string,
130
- TActions extends Record<string, TreeActionDef>,
131
- > = {
132
- readonly id: TFeature;
133
- readonly treeActions: TActions;
134
- };
package/src/tz-context.ts DELETED
@@ -1,63 +0,0 @@
1
- // TzContext — the type contract for ctx.tz (pure types; the factory lives in
2
- // @cosmicdrift/kumiko-framework, time/tz-context.ts).
3
- //
4
- // `Temporal` here is the ambient global from TypeScript's lib
5
- // (lib.esnext.temporal) — at runtime the framework installs the polyfill.
6
-
7
- import type { GeoAddress, GeoCoordinates, GeoTzProvider } from "./geo-tz";
8
-
9
- // JSON form for wall-clock + TZ — see createLocatedTimestampField() in
10
- // @cosmicdrift/kumiko-framework, engine/factories.ts. Two fields, foolproof.
11
- export type LocatedTimestampJson = {
12
- /** Wall-clock ISO without offset, e.g. "2026-04-03T10:00:00" */
13
- readonly at: string;
14
- /** IANA zone, e.g. "Europe/Lisbon" */
15
- readonly tz: string;
16
- };
17
-
18
- export type TzContext = {
19
- /** Default TZ of the tenant (from tenant.timezone, default "UTC"). */
20
- readonly tenant: string;
21
- /** Display TZ of the current user (profile override, fallback tenant). */
22
- readonly user: string;
23
-
24
- /** Current moment as UTC instant. */
25
- now(): Temporal.Instant;
26
- /** Current moment as ZonedDateTime in the requested zone. */
27
- nowIn(tz: string): Temporal.ZonedDateTime;
28
-
29
- /** Today's calendar date in the requested zone. */
30
- today(tz: string): Temporal.PlainDate;
31
- /** Day boundaries (00:00 to 24:00 next day) as UTC instants — for DB range queries. */
32
- todayRange(tz: string): { readonly start: Temporal.Instant; readonly end: Temporal.Instant };
33
-
34
- /** Wall-clock string + IANA zone → ZonedDateTime. */
35
- parse(wallClock: string, tz: string): Temporal.ZonedDateTime;
36
-
37
- /** ZonedDateTime → UTC instant. */
38
- toInstant(zdt: Temporal.ZonedDateTime): Temporal.Instant;
39
-
40
- /** ZonedDateTime → JSON pair { at, tz } (API boundary). */
41
- toLocatedJson(zdt: Temporal.ZonedDateTime): LocatedTimestampJson;
42
-
43
- /** JSON pair { at, tz } → ZonedDateTime (wall-clock + IANA). */
44
- fromLocatedJson(obj: LocatedTimestampJson): Temporal.ZonedDateTime;
45
-
46
- /** Geo coordinates → IANA zone via the configured GeoTzProvider.
47
- * Throws when no provider is configured (v1 default). */
48
- fromCoordinates(coords: GeoCoordinates): Promise<string>;
49
- /** Postal address → IANA zone via GeoTzProvider. Throws when no provider is
50
- * configured OR the provider does not support fromAddress (the offline
51
- * lat/lng provider does not). */
52
- fromAddress(address: GeoAddress): Promise<string>;
53
- };
54
-
55
- export type TzContextOptions = {
56
- /** Tenant default TZ. Default "UTC" when unset. */
57
- readonly tenant?: string;
58
- /** User override. Default = tenant. */
59
- readonly user?: string;
60
- /** Optional geo→zone adapter for ctx.tz.fromCoordinates / fromAddress.
61
- * Without a provider those methods throw. */
62
- readonly geoTz?: GeoTzProvider;
63
- };
@@ -1,68 +0,0 @@
1
- // WebSocket route definition — feature-declared WebSocket endpoints under
2
- // /api/ws/*. Auth (session + origin) runs before the upgrade; `connect`
3
- // then returns the per-connection handlers or a Response that rejects it.
4
-
5
- import type { Context } from "hono";
6
- import type { SessionUser, WriteResult } from "./handlers";
7
-
8
- export const WEBSOCKET_MAX_PAYLOAD_BYTES = 1024 * 1024;
9
- export const WEBSOCKET_DEFAULT_MAX_MESSAGE_BYTES = 64 * 1024;
10
- export const WEBSOCKET_ROUTE_PATH_PREFIX = "/api/ws/";
11
- // Bun closes a socket whose unsent outbound queue exceeds this (slow or stalled reader).
12
- export const WEBSOCKET_BACKPRESSURE_LIMIT_BYTES = 4 * 1024 * 1024;
13
- export const WEBSOCKET_DEFAULT_MAX_CONNECTIONS_PER_USER = 5;
14
- export const WEBSOCKET_MAX_CONNECTIONS_PER_USER_LIMIT = 100;
15
-
16
- export type WebSocketMessageData = string | Uint8Array;
17
-
18
- export type WebSocketConnection = {
19
- readonly send: (data: WebSocketMessageData) => void;
20
- readonly close: (code?: number, reason?: string) => void;
21
- /**
22
- * Aborts when the socket closes. onClose can run while onOpen/onMessage is
23
- * still awaiting, so after any await that allocates (e.g. an upstream
24
- * session), check `signal.aborted` and release it yourself.
25
- */
26
- readonly signal: AbortSignal;
27
- };
28
-
29
- export type WebSocketSessionHandlers = {
30
- /** May still be awaiting when onClose runs; see `WebSocketConnection.signal`. */
31
- readonly onOpen?: (connection: WebSocketConnection) => void | Promise<void>;
32
- readonly onMessage?: (
33
- data: WebSocketMessageData,
34
- connection: WebSocketConnection,
35
- ) => void | Promise<void>;
36
- /** Runs immediately on close, not queued behind a slow onMessage; pending messages never start after it. */
37
- readonly onClose?: (
38
- code: number,
39
- reason: string,
40
- connection: WebSocketConnection,
41
- ) => void | Promise<void>;
42
- };
43
-
44
- export type WebSocketRouteConnectDeps = {
45
- readonly user: SessionUser;
46
- readonly query: (type: string, payload: unknown) => Promise<unknown>;
47
- readonly write: (type: string, payload: unknown) => Promise<WriteResult>;
48
- /** Resolved via the server's trustedProxyHops-aware resolver, like HttpRouteHandlerDeps.clientIp. */
49
- readonly clientIp: string;
50
- };
51
-
52
- export type WebSocketRouteDefinition = {
53
- /** Must start with "/api/ws/"; `:param` segments allowed, no "*". */
54
- readonly path: string;
55
- /** Per-message cap; oversized messages close the socket with 1009. Default 64 KiB, max 1 MiB. */
56
- readonly maxMessageBytes?: number;
57
- /** Concurrent sockets per user and tenant on this route (per server process). Default 5, max 100; above it the upgrade gets 429. */
58
- readonly maxConnectionsPerUser?: number;
59
- /**
60
- * Runs after auth + origin checks, before the upgrade. Returning a Response rejects the upgrade with it.
61
- * Allocate per-connection resources in `onOpen`, not here: if the upgrade then fails, no `onClose` runs.
62
- */
63
- readonly connect: (
64
- // biome-ignore lint/suspicious/noExplicitAny: Hono context generics are invisible at the framework boundary
65
- c: Context<any, any>,
66
- deps: WebSocketRouteConnectDeps,
67
- ) => WebSocketSessionHandlers | Response | Promise<WebSocketSessionHandlers | Response>;
68
- };
@@ -1,31 +0,0 @@
1
- // WhereValue: primitive for eq, array for IN, null for IS NULL, or an
2
- // operator-object for range/comparisons. Deliberately NOT `unknown |
3
- // WhereOperator` — that union collapses to `unknown` and erases the
4
- // operator form at every call site (a typo like `{ gtee: x }` would
5
- // type-check, then bind as eq at runtime).
6
- export type WhereOperator = {
7
- readonly gt?: unknown;
8
- readonly gte?: unknown;
9
- readonly lt?: unknown;
10
- readonly lte?: unknown;
11
- readonly ne?: unknown;
12
- readonly in?: readonly unknown[];
13
- readonly like?: string;
14
- };
15
- export type WherePrimitive = string | number | boolean | bigint | Date | null | undefined;
16
- export type WhereValue = WherePrimitive | readonly WherePrimitive[] | WhereOperator;
17
- // Wider index so dynamic Record<string, unknown> builders still typecheck;
18
- // annotate literals as WhereValue / satisfies WhereValue to catch typos.
19
- export type WhereObject = Record<string, WhereValue | unknown>;
20
-
21
- export type OrderByClause = {
22
- readonly col: string;
23
- readonly direction?: "asc" | "desc";
24
- };
25
-
26
- export type SelectOptions = {
27
- readonly limit?: number;
28
- // Single column or array for multi-column tie-breaks (e.g.
29
- // [{col: "createdAt"}, {col: "id"}] for chronological-with-stable-id).
30
- readonly orderBy?: OrderByClause | readonly OrderByClause[];
31
- };
package/src/workspace.ts DELETED
@@ -1,42 +0,0 @@
1
- import type { AccessRule } from "./handlers";
2
-
3
- // Workspace declaration. A workspace is a persona-/role-scoped UI surface:
4
- // pure UI composition with no backend, DB or auth impact. The engine stores
5
- // these verbatim and the active web shell (shellWorkspaces) renders the
6
- // switcher and filters the nav tree by membership + access.
7
- //
8
- // Membership is computed from two sources, merged at boot:
9
- // 1. r.workspace({ nav: [...] }) — explicit list of nav QNs
10
- // 2. r.nav({ workspaces: [...] }) — nav entry self-assigns to workspaces
11
- // A nav entry that appears in neither source belongs to no workspace and
12
- // only shows up when no workspace is active (legacy / non-workspace apps).
13
- //
14
- // Cross-feature references are allowed: `nav` may point at any registered
15
- // nav QN. The boot validator checks references exist and that workspace
16
- // IDs referenced from r.nav are real.
17
- export type WorkspaceDefinition = {
18
- // Feature author writes the short id ("disposition"); the registry
19
- // overwrites `id` with the qualified name ("bmc:workspace:disposition")
20
- // in its stored copy. Same pattern as NavDefinition / ScreenDefinition.
21
- readonly id: string;
22
- // i18n translation key. Resolved at render time by the renderer's
23
- // useTranslation hook; engine keeps it opaque.
24
- readonly label: string;
25
- // Icon key — whatever the icon registry of the active renderer understands.
26
- // Engine doesn't validate; unknown icons surface as a missing icon on
27
- // screen, not a boot failure (mirrors NavDefinition.icon).
28
- readonly icon?: string;
29
- // Sort weight in the workspace switcher (lower = earlier). Ties broken
30
- // by registration order — features registered later appear lower.
31
- readonly order?: number;
32
- // Role / openToAll gate. Only users matching this rule see the workspace
33
- // in their switcher. Mirrors NavDefinition.access — same semantics across
34
- // the UI surface, so a default-deny app can do `{ roles: [] }`.
35
- readonly access?: AccessRule;
36
- // Explicit nav QNs that belong to this workspace. Merged with any nav
37
- // entries that self-assign via r.nav({ workspaces: [...] }).
38
- readonly nav?: readonly string[];
39
- // Default workspace at login when the user has access to multiple. Boot
40
- // validator rejects more than one default per app.
41
- readonly default?: boolean;
42
- };
@@ -1,20 +0,0 @@
1
- // Plain, JSON-serializable snapshot of a KumikoError for use on the write-path
2
- // (WriteResult.error, BatchResult.error). The dispatcher stores results under
3
- // an idempotency key — a KumikoError instance wouldn't round-trip through
4
- // JSON, so we keep structural data only and rebuild the instance on demand
5
- // via reraiseAsKumikoError when we need to throw upstream again.
6
- export type WriteErrorInfo = {
7
- readonly code: string;
8
- readonly httpStatus: number;
9
- readonly i18nKey: string;
10
- readonly i18nParams?: Readonly<Record<string, unknown>>;
11
- readonly message: string;
12
- readonly details?: unknown;
13
- };
14
-
15
- // The failure half of WriteResult — `{ isSuccess: false } + error`. Not
16
- // generic: the error carries zero data, so there's nothing to narrow.
17
- export type WriteFailure = {
18
- readonly isSuccess: false;
19
- readonly error: WriteErrorInfo;
20
- };
File without changes