graphddb 0.8.0 → 0.9.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.
@@ -0,0 +1,217 @@
1
+ import { Recorded, Component, ComponentGraphIR, PortSchema, BehaviorClass } from 'behavior-contracts';
2
+
3
+ /**
4
+ * GraphDDB's first-class SCP catalog — issue #297 SP1 (SCP authoring adoption),
5
+ * promoting the Phase-1 executor catalog (#288, `src/executor/catalog.ts`) into
6
+ * THE behavior-contracts–typed catalog the spec emitter is validated against.
7
+ *
8
+ * ## Source of truth (SP1 decision)
9
+ *
10
+ * ONE catalog lives here, in the spec layer — the layer that emits `components[]`
11
+ * (`src/spec/components.ts`) — and `src/executor/catalog.ts` re-exports it
12
+ * unchanged (the C4 handler registry keeps resolving against the same object).
13
+ * The Phase-1 module described itself as the C2 "the only per-DSL difference is
14
+ * the catalog" surface but its Port schemas mirrored the OLD-path executor
15
+ * inputs (`DynamoDBOperation` / `PutInput`), written before the Phase-3 emitter
16
+ * existed. Since #290 P3-5 the portable IR's actual wiring is the emitted
17
+ * component-graph ports, so promoting the catalog to LOAD-BEARING means the
18
+ * schemas here describe the EMITTED Port contract (what `readPorts` /
19
+ * `transactionItemPorts` in `components.ts` actually wire, and what a
20
+ * `runBehavior` handler actually receives) — the two latent Phase-1↔Phase-3
21
+ * inconsistencies are fixed loudly, not papered over:
22
+ *
23
+ * 1. **`ConditionCheck` was missing.** The emitter has emitted `ConditionCheck`
24
+ * componentRefs since Phase 3 (`buildTransactionComponent`), but the Phase-1
25
+ * catalog declared only 7 entries without it — so the "catalog" did not cover
26
+ * the emitted vocabulary. It is now a first-class entry.
27
+ * 2. **`TransactWrite` is not portable.** No portable document references
28
+ * `TransactWrite` (a transaction is emitted as a Component whose body
29
+ * references the per-item write primitives; the atomic TransactWriteItems
30
+ * envelope is the TS runtime's execution concern) — so its Phase-1
31
+ * `portableToIR: true` claim was false since P3-5. It stays a catalog entry
32
+ * (the executor-side atomic envelope, and a member of the write set) but is
33
+ * now honestly `portableToIR: false`.
34
+ *
35
+ * ## Port schema conventions
36
+ *
37
+ * A `CatalogEntry.inputPorts` names the STATIC ports of the emitted wiring. Two
38
+ * port families are dynamic by construction and are validated by
39
+ * {@link assertComponentsInCatalog} against documented patterns instead:
40
+ *
41
+ * - **Read key-attribute ports**: one port per `keyExpr` attribute, named by the
42
+ * physical key attribute — graphddb's fixed single-table convention
43
+ * `PK` / `SK` / `<index>PK` / `<index>SK` ({@link KEY_ATTR_PORT}).
44
+ * - **Write record ports**: a transaction item's `item` / `key` / `changes` /
45
+ * `add` records and the `condition.equals` / `condition.params` /
46
+ * `condition.values` slots are flattened one-port-per-field under a
47
+ * `<group>.<field>` key ({@link WRITE_PORT_FAMILIES}).
48
+ *
49
+ * ## Dynamic-port opt-in (`additionalPorts`, SP3)
50
+ *
51
+ * The seven read/write-item entries carry `additionalPorts: true` (bc#26): their
52
+ * dynamic port families above are BY DESIGN not statically enumerable, so bc's
53
+ * shared port check (`checkPortNames` — used by both the `catalogComponents`
54
+ * authoring recorder and `buildComponentDefinition`) must not reject them. This
55
+ * is an honest declaration, not a loosening: the dynamic families are still
56
+ * validated fail-closed by {@link assertComponentsInCatalog} (emit/registration
57
+ * time), and every DECLARED port keeps bc's required/type checks regardless of
58
+ * the opt-in. It is exactly this opt-in that makes `GRAPHDDB_CATALOG` directly
59
+ * consumable by the shared authoring surface (`catalogComponents(GRAPHDDB_CATALOG)`,
60
+ * bc#24 / #297 SP3) — the C2 contract that the catalog IS the whole per-DSL
61
+ * difference. `TransactWrite` stays fail-closed (its one port is static).
62
+ *
63
+ * ## Write set (SP1b) — and where `ConditionCheck` sits
64
+ *
65
+ * {@link WRITE_CATALOG_NAMES} is the CQRS write catalog: `PutItem` /
66
+ * `UpdateItem` / `DeleteItem` / `TransactWrite` / `ConditionCheck`.
67
+ * `ConditionCheck` mutates nothing — but it is classified WRITE deliberately:
68
+ * it exists only inside `TransactWriteItems` (DynamoDB accepts it in no read
69
+ * API), it acquires the item's transactional lock, and its failure aborts the
70
+ * sibling writes. A component referencing it therefore can only ever execute on
71
+ * the command path — for effect ROUTING (which is all the write set decides,
72
+ * bc#24) it is command-side infrastructure, not a read. The read set is exactly
73
+ * `GetItem` / `Query` / `BatchGetItem`; every catalog name is in exactly one set.
74
+ */
75
+
76
+ /**
77
+ * The catalog-name literal union — one entry per DynamoDB primitive GraphDDB
78
+ * declares: the `ReadOperationType` (`GetItem` / `Query` / `BatchGetItem`) and
79
+ * `WriteOperationType` (`PutItem` / `UpdateItem` / `DeleteItem`) enum members
80
+ * from `src/spec/types.ts`, the transaction-item assertion primitive
81
+ * (`ConditionCheck`), and the atomic envelope (`TransactWrite`).
82
+ */
83
+ type CatalogName = 'GetItem' | 'Query' | 'BatchGetItem' | 'PutItem' | 'UpdateItem' | 'DeleteItem' | 'ConditionCheck' | 'TransactWrite';
84
+ /** GraphDDB's CQRS effect vocabulary, mapped 1:1 from bc's `BehaviorEffect`. */
85
+ type ContractEffect = 'query' | 'command';
86
+
87
+ /**
88
+ * `publishBehaviors` — the shared-SCP authoring entry (issue #297 SP3; pairs
89
+ * graphddb with behavior-contracts bc#24 and connects to #296 P4-1).
90
+ *
91
+ * A user authors a **`SemanticBehavior` class** on behavior-contracts' SHARED
92
+ * authoring surface — `$` input wiring, `when` / `.map` structured control, the
93
+ * expression builders (`eq` / `concat` / `coalesce` / …), and the leaf
94
+ * components minted from graphddb's catalog via
95
+ * `catalogComponents(GRAPHDDB_CATALOG)` ({@link behaviorComponents}) — and
96
+ * publishes it here:
97
+ *
98
+ * ```ts
99
+ * import { graphddb, behaviorComponents } from 'graphddb';
100
+ * import { SemanticBehavior, concat, type In } from 'behavior-contracts';
101
+ *
102
+ * const G = behaviorComponents();
103
+ * class ArticleBehaviors extends SemanticBehavior {
104
+ * getArticleWithTags($: In<{ articleId: string }>) {
105
+ * const a = G.GetItem({ table: 'Articles', PK: concat('ARTICLE#', $.articleId), SK: 'META',
106
+ * projection: ['articleId', 'title', 'tagRefs'] });
107
+ * const tags = a.tagRefs.map(($t: Recorded) =>
108
+ * G.BatchGetItem({ table: 'Articles', PK: concat('TAG#', $t.tagId), SK: 'META',
109
+ * projection: ['tagId', 'label'] }), { batched: true });
110
+ * return { article: a, tags };
111
+ * }
112
+ * }
113
+ * const Articles = graphddb.publishBehaviors(ArticleBehaviors);
114
+ * ```
115
+ *
116
+ * ## Responsibility split (C2 — "the difference is the catalog only")
117
+ *
118
+ * - **behavior-contracts does ALL composition and lowering**: `compileBehaviors`
119
+ * evaluates each public method once (throwing-sentinel recording + native
120
+ * control-syntax source scan), lowers `$` references, component calls, `when`
121
+ * and `.map` into the portable component-graph IR, derives the plan, and
122
+ * self-checks the result with `assertPortableComponentGraph`. graphddb adds
123
+ * **no generic lowering of its own**.
124
+ * - **graphddb supplies only the catalog and the effects**: the leaf vocabulary
125
+ * is `GRAPHDDB_CATALOG` (#297 SP1 — the same load-bearing catalog the spec
126
+ * emitter is validated against), the dynamic port families are validated by
127
+ * the same {@link assertComponentsInCatalog}, and the Query/Command
128
+ * classification is DERIVED from the lowered graph per SP2/SP4
129
+ * ({@link deriveContractEffect}) — the author never declares an effect
130
+ * (authoring is effect-agnostic; a method that references a write-catalog
131
+ * primitive IS a command).
132
+ *
133
+ * The compiled components register additively into the operations document
134
+ * through `buildOperations`' `contractInputs.behaviors` (each component emitted
135
+ * as `<RegistrationKey>__<method>`), and the TS runtime executes them through
136
+ * bc's `runBehavior` with graphddb's real DynamoDB handlers
137
+ * (`src/executor/behavior-exec.ts` — the Phase-1 handler-registry seam's
138
+ * behavior-execution counterpart, mirroring `python/graphddb_runtime/behavior_exec.py`).
139
+ */
140
+
141
+ /**
142
+ * One published behavior method: the bc-lowered component (name = the method
143
+ * name), plus its graph-DERIVED CQRS effect (#297 SP2/SP4 — the classification
144
+ * source of truth is the component graph; `publishBehaviors` has no
145
+ * query/command vocabulary for the author to declare).
146
+ */
147
+ interface BehaviorMethodSpec {
148
+ /** The method (= root Behavior = component) name. */
149
+ readonly name: string;
150
+ /** Graph-derived Query/Command classification (never author-declared). */
151
+ readonly effect: ContractEffect;
152
+ /** The lowered portable component (bc `compileBehaviors` output). */
153
+ readonly component: Component;
154
+ }
155
+ /**
156
+ * A resolved behavior contract — `publishBehaviors` output. Carries the whole
157
+ * bc-lowered {@link ComponentGraphIR} (directly `runBehavior`-executable; the
158
+ * component names are the method names) and the per-method specs with their
159
+ * derived effects. Register it into the operations document via
160
+ * `buildOperations(..., { behaviors: { Name: contract } })`.
161
+ */
162
+ interface BehaviorModelContract {
163
+ /** Discriminates from the publishQuery/publishCommand contract objects. */
164
+ readonly kind: 'behaviors';
165
+ /** The authored class name (diagnostics only). */
166
+ readonly className: string;
167
+ /** The bc-lowered portable IR (all methods; `runBehavior`-executable). */
168
+ readonly ir: ComponentGraphIR;
169
+ /** The lowered components (`ir.components`, one per public method). */
170
+ readonly components: readonly Component[];
171
+ /** Method name → lowered component + derived effect. */
172
+ readonly methods: Readonly<Record<string, BehaviorMethodSpec>>;
173
+ }
174
+ /** Options passed through to bc `compileBehaviors` (additive; all optional). */
175
+ interface PublishBehaviorsOptions {
176
+ /**
177
+ * Input Port schema overrides (method → port → schema): build-time evaluation
178
+ * derives port NAMES from `$` accesses; TS types are erased, so supply the
179
+ * type strings here if the registered document should carry them.
180
+ */
181
+ readonly inputPorts?: Record<string, Record<string, PortSchema>>;
182
+ /** Plan concurrency recorded on the lowered components (bc default: 16). */
183
+ readonly concurrency?: number;
184
+ }
185
+ /** The `catalogComponents(GRAPHDDB_CATALOG)` leaf-function map (typed). */
186
+ type BehaviorComponentFns = Record<CatalogName, (ports: Record<string, unknown>) => Recorded>;
187
+ /**
188
+ * The graphddb leaf components for the shared authoring surface:
189
+ * `catalogComponents(GRAPHDDB_CATALOG)` bound once, lazily. Call it at module
190
+ * scope of an authoring module (`const G = behaviorComponents()`) and invoke
191
+ * the leaves inside `SemanticBehavior` method bodies. `TransactWrite` is in the
192
+ * map but is `portableToIR: false`, so wiring it is rejected at record time —
193
+ * the atomic envelope is a TS-runtime execution concern, never authored.
194
+ */
195
+ declare function behaviorComponents(): BehaviorComponentFns;
196
+ /**
197
+ * Publish a `SemanticBehavior` class as a graphddb behavior contract (#297 SP3).
198
+ *
199
+ * Pipeline (all loud, nothing dropped):
200
+ * 1. bc `compileBehaviors(cls)` lowers every public method into one portable
201
+ * component (bc owns ALL composition/lowering and self-checks portability);
202
+ * 2. graphddb validates every lowered component against `GRAPHDDB_CATALOG` —
203
+ * the SAME {@link assertComponentsInCatalog} the spec emitter runs (SP1c),
204
+ * covering the dynamic key-attribute / write record-family ports bc's
205
+ * static schema check cannot enumerate;
206
+ * 3. the CQRS effect of every method is DERIVED from its graph
207
+ * ({@link deriveContractEffect} — SP2/SP4; the author never declares it).
208
+ *
209
+ * @throws bc `AuthoringFailure` for a non-declarative body (native control
210
+ * syntax, coercion, unknown/missing ports, …); an `Error` from the catalog
211
+ * validation for an undeclared dynamic port.
212
+ */
213
+ declare function publishBehaviors(cls: BehaviorClass, options?: PublishBehaviorsOptions): BehaviorModelContract;
214
+ /** Runtime guard: is `value` a {@link BehaviorModelContract}? */
215
+ declare function isBehaviorModelContract(value: unknown): value is BehaviorModelContract;
216
+
217
+ export { type BehaviorModelContract as B, type PublishBehaviorsOptions as P, type BehaviorMethodSpec as a, type BehaviorComponentFns as b, behaviorComponents as c, isBehaviorModelContract as i, publishBehaviors as p };
@@ -1,7 +1,8 @@
1
- import { w as CdcEmulatorOptions, x as ChangeHandler, y as Unsubscribe, F as FaultSpec, z as ConcurrentRecomputeRef, v as ChangeEvent, A as EventLog, G as ReplayOptions, H as ShardId, I as MaintainTrigger, E as EffectPath, g as ProjectionMap, j as MembershipPredicate } from '../key-DR7_lpyk.js';
2
- export { J as BatchResult, K as CdcMode, L as ChangeBatch, N as ChangeEventName, O as ClockMode, V as StartingPosition, X as StreamViewType, Y as SubscribeHandler, Z as SubscribeHandlers, _ as buildSubscribeHandler } from '../key-DR7_lpyk.js';
3
- import { E as EntityMetadata } from '../types-BXLzIcQD.js';
4
- import '../types-2PMXEn5x.js';
1
+ import { w as CdcEmulatorOptions, x as ChangeHandler, y as Unsubscribe, F as FaultSpec, z as ConcurrentRecomputeRef, v as ChangeEvent, A as EventLog, G as ReplayOptions, H as ShardId, I as MaintainTrigger, E as EffectPath, g as ProjectionMap, j as MembershipPredicate } from '../key-Dne-a20Q.js';
2
+ export { J as BatchResult, K as CdcMode, L as ChangeBatch, N as ChangeEventName, O as ClockMode, V as StartingPosition, X as StreamViewType, Y as SubscribeHandler, Z as SubscribeHandlers, _ as buildSubscribeHandler } from '../key-Dne-a20Q.js';
3
+ import { E as EntityMetadata } from '../types-BnFsTZwl.js';
4
+ import '../types-CfxzTEFL.js';
5
+ import 'behavior-contracts';
5
6
 
