litedbmodel 1.2.9 → 2.0.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 (88) hide show
  1. package/README.md +1 -1
  2. package/dist/DBModel.d.ts.map +1 -1
  3. package/dist/DBModel.js +6 -0
  4. package/dist/DBModel.js.map +1 -1
  5. package/dist/scp/authoring-sql.d.ts +56 -0
  6. package/dist/scp/authoring-sql.d.ts.map +1 -0
  7. package/dist/scp/authoring-sql.js +83 -0
  8. package/dist/scp/authoring-sql.js.map +1 -0
  9. package/dist/scp/authoring.d.ts +155 -0
  10. package/dist/scp/authoring.d.ts.map +1 -0
  11. package/dist/scp/authoring.js +162 -0
  12. package/dist/scp/authoring.js.map +1 -0
  13. package/dist/scp/bridge.d.ts +64 -0
  14. package/dist/scp/bridge.d.ts.map +1 -0
  15. package/dist/scp/bridge.js +329 -0
  16. package/dist/scp/bridge.js.map +1 -0
  17. package/dist/scp/catalog.d.ts +91 -0
  18. package/dist/scp/catalog.d.ts.map +1 -0
  19. package/dist/scp/catalog.js +203 -0
  20. package/dist/scp/catalog.js.map +1 -0
  21. package/dist/scp/codegen.d.ts +131 -0
  22. package/dist/scp/codegen.d.ts.map +1 -0
  23. package/dist/scp/codegen.js +137 -0
  24. package/dist/scp/codegen.js.map +1 -0
  25. package/dist/scp/compile-dialect.d.ts +39 -0
  26. package/dist/scp/compile-dialect.d.ts.map +1 -0
  27. package/dist/scp/compile-dialect.js +62 -0
  28. package/dist/scp/compile-dialect.js.map +1 -0
  29. package/dist/scp/compile-sqlite.d.ts +114 -0
  30. package/dist/scp/compile-sqlite.d.ts.map +1 -0
  31. package/dist/scp/compile-sqlite.js +149 -0
  32. package/dist/scp/compile-sqlite.js.map +1 -0
  33. package/dist/scp/dialect.d.ts +141 -0
  34. package/dist/scp/dialect.d.ts.map +1 -0
  35. package/dist/scp/dialect.js +194 -0
  36. package/dist/scp/dialect.js.map +1 -0
  37. package/dist/scp/errors.d.ts +36 -0
  38. package/dist/scp/errors.d.ts.map +1 -0
  39. package/dist/scp/errors.js +72 -0
  40. package/dist/scp/errors.js.map +1 -0
  41. package/dist/scp/guard.d.ts +47 -0
  42. package/dist/scp/guard.d.ts.map +1 -0
  43. package/dist/scp/guard.js +137 -0
  44. package/dist/scp/guard.js.map +1 -0
  45. package/dist/scp/index.cjs +4744 -0
  46. package/dist/scp/index.d.ts +49 -0
  47. package/dist/scp/index.d.ts.map +1 -0
  48. package/dist/scp/index.js +164 -0
  49. package/dist/scp/index.js.map +1 -0
  50. package/dist/scp/index.mjs +2000 -0
  51. package/dist/scp/ir.d.ts +92 -0
  52. package/dist/scp/ir.d.ts.map +1 -0
  53. package/dist/scp/ir.js +28 -0
  54. package/dist/scp/ir.js.map +1 -0
  55. package/dist/scp/relation.d.ts +136 -0
  56. package/dist/scp/relation.d.ts.map +1 -0
  57. package/dist/scp/relation.js +191 -0
  58. package/dist/scp/relation.js.map +1 -0
  59. package/dist/scp/render.d.ts +40 -0
  60. package/dist/scp/render.d.ts.map +1 -0
  61. package/dist/scp/render.js +170 -0
  62. package/dist/scp/render.js.map +1 -0
  63. package/dist/scp/runtime.d.ts +295 -0
  64. package/dist/scp/runtime.d.ts.map +1 -0
  65. package/dist/scp/runtime.js +665 -0
  66. package/dist/scp/runtime.js.map +1 -0
  67. package/dist/scp/typed-object.d.ts +88 -0
  68. package/dist/scp/typed-object.d.ts.map +1 -0
  69. package/dist/scp/typed-object.js +163 -0
  70. package/dist/scp/typed-object.js.map +1 -0
  71. package/dist/scp/write-plan.d.ts +161 -0
  72. package/dist/scp/write-plan.d.ts.map +1 -0
  73. package/dist/scp/write-plan.js +528 -0
  74. package/dist/scp/write-plan.js.map +1 -0
  75. package/dist/scp/write-runtime.d.ts +80 -0
  76. package/dist/scp/write-runtime.d.ts.map +1 -0
  77. package/dist/scp/write-runtime.js +167 -0
  78. package/dist/scp/write-runtime.js.map +1 -0
  79. package/dist/scp/writes.d.ts +251 -0
  80. package/dist/scp/writes.d.ts.map +1 -0
  81. package/dist/scp/writes.js +176 -0
  82. package/dist/scp/writes.js.map +1 -0
  83. package/docs/proposal/contracts-architecture-feasibility.md +328 -0
  84. package/docs/proposal/contracts-architecture.md +579 -0
  85. package/docs/proposal/litedbmodel-v2-scp-architecture.md +382 -0
  86. package/docs/proposal/sql-dynamic-expansion-spec.md +175 -0
  87. package/package.json +27 -5
  88. package/docs/README_REVIEW.md +0 -23
