@githolon/dsl 0.101.6 → 0.102.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/dart/CHANGELOG.md +13 -0
- package/dart/lib/nomos_client.dart +3 -52
- package/dart/lib/src/dev_cloud.dart +5 -0
- package/dart/lib/src/home.dart +10 -15
- package/dart/lib/src/nms_conformance_runtime.dart +12 -0
- package/dart/lib/src/nms_generated_runtime.dart +29 -0
- package/dart/lib/src/nms_test_environment.dart +8 -0
- package/dart/lib/src/node_runner_transport.dart +56 -18
- package/dart/lib/src/provider.dart +5 -1
- package/dart/lib/src/record_origin.dart +55 -0
- package/dart/lib/src/runner/node-entry.mjs +9105 -0
- package/dart/lib/src/runner/offline-install.mjs +4729 -0
- package/dart/lib/src/session_bound.dart +23 -10
- package/dart/lib/src/source_trust.dart +51 -0
- package/dart/lib/src/test_harness.dart +490 -58
- package/dart/lib/src/webview_bridge.dart +167 -58
- package/dart/lib/src/workspace_name.dart +7 -1
- package/dart/pubspec.lock +3 -3
- package/dart/pubspec.yaml +4 -2
- package/dart/test/acquire_session_credentials_test.dart +34 -17
- package/dart/test/acquire_session_test.dart +109 -24
- package/dart/test/adv_realm_interference_test.dart +227 -99
- package/dart/test/bundle_version_pairing_test.dart +1 -1
- package/dart/test/cloud_bound_topology_test.dart +1 -1
- package/dart/test/cluster_attested_test.dart +52 -35
- package/dart/test/cluster_births_test.dart +5 -2
- package/dart/test/cluster_device_keyed_acceptance_test.dart +5 -2
- package/dart/test/cluster_local_autosync_test.dart +5 -2
- package/dart/test/cluster_scale_test.dart +5 -2
- package/dart/test/compat_test.dart +1 -1
- package/dart/test/dlq_session_surface_test.dart +2 -1
- package/dart/test/errors_test.dart +1 -1
- package/dart/test/first_app_gauntlet_test.dart +78 -51
- package/dart/test/four_layer_nested_topology_test.dart +1 -1
- package/dart/test/harness_phase_timeout_test.dart +1 -1
- package/dart/test/home_parity_test.dart +9 -5
- package/dart/test/local_sync_inert_test.dart +22 -14
- package/dart/test/node_runner_transport_test.dart +9 -5
- package/dart/test/null_slot_test.dart +1 -1
- package/dart/test/parent_signer_recovery_test.dart +5 -2
- package/dart/test/schema_validation_test.dart +1 -1
- package/dart/test/sealing_client_test.dart +2 -1
- package/dart/test/session_bound_test.dart +92 -119
- package/dart/test/stale_bundle_test.dart +1 -1
- package/dart/test/test_harness_test.dart +77 -22
- package/dart/test/vo_read_typing_test.dart +32 -14
- package/dart/test/watch_after_offer_stall_test.dart +2 -1
- package/dart/test/webview_bridge_test.dart +17 -4
- package/dart/test/wire_test.dart +1 -1
- package/dart_types/CHANGELOG.md +8 -0
- package/dart_types/lib/nomos_types.dart +7 -6
- package/dart_types/lib/src/activity.dart +23 -13
- package/dart_types/lib/src/foreign_ref.dart +61 -112
- package/dart_types/lib/src/invitation.dart +96 -0
- package/dart_types/lib/src/nomos_ref.dart +97 -59
- package/dart_types/pubspec.yaml +1 -1
- package/dart_types/test/surfaced_test.dart +125 -19
- package/package.json +7 -3
- package/runtime/generated-application-host.js +8851 -0
- package/src/activity.ts +2 -2
- package/src/aggregate.ts +24 -1
- package/src/application_composition.ts +282 -0
- package/src/application_topology.ts +151 -0
- package/src/attested_core.ts +2 -2
- package/src/authoring_context.ts +9 -0
- package/src/birth_meter_ensure.ts +1 -1
- package/src/births.ts +53 -5
- package/src/build_package.ts +79 -71
- package/src/business_birth.ts +93 -10
- package/src/clear_directive.ts +3 -1
- package/src/codegen_dart.ts +369 -420
- package/src/codegen_dart_application.ts +1508 -0
- package/src/codegen_dart_client.ts +156 -95
- package/src/codegen_dart_scenario.ts +299 -0
- package/src/codegen_openapi.ts +8 -3
- package/src/codegen_proof.ts +1113 -1137
- package/src/codegen_provider_dart.ts +12 -1
- package/src/codegen_ts.ts +1176 -496
- package/src/compat_package_main.ts +22 -10
- package/src/compile_package_main.ts +1536 -337
- package/src/contract.ts +10 -4
- package/src/dart_barrel_guard.ts +5 -1
- package/src/describe_model.ts +13 -5
- package/src/directive.ts +244 -5
- package/src/engine_entry.ts +56 -13
- package/src/engine_javascript.ts +31 -0
- package/src/evolve_preview.ts +3 -12
- package/src/framework/application_home.ts +24 -10
- package/src/framework/capability.ts +15 -1
- package/src/framework/domain_lifecycle.ts +8 -0
- package/src/framework/framework_aggregates.ts +2 -2
- package/src/framework/genesis.ts +11 -1
- package/src/framework/home.ts +178 -75
- package/src/framework/impure_capability.ts +24 -7
- package/src/framework/relations.ts +13 -5
- package/src/framework/workspaces.ts +13 -12
- package/src/generated_client_names.ts +42 -3
- package/src/idof_lint.ts +65 -13
- package/src/index.ts +46 -12
- package/src/intent.ts +587 -0
- package/src/law_check.ts +64 -16
- package/src/precondition.ts +16 -4
- package/src/read_projection_namespace.ts +2 -7
- package/src/recipient.ts +33 -0
- package/src/relation_schema.ts +93 -0
- package/src/secondary_ensure.ts +11 -2
- package/src/shape_compat.ts +11 -1
- package/src/usd.ts +30 -8
- package/src/usd_layers.ts +447 -246
- package/src/usd_state.ts +1 -1
- package/src/value_object.ts +49 -13
- package/src/wire_encode.ts +124 -26
- package/src/workspace_sharing.ts +269 -0
- package/src/zod_introspection.ts +84 -0
- package/dart/example/nomos_secure_key_store.dart +0 -82
- package/dart/example/nomos_webview_transport.dart +0 -63
- package/dart/lib/nomos_headless.dart +0 -50
- package/dart/lib/testing.dart +0 -14
- package/dart/test/co2_product_gauntlet_test.dart +0 -244
- package/src/framework/identity.ts +0 -537
package/dart/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
## 0.64.0
|
|
2
|
+
|
|
3
|
+
- Generate one self-documenting application object: intent-shaped business actions at the root, typed
|
|
4
|
+
aggregate collections for reads and navigation, aggregate-specific conflict decisions, and verified
|
|
5
|
+
activity. The generated application is the application state; raw runtime clients are private.
|
|
6
|
+
- Let one intent atomically create and ensure any number of aggregate consequences. Every created record and
|
|
7
|
+
reference-bearing query uses `NomosRef<T>`; secondary ensures keep their aggregate identity through
|
|
8
|
+
compilation and admission.
|
|
9
|
+
- Generate restart-safe offline scenarios and ownership-aware proofs while keeping keys, certificates,
|
|
10
|
+
signers, warrants, topology and retry machinery outside the tenant API.
|
|
11
|
+
- Mark the generator-only runtime library internal, so tenant imports receive an analyzer refusal while
|
|
12
|
+
compiler-generated application code retains the sole intentional implementation bridge.
|
|
13
|
+
|
|
1
14
|
## 0.63.1
|
|
2
15
|
|
|
3
16
|
- Make automatic sync a truthful client-owned lifecycle: local acceptance is durable, offline/restored
|
|
@@ -1,54 +1,5 @@
|
|
|
1
|
-
|
|
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
|
-
/// Nomos 2 Dart frontend types.
|
|
1
|
+
/// Nomos runtime implementation package.
|
|
9
2
|
///
|
|
10
|
-
///
|
|
11
|
-
///
|
|
12
|
-
/// serde_json. See `src/wire.dart`, `src/driver.dart`.
|
|
13
|
-
/// - The ONE effectful write verb `offer(intent)` (`src/offer.dart`) + the typed
|
|
14
|
-
/// reactive read engine `NomosReads` (`src/subscriptions.dart`).
|
|
15
|
-
/// - The framework PRIMITIVES ONLY. The CODE-GENERATED per-domain types
|
|
16
|
-
/// (aggregates + public intent payloads + enums + `watch…` read accessors) NO LONGER
|
|
17
|
-
/// live here — they were extracted into the co-located TENANT package
|
|
18
|
-
/// `co2_nomos_domains` (`ts_packages/co2-nomos-domains/dart/`), emitted there by
|
|
19
|
-
/// `ts_packages/co2-nomos-domains/src/emit_dart.ts`. Tenant domains squatting in
|
|
20
|
-
/// the framework package was the wrong topology; this barrel now exports ONLY the
|
|
21
|
-
/// hand-written framework wire/offer/read/provider primitives. App code that
|
|
22
|
-
/// wants the typed domain surface imports `package:co2_nomos_domains/co2_nomos_domains.dart`,
|
|
23
|
-
/// which re-exports this framework barrel PLUS every generated domain.
|
|
3
|
+
/// Tenant applications import their generated `<Domain>Application` package. No generic runtime surface is
|
|
4
|
+
/// exported here; generated code uses a private implementation import under `src/`.
|
|
24
5
|
library;
|
|
25
|
-
|
|
26
|
-
// THE PURE-DATA CORE — the hand-written kernel wire types, the `offer(intent)` codec,
|
|
27
|
-
// the tri-state `NomosSlot<T>`, `NomosReads`, schema validation, runtime aggregate
|
|
28
|
-
// metadata, the data-only error/trace types, and the typed diagnostics moved to the
|
|
29
|
-
// standalone `nomos_types` package (so generated per-domain TYPES files resolve against
|
|
30
|
-
// it alone). Re-exported here so this barrel's public API is unchanged for consumers.
|
|
31
|
-
export 'package:nomos_types/nomos_types.dart';
|
|
32
|
-
// homeNameOf(subject) — the canonical home-workspace name (parity with @githolon/client + the law side).
|
|
33
|
-
export 'src/home.dart';
|
|
34
|
-
export 'src/workspace_name.dart';
|
|
35
|
-
// THE WEBVIEW BRIDGE (app-binding boundary) — the async Dart runtime that drives the REAL githolon running
|
|
36
|
-
// in a WebView, so the generated typed client never needs a `MemoryPersistence` fake.
|
|
37
|
-
export 'src/webview_bridge.dart';
|
|
38
|
-
// SESSION-BOUND CLIENTS (architecture/session_bound_clients.md) — the typed session/client
|
|
39
|
-
// contract: NomosClientInterface (`XClient.interface`), session.assertCompatible(...), and the two
|
|
40
|
-
// typed mismatch errors (DomainClientSessionMismatch / DomainNotInstalledForSession).
|
|
41
|
-
export 'src/session_bound.dart';
|
|
42
|
-
// The PROVIDER boundary (server-side capability-provider SDK runtime: TaskOutcome /
|
|
43
|
-
// TaskSuccess / TaskFailure / TaskResult / TaskProvider / HostClock). The symmetric twin
|
|
44
|
-
// of `offer.dart`; the generated per-task provider classes build on it.
|
|
45
|
-
export 'src/provider.dart';
|
|
46
|
-
|
|
47
|
-
// ── NO generated domains here ──────────────────────────────────────────────
|
|
48
|
-
// The per-domain generated types moved to the tenant `co2_nomos_domains` package
|
|
49
|
-
// (`ts_packages/co2-nomos-domains/dart/lib/src/generated/`). The tenant barrel
|
|
50
|
-
// (`package:co2_nomos_domains/co2_nomos_domains.dart`) re-exports THIS framework
|
|
51
|
-
// barrel plus every generated domain — so importing it gives the whole typed
|
|
52
|
-
// surface (framework primitives + tenant domains) through one import. The colliding
|
|
53
|
-
// positional enums (`StatusEnum`/`KindEnum`/…) and their `hide` clauses now live on
|
|
54
|
-
// the tenant barrel's exports, not here.
|
|
@@ -14,6 +14,11 @@
|
|
|
14
14
|
// final remote = await cloud.remoteHead('estate'); // inspect remote head + commit count
|
|
15
15
|
// await cloud.stop();
|
|
16
16
|
// ```
|
|
17
|
+
@internal
|
|
18
|
+
library;
|
|
19
|
+
|
|
20
|
+
import 'package:meta/meta.dart' show internal;
|
|
21
|
+
|
|
17
22
|
import 'dart:async';
|
|
18
23
|
import 'dart:convert';
|
|
19
24
|
import 'dart:io';
|
package/dart/lib/src/home.dart
CHANGED
|
@@ -1,20 +1,15 @@
|
|
|
1
|
+
@internal
|
|
2
|
+
library;
|
|
3
|
+
|
|
4
|
+
import 'package:meta/meta.dart' show internal;
|
|
5
|
+
|
|
1
6
|
import 'dart:convert';
|
|
2
7
|
|
|
3
8
|
import 'package:crypto/crypto.dart';
|
|
4
9
|
|
|
5
|
-
///
|
|
6
|
-
///
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
/// every peer and on the cloud. Use it directly as the `workspace`:
|
|
11
|
-
///
|
|
12
|
-
/// ```dart
|
|
13
|
-
/// NomosScope.home(application: 'my-app', authToken: idToken, ...)
|
|
14
|
-
/// ```
|
|
15
|
-
///
|
|
16
|
-
/// Formula: `home-` + the first 40 hex chars of `sha256(utf8(subject))`.
|
|
17
|
-
String homeNameOf(String subject) {
|
|
18
|
-
final hex = sha256.convert(utf8.encode(subject)).toString(); // lowercase hex
|
|
19
|
-
return 'home-${hex.substring(0, 40)}';
|
|
10
|
+
/// Compiler/runtime-only receiving-group address. Generated application hosts call this; tenant code does
|
|
11
|
+
/// not choose or persist framework workspace names.
|
|
12
|
+
String nmsInternalReceivingGroupNameOf(String principal) {
|
|
13
|
+
final hex = sha256.convert(utf8.encode(principal)).toString();
|
|
14
|
+
return 'nomos-rg-${hex.substring(0, 40)}';
|
|
20
15
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
// Framework conformance surface. Nomos' own tests use this to exercise transport and lifecycle machinery.
|
|
2
|
+
// Generated tenant tests use nms_test_environment.dart instead.
|
|
3
|
+
@internal
|
|
4
|
+
library;
|
|
5
|
+
|
|
6
|
+
import 'package:meta/meta.dart' show internal;
|
|
7
|
+
|
|
8
|
+
export 'dev_cloud.dart';
|
|
9
|
+
export 'node_runner_transport.dart';
|
|
10
|
+
export 'session_bound.dart';
|
|
11
|
+
export 'test_harness.dart';
|
|
12
|
+
export 'webview_bridge.dart';
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/// Generator and framework-host implementation surface.
|
|
2
|
+
///
|
|
3
|
+
/// Deliberately lives under `src/`: tenant code imports its generated application package instead.
|
|
4
|
+
@internal
|
|
5
|
+
library;
|
|
6
|
+
|
|
7
|
+
import 'package:meta/meta.dart' show internal;
|
|
8
|
+
|
|
9
|
+
export 'package:nomos_types/nomos_types.dart';
|
|
10
|
+
export 'package:nomos_types/src/nomos_ref.dart' show NmsInternalNomosRefs;
|
|
11
|
+
export 'package:nomos_types/src/invitation.dart'
|
|
12
|
+
show NmsInternalInvitations, NmsInternalRecipients, NmsInternalUsers;
|
|
13
|
+
export 'package:nomos_types/src/foreign_ref.dart'
|
|
14
|
+
show
|
|
15
|
+
NmsInternalForeignRefs,
|
|
16
|
+
NomosForeignReader,
|
|
17
|
+
NomosForeignWorkspaceReader,
|
|
18
|
+
ForeignResolveResult,
|
|
19
|
+
ForeignFound,
|
|
20
|
+
ForeignNotFound,
|
|
21
|
+
ForeignDenied,
|
|
22
|
+
ForeignUnreachable;
|
|
23
|
+
export 'home.dart';
|
|
24
|
+
export 'workspace_name.dart';
|
|
25
|
+
export 'webview_bridge.dart';
|
|
26
|
+
export 'session_bound.dart';
|
|
27
|
+
export 'provider.dart';
|
|
28
|
+
export 'record_origin.dart';
|
|
29
|
+
export 'source_trust.dart';
|
|
@@ -7,10 +7,17 @@
|
|
|
7
7
|
//
|
|
8
8
|
// This file is a PURE RELAY: no orchestration, no op knowledge — the protocol implementation lives in
|
|
9
9
|
// createWebviewRunner (shared with the WebView path) and the orchestration in index.mjs, same as every peer.
|
|
10
|
+
@internal
|
|
11
|
+
library;
|
|
12
|
+
|
|
13
|
+
import 'package:meta/meta.dart' show internal;
|
|
14
|
+
|
|
10
15
|
import 'dart:async';
|
|
11
16
|
import 'dart:convert';
|
|
12
17
|
import 'dart:io';
|
|
13
18
|
|
|
19
|
+
import 'package:package_config/package_config.dart' show loadPackageConfigUri;
|
|
20
|
+
|
|
14
21
|
import 'webview_bridge.dart' show BridgeTransport;
|
|
15
22
|
|
|
16
23
|
class NodeRunnerTransport implements BridgeTransport {
|
|
@@ -21,10 +28,8 @@ class NodeRunnerTransport implements BridgeTransport {
|
|
|
21
28
|
bool _disposed = false;
|
|
22
29
|
|
|
23
30
|
NodeRunnerTransport._(this._proc, this._onDiagnostic) {
|
|
24
|
-
_proc.stdout
|
|
25
|
-
|
|
26
|
-
.transform(const LineSplitter())
|
|
27
|
-
.listen((line) {
|
|
31
|
+
_proc.stdout.transform(utf8.decoder).transform(const LineSplitter()).listen(
|
|
32
|
+
(line) {
|
|
28
33
|
final s = line.trim();
|
|
29
34
|
if (s.isEmpty) return;
|
|
30
35
|
Object? decoded;
|
|
@@ -39,8 +44,8 @@ class NodeRunnerTransport implements BridgeTransport {
|
|
|
39
44
|
}
|
|
40
45
|
}, onDone: () {
|
|
41
46
|
if (!_disposed && !_incoming.isClosed) {
|
|
42
|
-
_incoming
|
|
43
|
-
StateError('the nomos node runner exited unexpectedly'));
|
|
47
|
+
_incoming
|
|
48
|
+
.addError(StateError('the nomos node runner exited unexpectedly'));
|
|
44
49
|
}
|
|
45
50
|
});
|
|
46
51
|
_proc.stderr
|
|
@@ -79,24 +84,57 @@ class NodeRunnerTransport implements BridgeTransport {
|
|
|
79
84
|
node,
|
|
80
85
|
[entryPath],
|
|
81
86
|
environment: environment,
|
|
82
|
-
|
|
87
|
+
// [resolveFrom] locates a packaged runner when [entry] is omitted; it is not a runtime dependency of
|
|
88
|
+
// an explicit, self-contained entry. Reusing it as cwd made copied release tests fail with ENOENT even
|
|
89
|
+
// though the selected runner existed and was executable.
|
|
90
|
+
workingDirectory: entry == null ? resolveFrom : null,
|
|
83
91
|
);
|
|
84
92
|
return NodeRunnerTransport._(proc, onDiagnostic);
|
|
85
93
|
}
|
|
86
94
|
|
|
87
95
|
static Future<String> _resolveEntry(String node, String from) async {
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
96
|
+
String? packageConfigPath = Platform.packageConfig;
|
|
97
|
+
if (packageConfigPath == null) {
|
|
98
|
+
var directory = Directory(from).absolute;
|
|
99
|
+
while (true) {
|
|
100
|
+
final candidate = File(
|
|
101
|
+
'${directory.path}${Platform.pathSeparator}.dart_tool${Platform.pathSeparator}package_config.json',
|
|
102
|
+
);
|
|
103
|
+
if (candidate.existsSync()) {
|
|
104
|
+
packageConfigPath = candidate.uri.toString();
|
|
105
|
+
break;
|
|
106
|
+
}
|
|
107
|
+
final parent = directory.parent;
|
|
108
|
+
if (parent.path == directory.path) break;
|
|
109
|
+
directory = parent;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
if (packageConfigPath != null) {
|
|
113
|
+
final packages = await loadPackageConfigUri(
|
|
114
|
+
Uri.base.resolve(packageConfigPath),
|
|
115
|
+
);
|
|
116
|
+
final bundled = packages.resolve(
|
|
117
|
+
Uri.parse('package:nomos_client/src/runner/node-entry.mjs'),
|
|
118
|
+
);
|
|
119
|
+
if (bundled != null && bundled.scheme == 'file') {
|
|
120
|
+
final path = bundled.toFilePath();
|
|
121
|
+
if (File(path).existsSync()) return path;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
for (final entry in const [
|
|
125
|
+
'@githolon/client/runner/node-entry.mjs',
|
|
126
|
+
'@githolon/client/runner/node-entry.ts',
|
|
127
|
+
]) {
|
|
128
|
+
final r = await Process.run(
|
|
129
|
+
node,
|
|
130
|
+
['-p', "require.resolve('$entry')"],
|
|
131
|
+
workingDirectory: from,
|
|
132
|
+
);
|
|
133
|
+
final out = (r.stdout as String).trim();
|
|
134
|
+
if (r.exitCode == 0 && out.isNotEmpty) return out;
|
|
98
135
|
}
|
|
99
|
-
|
|
136
|
+
throw StateError('the Nomos release contains no bundled node runner and no '
|
|
137
|
+
'@githolon/client runner is installed; reinstall nomos_client');
|
|
100
138
|
}
|
|
101
139
|
|
|
102
140
|
@override
|
|
@@ -27,8 +27,11 @@
|
|
|
27
27
|
/// This file is HAND-WRITTEN and domain-AGNOSTIC (declared ONCE, here): the generated
|
|
28
28
|
/// per-task provider classes build on these interfaces, so the round-trip mechanism is
|
|
29
29
|
/// proven once and reused for every capability.
|
|
30
|
+
@internal
|
|
30
31
|
library;
|
|
31
32
|
|
|
33
|
+
import 'package:meta/meta.dart' show internal;
|
|
34
|
+
|
|
32
35
|
import 'dart:convert';
|
|
33
36
|
|
|
34
37
|
import 'package:nomos_types/nomos_types.dart' show NomosIntent;
|
|
@@ -122,7 +125,8 @@ abstract interface class TaskProvider<O, R> {
|
|
|
122
125
|
/// [NomosIntent] ready for the ONE write path (`offer`). `now` stamps the
|
|
123
126
|
/// terminal time. Decoding raw JSON happens HERE and only here; the handler the dev
|
|
124
127
|
/// writes sees ONLY the typed [O] and returns ONLY a typed [TaskOutcome].
|
|
125
|
-
NomosIntent handleObligation(String obligationPayloadJson,
|
|
128
|
+
NomosIntent handleObligation(String obligationPayloadJson,
|
|
129
|
+
{required HostClock now});
|
|
126
130
|
|
|
127
131
|
/// Convenience: decode an Obligation payload from an already-parsed map (the host may have
|
|
128
132
|
/// the row's `data` map in hand from a read). Same path as [handleObligation].
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/// Private generated-client state tying a decoded business object to the
|
|
2
|
+
/// workspace record it came from.
|
|
3
|
+
///
|
|
4
|
+
/// This deliberately lives under `src/` and is never exported by a tenant
|
|
5
|
+
/// application package. Generated navigation and write facades use it so a
|
|
6
|
+
/// business record can be passed to another business action without exposing
|
|
7
|
+
/// workspace coordinates to tenant code.
|
|
8
|
+
@internal
|
|
9
|
+
library;
|
|
10
|
+
|
|
11
|
+
import 'package:meta/meta.dart' show internal;
|
|
12
|
+
|
|
13
|
+
final class NmsInternalRecordOrigin {
|
|
14
|
+
const NmsInternalRecordOrigin({
|
|
15
|
+
required this.workspace,
|
|
16
|
+
required this.type,
|
|
17
|
+
required this.id,
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
final String workspace;
|
|
21
|
+
final String type;
|
|
22
|
+
final String id;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
final class NmsInternalRecordOrigins {
|
|
26
|
+
NmsInternalRecordOrigins._();
|
|
27
|
+
|
|
28
|
+
static final Expando<NmsInternalRecordOrigin> _origins =
|
|
29
|
+
Expando<NmsInternalRecordOrigin>('nms-record-origin');
|
|
30
|
+
|
|
31
|
+
static T remember<T>(
|
|
32
|
+
T record, {
|
|
33
|
+
required String workspace,
|
|
34
|
+
required String type,
|
|
35
|
+
required String id,
|
|
36
|
+
}) {
|
|
37
|
+
_origins[record as Object] = NmsInternalRecordOrigin(
|
|
38
|
+
workspace: workspace,
|
|
39
|
+
type: type,
|
|
40
|
+
id: id,
|
|
41
|
+
);
|
|
42
|
+
return record;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
static NmsInternalRecordOrigin require(Object record) {
|
|
46
|
+
final origin = _origins[record];
|
|
47
|
+
if (origin == null) {
|
|
48
|
+
throw StateError(
|
|
49
|
+
'This business record was not read through its generated application. '
|
|
50
|
+
'Read or follow the record first, then pass that returned record to the action.',
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
return origin;
|
|
54
|
+
}
|
|
55
|
+
}
|