6
7
  /**
7
8
  * CDC emulator (issue #72). Subscribes to the core write-capture seam
package/dist/cdc/index.js CHANGED
@@ -8,12 +8,12 @@ import {
8
8
  createMaintenanceDrainHandler,
9
9
  hashString,
10
10
  shardIdFor
11
- } from "../chunk-GS4C5VGO.js";
11
+ } from "../chunk-YGQ2NO6J.js";
12
12
  import {
13
13
  buildSubscribeHandler,
14
14
  parseChange
15
- } from "../chunk-HNY2EJPV.js";
16
- import "../chunk-L2NEDS7U.js";
15
+ } from "../chunk-KOIJ4SNO.js";
16
+ import "../chunk-ZNU7OI5I.js";
17
17
  import "../chunk-XTWXMOHD.js";
18
18
  export {
19
19
  CdcEmulator,
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  MetadataRegistry,
3
3
  attachHiddenKey
4
- } from "./chunk-L2NEDS7U.js";
4
+ } from "./chunk-ZNU7OI5I.js";
5
5
  import {
6
6
  resolveKey,
7
7
  segmentFieldNames
@@ -1,12 +1,12 @@
1
1
  import {
2
2
  evaluateKey
3
- } from "./chunk-I4LEJ4TF.js";
3
+ } from "./chunk-XZTA4VJH.js";
4
4
  import {
5
- SPEC_VERSION
6
- } from "./chunk-L4QRCHRQ.js";
5
+ SPEC_VERSION_KEY_EXPR
6
+ } from "./chunk-WOFRHRXY.js";
7
7
  import {
8
8
  MetadataRegistry
9
- } from "./chunk-L2NEDS7U.js";
9
+ } from "./chunk-ZNU7OI5I.js";
10
10
  import {
11
11
  TableMapping
12
12
  } from "./chunk-XTWXMOHD.js";
@@ -136,7 +136,9 @@ function buildManifest(registry = MetadataRegistry) {
136
136
  }
137
137
  }
138
138
  return {
139
- version: SPEC_VERSION,
139
+ // #289 Phase 2: the IR SSoT is version 2.0 (major bump); the manifest tracks
140
+ // the same major so validateEnvelope's major-match passes (see Manifest.version).
141
+ version: SPEC_VERSION_KEY_EXPR,
140
142
  tables: sortedRecord(tables),
141
143
  entities
142
144
  };