@kernhq/module-quire 0.2.0

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 (72) hide show
  1. package/LICENSE +662 -0
  2. package/README.md +71 -0
  3. package/dist/client/rank.d.ts +42 -0
  4. package/dist/client/rank.d.ts.map +1 -0
  5. package/dist/client/rank.js +97 -0
  6. package/dist/client/rank.js.map +1 -0
  7. package/dist/contract/capabilities.d.ts +35 -0
  8. package/dist/contract/capabilities.d.ts.map +1 -0
  9. package/dist/contract/capabilities.js +35 -0
  10. package/dist/contract/capabilities.js.map +1 -0
  11. package/dist/contract/events.d.ts +58 -0
  12. package/dist/contract/events.d.ts.map +1 -0
  13. package/dist/contract/events.js +18 -0
  14. package/dist/contract/events.js.map +1 -0
  15. package/dist/contract/index.d.ts +6 -0
  16. package/dist/contract/index.d.ts.map +1 -0
  17. package/dist/contract/index.js +6 -0
  18. package/dist/contract/index.js.map +1 -0
  19. package/dist/contract/models.d.ts +95 -0
  20. package/dist/contract/models.d.ts.map +1 -0
  21. package/dist/contract/models.js +82 -0
  22. package/dist/contract/models.js.map +1 -0
  23. package/dist/contract/permissions.d.ts +51 -0
  24. package/dist/contract/permissions.d.ts.map +1 -0
  25. package/dist/contract/permissions.js +59 -0
  26. package/dist/contract/permissions.js.map +1 -0
  27. package/dist/contract/router.d.ts +713 -0
  28. package/dist/contract/router.d.ts.map +1 -0
  29. package/dist/contract/router.js +109 -0
  30. package/dist/contract/router.js.map +1 -0
  31. package/dist/server/_impl.d.ts +815 -0
  32. package/dist/server/_impl.d.ts.map +1 -0
  33. package/dist/server/_impl.js +189 -0
  34. package/dist/server/_impl.js.map +1 -0
  35. package/dist/server/index.d.ts +3 -0
  36. package/dist/server/index.d.ts.map +1 -0
  37. package/dist/server/index.js +87 -0
  38. package/dist/server/index.js.map +1 -0
  39. package/dist/server/schema.d.ts +540 -0
  40. package/dist/server/schema.d.ts.map +1 -0
  41. package/dist/server/schema.js +86 -0
  42. package/dist/server/schema.js.map +1 -0
  43. package/dist/server/services/access.d.ts +78 -0
  44. package/dist/server/services/access.d.ts.map +1 -0
  45. package/dist/server/services/access.js +96 -0
  46. package/dist/server/services/access.js.map +1 -0
  47. package/dist/server/services/index.d.ts +15 -0
  48. package/dist/server/services/index.d.ts.map +1 -0
  49. package/dist/server/services/index.js +22 -0
  50. package/dist/server/services/index.js.map +1 -0
  51. package/dist/server/services/pages.d.ts +190 -0
  52. package/dist/server/services/pages.d.ts.map +1 -0
  53. package/dist/server/services/pages.js +242 -0
  54. package/dist/server/services/pages.js.map +1 -0
  55. package/dist/server/services/spaces.d.ts +95 -0
  56. package/dist/server/services/spaces.d.ts.map +1 -0
  57. package/dist/server/services/spaces.js +100 -0
  58. package/dist/server/services/spaces.js.map +1 -0
  59. package/migrations/0000_init.sql +43 -0
  60. package/migrations/0001_rls.sql +17 -0
  61. package/migrations/meta/0000_snapshot.json +358 -0
  62. package/migrations/meta/_journal.json +20 -0
  63. package/package.json +78 -0
  64. package/src/client/index.ts +67 -0
  65. package/src/client/rank.test.ts +92 -0
  66. package/src/client/rank.ts +100 -0
  67. package/src/contract/capabilities.ts +36 -0
  68. package/src/contract/events.ts +22 -0
  69. package/src/contract/index.ts +5 -0
  70. package/src/contract/models.ts +93 -0
  71. package/src/contract/permissions.ts +59 -0
  72. package/src/contract/router.ts +121 -0
