@githolon/dsl 0.103.12 → 0.103.13
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/dart/CHANGELOG.md +5 -0
- package/dart/lib/src/runner/node-entry.mjs +234 -170
- package/dart/lib/src/runner/offline-install.mjs +87 -112
- package/dart/lib/src/webview_bridge.dart +11 -11
- package/dart/pubspec.yaml +1 -1
- package/dart/test/webview_bridge_test.dart +10 -7
- package/dart_types/CHANGELOG.md +1 -1
- package/dart_types/lib/nomos_types.dart +4 -4
- package/dart_types/lib/src/versioned_nomos_ref.dart +13 -11
- package/package.json +1 -1
- package/runtime/generated-application-host.js +424 -237
- package/src/aggregate.ts +3 -1
- package/src/build_package.ts +77 -6
- package/src/check_package_main.ts +39 -16
- package/src/codegen_dart.ts +185 -48
- package/src/codegen_dart_application.ts +82 -16
- package/src/codegen_dart_client.ts +38 -10
- package/src/codegen_dot.ts +3 -3
- package/src/codegen_proof.ts +24 -2
- package/src/codegen_ts.ts +32 -19
- package/src/compile_package_main.ts +68 -11
- package/src/derived.ts +17 -0
- package/src/directive.ts +65 -0
- package/src/engine_entry.ts +22 -2
- package/src/enum_type.ts +71 -0
- package/src/fields.ts +135 -5
- package/src/flow_gate.ts +2 -1
- package/src/framework/workspaces.ts +73 -0
- package/src/idof_lint.ts +5 -1
- package/src/index.ts +20 -0
- package/src/kernel_capabilities.ts +12 -1
- package/src/law_check.ts +107 -28
- package/src/law_graph.ts +151 -20
- package/src/law_graph_usda.ts +23 -0
- package/src/law_value_type.ts +10 -3
- package/src/lsp_server.ts +26 -16
- package/src/package_config.ts +112 -9
- package/src/package_feature_topology.ts +174 -0
- package/src/plan_source_slice.ts +6 -0
- package/src/report.ts +6 -0
- package/src/stable_ids_for_module.ts +1 -0
- package/src/value_object.ts +9 -2
- package/src/workspace_sharding.ts +4 -4
|
@@ -19,6 +19,8 @@ import {
|
|
|
19
19
|
introspectPayload,
|
|
20
20
|
readModelClassName,
|
|
21
21
|
registerDartNames,
|
|
22
|
+
collectDartEnums,
|
|
23
|
+
dartEnumTypeForField,
|
|
22
24
|
} from "./codegen_dart.js";
|
|
23
25
|
import { dartClientClassName } from "./codegen_dart_client.js";
|
|
24
26
|
import { finishCount } from "./count.js";
|
|
@@ -109,7 +111,11 @@ function keyParam(key: string): string {
|
|
|
109
111
|
return safe(/^[0-9]/.test(cleaned) ? `v${cleaned}` : cleaned);
|
|
110
112
|
}
|
|
111
113
|
|
|
112
|
-
function keyType(
|
|
114
|
+
function keyType(
|
|
115
|
+
aggregate: AggregateHandle | undefined,
|
|
116
|
+
key: string,
|
|
117
|
+
enumDartTypes: ReadonlyMap<string, string>,
|
|
118
|
+
): string {
|
|
113
119
|
const first = key.includes(".") ? key.split(".")[0]! : key;
|
|
114
120
|
const field = aggregate?.fields[first] as Field | undefined;
|
|
115
121
|
if (field?.kind === "int" || field?.kind === "counter") return "int";
|
|
@@ -124,6 +130,8 @@ function keyType(aggregate: AggregateHandle | undefined, key: string): string {
|
|
|
124
130
|
if (field.refAggregateId !== undefined)
|
|
125
131
|
return `NomosRef<${concreteClassName(field.refAggregateId)}>`;
|
|
126
132
|
}
|
|
133
|
+
const enumType = dartEnumTypeForField(field, enumDartTypes);
|
|
134
|
+
if (enumType !== undefined) return enumType;
|
|
127
135
|
if (
|
|
128
136
|
field?.kind === "string" &&
|
|
129
137
|
isSha256DigestSchema(field.zod as z.ZodTypeAny)
|
|
@@ -392,6 +400,13 @@ export function generateDartApplication(
|
|
|
392
400
|
): string {
|
|
393
401
|
registerDartNames(mod.aggregates);
|
|
394
402
|
const domain = mod.domain ?? mod.name;
|
|
403
|
+
const enumDartTypes = collectDartEnums(
|
|
404
|
+
mod.aggregates,
|
|
405
|
+
mod.directives,
|
|
406
|
+
domain,
|
|
407
|
+
mod.valueObjects ?? [],
|
|
408
|
+
mod.deriveds ?? [],
|
|
409
|
+
).dartTypes;
|
|
395
410
|
const application = dartApplicationClassName(domain);
|
|
396
411
|
const activity = dartApplicationActivityClassName(domain);
|
|
397
412
|
const client = dartClientClassName(domain);
|
|
@@ -434,15 +449,15 @@ export function generateDartApplication(
|
|
|
434
449
|
);
|
|
435
450
|
if (hasVersionedRefs) {
|
|
436
451
|
claimApplicationMember(
|
|
437
|
-
"
|
|
452
|
+
"versionStatus",
|
|
438
453
|
"the generated versioned-reference boundary"
|
|
439
454
|
);
|
|
440
455
|
appLines.push(
|
|
441
456
|
` /// Check whether [reference]'s immutable publication is still current. This reads the`,
|
|
442
457
|
` /// stable series' one compiled pointer; it never reconstructs publication history.`,
|
|
443
|
-
` Future<
|
|
458
|
+
` Future<ReferenceVersionStatus<TVersion>> versionStatus<TVersion, TSeries>(`,
|
|
444
459
|
` VersionedNomosRef<TVersion, TSeries> reference) =>`,
|
|
445
|
-
` _client.
|
|
460
|
+
` _client.referenceVersionStatus(reference);`,
|
|
446
461
|
``
|
|
447
462
|
);
|
|
448
463
|
}
|
|
@@ -590,10 +605,21 @@ export function generateDartApplication(
|
|
|
590
605
|
(input) => input.idField
|
|
591
606
|
)
|
|
592
607
|
);
|
|
593
|
-
|
|
608
|
+
const targetBinding = directive.targetBinding;
|
|
609
|
+
const targetChecks = targetBinding === undefined
|
|
610
|
+
? []
|
|
611
|
+
: [
|
|
612
|
+
` _nmsRequireReference(target, ${JSON.stringify(
|
|
613
|
+
targetBinding.aggregateId
|
|
614
|
+
)}, _client.session?.workspace ?? '');`,
|
|
615
|
+
];
|
|
616
|
+
return [
|
|
617
|
+
...targetChecks,
|
|
618
|
+
...specs
|
|
594
619
|
.filter(
|
|
595
620
|
(spec) =>
|
|
596
621
|
(spec.toJson === "ref" || spec.toJson === "addressRef") &&
|
|
622
|
+
spec.name !== targetBinding?.field &&
|
|
597
623
|
!recordInputIds.has(spec.name)
|
|
598
624
|
)
|
|
599
625
|
.map((spec) => {
|
|
@@ -618,7 +644,8 @@ export function generateDartApplication(
|
|
|
618
644
|
targetWire
|
|
619
645
|
)}, ${expectedWorkspace}));`
|
|
620
646
|
: ` ${check}`;
|
|
621
|
-
})
|
|
647
|
+
}),
|
|
648
|
+
];
|
|
622
649
|
};
|
|
623
650
|
|
|
624
651
|
for (const aggregate of mod.aggregates) {
|
|
@@ -832,6 +859,9 @@ export function generateDartApplication(
|
|
|
832
859
|
// deriving the locator from the typed reference, rather than reaching for
|
|
833
860
|
// the deliberately removed raw workspace/id fields.
|
|
834
861
|
const factValue = (path: string): string => {
|
|
862
|
+
if (path === directive.targetBinding?.field) {
|
|
863
|
+
return "NmsInternalNomosRefs.id(target)";
|
|
864
|
+
}
|
|
835
865
|
if (!path.includes(".")) {
|
|
836
866
|
const workspaceOwner = foreignInputs.find(
|
|
837
867
|
(input) => input.workspaceField === path
|
|
@@ -850,8 +880,11 @@ export function generateDartApplication(
|
|
|
850
880
|
};
|
|
851
881
|
const trust = directive.businessSourceTrust;
|
|
852
882
|
const method = member(directive.id);
|
|
883
|
+
const call = directive.targetBinding === undefined
|
|
884
|
+
? `_client.${method}(facts)`
|
|
885
|
+
: `_client.${method}(target, facts)`;
|
|
853
886
|
if (trust === undefined) {
|
|
854
|
-
return { prelude: [], call
|
|
887
|
+
return { prelude: [], call };
|
|
855
888
|
}
|
|
856
889
|
const copied = Object.entries(trust.copy)
|
|
857
890
|
.sort(([a], [b]) => a.localeCompare(b))
|
|
@@ -875,7 +908,7 @@ export function generateDartApplication(
|
|
|
875
908
|
` },`,
|
|
876
909
|
` );`,
|
|
877
910
|
],
|
|
878
|
-
call
|
|
911
|
+
call,
|
|
879
912
|
};
|
|
880
913
|
};
|
|
881
914
|
|
|
@@ -923,6 +956,18 @@ export function generateDartApplication(
|
|
|
923
956
|
for (const [index, policy] of sharingPolicies.entries()) {
|
|
924
957
|
const pendingKey = policy.pending.key[0]!;
|
|
925
958
|
const pendingMethod = member(policy.pending.id);
|
|
959
|
+
const pendingAggregate = aggregates.get(policy.pending.returns);
|
|
960
|
+
const pendingField = pendingAggregate?.fields[pendingKey] as
|
|
961
|
+
| Field
|
|
962
|
+
| undefined;
|
|
963
|
+
const pendingValue =
|
|
964
|
+
pendingField?.kind === "enum"
|
|
965
|
+
? `${keyType(
|
|
966
|
+
pendingAggregate,
|
|
967
|
+
pendingKey,
|
|
968
|
+
enumDartTypes,
|
|
969
|
+
)}.fromWire(${JSON.stringify(policy.pendingValue)})`
|
|
970
|
+
: JSON.stringify(policy.pendingValue);
|
|
926
971
|
const person = sharingOrderValue(policy, policy.person, "wire");
|
|
927
972
|
const role = sharingOrderValue(policy, policy.role, "wire");
|
|
928
973
|
const scope = sharingOrderValue(policy, policy.scope, "wire");
|
|
@@ -992,7 +1037,7 @@ export function generateDartApplication(
|
|
|
992
1037
|
``,
|
|
993
1038
|
` Future<void> _nmsDrainWorkspaceSharingOnce${index}() async {`,
|
|
994
1039
|
` final orders = await _client.${pendingMethod}(`,
|
|
995
|
-
` ${member(pendingKey)}: ${
|
|
1040
|
+
` ${member(pendingKey)}: ${pendingValue},`,
|
|
996
1041
|
` );`,
|
|
997
1042
|
` for (final order in orders) {`,
|
|
998
1043
|
` late final ApplicationShareResult share;`,
|
|
@@ -1328,6 +1373,19 @@ export function generateDartApplication(
|
|
|
1328
1373
|
|
|
1329
1374
|
const method = member(directive.id);
|
|
1330
1375
|
const payload = dartActionInputClassName(directive);
|
|
1376
|
+
const targetOnly = directive.targetBinding !== undefined &&
|
|
1377
|
+
introspectPayload(directive.payloadSchema as z.ZodTypeAny, new Map()).every(
|
|
1378
|
+
(spec) =>
|
|
1379
|
+
spec.name === directive.targetBinding?.field ||
|
|
1380
|
+
spec.name === directive.businessPrincipalField,
|
|
1381
|
+
) &&
|
|
1382
|
+
(directive.businessRecordInputs?.length ?? 0) === 0;
|
|
1383
|
+
const targetParameter = directive.targetBinding === undefined
|
|
1384
|
+
? `${payload} facts`
|
|
1385
|
+
: targetOnly
|
|
1386
|
+
? `NomosRef<${concreteClassName(directive.targetBinding.aggregateId)}> target`
|
|
1387
|
+
: `NomosRef<${concreteClassName(directive.targetBinding.aggregateId)}> target, ${payload} facts`;
|
|
1388
|
+
const factsPrelude = targetOnly ? [` const facts = ${payload}();`] : [];
|
|
1331
1389
|
const referenceChecks = actionReferenceChecks(directive);
|
|
1332
1390
|
const outputs = dartActionOutputs(directive, mod.aggregates);
|
|
1333
1391
|
const resultClass = dartActionResultClassName(directive.id);
|
|
@@ -1379,7 +1437,8 @@ export function generateDartApplication(
|
|
|
1379
1437
|
` /// ${cap(camel(directive.id))}. ${businessActionDoc(directive)}`,
|
|
1380
1438
|
` /// Canonical write path: pass business facts here; never mirror this action in application state`,
|
|
1381
1439
|
` /// or call a lower-level client.`,
|
|
1382
|
-
` Future<${resultClass}> ${method}(${
|
|
1440
|
+
` Future<${resultClass}> ${method}(${targetParameter}) async {`,
|
|
1441
|
+
...factsPrelude,
|
|
1383
1442
|
...referenceChecks,
|
|
1384
1443
|
...sourceTrust.prelude,
|
|
1385
1444
|
` final change = await ${sourceTrust.call};`,
|
|
@@ -1393,7 +1452,8 @@ export function generateDartApplication(
|
|
|
1393
1452
|
` /// ${cap(camel(directive.id))}. ${businessActionDoc(directive)}`,
|
|
1394
1453
|
` /// Canonical write path: pass business facts here; never mirror this action in application state`,
|
|
1395
1454
|
` /// or call a lower-level client.`,
|
|
1396
|
-
` Future<NomosOperationReceipt> ${method}(${
|
|
1455
|
+
` Future<NomosOperationReceipt> ${method}(${targetParameter}) async {`,
|
|
1456
|
+
...factsPrelude,
|
|
1397
1457
|
...referenceChecks,
|
|
1398
1458
|
...sourceTrust.prelude,
|
|
1399
1459
|
` final change = await ${sourceTrust.call};`,
|
|
@@ -1411,7 +1471,8 @@ export function generateDartApplication(
|
|
|
1411
1471
|
` /// ${cap(
|
|
1412
1472
|
camel(directive.id)
|
|
1413
1473
|
)}. Returns every affected typed business record reference.`,
|
|
1414
|
-
` Future<${resultClass}> ${method}(${
|
|
1474
|
+
` Future<${resultClass}> ${method}(${targetParameter}) async {`,
|
|
1475
|
+
...factsPrelude,
|
|
1415
1476
|
...referenceChecks,
|
|
1416
1477
|
...sourceTrust.prelude,
|
|
1417
1478
|
` final change = await ${sourceTrust.call};`,
|
|
@@ -1422,7 +1483,8 @@ export function generateDartApplication(
|
|
|
1422
1483
|
} else {
|
|
1423
1484
|
addCollectionMember(directive.aggregateId, method, [
|
|
1424
1485
|
` /// ${cap(camel(directive.id))}.`,
|
|
1425
|
-
` Future<NomosOperationReceipt> ${method}(${
|
|
1486
|
+
` Future<NomosOperationReceipt> ${method}(${targetParameter}) async {`,
|
|
1487
|
+
...factsPrelude,
|
|
1426
1488
|
...referenceChecks,
|
|
1427
1489
|
...sourceTrust.prelude,
|
|
1428
1490
|
` final change = await ${sourceTrust.call};`,
|
|
@@ -1458,7 +1520,7 @@ export function generateDartApplication(
|
|
|
1458
1520
|
const model = readModelClassName(query.returns);
|
|
1459
1521
|
const aggregate = aggregates.get(query.returns);
|
|
1460
1522
|
const params = query.key
|
|
1461
|
-
.map((key) => `required ${keyType(aggregate, key)} ${keyParam(key)}`)
|
|
1523
|
+
.map((key) => `required ${keyType(aggregate, key, enumDartTypes)} ${keyParam(key)}`)
|
|
1462
1524
|
.join(", ");
|
|
1463
1525
|
const args = query.key
|
|
1464
1526
|
.map((key) => `${keyParam(key)}: ${keyParam(key)}`)
|
|
@@ -1786,7 +1848,9 @@ export function generateDartApplication(
|
|
|
1786
1848
|
for (const count of (mod.counts ?? []).map((raw) => finishCount(raw))) {
|
|
1787
1849
|
const method = member(count.id);
|
|
1788
1850
|
const groupType =
|
|
1789
|
-
count.by == null
|
|
1851
|
+
count.by == null
|
|
1852
|
+
? ""
|
|
1853
|
+
: keyType(aggregates.get(count.of), count.by, enumDartTypes);
|
|
1790
1854
|
addCollectionMember(count.of, method, [
|
|
1791
1855
|
count.by == null
|
|
1792
1856
|
? ` Future<int> ${method}() => _client.${method}();`
|
|
@@ -1798,7 +1862,9 @@ export function generateDartApplication(
|
|
|
1798
1862
|
for (const sum of (mod.sums ?? []).map((raw) => finishSum(raw))) {
|
|
1799
1863
|
const method = member(sum.id);
|
|
1800
1864
|
const groupType =
|
|
1801
|
-
sum.by == null
|
|
1865
|
+
sum.by == null
|
|
1866
|
+
? ""
|
|
1867
|
+
: keyType(aggregates.get(sum.of), sum.by, enumDartTypes);
|
|
1802
1868
|
addCollectionMember(sum.of, method, [
|
|
1803
1869
|
sum.by == null
|
|
1804
1870
|
? ` Future<int> ${method}() => _client.${method}();`
|
|
@@ -49,6 +49,8 @@ import {
|
|
|
49
49
|
dartBusinessRecordInputs,
|
|
50
50
|
dartActionInputClassName,
|
|
51
51
|
dartMemberName,
|
|
52
|
+
collectDartEnums,
|
|
53
|
+
dartEnumTypeForField,
|
|
52
54
|
} from "./codegen_dart.js";
|
|
53
55
|
import { finishCount } from "./count.js";
|
|
54
56
|
import { finishSum } from "./sum.js";
|
|
@@ -147,7 +149,11 @@ const dartStr = (s: string) =>
|
|
|
147
149
|
`'${s.replace(/\\/g, "\\\\").replace(/'/g, "\\'")}'`;
|
|
148
150
|
|
|
149
151
|
/** The Dart param type for a query index key. Aggregate relations keep their canonical typed ref. */
|
|
150
|
-
function dartKeyType(
|
|
152
|
+
function dartKeyType(
|
|
153
|
+
agg: AggregateHandle | undefined,
|
|
154
|
+
key: string,
|
|
155
|
+
enumDartTypes: ReadonlyMap<string, string>,
|
|
156
|
+
): string {
|
|
151
157
|
const lead = key.includes(".") ? key.split(".")[0]! : key;
|
|
152
158
|
const f = agg?.fields[lead] as Field | undefined;
|
|
153
159
|
if (f && (f.kind === "int" || f.kind === "counter")) return "int";
|
|
@@ -162,6 +168,8 @@ function dartKeyType(agg: AggregateHandle | undefined, key: string): string {
|
|
|
162
168
|
if (f.refAggregateId !== undefined)
|
|
163
169
|
return `NomosRef<${concreteClassName(f.refAggregateId)}>`;
|
|
164
170
|
}
|
|
171
|
+
const enumType = dartEnumTypeForField(f, enumDartTypes);
|
|
172
|
+
if (enumType !== undefined) return enumType;
|
|
165
173
|
if (f?.kind === "string" && isSha256DigestSchema(f.zod as z.ZodTypeAny)) {
|
|
166
174
|
return "Sha256Digest";
|
|
167
175
|
}
|
|
@@ -181,6 +189,7 @@ function dartKeyExpr(agg: AggregateHandle | undefined, key: string): string {
|
|
|
181
189
|
) {
|
|
182
190
|
return `${param}.value`;
|
|
183
191
|
}
|
|
192
|
+
if (field?.kind === "enum") return `${param}.wire`;
|
|
184
193
|
if (
|
|
185
194
|
field?.kind === "string" &&
|
|
186
195
|
isGitObjectIdSchema(field.zod as z.ZodTypeAny)
|
|
@@ -325,6 +334,13 @@ export function generateDartBridgeClient(
|
|
|
325
334
|
};
|
|
326
335
|
registerDartNames(mod.aggregates); // `.dartName` overrides for read-model class names in the client.
|
|
327
336
|
const domain = mod.domain ?? mod.name;
|
|
337
|
+
const enumDartTypes = collectDartEnums(
|
|
338
|
+
mod.aggregates,
|
|
339
|
+
mod.directives,
|
|
340
|
+
domain,
|
|
341
|
+
mod.valueObjects ?? [],
|
|
342
|
+
mod.deriveds ?? [],
|
|
343
|
+
).dartTypes;
|
|
328
344
|
assertModelClientMemberAvailable(mod);
|
|
329
345
|
const describeModel =
|
|
330
346
|
opts.describeModel ?? buildNomosDescribeModel([mod], domain);
|
|
@@ -457,9 +473,9 @@ export function generateDartBridgeClient(
|
|
|
457
473
|
methods.push(
|
|
458
474
|
` /// Check only whether an immutable publication pin is still the stable series' current`,
|
|
459
475
|
` /// publication. The kernel reads one compiled current pointer; it does not resolve history.`,
|
|
460
|
-
` Future<
|
|
476
|
+
` Future<ReferenceVersionStatus<TVersion>> referenceVersionStatus<TVersion, TSeries>(`,
|
|
461
477
|
` VersionedNomosRef<TVersion, TSeries> reference) =>`,
|
|
462
|
-
` bridge.
|
|
478
|
+
` bridge.checkReferenceVersion(reference);`,
|
|
463
479
|
``
|
|
464
480
|
);
|
|
465
481
|
}
|
|
@@ -578,6 +594,13 @@ export function generateDartBridgeClient(
|
|
|
578
594
|
}
|
|
579
595
|
for (const d of dirs) {
|
|
580
596
|
const payloadClass = dartActionInputClassName(d);
|
|
597
|
+
const targetBinding = isBusinessIntent(d) ? d.targetBinding : undefined;
|
|
598
|
+
const targetType = targetBinding === undefined
|
|
599
|
+
? undefined
|
|
600
|
+
: `NomosRef<${concreteClassName(targetBinding.aggregateId)}>`;
|
|
601
|
+
const actionParameters = targetBinding === undefined
|
|
602
|
+
? `${payloadClass} payload`
|
|
603
|
+
: `${targetType} target, ${payloadClass} payload`;
|
|
581
604
|
const stamps = autoStampFields(
|
|
582
605
|
(d as unknown as { payloadSchema: z.ZodTypeAny }).payloadSchema
|
|
583
606
|
);
|
|
@@ -628,6 +651,9 @@ export function generateDartBridgeClient(
|
|
|
628
651
|
` }`,
|
|
629
652
|
];
|
|
630
653
|
const payloadJsonArgs = [
|
|
654
|
+
...(targetBinding === undefined
|
|
655
|
+
? []
|
|
656
|
+
: ["nmsInternalTarget: target"]),
|
|
631
657
|
...(principalField === undefined
|
|
632
658
|
? []
|
|
633
659
|
: ["nmsInternalPrincipal: nmsInternalPrincipal"]),
|
|
@@ -702,7 +728,7 @@ export function generateDartBridgeClient(
|
|
|
702
728
|
: "Encrypted field(s) are SEALED via the bound [keyStore] before dispatch (pass `seal: false` to skip)."
|
|
703
729
|
}${stampsDoc}`,
|
|
704
730
|
...(gateDoc ? [gateDoc] : []),
|
|
705
|
-
` Future<NomosOfferOutcome> ${method}(${
|
|
731
|
+
` Future<NomosOfferOutcome> ${method}(${actionParameters}${
|
|
706
732
|
ownedSeal ? "" : ", {bool seal = true}"
|
|
707
733
|
}) async {`,
|
|
708
734
|
...(gateGuard ? [gateGuard] : []),
|
|
@@ -734,7 +760,7 @@ export function generateDartBridgeClient(
|
|
|
734
760
|
methods.push(
|
|
735
761
|
` /// Author \`${domain}/${d.id}\` locally under the installed law; returns the typed [NomosOfferOutcome].${createsDoc}${stampsDoc}`,
|
|
736
762
|
...(gateDoc ? [gateDoc] : []),
|
|
737
|
-
` Future<NomosOfferOutcome> ${method}(${
|
|
763
|
+
` Future<NomosOfferOutcome> ${method}(${actionParameters}) {`,
|
|
738
764
|
...(gateGuard ? [gateGuard] : []),
|
|
739
765
|
...principalPrelude,
|
|
740
766
|
` final data = ${payloadJson};`,
|
|
@@ -750,7 +776,7 @@ export function generateDartBridgeClient(
|
|
|
750
776
|
methods.push(
|
|
751
777
|
` /// Author \`${domain}/${d.id}\` locally under the installed law; returns the typed [NomosOfferOutcome].${createsDoc}`,
|
|
752
778
|
gateDoc,
|
|
753
|
-
` Future<NomosOfferOutcome> ${method}(${
|
|
779
|
+
` Future<NomosOfferOutcome> ${method}(${actionParameters}) {`,
|
|
754
780
|
...(gateGuard ? [gateGuard] : []),
|
|
755
781
|
...principalPrelude,
|
|
756
782
|
` return _offer(${dartStr(d.id)}, ${payloadJson});`,
|
|
@@ -761,7 +787,7 @@ export function generateDartBridgeClient(
|
|
|
761
787
|
methods.push(
|
|
762
788
|
` /// Author \`${domain}/${d.id}\` locally under the installed law; returns the typed [NomosOfferOutcome].${createsDoc}`,
|
|
763
789
|
...(gateDoc ? [gateDoc] : []),
|
|
764
|
-
` Future<NomosOfferOutcome> ${method}(${
|
|
790
|
+
` Future<NomosOfferOutcome> ${method}(${actionParameters}) =>`,
|
|
765
791
|
` _offer(${dartStr(d.id)}, ${payloadJson});`,
|
|
766
792
|
``
|
|
767
793
|
);
|
|
@@ -993,7 +1019,7 @@ export function generateDartBridgeClient(
|
|
|
993
1019
|
const model = readModelClassName(q.returns);
|
|
994
1020
|
const agg = aggById.get(q.returns);
|
|
995
1021
|
const params = q.key
|
|
996
|
-
.map((k) => `required ${dartKeyType(agg, k)} ${dartKeyParam(k)}`)
|
|
1022
|
+
.map((k) => `required ${dartKeyType(agg, k, enumDartTypes)} ${dartKeyParam(k)}`)
|
|
997
1023
|
.join(", ");
|
|
998
1024
|
const argMap = `{${q.key
|
|
999
1025
|
.map((k) => `${dartStr(k)}: ${dartKeyExpr(agg, k)}`)
|
|
@@ -1119,7 +1145,8 @@ export function generateDartBridgeClient(
|
|
|
1119
1145
|
for (const c of (mod.counts ?? []).map((raw) => finishCount(raw))) {
|
|
1120
1146
|
const m = safeMethod(lcFirst(camel(c.id)));
|
|
1121
1147
|
const aggregate = aggById.get(c.of);
|
|
1122
|
-
const groupType =
|
|
1148
|
+
const groupType =
|
|
1149
|
+
c.by == null ? "" : dartKeyType(aggregate, c.by, enumDartTypes);
|
|
1123
1150
|
const groupValue = c.by == null ? "" : dartKeyExpr(aggregate, c.by);
|
|
1124
1151
|
methods.push(
|
|
1125
1152
|
c.by != null
|
|
@@ -1155,7 +1182,8 @@ export function generateDartBridgeClient(
|
|
|
1155
1182
|
for (const s of (mod.sums ?? []).map((raw) => finishSum(raw))) {
|
|
1156
1183
|
const m = safeMethod(lcFirst(camel(s.id)));
|
|
1157
1184
|
const aggregate = aggById.get(s.of);
|
|
1158
|
-
const groupType =
|
|
1185
|
+
const groupType =
|
|
1186
|
+
s.by == null ? "" : dartKeyType(aggregate, s.by, enumDartTypes);
|
|
1159
1187
|
const groupValue = s.by == null ? "" : dartKeyExpr(aggregate, s.by);
|
|
1160
1188
|
methods.push(
|
|
1161
1189
|
s.by != null
|
package/src/codegen_dot.ts
CHANGED
|
@@ -39,7 +39,7 @@ import type { AggregateHandle } from "./aggregate.js";
|
|
|
39
39
|
import type { Field, FieldKind } from "./fields.js";
|
|
40
40
|
import type { Directive } from "./directive.js";
|
|
41
41
|
import type { RelationDecl } from "./relation.js";
|
|
42
|
-
import type {
|
|
42
|
+
import type { AnyDerivedDecl } from "./derived.js";
|
|
43
43
|
import type { CombinedDecl } from "./combined.js";
|
|
44
44
|
import type { DomainModule } from "./codegen_dart.js";
|
|
45
45
|
|
|
@@ -224,7 +224,7 @@ function contextOf(
|
|
|
224
224
|
function aggregateLabel(
|
|
225
225
|
agg: AggregateHandle,
|
|
226
226
|
border: string,
|
|
227
|
-
deriveds: readonly
|
|
227
|
+
deriveds: readonly AnyDerivedDecl[],
|
|
228
228
|
combineds: readonly CombinedDecl[],
|
|
229
229
|
showInvariant: boolean,
|
|
230
230
|
): string {
|
|
@@ -299,7 +299,7 @@ export function emitDomainDot(mod: DomainModule, opts: DotOptions = {}): string
|
|
|
299
299
|
const knownIds = new Set(aggregates.map((a) => a.id));
|
|
300
300
|
|
|
301
301
|
// derived/combined read fields grouped by owner aggregate type.
|
|
302
|
-
const derivedsByType = new Map<string,
|
|
302
|
+
const derivedsByType = new Map<string, AnyDerivedDecl[]>();
|
|
303
303
|
for (const d of mod.deriveds ?? []) {
|
|
304
304
|
const list = derivedsByType.get(d.of) ?? [];
|
|
305
305
|
list.push(d);
|
package/src/codegen_proof.ts
CHANGED
|
@@ -3343,9 +3343,9 @@ function generateSealedApplicationProof(
|
|
|
3343
3343
|
` ? (sample: { readonly operation: string; readonly name: string; readonly durationMs: number; readonly domain?: string; readonly directive?: string }) =>`,
|
|
3344
3344
|
` console.error("[nomos-application-performance] " + JSON.stringify(sample))`,
|
|
3345
3345
|
` : undefined;`,
|
|
3346
|
-
`const
|
|
3346
|
+
`const commissionStarted = performance.now();`,
|
|
3347
3347
|
`const application = await ${opener}({ cloud, application: applicationName, signIn, onPerformance: reportPerformance });`,
|
|
3348
|
-
`if (reportPerformance) reportPerformance({ operation: "open", name: "
|
|
3348
|
+
`if (reportPerformance) reportPerformance({ operation: "open", name: "first application commissioning", durationMs: performance.now() - commissionStarted });`,
|
|
3349
3349
|
`ok("opened the generated ${applicationName}; identity, custody, recovery and sync stay inside Nomos");`,
|
|
3350
3350
|
`const waitUntilSaved = async (): Promise<void> => {`,
|
|
3351
3351
|
` const current = await application.currentStatus();`,
|
|
@@ -3369,8 +3369,17 @@ function generateSealedApplicationProof(
|
|
|
3369
3369
|
);
|
|
3370
3370
|
out.push(
|
|
3371
3371
|
`const facts = ${JSON.stringify(businessPayload)};`,
|
|
3372
|
+
`const businessBirthStarted = performance.now();`,
|
|
3372
3373
|
`const born = await application.${applicationBirthMethod!}(facts);`,
|
|
3374
|
+
`reportPerformance?.({ operation: "birth", name: "generated workspace birth e2e", durationMs: performance.now() - businessBirthStarted, domain: ${JSON.stringify(domain)}, directive: ${JSON.stringify(businessBirth.birthDirectiveId)} });`,
|
|
3373
3375
|
`if (born === undefined) fail("business birth returned no child application");`,
|
|
3376
|
+
`const generatedReadStarted = performance.now();`,
|
|
3377
|
+
`const bornRoots = await born.${generatedAggregateCollectionName(businessBirth.businessAggregateId!)}.all();`,
|
|
3378
|
+
`reportPerformance?.({ operation: "read", name: "generated business read e2e", durationMs: performance.now() - generatedReadStarted, domain: ${JSON.stringify(businessBirth.childDomain)} });`,
|
|
3379
|
+
`if (bornRoots.length === 0) fail("the born application could not read its generated root record");`,
|
|
3380
|
+
`const convergenceStarted = performance.now();`,
|
|
3381
|
+
`await born.creationReceipt;`,
|
|
3382
|
+
`reportPerformance?.({ operation: "sync", name: "generated workspace convergence receipt", durationMs: performance.now() - convergenceStarted, domain: ${JSON.stringify(businessBirth.childDomain)} });`,
|
|
3374
3383
|
`await waitUntilSaved();`,
|
|
3375
3384
|
`ok(${JSON.stringify(`birth(${businessBirth.businessAggregateId}) saved through the generated application`)});`,
|
|
3376
3385
|
);
|
|
@@ -3449,7 +3458,9 @@ function generateSealedApplicationProof(
|
|
|
3449
3458
|
`if (cleared${proofTypeIdent(field)}?.[${JSON.stringify(field)}] !== null) fail(${JSON.stringify(`CLEAR-LANE PROOF — ${aggregate.id}.${field} did not read back as explicit null`)});`,
|
|
3450
3459
|
]);
|
|
3451
3460
|
out.push(
|
|
3461
|
+
`const businessOfferStarted = performance.now();`,
|
|
3452
3462
|
`const result = await application.${action.id}(${payloadLiteral});`,
|
|
3463
|
+
`reportPerformance?.({ operation: "offer", name: "generated ordinary offer e2e", durationMs: performance.now() - businessOfferStarted, domain: ${JSON.stringify(domain)}, directive: ${JSON.stringify(action.id)} });`,
|
|
3453
3464
|
`const created = result.${proofResultMember(aggregate.id)};`,
|
|
3454
3465
|
`${proofRefSlot(aggregate.id)} = created;`,
|
|
3455
3466
|
`ok(${JSON.stringify(`${domain}/${action.id} accepted business facts and returned a typed reference`)});`,
|
|
@@ -3458,7 +3469,9 @@ function generateSealedApplicationProof(
|
|
|
3458
3469
|
`await waitUntilSaved();`,
|
|
3459
3470
|
...clearReadLines,
|
|
3460
3471
|
`const reopened = await ${opener}({ cloud, application: applicationName, signIn });`,
|
|
3472
|
+
`const generatedReadStarted = performance.now();`,
|
|
3461
3473
|
`const rows = await reopened.${generatedAggregateCollectionName(aggregate.id)}.all();`,
|
|
3474
|
+
`reportPerformance?.({ operation: "read", name: "generated business read e2e", durationMs: performance.now() - generatedReadStarted, domain: ${JSON.stringify(domain)} });`,
|
|
3462
3475
|
`if (!rows.some((row) => sameRecord(row.ref, created))) fail("a fresh generated application could not read " + created.address + "; restored addresses: " + (rows.map((row) => row.ref.address).join(", ") || "(none)"));`,
|
|
3463
3476
|
`ok("a fresh generated application read the saved record after synchronization");`,
|
|
3464
3477
|
);
|
|
@@ -3475,6 +3488,15 @@ function generateSealedApplicationProof(
|
|
|
3475
3488
|
`const _proofDispose = _proofDisposable[Symbol.asyncDispose];`,
|
|
3476
3489
|
`if (_proofDispose) await Promise.race([_proofDispose(), new Promise<void>((resolve) => setTimeout(resolve, 1_000))]);`,
|
|
3477
3490
|
`if (performanceEnabled) {`,
|
|
3491
|
+
` process.env.NOMOS_FORCE_COLD_APPLICATION_PLANE = "1";`,
|
|
3492
|
+
` const coldOpenStarted = performance.now();`,
|
|
3493
|
+
` const coldApplication = await ${opener}({ cloud, application: applicationName, signIn, onPerformance: reportPerformance });`,
|
|
3494
|
+
` reportPerformance?.({ operation: "open", name: "generated application ready (cold restore)", durationMs: performance.now() - coldOpenStarted });`,
|
|
3495
|
+
` delete process.env.NOMOS_FORCE_COLD_APPLICATION_PLANE;`,
|
|
3496
|
+
` const coldStatus = await coldApplication.currentStatus();`,
|
|
3497
|
+
` if (coldStatus.phase === "attention") fail(coldStatus.message ?? "the cold-restored application needs attention");`,
|
|
3498
|
+
` const coldDisposable = coldApplication as unknown as { [Symbol.asyncDispose]?: () => Promise<void> };`,
|
|
3499
|
+
` if (coldDisposable[Symbol.asyncDispose]) await Promise.race([coldDisposable[Symbol.asyncDispose]!(), new Promise<void>((resolve) => setTimeout(resolve, 1_000))]);`,
|
|
3478
3500
|
` const warmOpenStarted = performance.now();`,
|
|
3479
3501
|
` const warmApplication = await ${opener}({ cloud, application: applicationName, signIn, onPerformance: reportPerformance });`,
|
|
3480
3502
|
` reportPerformance?.({ operation: "open", name: "generated application ready (warm)", durationMs: performance.now() - warmOpenStarted });`,
|
package/src/codegen_ts.ts
CHANGED
|
@@ -55,7 +55,7 @@ import { voMetaOf, collectPayloadValueObjectDescriptors, idOfMetaOf, idOfTargetK
|
|
|
55
55
|
import { recursiveTypeBaseName, zodUnwrapLazy } from "./zod_lazy.js";
|
|
56
56
|
import { finishCount } from "./count.js";
|
|
57
57
|
import { finishSum } from "./sum.js";
|
|
58
|
-
import type {
|
|
58
|
+
import type { AnyDerivedDecl } from "./derived.js";
|
|
59
59
|
import type { CombinedDecl } from "./combined.js";
|
|
60
60
|
import { resolveWorkspaceTypes, type ResolvedWorkspaceType, type WorkspaceTypeDecl } from "./workspace_type.js";
|
|
61
61
|
import {
|
|
@@ -733,7 +733,11 @@ function tsTypeOfReturns(returns: unknown): string {
|
|
|
733
733
|
function aggregatesOf(mod: Record<string, unknown>): AggregateHandle[] {
|
|
734
734
|
const out: AggregateHandle[] = [];
|
|
735
735
|
for (const v of Object.values(mod)) {
|
|
736
|
-
if (
|
|
736
|
+
if (
|
|
737
|
+
v && typeof v === "object" &&
|
|
738
|
+
(v as { __isAggregateHandle?: boolean }).__isAggregateHandle === true &&
|
|
739
|
+
(v as { __isForwardRef?: boolean }).__isForwardRef !== true
|
|
740
|
+
) {
|
|
737
741
|
out.push(v as AggregateHandle);
|
|
738
742
|
}
|
|
739
743
|
}
|
|
@@ -1634,27 +1638,27 @@ export function generateTsClient(modules: readonly DomainModule[], opts: TsClien
|
|
|
1634
1638
|
`}`,
|
|
1635
1639
|
...(hasVersionedRefs
|
|
1636
1640
|
? [
|
|
1637
|
-
`export type
|
|
1641
|
+
`export type ReferenceVersionStatus<TVersion> =`,
|
|
1638
1642
|
` | { readonly status: "current"; readonly latest: NomosRef<TVersion> }`,
|
|
1639
|
-
` | { readonly status: "
|
|
1643
|
+
` | { readonly status: "outdated"; readonly latest: NomosRef<TVersion> }`,
|
|
1640
1644
|
` | { readonly status: "unavailable"; readonly reason: string };`,
|
|
1641
1645
|
`/** An immutable publication pin plus the stable series which declares its current publication.`,
|
|
1642
|
-
` *
|
|
1646
|
+
` * versionStatus() is O(current state): it never reconstructs the pinned record or walks history. */`,
|
|
1643
1647
|
`export interface VersionedNomosRef<TVersion, TSeries> {`,
|
|
1644
1648
|
` readonly pinned: NomosRef<TVersion>;`,
|
|
1645
1649
|
` readonly series: NomosRef<TSeries>;`,
|
|
1646
|
-
`
|
|
1650
|
+
` versionStatus(): Promise<ReferenceVersionStatus<TVersion>>;`,
|
|
1647
1651
|
`}`,
|
|
1648
1652
|
`type _NomosRawAddress = { workspace: string; type: string; id: string };`,
|
|
1649
1653
|
`function _versionedNomosRef<TVersion, TSeries>(nomos: NomosHolon, raw: { pinned: _NomosRawAddress; series: _NomosRawAddress }, currentField: string): VersionedNomosRef<TVersion, TSeries> {`,
|
|
1650
1654
|
` const pinned = _nmsRef<TVersion>(raw.pinned.workspace, raw.pinned.type, raw.pinned.id);`,
|
|
1651
1655
|
` const series = _nmsRef<TSeries>(raw.series.workspace, raw.series.type, raw.series.id);`,
|
|
1652
|
-
` return { pinned, series, async
|
|
1653
|
-
` if (nomos.
|
|
1654
|
-
` const result = await nomos.
|
|
1656
|
+
` return { pinned, series, async versionStatus() {`,
|
|
1657
|
+
` if (nomos.checkReferenceVersions === undefined) return { status: "unavailable", reason: "installed Nomos runtime does not support reference version checks" };`,
|
|
1658
|
+
` const result = await nomos.checkReferenceVersions([{ pinned: raw.pinned, series: raw.series, currentField }]);`,
|
|
1655
1659
|
` const outcome = result.unique[0]?.outcome;`,
|
|
1656
1660
|
` if (outcome?.status === "current") return { status: "current", latest: pinned };`,
|
|
1657
|
-
` if (outcome?.status === "
|
|
1661
|
+
` if (outcome?.status === "outdated" && outcome.latest !== undefined) return { status: "outdated", latest: _nmsRef<TVersion>(outcome.latest.workspace, outcome.latest.type, outcome.latest.id) };`,
|
|
1658
1662
|
` return { status: "unavailable", reason: String(outcome?.status ?? "unknown") };`,
|
|
1659
1663
|
` } };`,
|
|
1660
1664
|
`}`,
|
|
@@ -1794,7 +1798,7 @@ export function generateTsClient(modules: readonly DomainModule[], opts: TsClien
|
|
|
1794
1798
|
...(hasVersionedRefs
|
|
1795
1799
|
? [
|
|
1796
1800
|
` /** Framework-private O(current-state) version check used by generated VersionedNomosRef. */`,
|
|
1797
|
-
`
|
|
1801
|
+
` checkReferenceVersions?(refs: readonly { pinned: _NomosRawAddress; series: _NomosRawAddress; currentField: string }[]): Promise<{ unique: { outcome: { status: string; latest?: _NomosRawAddress } }[]; order: number[] }>;`,
|
|
1798
1802
|
]
|
|
1799
1803
|
: []),
|
|
1800
1804
|
` /** FRAMEWORK-INTERNAL exact-history adoption seam. Generated clients expose only`,
|
|
@@ -2416,9 +2420,11 @@ export function generateTsClient(modules: readonly DomainModule[], opts: TsClien
|
|
|
2416
2420
|
// ── read models: one interface per aggregate wire type (deduped), deriveds/combineds merged ──
|
|
2417
2421
|
const extrasByType = new Map<string, string[]>();
|
|
2418
2422
|
for (const mod of modules) {
|
|
2419
|
-
for (const d of (mod.deriveds ?? []) as
|
|
2423
|
+
for (const d of (mod.deriveds ?? []) as AnyDerivedDecl[]) {
|
|
2420
2424
|
(extrasByType.get(d.of) ?? extrasByType.set(d.of, []).get(d.of)!).push(
|
|
2421
|
-
|
|
2425
|
+
"kind" in d && d.kind === "temporalEnum"
|
|
2426
|
+
? ` /** native temporal enum read field (captured-clock projection) */\n ${d.id}: ${tsTypeOfReturns(d.returns)};`
|
|
2427
|
+
: ` /** derived read field (engine-projected) */\n ${d.id}?: ${tsTypeOfReturns(d.returns)};`,
|
|
2422
2428
|
);
|
|
2423
2429
|
}
|
|
2424
2430
|
for (const c of (mod.combineds ?? []) as CombinedDecl[]) {
|
|
@@ -2820,6 +2826,7 @@ export function generateTsClient(modules: readonly DomainModule[], opts: TsClien
|
|
|
2820
2826
|
const usedResultNames = new Set<string>();
|
|
2821
2827
|
const applicationBirths: Array<{
|
|
2822
2828
|
sourceDomain: string;
|
|
2829
|
+
directiveId: string;
|
|
2823
2830
|
method: string;
|
|
2824
2831
|
payloadName: string;
|
|
2825
2832
|
aggregateId: string;
|
|
@@ -3186,6 +3193,7 @@ export function generateTsClient(modules: readonly DomainModule[], opts: TsClien
|
|
|
3186
3193
|
const applicationMethod = isBusinessIntent(d) ? d.id : "birth";
|
|
3187
3194
|
applicationBirths.push({
|
|
3188
3195
|
sourceDomain: domain,
|
|
3196
|
+
directiveId: d.id,
|
|
3189
3197
|
method: applicationMethod,
|
|
3190
3198
|
payloadName,
|
|
3191
3199
|
aggregateId: businessBirth.aggregateId,
|
|
@@ -3206,9 +3214,6 @@ export function generateTsClient(modules: readonly DomainModule[], opts: TsClien
|
|
|
3206
3214
|
...(ownedBirthDescriptor !== undefined
|
|
3207
3215
|
? [` if (born.workspace !== _ownedBirthKey.workspace) throw new Error("birth() returned a workspace different from the deterministic owned-custody address");`]
|
|
3208
3216
|
: []),
|
|
3209
|
-
` await holon.sync?.();`,
|
|
3210
|
-
` if (!holon.settleBirth) throw new Error("birth() requires the current @githolon/client to complete durable recovery");`,
|
|
3211
|
-
` await holon.settleBirth(born.workspace);`,
|
|
3212
3217
|
` return _nmsRef<${businessBirth.aggregateId}>(born.workspace, ${JSON.stringify(businessBirth.aggregateId)}, ${JSON.stringify(businessBirth.rootId)});`,
|
|
3213
3218
|
` },`,
|
|
3214
3219
|
);
|
|
@@ -3916,7 +3921,7 @@ export function generateTsClient(modules: readonly DomainModule[], opts: TsClien
|
|
|
3916
3921
|
`type ${tsDomainApplicationType(domain)} = _NomosPublicDomain<ReturnType<typeof ${tsClientFactoryName(domain)}>>;`
|
|
3917
3922
|
),
|
|
3918
3923
|
...childApplicationTypes.map((birth) =>
|
|
3919
|
-
`export type ${birth.applicationType} = _NomosPublicDomain<ReturnType<typeof ${tsClientFactoryName(birth.targetDomain)}
|
|
3924
|
+
`export type ${birth.applicationType} = _NomosPublicDomain<ReturnType<typeof ${tsClientFactoryName(birth.targetDomain)}>> & { readonly creationReceipt: Promise<void> };`
|
|
3920
3925
|
),
|
|
3921
3926
|
`type _${applicationName}Business = ${applicationType};`,
|
|
3922
3927
|
`export type ${applicationName}Status = _NomosApplicationStatus;`,
|
|
@@ -3996,11 +4001,19 @@ export function generateTsClient(modules: readonly DomainModule[], opts: TsClien
|
|
|
3996
4001
|
` application[${JSON.stringify(birth.method)}] = async (input: ${birth.payloadName}): Promise<${birth.applicationType}> => {`,
|
|
3997
4002
|
` const root = await _nmsRoot${rootIndex}[${JSON.stringify(birth.method)}](input);`,
|
|
3998
4003
|
` const address = _nmsReferenceData(root);`,
|
|
3999
|
-
`
|
|
4004
|
+
` const child = await nomosInternalOpenGeneratedChildApplication(`,
|
|
4000
4005
|
` holon,`,
|
|
4001
4006
|
` address.workspace,`,
|
|
4002
4007
|
` (child) => _nomosPublicDomain(${tsClientFactoryName(birth.targetDomain)}(child as NomosHolon)),`,
|
|
4003
4008
|
` );`,
|
|
4009
|
+
` const creationReceipt = (async (): Promise<void> => {`,
|
|
4010
|
+
` await holon.sync?.();`,
|
|
4011
|
+
` if (!holon.settleBirth) throw new Error("birth() requires the current @githolon/client to prove remote custody convergence");`,
|
|
4012
|
+
` await holon.settleBirth(address.workspace);`,
|
|
4013
|
+
` })();`,
|
|
4014
|
+
` void creationReceipt.catch(() => {});`,
|
|
4015
|
+
` Object.defineProperty(child, "creationReceipt", { value: creationReceipt, enumerable: true, configurable: false, writable: false });`,
|
|
4016
|
+
` return child as ${birth.applicationType};`,
|
|
4004
4017
|
` };`,
|
|
4005
4018
|
];
|
|
4006
4019
|
}),
|
|
@@ -4061,7 +4074,7 @@ export function generateTsClient(modules: readonly DomainModule[], opts: TsClien
|
|
|
4061
4074
|
` * or parallel cache around it. Nomos owns offline custody and synchronization. */`,
|
|
4062
4075
|
`export function ${applicationOpener}(options: ${applicationName}OpenOptions): Promise<${applicationName}> {`,
|
|
4063
4076
|
` return nomosInternalOpenGeneratedApplication(`,
|
|
4064
|
-
` { cloud: options.cloud, application: options.application, signIn: options.signIn, onPerformance: options.onPerformance, lawHash: ${hashConst} },`,
|
|
4077
|
+
` { cloud: options.cloud, application: options.application, signIn: options.signIn, onPerformance: options.onPerformance, lawHash: ${hashConst}, readyCommands: [${rootBirths.map((birth) => `{ domain: ${JSON.stringify(birth.sourceDomain)}, packageHash: ${hashConst}, directiveId: ${JSON.stringify(birth.directiveId)} }`).join(", ")}] },`,
|
|
4065
4078
|
` (holon, user) => _nomosBind${applicationName}(holon as NomosHolon, user),`,
|
|
4066
4079
|
` );`,
|
|
4067
4080
|
`}`,
|