@@ -0,0 +1,155 @@
1
+ /**
2
+ * litedbmodel v2 SCP — Authoring Parse (WS2, #22).
3
+ *
4
+ * The litedbmodel authoring surface (spec §2.4 / §7) and the SINGLE compile path
5
+ * (spec §9) that lowers BOTH the SCP declaration blocks and the eager public API into
6
+ * ONE internal Component-graph IR (behavior-contracts' portable JSON). This module is a
7
+ * thin SQL-backend consumer over bc's shared authoring layer (`SemanticBehavior` /
8
+ * `compileBehaviors` / `catalogComponents` — bc#24): litedbmodel supplies ONLY the
9
+ * Catalog ({@link LITEDBMODEL_CATALOG}) and the CQRS effect derivation; bc owns all
10
+ * composition, `$`-wiring, structured control (`when` / `.map`), expression lowering,
11
+ * plan derivation and the portability self-check (C2: "the difference is the catalog
12
+ * only"). It mirrors graphddb's `publishBehaviors` precedent exactly.
13
+ *
14
+ * ## Authoring surface (spec §2.4)
15
+ *
16
+ * - **Root = class**: a `SemanticBehavior` subclass (default) or an `@behavior`-marked
17
+ * class; each PUBLIC method is one root Behavior (= one component; name = method name).
18
+ * `#`-private / `_`-prefixed members are helpers and are not published. The marker is
19
+ * one-per-class and effect-agnostic — there is NO query/command vocabulary to author.
20
+ * - **Input Port** = the method's `$: In<...>` argument; **Output Port** = its return
21
+ * value; the internal DAG is derived from `$`-refs, `.map` and `when` wiring.
22
+ * - **Leaf vocabulary** = the Catalog only ({@link components} = `catalogComponents(
23
+ * LITEDBMODEL_CATALOG)` — `Select` / `Insert` / `Update` / `Delete` / `Fragment`). There
24
+ * is NO litedbmodel-local authoring vocabulary beyond the Catalog. Conditions/values are
25
+ * written with bc's expression builders (`eq` / `ne` / `coalesce` / …); `cond ? [...] :
26
+ * SKIP` is written as `when(cond, () => <fragment>)` — in a `where` port it lowers to a
27
+ * pure `{cond:[c, <frag>, null]}` Expression IR node (SKIP is the ABSENCE of the
28
+ * fragment when `c` is false — spec §7, WS1 render), NOT a new opcode. Native `?:` / `??`
29
+ * / `&&` are rejected by bc's source scan; use `when` / `coalesce` / `and`.
30
+ *
31
+ * ## CQRS effect (spec §2.4 — derived, never authored)
32
+ *
33
+ * Query vs Command is DERIVED from whether a lowered component references a write-Catalog
34
+ * primitive (`Insert` / `Update` / `Delete` / `Tx`), via {@link deriveContractEffect}
35
+ * (bc `classifyBehaviorEffect` over {@link WRITE_CATALOG_NAMES}). Class names carry no
36
+ * meaning.
37
+ *
38
+ * ## Single compile path (spec §9 — a real invariant)
39
+ *
40
+ * The eager public API ({@link compileEager}) does NOT interpret model metadata on a
41
+ * separate path. It synthesizes the SAME authoring (a one-method `SemanticBehavior`
42
+ * subclass) and runs it through the SAME {@link compileBehaviors}. `test/scp` pins that
43
+ * the eager path and the declaration path for an equivalent query produce byte-identical
44
+ * component IR.
45
+ */
46
+ import { type BehaviorClass, type Component, type ComponentGraphIR, type MapNode, type ComponentRefNode, type PortSchema, type Recorded } from 'behavior-contracts';
47
+ import { type CatalogName, type ContractEffect } from './catalog';
48
+ /**
49
+ * The litedbmodel leaf-component functions for the shared authoring surface —
50
+ * `catalogComponents(LITEDBMODEL_CATALOG)` bound once, lazily (so importing this module
51
+ * does not pay for the binding until authoring actually runs). Invoke them inside
52
+ * `SemanticBehavior` method bodies:
53
+ *
54
+ * ```ts
55
+ * const L = components();
56
+ * class PostBehaviors extends SemanticBehavior {
57
+ * PostSearch($: In<{ authorId: number; status?: string; since: string }>) {
58
+ * const posts = L.Select({ table: 'posts', select: ['id', 'author_id', 'title'],
59
+ * where: [ eq($.authorId, $.authorId),
60
+ * when(ne($.status, null), () => eq($.status, $.status)), // SKIP-optional
61
+ * ge($.since, $.since) ] });
62
+ * const authors = posts.map(($p: Recorded) =>
63
+ * L.Select({ table: 'users', select: ['id', 'name'], where: [ eq($p.author_id, $p.author_id) ] }));
64
+ * return { posts, authors };
65
+ * }
66
+ * }
67
+ * ```
68
+ *
69
+ * `Tx` is in the map but is `portableToIR: false`, so wiring it is rejected at record
70
+ * time — the atomic transaction envelope is a WS3 runtime concern, never authored.
71
+ */
72
+ export type ComponentFns = Record<CatalogName, (ports: Record<string, unknown>) => Recorded>;
73
+ /** The `catalogComponents(LITEDBMODEL_CATALOG)` leaf-function map (typed, memoized). */
74
+ export declare function components(): ComponentFns;
75
+ /**
76
+ * One published behavior method: the bc-lowered component (name = the method name) plus
77
+ * its graph-DERIVED CQRS effect (spec §2.4 — the classification source of truth is the
78
+ * component graph; there is no query/command vocabulary for the author to declare).
79
+ */
80
+ export interface BehaviorMethodSpec {
81
+ /** The method (= root Behavior = component) name. */
82
+ readonly name: string;
83
+ /** Graph-derived Query/Command classification (never author-declared). */
84
+ readonly effect: ContractEffect;
85
+ /** The lowered portable component (bc `compileBehaviors` output). */
86
+ readonly component: Component;
87
+ }
88
+ /**
89
+ * A resolved behavior contract — {@link publishBehaviors} output. Carries the whole
90
+ * bc-lowered {@link ComponentGraphIR} (directly consumable by WS3's runtime + WS1's
91
+ * backend-compile) and the per-method specs with their derived effects.
92
+ */
93
+ export interface BehaviorModelContract {
94
+ /** The authored class name (diagnostics only). */
95
+ readonly className: string;
96
+ /** The bc-lowered portable IR (all methods; the shared internal IR — spec §9). */
97
+ readonly ir: ComponentGraphIR;
98
+ /** The lowered components (`ir.components`, one per public method). */
99
+ readonly components: readonly Component[];
100
+ /** Method name → lowered component + derived effect. */
101
+ readonly methods: Readonly<Record<string, BehaviorMethodSpec>>;
102
+ }
103
+ /** Options passed through to bc `compileBehaviors` (additive; all optional). */
104
+ export interface PublishBehaviorsOptions {
105
+ /**
106
+ * Input Port schema overrides (method → port → schema): build-time evaluation derives
107
+ * port NAMES from `$` accesses, but TS types (`In<...>`) are erased at runtime, so a
108
+ * consumer that wants the IR to carry the declared type strings supplies them here.
109
+ */
110
+ readonly inputPorts?: Record<string, Record<string, PortSchema>>;
111
+ /** Plan concurrency recorded on the lowered components (bc default: 16). */
112
+ readonly concurrency?: number;
113
+ }
114
+ /**
115
+ * Publish an SCP declaration block: a `SemanticBehavior` (or `@behavior`) class whose
116
+ * public methods are the root Behaviors (spec §2.4). Lowers through the single compile
117
+ * path ({@link lowerBehaviorClass}).
118
+ *
119
+ * @throws bc `AuthoringFailure` for a non-declarative body (native control syntax,
120
+ * coercion, unknown/missing ports, …); an `Error` from the catalog validation for an
121
+ * undeclared dynamic port; a `PortabilityError` for a non-portable expression.
122
+ */
123
+ export declare function publishBehaviors(cls: BehaviorClass, options?: PublishBehaviorsOptions): BehaviorModelContract;
124
+ /**
125
+ * An eager authoring body: the composition a public-API call (`find` / `create` / …)
126
+ * would run, expressed in the SAME authoring vocabulary as a declaration-block method.
127
+ * `$` is the recorder Input Port and `L` is the litedbmodel leaf-component map
128
+ * ({@link components}); it returns the Output Port. Expression builders (`eq` /
129
+ * `coalesce` / …) and `when` MUST be used over `$` (they only work inside the recording
130
+ * frame) — never native `?:` / `??` / `&&`.
131
+ *
132
+ * The public API funnels here so its lowering shares one compiler with the declaration
133
+ * path (spec §9). It is installed AS the class method (below), so bc's source scan covers
134
+ * it in full — the eager path has the same fail-closed coverage as the declaration path.
135
+ */
136
+ export type EagerBehavior = ($: Recorded, L: ComponentFns) => unknown;
137
+ /**
138
+ * Compile an eager public-API call through the SINGLE compile path (spec §9). It does NOT
139
+ * interpret model metadata on a separate path: it synthesizes a one-method
140
+ * `SemanticBehavior` subclass whose single public method IS `fn` (with `L` bound), and
141
+ * runs it through the SAME {@link compileBehaviors} the declaration path uses.
142
+ * Consequently the eager path and an equivalent declaration method produce byte-identical
143
+ * component IR (pinned by the single-compile-path equivalence test in `test/scp/authoring.test.ts`).
144
+ *
145
+ * Because `fn` is installed AS the class method (not delegated to via a closure), bc's
146
+ * source scan runs over `fn`'s own source — native control syntax inside `fn` is rejected
147
+ * fail-closed exactly as in a declaration block (no unscanned-thunk residual). The
148
+ * synthesized method is named `name` so the emitted component name matches a
149
+ * declaration-block method of the same name (byte-identity requires equal names).
150
+ *
151
+ * @throws the same failures as {@link publishBehaviors} (single path, single guard).
152
+ */
153
+ export declare function compileEager(name: string, fn: EagerBehavior, options?: PublishBehaviorsOptions): BehaviorModelContract;
154
+ export type { Component, ComponentGraphIR, MapNode, ComponentRefNode };
155
+ //# sourceMappingURL=authoring.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authoring.d.ts","sourceRoot":"","sources":["../../src/scp/authoring.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4CG;AAEH,OAAO,EAIL,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,gBAAgB,EACrB,KAAK,OAAO,EACZ,KAAK,gBAAgB,EACrB,KAAK,UAAU,EACf,KAAK,QAAQ,EACd,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAIL,KAAK,WAAW,EAChB,KAAK,cAAc,EACpB,MAAM,WAAW,CAAC;AAGnB;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,MAAM,MAAM,YAAY,GAAG,MAAM,CAAC,WAAW,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;AAI7F,wFAAwF;AACxF,wBAAgB,UAAU,IAAI,YAAY,CAKzC;AAED;;;;GAIG;AACH,MAAM,WAAW,kBAAkB;IACjC,qDAAqD;IACrD,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,0EAA0E;IAC1E,QAAQ,CAAC,MAAM,EAAE,cAAc,CAAC;IAChC,qEAAqE;IACrE,QAAQ,CAAC,SAAS,EAAE,SAAS,CAAC;CAC/B;AAED;;;;GAIG;AACH,MAAM,WAAW,qBAAqB;IACpC,kDAAkD;IAClD,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,kFAAkF;IAClF,QAAQ,CAAC,EAAE,EAAE,gBAAgB,CAAC;IAC9B,uEAAuE;IACvE,QAAQ,CAAC,UAAU,EAAE,SAAS,SAAS,EAAE,CAAC;IAC1C,wDAAwD;IACxD,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAAC,CAAC;CAChE;AAED,gFAAgF;AAChF,MAAM,WAAW,uBAAuB;IACtC;;;;OAIG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,CAAC;IACjE,4EAA4E;IAC5E,QAAQ,CAAC,WAAW,CAAC,EAAE,MAAM,CAAC;CAC/B;AA+CD;;;;;;;;GAQG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,aAAa,EAClB,OAAO,GAAE,uBAA4B,GACpC,qBAAqB,CAEvB;AAID;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,aAAa,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,CAAC,EAAE,YAAY,KAAK,OAAO,CAAC;AAEtE;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,aAAa,EACjB,OAAO,GAAE,uBAA4B,GACpC,qBAAqB,CAGvB;AA+BD,YAAY,EAAE,SAAS,EAAE,gBAAgB,EAAE,OAAO,EAAE,gBAAgB,EAAE,CAAC"}
@@ -0,0 +1,162 @@
1
+ "use strict";
2
+ /**
3
+ * litedbmodel v2 SCP — Authoring Parse (WS2, #22).
4
+ *
5
+ * The litedbmodel authoring surface (spec §2.4 / §7) and the SINGLE compile path
6
+ * (spec §9) that lowers BOTH the SCP declaration blocks and the eager public API into
7
+ * ONE internal Component-graph IR (behavior-contracts' portable JSON). This module is a
8
+ * thin SQL-backend consumer over bc's shared authoring layer (`SemanticBehavior` /
9
+ * `compileBehaviors` / `catalogComponents` — bc#24): litedbmodel supplies ONLY the
10
+ * Catalog ({@link LITEDBMODEL_CATALOG}) and the CQRS effect derivation; bc owns all
11
+ * composition, `$`-wiring, structured control (`when` / `.map`), expression lowering,
12
+ * plan derivation and the portability self-check (C2: "the difference is the catalog
13
+ * only"). It mirrors graphddb's `publishBehaviors` precedent exactly.
14
+ *
15
+ * ## Authoring surface (spec §2.4)
16
+ *
17
+ * - **Root = class**: a `SemanticBehavior` subclass (default) or an `@behavior`-marked
18
+ * class; each PUBLIC method is one root Behavior (= one component; name = method name).
19
+ * `#`-private / `_`-prefixed members are helpers and are not published. The marker is
20
+ * one-per-class and effect-agnostic — there is NO query/command vocabulary to author.
21
+ * - **Input Port** = the method's `$: In<...>` argument; **Output Port** = its return
22
+ * value; the internal DAG is derived from `$`-refs, `.map` and `when` wiring.
23
+ * - **Leaf vocabulary** = the Catalog only ({@link components} = `catalogComponents(
24
+ * LITEDBMODEL_CATALOG)` — `Select` / `Insert` / `Update` / `Delete` / `Fragment`). There
25
+ * is NO litedbmodel-local authoring vocabulary beyond the Catalog. Conditions/values are
26
+ * written with bc's expression builders (`eq` / `ne` / `coalesce` / …); `cond ? [...] :
27
+ * SKIP` is written as `when(cond, () => <fragment>)` — in a `where` port it lowers to a
28
+ * pure `{cond:[c, <frag>, null]}` Expression IR node (SKIP is the ABSENCE of the
29
+ * fragment when `c` is false — spec §7, WS1 render), NOT a new opcode. Native `?:` / `??`
30
+ * / `&&` are rejected by bc's source scan; use `when` / `coalesce` / `and`.
31
+ *
32
+ * ## CQRS effect (spec §2.4 — derived, never authored)
33
+ *
34
+ * Query vs Command is DERIVED from whether a lowered component references a write-Catalog
35
+ * primitive (`Insert` / `Update` / `Delete` / `Tx`), via {@link deriveContractEffect}
36
+ * (bc `classifyBehaviorEffect` over {@link WRITE_CATALOG_NAMES}). Class names carry no
37
+ * meaning.
38
+ *
39
+ * ## Single compile path (spec §9 — a real invariant)
40
+ *
41
+ * The eager public API ({@link compileEager}) does NOT interpret model metadata on a
42
+ * separate path. It synthesizes the SAME authoring (a one-method `SemanticBehavior`
43
+ * subclass) and runs it through the SAME {@link compileBehaviors}. `test/scp` pins that
44
+ * the eager path and the declaration path for an equivalent query produce byte-identical
45
+ * component IR.
46
+ */
47
+ Object.defineProperty(exports, "__esModule", { value: true });
48
+ exports.components = components;
49
+ exports.publishBehaviors = publishBehaviors;
50
+ exports.compileEager = compileEager;
51
+ const behavior_contracts_1 = require("behavior-contracts");
52
+ const catalog_1 = require("./catalog");
53
+ const guard_1 = require("./guard");
54
+ let boundComponents;
55
+ /** The `catalogComponents(LITEDBMODEL_CATALOG)` leaf-function map (typed, memoized). */
56
+ function components() {
57
+ if (boundComponents === undefined) {
58
+ boundComponents = (0, behavior_contracts_1.catalogComponents)(catalog_1.LITEDBMODEL_CATALOG);
59
+ }
60
+ return boundComponents;
61
+ }
62
+ /**
63
+ * The single lowering core (spec §9): bc `compileBehaviors` → litedbmodel catalog check →
64
+ * litedbmodel portability guard → CQRS effect derivation. BOTH {@link publishBehaviors}
65
+ * (declaration path) and {@link compileEager} (eager public-API path) call this so there
66
+ * is exactly one compile path and one guard application.
67
+ *
68
+ * Pipeline (all loud, nothing dropped):
69
+ * 1. bc `compileBehaviors(cls)` lowers every public method into one portable component
70
+ * (bc owns ALL composition/lowering and runs its own `assertPortableComponentGraph`);
71
+ * 2. {@link assertComponentsInCatalog} validates every lowered component against
72
+ * `LITEDBMODEL_CATALOG` — the SAME check the WS1 emitter path uses (covers the
73
+ * dynamic `values.<field>` / `set.<field>` write families bc's static schema check
74
+ * cannot enumerate);
75
+ * 3. {@link assertComponentGraphPortable} AUTO-APPLIES litedbmodel's portability guard
76
+ * over every port Expression IR node (WS2 AC — the lower path rejects any opcode
77
+ * outside bc's closed set fail-closed, independently of bc's own self-check);
78
+ * 4. the CQRS effect of every method is DERIVED from its graph
79
+ * ({@link deriveContractEffect}); the author never declares it.
80
+ */
81
+ function lowerBehaviorClass(cls, options) {
82
+ const ir = (0, behavior_contracts_1.compileBehaviors)(cls, {
83
+ ...(options.inputPorts !== undefined ? { inputPorts: options.inputPorts } : {}),
84
+ ...(options.concurrency !== undefined ? { concurrency: options.concurrency } : {}),
85
+ });
86
+ (0, catalog_1.assertComponentsInCatalog)(ir.components);
87
+ (0, guard_1.assertComponentGraphPortable)(ir);
88
+ const methods = {};
89
+ for (const component of ir.components) {
90
+ methods[component.name] = {
91
+ name: component.name,
92
+ effect: (0, catalog_1.deriveContractEffect)(component),
93
+ component,
94
+ };
95
+ }
96
+ return {
97
+ className: cls.name ?? '<anonymous>',
98
+ ir,
99
+ components: ir.components,
100
+ methods,
101
+ };
102
+ }
103
+ /**
104
+ * Publish an SCP declaration block: a `SemanticBehavior` (or `@behavior`) class whose
105
+ * public methods are the root Behaviors (spec §2.4). Lowers through the single compile
106
+ * path ({@link lowerBehaviorClass}).
107
+ *
108
+ * @throws bc `AuthoringFailure` for a non-declarative body (native control syntax,
109
+ * coercion, unknown/missing ports, …); an `Error` from the catalog validation for an
110
+ * undeclared dynamic port; a `PortabilityError` for a non-portable expression.
111
+ */
112
+ function publishBehaviors(cls, options = {}) {
113
+ return lowerBehaviorClass(cls, options);
114
+ }
115
+ /**
116
+ * Compile an eager public-API call through the SINGLE compile path (spec §9). It does NOT
117
+ * interpret model metadata on a separate path: it synthesizes a one-method
118
+ * `SemanticBehavior` subclass whose single public method IS `fn` (with `L` bound), and
119
+ * runs it through the SAME {@link compileBehaviors} the declaration path uses.
120
+ * Consequently the eager path and an equivalent declaration method produce byte-identical
121
+ * component IR (pinned by the single-compile-path equivalence test in `test/scp/authoring.test.ts`).
122
+ *
123
+ * Because `fn` is installed AS the class method (not delegated to via a closure), bc's
124
+ * source scan runs over `fn`'s own source — native control syntax inside `fn` is rejected
125
+ * fail-closed exactly as in a declaration block (no unscanned-thunk residual). The
126
+ * synthesized method is named `name` so the emitted component name matches a
127
+ * declaration-block method of the same name (byte-identity requires equal names).
128
+ *
129
+ * @throws the same failures as {@link publishBehaviors} (single path, single guard).
130
+ */
131
+ function compileEager(name, fn, options = {}) {
132
+ const cls = makeEagerClass(name, fn);
133
+ return lowerBehaviorClass(cls, options);
134
+ }
135
+ /**
136
+ * Build a one-method `SemanticBehavior` subclass whose PUBLIC method is named `name` and
137
+ * IS `fn` bound to the litedbmodel leaf map. bc records the method with a recorder `$`;
138
+ * `fn`'s source is what bc scans for native control syntax (full fail-closed coverage).
139
+ */
140
+ function makeEagerClass(name, fn) {
141
+ const L = components();
142
+ const cls = class extends behavior_contracts_1.SemanticBehavior {
143
+ };
144
+ // The method's source that bc scans is `fn.toString()` (via `method`), so native control
145
+ // syntax inside `fn` is rejected. `L` is bound by partial application, NOT closed over
146
+ // inside `fn`'s scanned body.
147
+ const method = function ($) {
148
+ return fn($, L);
149
+ };
150
+ // Make bc scan `fn`'s source (the authored body), not the trivial wrapper: expose `fn`'s
151
+ // source as the method's `toString`. bc's scanNativeControlSyntax reads `method.toString()`.
152
+ Object.defineProperty(method, 'toString', { value: () => fn.toString(), configurable: true });
153
+ Object.defineProperty(cls.prototype, name, {
154
+ value: method,
155
+ writable: true,
156
+ enumerable: false,
157
+ configurable: true,
158
+ });
159
+ Object.defineProperty(cls, 'name', { value: name, configurable: true });
160
+ return cls;
161
+ }
162
+ //# sourceMappingURL=authoring.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"authoring.js","sourceRoot":"","sources":["../../src/scp/authoring.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,64 @@
1
+ /**
2
+ * litedbmodel v2 SCP — the WS1↔WS3 Backend-Compile bridge (WS3, #23).
3
+ *
4
+ * WS2 (`authoring.ts`) produces the REAL behavior-contracts `ComponentGraphIR`: a
5
+ * Component's body carries `componentRef` / `map` nodes whose `ports` are Expression IR.
6
+ * The SQL-structural ports (`where`, `select`, `values.<field>`, `set.<field>`, `limit`,
7
+ * `order`, …) are NOT plain scalars — the `where` port is `{arr:[ <cond-expr>, … ]}` where
8
+ * a SKIP-optional condition is a pure `{cond:[c, <frag-expr>, null]}` node (WS2), and a
9
+ * comparison condition is a closed-set Expression `{eq:[<colRef>, <valueExpr>]}` (spec §7).
10
+ *
11
+ * WS1's Backend-Compile (`compile-sqlite.ts`) consumes a structured `SelectDesc` /
12
+ * `Condition[]`. NOTHING produced that shape from the real IR — this module closes that
13
+ * gap. It reads a raw `componentRef`/`map` node's ports directly and lowers them to WS1's
14
+ * `CompiledOperation` (SQL text + fragment tree + static param slots), performing the
15
+ * **SKIP → fragment-existence collapse**: a `{cond:[c, frag, null]}` where-member becomes a
16
+ * fragment guarded by `when: c` (present iff `c` is present), exactly the existence rule
17
+ * `render.ts` implements (dynamic-expansion spec §2). This is the single place that maps
18
+ * the real bc port shape → WS1 compile input; WS1's compiler is unchanged (its golden
19
+ * SQL text is the pinned bar) and now has a producer for its `SelectDesc`/`Condition`.
20
+ *
21
+ * ## WHERE condition interpretation (spec §7) — closed-set ONLY
22
+ *
23
+ * SKIP existence, IN-list membership and IS NULL are **fragment structure, NOT Expression
24
+ * IR opcodes** (catalog `where` port type is `fragment`; bc `expression-ir.md` §4: SKIP is
25
+ * OUTSIDE Expression IR). But bc's authoring lowering (`compileBehaviors`) only emits
26
+ * closed-set Expression IR into a port, so every where-member arrives as a closed-set node.
27
+ * This bridge therefore reads them STRUCTURALLY into fragment kinds WITHOUT inventing any
28
+ * opcode (the hard rule): every member is one of bc's closed operators, decoded here.
29
+ *
30
+ * - `{eq:[<colRef>, null]}` → `{ kind:'isNull', column }` (SQL `col IS NULL`)
31
+ * - `{eq:[<colRef>, <valueExpr>]}` → `{ kind:'eq', column, value:<valueExpr> }`
32
+ * - `{eq:[{ref:[IN_SENTINEL, col]}, <arrExpr>]}` → `{ kind:'in', column, value:<arrExpr> }`
33
+ * - `{lt|le|gt|ge|ne:[<colRef>, v]}` → `{ kind:'cmp', column, op, value:v }`
34
+ * - `{and|or:[m1, m2, …]}` → a nested `{ kind:'group', connector, conditions }`
35
+ * - `{cond:[c, <member>, null]}` → the lowered `<member>` with `skipWhen: c` (SKIP)
36
+ *
37
+ * The LEFT operand of a comparison names the column (spec §7 `{ref:["author_id"]}`): its
38
+ * `ref` path's LAST segment is the column name. The RIGHT operand is the value slot — a
39
+ * closed-set Expression IR node bound at render time. The litedbmodel authoring helpers
40
+ * ({@link import('./authoring-sql')}) produce exactly these closed-set encodings, so the
41
+ * WS2 portability guard passes and this decoder round-trips them to the WS1 fragment tree.
42
+ */
43
+ /** The reserved column-ref path head that marks an IN-list membership (see module doc). */
44
+ export declare const IN_SENTINEL = "@in";
45
+ import type { Component, ComponentRefNode, MapNode } from './authoring';
46
+ import { type Dialect } from './dialect';
47
+ import type { CompiledOperation } from './ir';
48
+ /** A bc body node that references a catalog component (not a `cond` node). */
49
+ type RefLike = ComponentRefNode | MapNode;
50
+ /**
51
+ * Backend-Compile ONE catalog `componentRef`/`map` body node into a WS1
52
+ * {@link CompiledOperation}. This is the real IR → WS1 compile-input bridge for the
53
+ * SQL CRUD primitives.
54
+ */
55
+ export declare function compileNode(node: RefLike, dialect?: Dialect): CompiledOperation;
56
+ /**
57
+ * Backend-Compile every catalog node of a component into a `nodeId → CompiledOperation`
58
+ * map. `cond` nodes carry no catalog reference and are skipped (they are pure Expression,
59
+ * evaluated by bc's `runBehavior`). The thin runtime looks up a node's `CompiledOperation`
60
+ * by `ctx.nodeId` when its handler fires.
61
+ */
62
+ export declare function compileComponentNodes(component: Component, dialect?: Dialect): Map<string, CompiledOperation>;
63
+ export {};
64
+ //# sourceMappingURL=bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../../src/scp/bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAEH,2FAA2F;AAC3F,eAAO,MAAM,WAAW,QAAQ,CAAC;AAEjC,OAAO,KAAK,EAAE,SAAS,EAAE,gBAAgB,EAAE,OAAO,EAAE,MAAM,aAAa,CAAC;AAYxE,OAAO,EAAU,KAAK,OAAO,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,KAAK,EAAE,iBAAiB,EAAY,MAAM,MAAM,CAAC;AAExD,8EAA8E;AAC9E,KAAK,OAAO,GAAG,gBAAgB,GAAG,OAAO,CAAC;AAiN1C;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,OAAO,EAAE,OAAO,GAAE,OAAgB,GAAG,iBAAiB,CAkDvF;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,SAAS,EAAE,SAAS,EAAE,OAAO,GAAE,OAAgB,GAAG,GAAG,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAOrH"}