package/README.md ADDED
@@ -0,0 +1,71 @@
1
+ # Module template
2
+
3
+ Copy this to start a Kern module. It is a working module: a `Note` entity with list, create and
4
+ delete, its own Postgres schema, row-level security, permissions, events, and a test that refuses to
5
+ let the contract and the router drift apart.
6
+
7
+ The fastest way to copy it correctly is not to copy it by hand:
8
+
9
+ ```bash
10
+ cd repos/modules
11
+ pnpm new-module crm # generates this package *and* its half in the app
12
+ ```
13
+
14
+ Read the rest of this file if you are doing it by hand, or if you want to know what the generator
15
+ wrote.
16
+
17
+ ## What is in here
18
+
19
+ | File | What it is |
20
+ |---|---|
21
+ | `src/contract.ts` | Zod models, the oRPC contract, events, permission keys, capabilities. Imported by both halves, so no Node code. |
22
+ | `src/server/schema.ts` | Drizzle tables in `mod_<id>`. |
23
+ | `src/server/_impl.ts` | The router. Separate from `index.ts` so the test can walk it without a kernel. |
24
+ | `src/server/index.ts` | `defineServerModule` — schema, migrations, router, subscriptions. |
25
+ | `src/client/index.ts` | The typed API client and module logic. **Ships as source.** |
26
+ | `src/module.test.ts` | Contract-to-router parity and the authorisation guard. Keep it. |
27
+ | `migrations/0000_init.sql` | Generated by `pnpm db:generate`. |
28
+ | `migrations/0001_rls.sql` | Hand-written. Never generated. |
29
+
30
+ ## Copying it by hand
31
+
32
+ Each of these has been got wrong before.
33
+
34
+ 1. **`package.json`** — set `name` to `@kernhq/module-<id>`, and **delete `"private": true`**. A
35
+ private package is skipped silently by changesets: the commit lands, CI is green, and nothing
36
+ publishes.
37
+ 2. **`files`** must cover every directory `./client` reaches — `src/client` *and* `src/contract`.
38
+ The client ships as source, so a re-export the tarball omits breaks the consumer and nothing
39
+ local notices, because the workspace resolves the file the package does not ship.
40
+ `pnpm check:pack` catches it.
41
+ 3. **The id agrees in four places**: `MODULE_ID`, `moduleSchema('<id>')`, `schemaFilter` in
42
+ `drizzle.config.ts`, and every permission and event prefix.
43
+ 4. **Version comes from the package**, never a literal: `packageVersion(import.meta.url)`. A literal
44
+ is not bumped by a release — chat once shipped as 0.2.0 while telling every admin it was 0.1.0,
45
+ and that literal is what `workspace_modules.installed_version` recorded.
46
+ 5. **Write the RLS migration.** `pnpm db:generate` will not. Copy `0001_rls.sql` and change the
47
+ table names; `rlsPolicySql` from `@kernhq/kernel` emits the same text.
48
+ 6. **Host it.** A module nothing imports is invisible: its tests pass, it publishes, and every call
49
+ 404s. Add it to `featureModules` in the `core` repo's `src/service.ts`, or to whichever service
50
+ should hold it.
51
+ 7. **Register the client** in the app's `src/lib/modules/registry.ts`.
52
+
53
+ ## What a module can contribute
54
+
55
+ The server half declares tables, migrations, a router, `procedures` other modules call through
56
+ `kernel.call()`, `jobs`, `subscriptions`, search indexers and lifecycle hooks.
57
+
58
+ The client half — the manifest in the app — declares `nav`, `commands`, `settingsPages`, `widgets`
59
+ for the dashboard, and `sidebar` for the column beside the rail. Read the `kern-widget` skill before
60
+ writing a widget, and `kern-module` for the whole sequence.
61
+
62
+ ## Before you call it done
63
+
64
+ ```bash
65
+ pnpm typecheck && pnpm lint && pnpm test && pnpm build
66
+ pnpm check:pack # the tarball contains what ./client imports
67
+ pnpm check:versions # the manifest version matches package.json
68
+ ```
69
+
70
+ Then use it through the interface, signed in, with the module enabled for a workspace. A module that
71
+ has never served a request is not finished, whatever the type-checker says.
@@ -0,0 +1,42 @@
1
+ /**
2
+ * Fractional indexing for `Page.position`.
3
+ *
4
+ * Copied from the tracker's `rank.ts` rather than imported: modules do not depend on one another,
5
+ * and a pure algorithm is the one thing worth duplicating. Keep them in step if either changes.
6
+ *
7
+ * A page tree must survive concurrent edits: two people dragging different pages at the same time
8
+ * should not have to renumber anything. Each page therefore carries a short string key, and moving
9
+ * one between two siblings only mints a new key strictly between its neighbours — no other row is
10
+ * touched, and the result sorts with a plain string comparison.
11
+ *
12
+ * The alphabet is ordered by code point (digits, uppercase, lowercase) so lexicographic order and
13
+ * numeric order agree, which is what `ORDER BY position` in Postgres relies on.
14
+ */
15
+ /** True when `rank` only uses the rank alphabet and has no trailing zero (the canonical form). */
16
+ export declare function isValidRank(rank: string): boolean;
17
+ /**
18
+ * A key strictly between `before` and `after`. Pass `null` for an open end: `rankBetween(null, first)`
19
+ * puts an item at the top of the list, `rankBetween(last, null)` at the bottom.
20
+ */
21
+ export declare function rankBetween(before: string | null, after: string | null): string;
22
+ /** First rank in an empty list. */
23
+ export declare function initialRank(): string;
24
+ /**
25
+ * `count` evenly spread ranks, for seeding a list. Cheaper and tidier than calling `rankBetween`
26
+ * repeatedly, which would bias every new key towards the end.
27
+ */
28
+ export declare function rankSequence(count: number): string[];
29
+ /** Ascending comparator for anything carrying a `rank`. */
30
+ export declare function byRank(a: {
31
+ rank: string;
32
+ }, b: {
33
+ rank: string;
34
+ }): number;
35
+ /**
36
+ * The rank an item needs to land at `targetIndex` of `ordered` (the list it is being dropped into,
37
+ * already excluding the dragged item).
38
+ */
39
+ export declare function rankForIndex(ordered: Array<{
40
+ rank: string;
41
+ }>, targetIndex: number): string;
42
+ //# sourceMappingURL=rank.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rank.d.ts","sourceRoot":"","sources":["../../src/client/rank.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAWH,kGAAkG;AAClG,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAIjD;AAED;;;GAGG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,CA8B/E;AAED,mCAAmC;AACnC,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAQpD;AAED,2DAA2D;AAC3D,wBAAgB,MAAM,CAAC,CAAC,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC,EAAE;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAEvE;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,CAI1F"}
@@ -0,0 +1,97 @@
1
+ /**
2
+ * Fractional indexing for `Page.position`.
3
+ *
4
+ * Copied from the tracker's `rank.ts` rather than imported: modules do not depend on one another,
5
+ * and a pure algorithm is the one thing worth duplicating. Keep them in step if either changes.
6
+ *
7
+ * A page tree must survive concurrent edits: two people dragging different pages at the same time
8
+ * should not have to renumber anything. Each page therefore carries a short string key, and moving
9
+ * one between two siblings only mints a new key strictly between its neighbours — no other row is
10
+ * touched, and the result sorts with a plain string comparison.
11
+ *
12
+ * The alphabet is ordered by code point (digits, uppercase, lowercase) so lexicographic order and
13
+ * numeric order agree, which is what `ORDER BY position` in Postgres relies on.
14
+ */
15
+ const DIGITS = '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
16
+ const BASE = DIGITS.length;
17
+ const indexOfDigit = (ch) => {
18
+ const i = DIGITS.indexOf(ch);
19
+ if (i < 0)
20
+ throw new Error(`invalid rank character: ${JSON.stringify(ch)}`);
21
+ return i;
22
+ };
23
+ /** True when `rank` only uses the rank alphabet and has no trailing zero (the canonical form). */
24
+ export function isValidRank(rank) {
25
+ if (rank.length === 0)
26
+ return false;
27
+ for (const ch of rank)
28
+ if (!DIGITS.includes(ch))
29
+ return false;
30
+ return !rank.endsWith(DIGITS[0]);
31
+ }
32
+ /**
33
+ * A key strictly between `before` and `after`. Pass `null` for an open end: `rankBetween(null, first)`
34
+ * puts an item at the top of the list, `rankBetween(last, null)` at the bottom.
35
+ */
36
+ export function rankBetween(before, after) {
37
+ const lo = before ?? '';
38
+ const hi = after ?? '';
39
+ if (lo && hi && lo >= hi) {
40
+ throw new Error(`rankBetween expects before < after, got ${JSON.stringify(lo)} >= ${JSON.stringify(hi)}`);
41
+ }
42
+ let prefix = '';
43
+ // once the digit we keep is strictly below the upper bound's digit, the rest of `hi` cannot
44
+ // constrain us any more and we are free to use the whole alphabet
45
+ let free = hi === '';
46
+ for (let i = 0;; i++) {
47
+ const da = i < lo.length ? indexOfDigit(lo[i]) : -1;
48
+ const db = free ? BASE : i < hi.length ? indexOfDigit(hi[i]) : 0;
49
+ /**
50
+ * An absent lower bound is digit 0, not "below 0".
51
+ *
52
+ * Digit 0 can never be the last digit of a key: nothing sorts strictly between `''` and `'0'`,
53
+ * so a key ending in 0 leaves no room to insert in front of it. Treating the absent bound as -1
54
+ * makes the midpoint of (nothing, '2') come out as '0', and the next insertion at the front then
55
+ * looks for a key below '0', finds none, and appends a digit for ever — a loop inside a request
56
+ * handler that allocates until the process dies. Reaching it takes five insertions at the top of
57
+ * the same list.
58
+ */
59
+ const low = da >= 0 ? da : 0;
60
+ if (db - low > 1)
61
+ return prefix + DIGITS[Math.floor((low + db) / 2)];
62
+ prefix += DIGITS[low];
63
+ if (!free && low < db)
64
+ free = true;
65
+ }
66
+ }
67
+ /** First rank in an empty list. */
68
+ export function initialRank() {
69
+ return rankBetween(null, null);
70
+ }
71
+ /**
72
+ * `count` evenly spread ranks, for seeding a list. Cheaper and tidier than calling `rankBetween`
73
+ * repeatedly, which would bias every new key towards the end.
74
+ */
75
+ export function rankSequence(count) {
76
+ const out = [];
77
+ let prev = null;
78
+ for (let i = 0; i < count; i++) {
79
+ prev = rankBetween(prev, null);
80
+ out.push(prev);
81
+ }
82
+ return out;
83
+ }
84
+ /** Ascending comparator for anything carrying a `rank`. */
85
+ export function byRank(a, b) {
86
+ return a.rank < b.rank ? -1 : a.rank > b.rank ? 1 : 0;
87
+ }
88
+ /**
89
+ * The rank an item needs to land at `targetIndex` of `ordered` (the list it is being dropped into,
90
+ * already excluding the dragged item).
91
+ */
92
+ export function rankForIndex(ordered, targetIndex) {
93
+ const before = targetIndex > 0 ? (ordered[targetIndex - 1]?.rank ?? null) : null;
94
+ const after = targetIndex < ordered.length ? (ordered[targetIndex]?.rank ?? null) : null;
95
+ return rankBetween(before, after);
96
+ }
97
+ //# sourceMappingURL=rank.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rank.js","sourceRoot":"","sources":["../../src/client/rank.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,MAAM,GAAG,gEAAgE,CAAA;AAC/E,MAAM,IAAI,GAAG,MAAM,CAAC,MAAM,CAAA;AAE1B,MAAM,YAAY,GAAG,CAAC,EAAU,EAAE,EAAE;IAClC,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAA;IAC5B,IAAI,CAAC,GAAG,CAAC;QAAE,MAAM,IAAI,KAAK,CAAC,2BAA2B,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;IAC3E,OAAO,CAAC,CAAA;AACV,CAAC,CAAA;AAED,kGAAkG;AAClG,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,KAAK,CAAA;IACnC,KAAK,MAAM,EAAE,IAAI,IAAI;QAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,CAAC;YAAE,OAAO,KAAK,CAAA;IAC7D,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAW,CAAC,CAAA;AAC5C,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,WAAW,CAAC,MAAqB,EAAE,KAAoB;IACrE,MAAM,EAAE,GAAG,MAAM,IAAI,EAAE,CAAA;IACvB,MAAM,EAAE,GAAG,KAAK,IAAI,EAAE,CAAA;IACtB,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,2CAA2C,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC,EAAE,CAAC,CAAA;IAC3G,CAAC;IAED,IAAI,MAAM,GAAG,EAAE,CAAA;IACf,4FAA4F;IAC5F,kEAAkE;IAClE,IAAI,IAAI,GAAG,EAAE,KAAK,EAAE,CAAA;IAEpB,KAAK,IAAI,CAAC,GAAG,CAAC,GAAI,CAAC,EAAE,EAAE,CAAC;QACtB,MAAM,EAAE,GAAG,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAC7D,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,EAAE,CAAC,CAAC,CAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;QAC1E;;;;;;;;;WASG;QACH,MAAM,GAAG,GAAG,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAA;QAC5B,IAAI,EAAE,GAAG,GAAG,GAAG,CAAC;YAAE,OAAO,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAA;QACpE,MAAM,IAAI,MAAM,CAAC,GAAG,CAAC,CAAA;QACrB,IAAI,CAAC,IAAI,IAAI,GAAG,GAAG,EAAE;YAAE,IAAI,GAAG,IAAI,CAAA;IACpC,CAAC;AACH,CAAC;AAED,mCAAmC;AACnC,MAAM,UAAU,WAAW;IACzB,OAAO,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;AAChC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,KAAa;IACxC,MAAM,GAAG,GAAa,EAAE,CAAA;IACxB,IAAI,IAAI,GAAkB,IAAI,CAAA;IAC9B,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC;QAC/B,IAAI,GAAG,WAAW,CAAC,IAAI,EAAE,IAAI,CAAC,CAAA;QAC9B,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAChB,CAAC;IACD,OAAO,GAAG,CAAA;AACZ,CAAC;AAED,2DAA2D;AAC3D,MAAM,UAAU,MAAM,CAAC,CAAmB,EAAE,CAAmB;IAC7D,OAAO,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;AACvD,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,OAAgC,EAAE,WAAmB;IAChF,MAAM,MAAM,GAAG,WAAW,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,GAAG,CAAC,CAAC,EAAE,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IAChF,MAAM,KAAK,GAAG,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,WAAW,CAAC,EAAE,IAAI,IAAI,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAA;IACxF,OAAO,WAAW,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;AACnC,CAAC"}
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Sub-features a workspace can switch off inside this module.
3
+ *
4
+ * Only the foundation exists today, and it is `required` — always on, never offered as a switch — so
5
+ * that the optional ones arriving later have something to depend on. A capability is not a second
6
+ * permission system: a permission asks whether this *person* may do something, a capability asks
7
+ * whether this *workspace* has the feature at all, and a procedure behind a disabled one answers
8
+ * `notFound` rather than `forbidden`, because a surface the workspace never enabled is not being
9
+ * withheld — it is not there.
10
+ *
11
+ * Planned, each of which is a real "different customers want different amounts of this": databases,
12
+ * public publishing, blogs and page analytics. They are declared when the feature lands, not before:
13
+ * a switch that does nothing is worse than no switch.
14
+ */
15
+ export declare const quireCapabilities: readonly {
16
+ id: string;
17
+ label: string;
18
+ dependsOn: string[];
19
+ defaultEnabled: boolean;
20
+ level: 3 | 1 | 2;
21
+ required: boolean;
22
+ description?: string | undefined;
23
+ }[];
24
+ /**
25
+ * Which procedures belong to which capability, as data.
26
+ *
27
+ * Declared rather than inferred, because a missing `requiresCapability` is invisible: the procedure
28
+ * type-checks, the tests pass, and the only symptom is that a workspace which switched the feature
29
+ * off can still call it. `module.test.ts` reads this and fails when a procedure named here is not
30
+ * carrying the extra middleware.
31
+ *
32
+ * Everything Quire offers today belongs to the module as a whole, so this is empty.
33
+ */
34
+ export declare const quireCapabilityProcedures: Record<string, readonly string[]>;
35
+ //# sourceMappingURL=capabilities.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.d.ts","sourceRoot":"","sources":["../../src/contract/capabilities.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,iBAAiB;;;;;;;;GAO5B,CAAA;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,yBAAyB,EAAE,MAAM,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAM,CAAA"}
@@ -0,0 +1,35 @@
1
+ import { defineCapabilities } from '@kernhq/contracts';
2
+ /**
3
+ * Sub-features a workspace can switch off inside this module.
4
+ *
5
+ * Only the foundation exists today, and it is `required` — always on, never offered as a switch — so
6
+ * that the optional ones arriving later have something to depend on. A capability is not a second
7
+ * permission system: a permission asks whether this *person* may do something, a capability asks
8
+ * whether this *workspace* has the feature at all, and a procedure behind a disabled one answers
9
+ * `notFound` rather than `forbidden`, because a surface the workspace never enabled is not being
10
+ * withheld — it is not there.
11
+ *
12
+ * Planned, each of which is a real "different customers want different amounts of this": databases,
13
+ * public publishing, blogs and page analytics. They are declared when the feature lands, not before:
14
+ * a switch that does nothing is worse than no switch.
15
+ */
16
+ export const quireCapabilities = defineCapabilities([
17
+ {
18
+ id: 'pages',
19
+ label: 'Spaces and pages',
20
+ description: 'The page tree itself',
21
+ required: true,
22
+ },
23
+ ]);
24
+ /**
25
+ * Which procedures belong to which capability, as data.
26
+ *
27
+ * Declared rather than inferred, because a missing `requiresCapability` is invisible: the procedure
28
+ * type-checks, the tests pass, and the only symptom is that a workspace which switched the feature
29
+ * off can still call it. `module.test.ts` reads this and fails when a procedure named here is not
30
+ * carrying the extra middleware.
31
+ *
32
+ * Everything Quire offers today belongs to the module as a whole, so this is empty.
33
+ */
34
+ export const quireCapabilityProcedures = {};
35
+ //# sourceMappingURL=capabilities.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"capabilities.js","sourceRoot":"","sources":["../../src/contract/capabilities.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAA;AAEtD;;;;;;;;;;;;;GAaG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,kBAAkB,CAAC;IAClD;QACE,EAAE,EAAE,OAAO;QACX,KAAK,EAAE,kBAAkB;QACzB,WAAW,EAAE,sBAAsB;QACnC,QAAQ,EAAE,IAAI;KACf;CACF,CAAC,CAAA;AAEF;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAsC,EAAE,CAAA"}
@@ -0,0 +1,58 @@
1
+ import { z } from 'zod';
2
+ /** `<module>.<entity>.<action>`. Anything that emits one declares it here. */
3
+ export declare const quireEvents: {
4
+ readonly spaceCreated: import("@kernhq/contracts").EventDef<"quire.space.created", z.ZodObject<{
5
+ spaceId: z.ZodUUID;
6
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
7
+ }, z.core.$strip>>;
8
+ readonly spaceUpdated: import("@kernhq/contracts").EventDef<"quire.space.updated", z.ZodObject<{
9
+ spaceId: z.ZodUUID;
10
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
11
+ }, z.core.$strip>>;
12
+ readonly spaceArchived: import("@kernhq/contracts").EventDef<"quire.space.archived", z.ZodObject<{
13
+ spaceId: z.ZodUUID;
14
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
15
+ archived: z.ZodBoolean;
16
+ }, z.core.$strip>>;
17
+ readonly pageCreated: import("@kernhq/contracts").EventDef<"quire.page.created", z.ZodObject<{
18
+ pageId: z.ZodUUID;
19
+ spaceId: z.ZodUUID;
20
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
21
+ }, z.core.$strip>>;
22
+ readonly pageUpdated: import("@kernhq/contracts").EventDef<"quire.page.updated", z.ZodObject<{
23
+ pageId: z.ZodUUID;
24
+ spaceId: z.ZodUUID;
25
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
26
+ }, z.core.$strip>>;
27
+ readonly pageMoved: import("@kernhq/contracts").EventDef<"quire.page.moved", z.ZodObject<{
28
+ pageId: z.ZodUUID;
29
+ spaceId: z.ZodUUID;
30
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
31
+ parentId: z.ZodNullable<z.ZodUUID>;
32
+ }, z.core.$strip>>;
33
+ readonly pageArchived: import("@kernhq/contracts").EventDef<"quire.page.archived", z.ZodObject<{
34
+ pageId: z.ZodUUID;
35
+ spaceId: z.ZodUUID;
36
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
37
+ archived: z.ZodBoolean;
38
+ }, z.core.$strip>>;
39
+ readonly pageTrashed: import("@kernhq/contracts").EventDef<"quire.page.trashed", z.ZodObject<{
40
+ pageId: z.ZodUUID;
41
+ spaceId: z.ZodUUID;
42
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
43
+ count: z.ZodNumber;
44
+ }, z.core.$strip>>;
45
+ readonly pageRestored: import("@kernhq/contracts").EventDef<"quire.page.restored", z.ZodObject<{
46
+ pageId: z.ZodUUID;
47
+ spaceId: z.ZodUUID;
48
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
49
+ }, z.core.$strip>>;
50
+ /** The page and its descendants are gone; anything holding a reference should drop it. */
51
+ readonly pageDeleted: import("@kernhq/contracts").EventDef<"quire.page.deleted", z.ZodObject<{
52
+ pageId: z.ZodUUID;
53
+ spaceId: z.ZodUUID;
54
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
55
+ pageIds: z.ZodArray<z.ZodUUID>;
56
+ }, z.core.$strip>>;
57
+ };
58
+ //# sourceMappingURL=events.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.d.ts","sourceRoot":"","sources":["../../src/contract/events.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAIvB,8EAA8E;AAC9E,eAAO,MAAM,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;IAatB,0FAA0F;;;;;;;CAElF,CAAA"}
@@ -0,0 +1,18 @@
1
+ import { defineEvent, Id, WorkspaceId } from '@kernhq/contracts';
2
+ import { z } from 'zod';
3
+ const page = z.object({ pageId: Id, spaceId: Id, workspaceId: WorkspaceId });
4
+ /** `<module>.<entity>.<action>`. Anything that emits one declares it here. */
5
+ export const quireEvents = {
6
+ spaceCreated: defineEvent('quire.space.created', z.object({ spaceId: Id, workspaceId: WorkspaceId })),
7
+ spaceUpdated: defineEvent('quire.space.updated', z.object({ spaceId: Id, workspaceId: WorkspaceId })),
8
+ spaceArchived: defineEvent('quire.space.archived', z.object({ spaceId: Id, workspaceId: WorkspaceId, archived: z.boolean() })),
9
+ pageCreated: defineEvent('quire.page.created', page),
10
+ pageUpdated: defineEvent('quire.page.updated', page),
11
+ pageMoved: defineEvent('quire.page.moved', page.extend({ parentId: Id.nullable() })),
12
+ pageArchived: defineEvent('quire.page.archived', page.extend({ archived: z.boolean() })),
13
+ pageTrashed: defineEvent('quire.page.trashed', page.extend({ count: z.number().int().nonnegative() })),
14
+ pageRestored: defineEvent('quire.page.restored', page),
15
+ /** The page and its descendants are gone; anything holding a reference should drop it. */
16
+ pageDeleted: defineEvent('quire.page.deleted', page.extend({ pageIds: z.array(Id) })),
17
+ };
18
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/contract/events.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,EAAE,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAChE,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,MAAM,IAAI,GAAG,CAAC,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAA;AAE5E,8EAA8E;AAC9E,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,YAAY,EAAE,WAAW,CAAC,qBAAqB,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC;IACrG,YAAY,EAAE,WAAW,CAAC,qBAAqB,EAAE,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,CAAC,CAAC;IACrG,aAAa,EAAE,WAAW,CACxB,sBAAsB,EACtB,CAAC,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,WAAW,EAAE,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAC3E;IACD,WAAW,EAAE,WAAW,CAAC,oBAAoB,EAAE,IAAI,CAAC;IACpD,WAAW,EAAE,WAAW,CAAC,oBAAoB,EAAE,IAAI,CAAC;IACpD,SAAS,EAAE,WAAW,CAAC,kBAAkB,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,EAAE,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC;IACpF,YAAY,EAAE,WAAW,CAAC,qBAAqB,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC;IACxF,WAAW,EAAE,WAAW,CAAC,oBAAoB,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC;IACtG,YAAY,EAAE,WAAW,CAAC,qBAAqB,EAAE,IAAI,CAAC;IACtD,0FAA0F;IAC1F,WAAW,EAAE,WAAW,CAAC,oBAAoB,EAAE,IAAI,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;CAC7E,CAAA"}
@@ -0,0 +1,6 @@
1
+ export * from './capabilities.js';
2
+ export * from './events.js';
3
+ export * from './models.js';
4
+ export * from './permissions.js';
5
+ export * from './router.js';
6
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/contract/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,kBAAkB,CAAA;AAChC,cAAc,aAAa,CAAA"}
@@ -0,0 +1,6 @@
1
+ export * from './capabilities.js';
2
+ export * from './events.js';
3
+ export * from './models.js';
4
+ export * from './permissions.js';
5
+ export * from './router.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/contract/index.ts"],"names":[],"mappings":"AAAA,cAAc,mBAAmB,CAAA;AACjC,cAAc,aAAa,CAAA;AAC3B,cAAc,aAAa,CAAA;AAC3B,cAAc,kBAAkB,CAAA;AAChC,cAAc,aAAa,CAAA"}
@@ -0,0 +1,95 @@
1
+ import { z } from 'zod';
2
+ /** Lowercase, 2-32 characters. Names the API prefix, the Postgres schema `mod_quire` and every event. */
3
+ export declare const MODULE_ID = "quire";
4
+ /**
5
+ * How a space decides who may see it before any binding is consulted.
6
+ *
7
+ * `open` — every member of the workspace may read it.
8
+ * `restricted` — members may find it and see its name, and need a binding to read a page.
9
+ * `private` — only people with a binding know it exists at all.
10
+ */
11
+ export declare const SpaceVisibility: z.ZodEnum<{
12
+ open: "open";
13
+ restricted: "restricted";
14
+ private: "private";
15
+ }>;
16
+ export type SpaceVisibility = z.infer<typeof SpaceVisibility>;
17
+ export declare const Space: z.ZodObject<{
18
+ id: z.ZodUUID;
19
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
20
+ key: z.ZodString;
21
+ name: z.ZodString;
22
+ description: z.ZodString;
23
+ icon: z.ZodNullable<z.ZodString>;
24
+ visibility: z.ZodEnum<{
25
+ open: "open";
26
+ restricted: "restricted";
27
+ private: "private";
28
+ }>;
29
+ homepageId: z.ZodNullable<z.ZodUUID>;
30
+ createdBy: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "UserId", "out">>;
31
+ createdAt: z.ZodISODateTime;
32
+ updatedAt: z.ZodISODateTime;
33
+ archivedAt: z.ZodNullable<z.ZodISODateTime>;
34
+ }, z.core.$strip>;
35
+ export type Space = z.infer<typeof Space>;
36
+ /**
37
+ * What a page *is*, which decides what a reader sees.
38
+ *
39
+ * `page` — has a published version and a draft. Everyone editing shares one live document; a reader
40
+ * without edit rights, and every public URL, is served the last published version instead. This is
41
+ * what a documentation site is made of.
42
+ * `live` — always live, like a shared note. There is no draft and no unpublished-changes state;
43
+ * versions still accumulate so history and restore work the same way.
44
+ * `database` — the page *is* a database. Its own body is the description above the view.
45
+ */
46
+ export declare const PageKind: z.ZodEnum<{
47
+ page: "page";
48
+ live: "live";
49
+ database: "database";
50
+ }>;
51
+ export type PageKind = z.infer<typeof PageKind>;
52
+ export declare const Page: z.ZodObject<{
53
+ id: z.ZodUUID;
54
+ workspaceId: z.core.$ZodBranded<z.ZodUUID, "WorkspaceId", "out">;
55
+ spaceId: z.ZodUUID;
56
+ parentId: z.ZodNullable<z.ZodUUID>;
57
+ position: z.ZodString;
58
+ kind: z.ZodEnum<{
59
+ page: "page";
60
+ live: "live";
61
+ database: "database";
62
+ }>;
63
+ title: z.ZodString;
64
+ icon: z.ZodNullable<z.ZodString>;
65
+ coverUrl: z.ZodNullable<z.ZodString>;
66
+ publishedVersionId: z.ZodNullable<z.ZodUUID>;
67
+ hasUnpublishedChanges: z.ZodBoolean;
68
+ createdBy: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "UserId", "out">>;
69
+ updatedBy: z.ZodNullable<z.core.$ZodBranded<z.ZodUUID, "UserId", "out">>;
70
+ createdAt: z.ZodISODateTime;
71
+ updatedAt: z.ZodISODateTime;
72
+ archivedAt: z.ZodNullable<z.ZodISODateTime>;
73
+ deletedAt: z.ZodNullable<z.ZodISODateTime>;
74
+ }, z.core.$strip>;
75
+ export type Page = z.infer<typeof Page>;
76
+ /** A page in the sidebar tree: enough to draw a row, and nothing that costs a join. */
77
+ export declare const PageNode: z.ZodObject<{
78
+ id: z.ZodUUID;
79
+ parentId: z.ZodNullable<z.ZodUUID>;
80
+ position: z.ZodString;
81
+ kind: z.ZodEnum<{
82
+ page: "page";
83
+ live: "live";
84
+ database: "database";
85
+ }>;
86
+ title: z.ZodString;
87
+ icon: z.ZodNullable<z.ZodString>;
88
+ hasChildren: z.ZodBoolean;
89
+ archivedAt: z.ZodNullable<z.ZodISODateTime>;
90
+ }, z.core.$strip>;
91
+ export type PageNode = z.infer<typeof PageNode>;
92
+ export declare const Ok: z.ZodObject<{
93
+ ok: z.ZodLiteral<true>;
94
+ }, z.core.$strip>;
95
+ //# sourceMappingURL=models.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.d.ts","sourceRoot":"","sources":["../../src/contract/models.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAEvB,yGAAyG;AACzG,eAAO,MAAM,SAAS,UAAU,CAAA;AAEhC;;;;;;GAMG;AACH,eAAO,MAAM,eAAe;;;;EAA4C,CAAA;AACxE,MAAM,MAAM,eAAe,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAA;AAE7D,eAAO,MAAM,KAAK;;;;;;;;;;;;;;;;;iBAoBhB,CAAA;AACF,MAAM,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,KAAK,CAAC,CAAA;AAEzC;;;;;;;;;GASG;AACH,eAAO,MAAM,QAAQ;;;;EAAuC,CAAA;AAC5D,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAA;AAE/C,eAAO,MAAM,IAAI;;;;;;;;;;;;;;;;;;;;;;iBAwBf,CAAA;AACF,MAAM,MAAM,IAAI,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,IAAI,CAAC,CAAA;AAEvC,uFAAuF;AACvF,eAAO,MAAM,QAAQ;;;;;;;;;;;;;iBASnB,CAAA;AACF,MAAM,MAAM,QAAQ,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,QAAQ,CAAC,CAAA;AAE/C,eAAO,MAAM,EAAE;;iBAAoC,CAAA"}
@@ -0,0 +1,82 @@
1
+ import { Id, Timestamp, UserId, WorkspaceId } from '@kernhq/contracts';
2
+ import { z } from 'zod';
3
+ /** Lowercase, 2-32 characters. Names the API prefix, the Postgres schema `mod_quire` and every event. */
4
+ export const MODULE_ID = 'quire';
5
+ /**
6
+ * How a space decides who may see it before any binding is consulted.
7
+ *
8
+ * `open` — every member of the workspace may read it.
9
+ * `restricted` — members may find it and see its name, and need a binding to read a page.
10
+ * `private` — only people with a binding know it exists at all.
11
+ */
12
+ export const SpaceVisibility = z.enum(['open', 'restricted', 'private']);
13
+ export const Space = z.object({
14
+ id: Id,
15
+ workspaceId: WorkspaceId,
16
+ /** unique per workspace; it is what appears in the URL */
17
+ key: z
18
+ .string()
19
+ .min(2)
20
+ .max(48)
21
+ .regex(/^[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/, 'lowercase letters, digits and dashes'),
22
+ name: z.string().min(1).max(120),
23
+ description: z.string().max(2000),
24
+ /** a Lucide icon name, or an emoji */
25
+ icon: z.string().max(64).nullable(),
26
+ visibility: SpaceVisibility,
27
+ /** the page shown when somebody opens the space; null until one is set */
28
+ homepageId: Id.nullable(),
29
+ createdBy: UserId.nullable(),
30
+ createdAt: Timestamp,
31
+ updatedAt: Timestamp,
32
+ archivedAt: Timestamp.nullable(),
33
+ });
34
+ /**
35
+ * What a page *is*, which decides what a reader sees.
36
+ *
37
+ * `page` — has a published version and a draft. Everyone editing shares one live document; a reader
38
+ * without edit rights, and every public URL, is served the last published version instead. This is
39
+ * what a documentation site is made of.
40
+ * `live` — always live, like a shared note. There is no draft and no unpublished-changes state;
41
+ * versions still accumulate so history and restore work the same way.
42
+ * `database` — the page *is* a database. Its own body is the description above the view.
43
+ */
44
+ export const PageKind = z.enum(['page', 'live', 'database']);
45
+ export const Page = z.object({
46
+ id: Id,
47
+ workspaceId: WorkspaceId,
48
+ spaceId: Id,
49
+ parentId: Id.nullable(),
50
+ /**
51
+ * A fractional index, not an integer. Moving one page between two others must not renumber its
52
+ * siblings: two people reordering at once would then write different numbers for the same rows.
53
+ */
54
+ position: z.string().min(1).max(256),
55
+ kind: PageKind,
56
+ title: z.string().max(300),
57
+ icon: z.string().max(64).nullable(),
58
+ coverUrl: z.string().max(2048).nullable(),
59
+ /** the version a reader without edit rights sees; null while a `page` has never been published */
60
+ publishedVersionId: Id.nullable(),
61
+ /** whether the live document has changed since `publishedVersionId` was written */
62
+ hasUnpublishedChanges: z.boolean(),
63
+ createdBy: UserId.nullable(),
64
+ updatedBy: UserId.nullable(),
65
+ createdAt: Timestamp,
66
+ updatedAt: Timestamp,
67
+ archivedAt: Timestamp.nullable(),
68
+ deletedAt: Timestamp.nullable(),
69
+ });
70
+ /** A page in the sidebar tree: enough to draw a row, and nothing that costs a join. */
71
+ export const PageNode = z.object({
72
+ id: Id,
73
+ parentId: Id.nullable(),
74
+ position: z.string(),
75
+ kind: PageKind,
76
+ title: z.string(),
77
+ icon: z.string().nullable(),
78
+ hasChildren: z.boolean(),
79
+ archivedAt: Timestamp.nullable(),
80
+ });
81
+ export const Ok = z.object({ ok: z.literal(true) });
82
+ //# sourceMappingURL=models.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"models.js","sourceRoot":"","sources":["../../src/contract/models.ts"],"names":[],"mappings":"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"}