@githolon/dsl 0.1.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.
- package/LICENSE.md +36 -0
- package/compile_package.mjs +50 -0
- package/package.json +59 -0
- package/src/aggregate.ts +167 -0
- package/src/authoring.ts +119 -0
- package/src/build_package.ts +636 -0
- package/src/certified_read.ts +313 -0
- package/src/codegen_dart.ts +2732 -0
- package/src/codegen_dot.ts +466 -0
- package/src/codegen_provider_dart.ts +358 -0
- package/src/codegen_ts.ts +365 -0
- package/src/codegen_usda.ts +388 -0
- package/src/combined.ts +195 -0
- package/src/compile_engine.ts +567 -0
- package/src/compile_package_main.ts +496 -0
- package/src/compose.ts +317 -0
- package/src/count.ts +218 -0
- package/src/ctx.ts +57 -0
- package/src/derived.ts +138 -0
- package/src/directive.ts +306 -0
- package/src/drivers.ts +95 -0
- package/src/emits_guard.ts +123 -0
- package/src/engine_entry.ts +449 -0
- package/src/exists.ts +170 -0
- package/src/extremum.ts +227 -0
- package/src/fields.ts +291 -0
- package/src/framework/bootstrap.ts +22 -0
- package/src/framework/disclosure.ts +108 -0
- package/src/framework/domain_lifecycle.ts +108 -0
- package/src/framework/identity.ts +537 -0
- package/src/framework/impure_capability.ts +643 -0
- package/src/framework/rbac.ts +418 -0
- package/src/framework/repair.ts +150 -0
- package/src/framework/sync_lifecycle.ts +125 -0
- package/src/framework/workspace_invariant.ts +128 -0
- package/src/framework/workspaces.ts +817 -0
- package/src/index.ts +317 -0
- package/src/manifest.ts +947 -0
- package/src/ops.ts +145 -0
- package/src/ordered_read.ts +228 -0
- package/src/predicate.ts +203 -0
- package/src/query/compile.ts +0 -0
- package/src/query/relations.ts +144 -0
- package/src/query.ts +151 -0
- package/src/read.ts +54 -0
- package/src/relation.ts +189 -0
- package/src/report/csv.ts +54 -0
- package/src/report.ts +401 -0
- package/src/spatial.ts +115 -0
- package/src/sum.ts +194 -0
- package/src/usd.ts +563 -0
- package/src/wire.ts +149 -0
- package/src/wire_encode.ts +250 -0
package/src/sum.ts
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
// NOMOS — Nomos Sovereign: participants act · verify · remember LOCALLY; hosted
|
|
2
|
+
// remotes are replaceable custody/transport, not truth. ⇒ ONE Nomos GitHolon
|
|
3
|
+
// wasm32-wasip1 artifact {kernel · projection · embedded
|
|
4
|
+
// QuickJS engine} on V8 + WASI-shim, byte-identical everywhere. V8 = portability; the one
|
|
5
|
+
// wasm = determinism. No native, no wasmtime, no 2nd artifact, no domain-JS on bare V8.
|
|
6
|
+
// If a file isn't this / hosting this / authoring for this / proving this — it's gone.
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* `sum(id, field)` builder — the NUMERIC AGGREGATION sibling of `count`.
|
|
10
|
+
*
|
|
11
|
+
* A `sum` declares a NAMED, MAINTAINED running total of an `int`-kind field across
|
|
12
|
+
* every aggregate of the `of`-type (optionally filtered by a `.where(pred)` predicate
|
|
13
|
+
* and partitioned by a `.by(field)` group-by). The result is ONE number per group,
|
|
14
|
+
* maintained incrementally as the workspace folds — NEVER a `SUM(*)` scan (the same
|
|
15
|
+
* O(1) perf invariant as `count`).
|
|
16
|
+
*
|
|
17
|
+
* The TYPE-STATE mirrors `count.ts` exactly:
|
|
18
|
+
* `sum(id, field)` → `TypelessSum` (only `.of` available)
|
|
19
|
+
* `.of(agg)` → `Sum` builder (`.where`, `.by` available; grand-total usable)
|
|
20
|
+
* `.where(p)` → `Sum` with predicate baked in (`.by` still available)
|
|
21
|
+
* `.by(k)` → `SumDecl` (finished, grouped declaration)
|
|
22
|
+
*
|
|
23
|
+
* Both a bare `Sum` (grand-total) and a grouped `SumDecl` satisfy `AnySum` — what
|
|
24
|
+
* `DomainModule.sums` accepts. `finishSum` normalizes either to a `SumDecl`.
|
|
25
|
+
*
|
|
26
|
+
* VALIDATION RULE (manifest-load, not type-level): the `sumField` parameter MUST be
|
|
27
|
+
* an `int`-kind field of the `of`-aggregate. The DSL type system cannot enforce this
|
|
28
|
+
* at the `sum(id, sumField)` call site (the aggregate is not yet known), but
|
|
29
|
+
* `AggregateSchemas::parse` (readmodel/src/manifest.rs) performs a no-fallback reject
|
|
30
|
+
* if the field is absent or non-int on the declared aggregate.
|
|
31
|
+
*
|
|
32
|
+
* ORDER-SENSITIVE GUARDRAIL: sum exposes NO `.first`/`.take`/`.orderBy`. Same
|
|
33
|
+
* rationale as `count.ts`. Assert the absence; do NOT add dead methods (LAW 3).
|
|
34
|
+
*
|
|
35
|
+
* SUM-OF-0 AMBIGUITY (documented, acceptable for Slice 1): a group whose running
|
|
36
|
+
* total reaches 0 is pruned from the `sums` table and reads as 0 — indistinguishable
|
|
37
|
+
* from an absent group. A future `exists` primitive (Slice 2) handles the distinction.
|
|
38
|
+
*/
|
|
39
|
+
import type { AggregateHandle } from "./aggregate.js";
|
|
40
|
+
import type { Field } from "./fields.js";
|
|
41
|
+
import { type Predicate, type CanonicalPred, predBuilder, canonicalizePred } from "./predicate.js";
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* A FINISHED sum declaration (the read-engine's input shape, analogous to
|
|
45
|
+
* {@link CountDecl}): an id, the aggregate TYPE it tallies, the FIELD being summed,
|
|
46
|
+
* the OPTIONAL predicate, and the OPTIONAL group-by field.
|
|
47
|
+
*/
|
|
48
|
+
export interface SumDecl {
|
|
49
|
+
readonly id: string;
|
|
50
|
+
/** The aggregate TYPE id the sum tallies, e.g. `ListingAggregate`. */
|
|
51
|
+
readonly of: string;
|
|
52
|
+
/**
|
|
53
|
+
* The `int`-kind field being summed, e.g. `"quantity"` or `"itemValue"`. MUST
|
|
54
|
+
* be an `int`-kind field of the `of`-aggregate (validated at manifest-load).
|
|
55
|
+
*/
|
|
56
|
+
readonly sumField: string;
|
|
57
|
+
/**
|
|
58
|
+
* The optional predicate: ONLY aggregates satisfying this predicate contribute
|
|
59
|
+
* to the sum. ABSENT ⇒ every aggregate of the `of`-type is summed.
|
|
60
|
+
*/
|
|
61
|
+
readonly where?: CanonicalPred;
|
|
62
|
+
/**
|
|
63
|
+
* The group-by field name. ABSENT ⇒ a grand total across all (matching)
|
|
64
|
+
* aggregates of the `of`-type (one synthetic group).
|
|
65
|
+
*/
|
|
66
|
+
readonly by?: string;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* The `Sum` BUILDER: it has named its `of`-type (and summed field), so `.where(...)`
|
|
71
|
+
* and `.by(...)` are available. The `F` type parameter carries the `of`-aggregate's
|
|
72
|
+
* field map so `.where(p => p.field("status").eq("active"))` is keyof-checked.
|
|
73
|
+
*/
|
|
74
|
+
export interface Sum<F extends Record<string, Field> = Record<string, Field>> {
|
|
75
|
+
readonly id: string;
|
|
76
|
+
/** The aggregate TYPE id the sum tallies. */
|
|
77
|
+
readonly of: string;
|
|
78
|
+
/** The `int`-kind field being summed. */
|
|
79
|
+
readonly sumField: string;
|
|
80
|
+
/**
|
|
81
|
+
* Attach an optional PREDICATE: only aggregates satisfying the predicate contribute
|
|
82
|
+
* to the sum. Returns a new `Sum` with the predicate baked in; `.by(...)` is still
|
|
83
|
+
* available.
|
|
84
|
+
*/
|
|
85
|
+
where(fn: (p: ReturnType<typeof predBuilder<F>>) => Predicate<F>): Sum<F>;
|
|
86
|
+
/**
|
|
87
|
+
* Partition the sum by a GROUP-BY field. Every distinct value of `groupField`
|
|
88
|
+
* maintains its own running total. Returns a finished `SumDecl`.
|
|
89
|
+
*/
|
|
90
|
+
by(groupField: string): SumDecl;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
/**
|
|
94
|
+
* The INITIAL, un-typed sum — its ONLY method is `.of(...)`. A `sum(id, field)`
|
|
95
|
+
* without `.of(...)` cannot be used as a declaration: the aggregate type is not
|
|
96
|
+
* optional.
|
|
97
|
+
*/
|
|
98
|
+
export interface TypelessSum {
|
|
99
|
+
readonly id: string;
|
|
100
|
+
/** The `int`-kind field to sum. */
|
|
101
|
+
readonly sumField: string;
|
|
102
|
+
/**
|
|
103
|
+
* Declare the aggregate TYPE whose `sumField` values are summed. Takes a typed
|
|
104
|
+
* HANDLE (never a string id). Returns the `Sum` builder (the only shape exposing
|
|
105
|
+
* `.where` and `.by`), which is already a usable grand-total sum.
|
|
106
|
+
*/
|
|
107
|
+
of<F extends Record<string, Field>>(aggregate: AggregateHandle<string, F>): Sum<F>;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Either form a domain may declare in `DomainModule.sums`. `Sum<any>` for the same
|
|
112
|
+
* reason as `AnyCount = CountDecl | Count<any>`: `Sum<F>` is invariant in `F`
|
|
113
|
+
* (the `where` method), so `Sum<SpecificFields>` is not assignable to
|
|
114
|
+
* `Sum<Record<string,Field>>`. The consumer only accesses `id`/`of`/`sumField`/`by`
|
|
115
|
+
* string fields and the `_where` slot — it never calls `.where(fn)` — so `any` is safe.
|
|
116
|
+
*/
|
|
117
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
118
|
+
export type AnySum = SumDecl | Sum<any>;
|
|
119
|
+
|
|
120
|
+
/** Narrow: a `Sum` builder exposes a `by` METHOD; a `SumDecl` does not. */
|
|
121
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
122
|
+
function isSumBuilder(s: AnySum): s is Sum<any> {
|
|
123
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
124
|
+
return typeof (s as Sum<any>).by === "function";
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Normalize an `AnySum` to a finished `SumDecl`. The grand-total builder (bare
|
|
129
|
+
* `.of(...)`) becomes `{id, of, sumField}` (no `by`); a grouped `.by(...)` result is
|
|
130
|
+
* already a `SumDecl` and passes through. A `.where(pred)` result transfers the
|
|
131
|
+
* canonical predicate.
|
|
132
|
+
*/
|
|
133
|
+
export function finishSum(s: AnySum): SumDecl {
|
|
134
|
+
if (isSumBuilder(s)) {
|
|
135
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
136
|
+
const b = s as any;
|
|
137
|
+
const w: CanonicalPred | undefined = b._where;
|
|
138
|
+
return {
|
|
139
|
+
id: b.id,
|
|
140
|
+
of: b.of,
|
|
141
|
+
sumField: b.sumField,
|
|
142
|
+
...(w !== undefined ? { where: w } : {}),
|
|
143
|
+
};
|
|
144
|
+
}
|
|
145
|
+
return s;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
/** Internal factory so `.where(...)` can return a new Sum without duplicating impl. */
|
|
149
|
+
function makeSum<F extends Record<string, Field>>(
|
|
150
|
+
id: string,
|
|
151
|
+
ofType: string,
|
|
152
|
+
sumField: string,
|
|
153
|
+
where: CanonicalPred | undefined,
|
|
154
|
+
): Sum<F> {
|
|
155
|
+
// Same exactOptionalPropertyTypes pattern as makeCount: spread `_where` only when
|
|
156
|
+
// defined so the key is absent (not `undefined`) in the predicate-free case.
|
|
157
|
+
const s = {
|
|
158
|
+
id,
|
|
159
|
+
of: ofType,
|
|
160
|
+
sumField,
|
|
161
|
+
...(where !== undefined ? { _where: where } : {}),
|
|
162
|
+
where(fn: (p: ReturnType<typeof predBuilder<F>>) => Predicate<F>): Sum<F> {
|
|
163
|
+
const pred = fn(predBuilder<F>());
|
|
164
|
+
const canonical = canonicalizePred(pred as Predicate<Record<string, Field>>);
|
|
165
|
+
return makeSum<F>(id, ofType, sumField, canonical);
|
|
166
|
+
},
|
|
167
|
+
by(groupField: string): SumDecl {
|
|
168
|
+
return {
|
|
169
|
+
id,
|
|
170
|
+
of: ofType,
|
|
171
|
+
sumField,
|
|
172
|
+
...(where !== undefined ? { where } : {}),
|
|
173
|
+
by: groupField,
|
|
174
|
+
};
|
|
175
|
+
},
|
|
176
|
+
} as unknown as Sum<F>;
|
|
177
|
+
return s;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/**
|
|
181
|
+
* Begin a sum declaration. `id` is the sum's canonical name (e.g.
|
|
182
|
+
* `"totalItemValuePerSite"`); `sumField` is the `int`-kind field on the `of`-aggregate
|
|
183
|
+
* whose values are accumulated. Returns a `TypelessSum`: until `.of(aggregate)` is
|
|
184
|
+
* called, the aggregate type is unknown and no usable declaration exists.
|
|
185
|
+
*/
|
|
186
|
+
export function sum(id: string, sumField: string): TypelessSum {
|
|
187
|
+
return {
|
|
188
|
+
id,
|
|
189
|
+
sumField,
|
|
190
|
+
of<F extends Record<string, Field>>(aggregate: AggregateHandle<string, F>): Sum<F> {
|
|
191
|
+
return makeSum<F>(id, aggregate.id, sumField, undefined);
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
}
|