@fabricorg/platform 1.9.0 → 1.10.1
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/CHANGELOG.md +56 -0
- package/README.md +48 -2
- package/dist/actions/index.cjs +45 -26
- package/dist/actions/index.cjs.map +1 -1
- package/dist/actions/index.d.cts +225 -226
- package/dist/actions/index.d.ts +225 -226
- package/dist/actions/index.js +41 -2
- package/dist/actions/index.js.map +1 -1
- package/dist/adapters/index.cjs +696 -66
- package/dist/adapters/index.cjs.map +1 -1
- package/dist/adapters/index.d.cts +367 -365
- package/dist/adapters/index.d.ts +367 -365
- package/dist/adapters/index.js +682 -2
- package/dist/adapters/index.js.map +1 -1
- package/dist/agent-hitl/index.cjs +21 -10
- package/dist/agent-hitl/index.cjs.map +1 -1
- package/dist/agent-hitl/index.d.cts +30 -30
- package/dist/agent-hitl/index.d.ts +30 -30
- package/dist/agent-hitl/index.js +21 -2
- package/dist/agent-hitl/index.js.map +1 -1
- package/dist/certification/index.cjs +109 -24
- package/dist/certification/index.cjs.map +1 -1
- package/dist/certification/index.d.cts +33 -39
- package/dist/certification/index.d.ts +33 -39
- package/dist/certification/index.js +107 -8
- package/dist/certification/index.js.map +1 -1
- package/dist/discovery/index.cjs +12 -10
- package/dist/discovery/index.cjs.map +1 -1
- package/dist/discovery/index.d.cts +2 -10
- package/dist/discovery/index.d.ts +2 -10
- package/dist/discovery/index.js +12 -2
- package/dist/discovery/index.js.map +1 -1
- package/dist/engine-B4csEOEc.js +223 -0
- package/dist/engine-B4csEOEc.js.map +1 -0
- package/dist/engine-BqScuhrT.cjs +246 -0
- package/dist/engine-BqScuhrT.cjs.map +1 -0
- package/dist/events/index.cjs +39 -10
- package/dist/events/index.cjs.map +1 -1
- package/dist/events/index.d.cts +43 -43
- package/dist/events/index.d.ts +43 -43
- package/dist/events/index.js +39 -2
- package/dist/events/index.js.map +1 -1
- package/dist/evidence/index.cjs +12 -50
- package/dist/evidence/index.d.cts +2 -229
- package/dist/evidence/index.d.ts +2 -229
- package/dist/evidence/index.js +1 -5
- package/dist/evidence-BuCICb0c.js +516 -0
- package/dist/evidence-BuCICb0c.js.map +1 -0
- package/dist/evidence-Cq48eDvA.cjs +575 -0
- package/dist/evidence-Cq48eDvA.cjs.map +1 -0
- package/dist/governance/index.cjs +24 -18
- package/dist/governance/index.cjs.map +1 -1
- package/dist/governance/index.d.cts +80 -83
- package/dist/governance/index.d.ts +80 -83
- package/dist/governance/index.js +22 -2
- package/dist/governance/index.js.map +1 -1
- package/dist/ids/index.cjs +52 -22
- package/dist/ids/index.cjs.map +1 -1
- package/dist/ids/index.d.cts +17 -17
- package/dist/ids/index.d.ts +17 -17
- package/dist/ids/index.js +49 -2
- package/dist/ids/index.js.map +1 -1
- package/dist/index-9jasmw76.d.cts +124 -0
- package/dist/index-BXpeFdk2.d.cts +190 -0
- package/dist/index-BXpeFdk2.d.ts +190 -0
- package/dist/index-BnbsKZsT.d.cts +231 -0
- package/dist/index-CIl1rYRv.d.cts +11 -0
- package/dist/index-CIl1rYRv.d.ts +11 -0
- package/dist/index-CVHA1ypT.d.cts +262 -0
- package/dist/index-DZ4mnNb7.d.cts +78 -0
- package/dist/index-DZ4mnNb7.d.ts +78 -0
- package/dist/index-IqcDvl69.d.ts +124 -0
- package/dist/index-fmUiRBXu.d.cts +57 -0
- package/dist/index-fmUiRBXu.d.ts +57 -0
- package/dist/index-sPUPs8pr.d.ts +262 -0
- package/dist/index-z9-CYOIo.d.ts +231 -0
- package/dist/index.cjs +111 -385
- package/dist/index.d.cts +18 -17
- package/dist/index.d.ts +18 -17
- package/dist/index.js +19 -20
- package/dist/manifest/index.cjs +224 -35
- package/dist/manifest/index.cjs.map +1 -1
- package/dist/manifest/index.d.cts +130 -131
- package/dist/manifest/index.d.ts +130 -131
- package/dist/manifest/index.js +219 -7
- package/dist/manifest/index.js.map +1 -1
- package/dist/modules/index.cjs +281 -42
- package/dist/modules/index.cjs.map +1 -1
- package/dist/modules/index.d.cts +157 -159
- package/dist/modules/index.d.ts +157 -159
- package/dist/modules/index.js +274 -6
- package/dist/modules/index.js.map +1 -1
- package/dist/objects/index.cjs +355 -22
- package/dist/objects/index.cjs.map +1 -1
- package/dist/objects/index.d.cts +2 -77
- package/dist/objects/index.d.ts +2 -77
- package/dist/objects/index.js +352 -2
- package/dist/objects/index.js.map +1 -1
- package/dist/policies/index.cjs +14 -48
- package/dist/policies/index.d.cts +2 -247
- package/dist/policies/index.d.ts +2 -247
- package/dist/policies/index.js +1 -3
- package/dist/policies-DH_GCXQ-.js +627 -0
- package/dist/policies-DH_GCXQ-.js.map +1 -0
- package/dist/policies-Nxbp1CH8.cjs +698 -0
- package/dist/policies-Nxbp1CH8.cjs.map +1 -0
- package/dist/privacy/index.cjs +26 -43
- package/dist/privacy/index.cjs.map +1 -1
- package/dist/privacy/index.d.cts +2 -189
- package/dist/privacy/index.d.ts +2 -189
- package/dist/privacy/index.js +18 -3
- package/dist/privacy/index.js.map +1 -1
- package/dist/projections/index.cjs +241 -23
- package/dist/projections/index.cjs.map +1 -1
- package/dist/projections/index.d.cts +2 -125
- package/dist/projections/index.d.ts +2 -125
- package/dist/projections/index.js +238 -3
- package/dist/projections/index.js.map +1 -1
- package/dist/state-machines/index.cjs +76 -18
- package/dist/state-machines/index.cjs.map +1 -1
- package/dist/state-machines/index.d.cts +2 -55
- package/dist/state-machines/index.d.ts +2 -55
- package/dist/state-machines/index.js +74 -2
- package/dist/state-machines/index.js.map +1 -1
- package/dist/testing/index.cjs +27 -19
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +17 -19
- package/dist/testing/index.d.ts +17 -19
- package/dist/testing/index.js +25 -3
- package/dist/testing/index.js.map +1 -1
- package/package.json +6 -5
- package/dist/chunk-2AE6TMAX.cjs +0 -44
- package/dist/chunk-2AE6TMAX.cjs.map +0 -1
- package/dist/chunk-6HY35TKB.cjs +0 -491
- package/dist/chunk-6HY35TKB.cjs.map +0 -1
- package/dist/chunk-6UGEIDLC.cjs +0 -26
- package/dist/chunk-6UGEIDLC.cjs.map +0 -1
- package/dist/chunk-7GAWSUOG.js +0 -64
- package/dist/chunk-7GAWSUOG.js.map +0 -1
- package/dist/chunk-AFXFAEWA.js +0 -673
- package/dist/chunk-AFXFAEWA.js.map +0 -1
- package/dist/chunk-AFXKSIVI.cjs +0 -540
- package/dist/chunk-AFXKSIVI.cjs.map +0 -1
- package/dist/chunk-B5DOGDPG.js +0 -42
- package/dist/chunk-B5DOGDPG.js.map +0 -1
- package/dist/chunk-BJGZE3GE.js +0 -20
- package/dist/chunk-BJGZE3GE.js.map +0 -1
- package/dist/chunk-CRZXTZ36.cjs +0 -258
- package/dist/chunk-CRZXTZ36.cjs.map +0 -1
- package/dist/chunk-D4SWRBUH.cjs +0 -22
- package/dist/chunk-D4SWRBUH.cjs.map +0 -1
- package/dist/chunk-DBTAUI6C.cjs +0 -395
- package/dist/chunk-DBTAUI6C.cjs.map +0 -1
- package/dist/chunk-EMSAFNPX.js +0 -98
- package/dist/chunk-EMSAFNPX.js.map +0 -1
- package/dist/chunk-F3E5SXPN.cjs +0 -28
- package/dist/chunk-F3E5SXPN.cjs.map +0 -1
- package/dist/chunk-HEYMMVDP.js +0 -480
- package/dist/chunk-HEYMMVDP.js.map +0 -1
- package/dist/chunk-IFW43ELT.cjs +0 -331
- package/dist/chunk-IFW43ELT.cjs.map +0 -1
- package/dist/chunk-LFE74IJX.js +0 -20
- package/dist/chunk-LFE74IJX.js.map +0 -1
- package/dist/chunk-LZSE6QGQ.cjs +0 -60
- package/dist/chunk-LZSE6QGQ.cjs.map +0 -1
- package/dist/chunk-MCWSUGB3.cjs +0 -102
- package/dist/chunk-MCWSUGB3.cjs.map +0 -1
- package/dist/chunk-MLBALEUR.js +0 -290
- package/dist/chunk-MLBALEUR.js.map +0 -1
- package/dist/chunk-NNXQZPB3.cjs +0 -31
- package/dist/chunk-NNXQZPB3.cjs.map +0 -1
- package/dist/chunk-OFCCZ27Z.js +0 -26
- package/dist/chunk-OFCCZ27Z.js.map +0 -1
- package/dist/chunk-PDN5DOLQ.js +0 -242
- package/dist/chunk-PDN5DOLQ.js.map +0 -1
- package/dist/chunk-PIDZQAEL.js +0 -50
- package/dist/chunk-PIDZQAEL.js.map +0 -1
- package/dist/chunk-Q4Q4JPR3.js +0 -524
- package/dist/chunk-Q4Q4JPR3.js.map +0 -1
- package/dist/chunk-RALMUSOX.js +0 -55
- package/dist/chunk-RALMUSOX.js.map +0 -1
- package/dist/chunk-SNTV45LH.cjs +0 -295
- package/dist/chunk-SNTV45LH.cjs.map +0 -1
- package/dist/chunk-TBS2S5AX.cjs +0 -40
- package/dist/chunk-TBS2S5AX.cjs.map +0 -1
- package/dist/chunk-TYNIFC7J.js +0 -253
- package/dist/chunk-TYNIFC7J.js.map +0 -1
- package/dist/chunk-UGWGHTNC.cjs +0 -56
- package/dist/chunk-UGWGHTNC.cjs.map +0 -1
- package/dist/chunk-WI7CWNYI.cjs +0 -68
- package/dist/chunk-WI7CWNYI.cjs.map +0 -1
- package/dist/chunk-WNZP53GI.js +0 -386
- package/dist/chunk-WNZP53GI.js.map +0 -1
- package/dist/chunk-WQ3BYI7T.cjs +0 -249
- package/dist/chunk-WQ3BYI7T.cjs.map +0 -1
- package/dist/chunk-Y2PJLRIY.js +0 -36
- package/dist/chunk-Y2PJLRIY.js.map +0 -1
- package/dist/chunk-YGIPN3TU.cjs +0 -684
- package/dist/chunk-YGIPN3TU.cjs.map +0 -1
- package/dist/chunk-ZAEVQSB5.js +0 -326
- package/dist/chunk-ZAEVQSB5.js.map +0 -1
- package/dist/chunk-ZMQTV5OJ.js +0 -27
- package/dist/chunk-ZMQTV5OJ.js.map +0 -1
- package/dist/evidence/index.cjs.map +0 -1
- package/dist/evidence/index.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/policies/index.cjs.map +0 -1
- package/dist/policies/index.js.map +0 -1
package/dist/modules/index.d.ts
CHANGED
|
@@ -1,93 +1,92 @@
|
|
|
1
|
-
import { ActionDefinition } from
|
|
2
|
-
import { JsonValue, PortableJsonSchema } from
|
|
3
|
-
import { PolicyId, PolicyEvaluator } from
|
|
4
|
-
import { StateMachineDefinition } from
|
|
5
|
-
import { ViewContract } from
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
type
|
|
37
|
-
type
|
|
38
|
-
|
|
39
|
-
|
|
1
|
+
import { ActionDefinition } from "../actions/index.js";
|
|
2
|
+
import { i as JsonValue, o as PortableJsonSchema } from "../index-DZ4mnNb7.js";
|
|
3
|
+
import { C as PolicyId, _ as PolicyEvaluator } from "../index-sPUPs8pr.js";
|
|
4
|
+
import { i as StateMachineDefinition } from "../index-fmUiRBXu.js";
|
|
5
|
+
import { l as ViewContract } from "../index-IqcDvl69.js";
|
|
6
|
+
//#region modules/index.d.ts
|
|
7
|
+
export interface ModuleDependency {
|
|
8
|
+
namespace: string;
|
|
9
|
+
version?: string;
|
|
10
|
+
optional?: boolean;
|
|
11
|
+
}
|
|
12
|
+
export type ModuleDependencyInput = string | ModuleDependency;
|
|
13
|
+
export interface IdPrefixRegistration {
|
|
14
|
+
prefix: string;
|
|
15
|
+
name: string;
|
|
16
|
+
module: string;
|
|
17
|
+
}
|
|
18
|
+
export interface EventTypeRegistration {
|
|
19
|
+
eventType: string;
|
|
20
|
+
schemaVersion: number;
|
|
21
|
+
description?: string;
|
|
22
|
+
schema?: PortableJsonSchema;
|
|
23
|
+
}
|
|
24
|
+
export type EventTypeRegistrationInput = string | EventTypeRegistration;
|
|
25
|
+
export interface ObjectTypeRegistration {
|
|
26
|
+
type: string;
|
|
27
|
+
displayName?: string;
|
|
28
|
+
idPrefix?: string;
|
|
29
|
+
isCoreModuleType?: boolean;
|
|
30
|
+
schema?: PortableJsonSchema;
|
|
31
|
+
semantics?: Record<string, JsonValue>;
|
|
32
|
+
relations?: ObjectRelationDefinition[];
|
|
33
|
+
invariants?: DeclarativeInvariant[];
|
|
34
|
+
}
|
|
35
|
+
export type ObjectRelationCardinality = "one" | "many";
|
|
36
|
+
export type ObjectRelationSemantics = "reference" | "owned";
|
|
37
|
+
export type ObjectRelationDeleteBehavior = "restrict" | "cascade" | "set-null";
|
|
38
|
+
export interface ObjectRelationDefinition {
|
|
39
|
+
name: string;
|
|
40
|
+
target: `${string}.${string}`;
|
|
41
|
+
cardinality: ObjectRelationCardinality;
|
|
42
|
+
required?: boolean;
|
|
43
|
+
semantics: ObjectRelationSemantics;
|
|
44
|
+
onTargetDelete: ObjectRelationDeleteBehavior;
|
|
45
|
+
}
|
|
46
|
+
export type InvariantEnforcement = "json-schema" | "state-machine" | "policy" | "host-adapter" | "application";
|
|
47
|
+
export interface DeclarativeInvariant {
|
|
48
|
+
id: string;
|
|
49
|
+
description: string;
|
|
50
|
+
required?: boolean;
|
|
51
|
+
enforcement: InvariantEnforcement;
|
|
52
|
+
enforcementRef?: string;
|
|
53
|
+
}
|
|
54
|
+
export type ObjectTypeRegistrationInput = string | ObjectTypeRegistration;
|
|
55
|
+
export interface PolicyRegistration {
|
|
56
|
+
id: string;
|
|
57
|
+
version?: string;
|
|
58
|
+
description?: string;
|
|
59
|
+
}
|
|
60
|
+
export interface StateMachineRegistration {
|
|
61
|
+
entityType: string;
|
|
62
|
+
states: string[];
|
|
63
|
+
}
|
|
64
|
+
export interface CapabilityPortRequirement {
|
|
65
|
+
name: string;
|
|
66
|
+
version?: string;
|
|
67
|
+
standard?: {
|
|
40
68
|
name: string;
|
|
41
|
-
target: `${string}.${string}`;
|
|
42
|
-
cardinality: ObjectRelationCardinality;
|
|
43
|
-
required?: boolean;
|
|
44
|
-
semantics: ObjectRelationSemantics;
|
|
45
|
-
onTargetDelete: ObjectRelationDeleteBehavior;
|
|
46
|
-
}
|
|
47
|
-
type InvariantEnforcement = "json-schema" | "state-machine" | "policy" | "host-adapter" | "application";
|
|
48
|
-
interface DeclarativeInvariant {
|
|
49
|
-
id: string;
|
|
50
|
-
description: string;
|
|
51
|
-
required?: boolean;
|
|
52
|
-
enforcement: InvariantEnforcement;
|
|
53
|
-
enforcementRef?: string;
|
|
54
|
-
}
|
|
55
|
-
type ObjectTypeRegistrationInput = string | ObjectTypeRegistration;
|
|
56
|
-
interface PolicyRegistration {
|
|
57
|
-
id: string;
|
|
58
69
|
version?: string;
|
|
59
|
-
|
|
60
|
-
}
|
|
61
|
-
interface
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
}
|
|
79
|
-
interface CapabilityWorkflowTimer {
|
|
80
|
-
/** Workflow-local identity of the deadline, for example "right-to-cure". */
|
|
81
|
-
name: string;
|
|
82
|
-
/** Configuration key the duration is resolved from when the workflow starts. */
|
|
83
|
-
configKey: string;
|
|
84
|
-
description?: string;
|
|
85
|
-
}
|
|
86
|
-
interface CapabilityWorkflowCompensation {
|
|
87
|
-
/** Workflow step whose effect this reverses. */
|
|
88
|
-
step: string;
|
|
89
|
-
/** Governed action that performs the reversal. Must belong to the declaring module. */
|
|
90
|
-
actionId: `${string}.${string}`;
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
export interface CapabilityRequirements {
|
|
73
|
+
ports?: CapabilityPortRequirement[];
|
|
74
|
+
permissions?: string[];
|
|
75
|
+
entitlements?: string[];
|
|
76
|
+
featureFlags?: string[];
|
|
77
|
+
}
|
|
78
|
+
export interface CapabilityWorkflowTimer {
|
|
79
|
+
/** Workflow-local identity of the deadline, for example "right-to-cure". */
|
|
80
|
+
name: string;
|
|
81
|
+
/** Configuration key the duration is resolved from when the workflow starts. */
|
|
82
|
+
configKey: string;
|
|
83
|
+
description?: string;
|
|
84
|
+
}
|
|
85
|
+
export interface CapabilityWorkflowCompensation {
|
|
86
|
+
/** Workflow step whose effect this reverses. */
|
|
87
|
+
step: string;
|
|
88
|
+
/** Governed action that performs the reversal. Must belong to the declaring module. */
|
|
89
|
+
actionId: `${string}.${string}`;
|
|
91
90
|
}
|
|
92
91
|
/**
|
|
93
92
|
* A durable workflow this capability owns. Declaring it makes durability a
|
|
@@ -95,76 +94,75 @@ interface CapabilityWorkflowCompensation {
|
|
|
95
94
|
* the queue it runs on, the deadlines it carries, and what reverses each step
|
|
96
95
|
* are all diffable.
|
|
97
96
|
*/
|
|
98
|
-
interface CapabilityWorkflowDeclaration {
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
}
|
|
107
|
-
interface CapabilityMetadata {
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
}
|
|
126
|
-
interface FabricModule<TDb = unknown> {
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
}
|
|
151
|
-
interface ModuleRegistry<TDb = unknown> {
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
}
|
|
159
|
-
declare function getModuleDependencyNamespace(dependency: ModuleDependencyInput): string;
|
|
160
|
-
declare function getObjectTypeName(objectType: ObjectTypeRegistrationInput): string;
|
|
161
|
-
declare function getEventTypeName(eventType: EventTypeRegistrationInput): string;
|
|
162
|
-
declare function validateModuleNamespace(namespace: string): void;
|
|
163
|
-
declare function createModuleRegistry<TDb = unknown>(modules?: FabricModule<TDb>[]): ModuleRegistry<TDb>;
|
|
164
|
-
declare function validateAndOrderFabricModules<TDb = unknown>(modules: FabricModule<TDb>[]): FabricModule<TDb>[];
|
|
97
|
+
export interface CapabilityWorkflowDeclaration {
|
|
98
|
+
name: string;
|
|
99
|
+
/** Routing identity, conventionally `capability.vertical`. */
|
|
100
|
+
taskQueue: string;
|
|
101
|
+
/** Event type whose arrival starts this workflow by choreography. */
|
|
102
|
+
startedBy?: string;
|
|
103
|
+
timers?: CapabilityWorkflowTimer[];
|
|
104
|
+
compensations?: CapabilityWorkflowCompensation[];
|
|
105
|
+
}
|
|
106
|
+
export interface CapabilityMetadata {
|
|
107
|
+
displayName: string;
|
|
108
|
+
description: string;
|
|
109
|
+
stability: "experimental" | "beta" | "stable" | "deprecated";
|
|
110
|
+
deprecated?: {
|
|
111
|
+
since: string;
|
|
112
|
+
replacement?: string;
|
|
113
|
+
message: string;
|
|
114
|
+
};
|
|
115
|
+
requirements?: CapabilityRequirements;
|
|
116
|
+
certification?: {
|
|
117
|
+
profile: string;
|
|
118
|
+
required: boolean;
|
|
119
|
+
};
|
|
120
|
+
/** Durable workflows this capability owns, with their queues, deadlines and reversals. */
|
|
121
|
+
workflows?: CapabilityWorkflowDeclaration[];
|
|
122
|
+
/** Namespaced declared data preserved by Platform and interpreted only by its owning package. */
|
|
123
|
+
extensions?: Record<string, JsonValue>;
|
|
124
|
+
}
|
|
125
|
+
export interface FabricModule<TDb = unknown> {
|
|
126
|
+
namespace: string;
|
|
127
|
+
version?: string;
|
|
128
|
+
/** Compiler manifest digest for exact runtime assembly verification. */
|
|
129
|
+
manifestDigest?: string;
|
|
130
|
+
displayName?: string;
|
|
131
|
+
description?: string;
|
|
132
|
+
capability?: CapabilityMetadata;
|
|
133
|
+
dependencies?: ModuleDependencyInput[];
|
|
134
|
+
objectTypes?: ObjectTypeRegistrationInput[];
|
|
135
|
+
subjectTypes?: string[];
|
|
136
|
+
idPrefixes?: IdPrefixRegistration[];
|
|
137
|
+
eventTypes?: EventTypeRegistrationInput[];
|
|
138
|
+
actions?: ActionDefinition<TDb>[];
|
|
139
|
+
policies?: unknown[];
|
|
140
|
+
stateMachines?: unknown[];
|
|
141
|
+
adapterDefinitions?: unknown[];
|
|
142
|
+
permissions?: unknown[];
|
|
143
|
+
roles?: unknown[];
|
|
144
|
+
redactionRules?: unknown[];
|
|
145
|
+
dataClassifications?: unknown[];
|
|
146
|
+
retentionRules?: unknown[];
|
|
147
|
+
evidenceRenderers?: unknown[];
|
|
148
|
+
views?: ViewContract[];
|
|
149
|
+
}
|
|
150
|
+
export interface ModuleRegistry<TDb = unknown> {
|
|
151
|
+
modules: ReadonlyMap<string, FabricModule<TDb>>;
|
|
152
|
+
orderedModules: readonly FabricModule<TDb>[];
|
|
153
|
+
resolveAction(actionId: `${string}.${string}`): ActionDefinition<TDb> | undefined;
|
|
154
|
+
resolvePolicy(policyId: PolicyId): PolicyEvaluator | undefined;
|
|
155
|
+
resolveStateMachine(entityType: string): StateMachineDefinition | undefined;
|
|
156
|
+
resolveView(name: string, version: string): ViewContract | undefined;
|
|
157
|
+
}
|
|
158
|
+
export declare function getModuleDependencyNamespace(dependency: ModuleDependencyInput): string;
|
|
159
|
+
export declare function getObjectTypeName(objectType: ObjectTypeRegistrationInput): string;
|
|
160
|
+
export declare function getEventTypeName(eventType: EventTypeRegistrationInput): string;
|
|
161
|
+
export declare function validateModuleNamespace(namespace: string): void;
|
|
162
|
+
export declare function createModuleRegistry<TDb = unknown>(modules?: FabricModule<TDb>[]): ModuleRegistry<TDb>;
|
|
163
|
+
export declare function validateAndOrderFabricModules<TDb = unknown>(modules: FabricModule<TDb>[]): FabricModule<TDb>[];
|
|
165
164
|
/** @deprecated Use createModuleRegistry(); registration is now explicit and instance-scoped. */
|
|
166
|
-
declare function registerFabricModules<TDb = unknown>(modules: FabricModule<TDb>[]): FabricModule<TDb>[];
|
|
165
|
+
export declare function registerFabricModules<TDb = unknown>(modules: FabricModule<TDb>[]): FabricModule<TDb>[];
|
|
167
166
|
/** @deprecated Use createModuleRegistry([module]); registration is now explicit and instance-scoped. */
|
|
168
|
-
declare function registerFabricModule<TDb = unknown>(module: FabricModule<TDb>): void;
|
|
169
|
-
|
|
170
|
-
export { type CapabilityMetadata, type CapabilityPortRequirement, type CapabilityRequirements, type CapabilityWorkflowCompensation, type CapabilityWorkflowDeclaration, type CapabilityWorkflowTimer, type DeclarativeInvariant, type EventTypeRegistration, type EventTypeRegistrationInput, type FabricModule, type IdPrefixRegistration, type InvariantEnforcement, type ModuleDependency, type ModuleDependencyInput, type ModuleRegistry, type ObjectRelationCardinality, type ObjectRelationDefinition, type ObjectRelationDeleteBehavior, type ObjectRelationSemantics, type ObjectTypeRegistration, type ObjectTypeRegistrationInput, type PolicyRegistration, type StateMachineRegistration, createModuleRegistry, getEventTypeName, getModuleDependencyNamespace, getObjectTypeName, registerFabricModule, registerFabricModules, validateAndOrderFabricModules, validateModuleNamespace };
|
|
167
|
+
export declare function registerFabricModule<TDb = unknown>(module: FabricModule<TDb>): void;
|
|
168
|
+
//#endregion
|
package/dist/modules/index.js
CHANGED
|
@@ -1,7 +1,275 @@
|
|
|
1
|
-
|
|
2
|
-
import
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import { createEventContractRegistry } from "../events/index.js";
|
|
2
|
+
import { assertSurfaceDeclaration } from "../discovery/index.js";
|
|
3
|
+
import { assertPortableJsonSchema } from "../objects/index.js";
|
|
4
|
+
import { viewContractKey } from "../projections/index.js";
|
|
5
|
+
//#region modules/index.ts
|
|
6
|
+
function getModuleDependencyNamespace(dependency) {
|
|
7
|
+
return typeof dependency === "string" ? dependency : dependency.namespace;
|
|
8
|
+
}
|
|
9
|
+
function getObjectTypeName(objectType) {
|
|
10
|
+
return typeof objectType === "string" ? objectType : objectType.type;
|
|
11
|
+
}
|
|
12
|
+
function getEventTypeName(eventType) {
|
|
13
|
+
return typeof eventType === "string" ? eventType : eventType.eventType;
|
|
14
|
+
}
|
|
15
|
+
function validateModuleNamespace(namespace) {
|
|
16
|
+
if (!namespace) throw new Error("Module namespace cannot be empty");
|
|
17
|
+
if (!/^[a-z][a-z0-9-]*$/.test(namespace)) throw new Error(`Invalid module namespace: "${namespace}". Must be lowercase letters, numbers, and hyphens only.`);
|
|
18
|
+
}
|
|
19
|
+
function createModuleRegistry(modules = []) {
|
|
20
|
+
const orderedModules = validateAndOrderFabricModules(modules);
|
|
21
|
+
const registered = new Map(orderedModules.map((module) => [module.namespace, module]));
|
|
22
|
+
const actions = new Map(orderedModules.flatMap((module) => (module.actions ?? []).map((action) => [action.actionId, action])));
|
|
23
|
+
const policies = new Map(orderedModules.flatMap((module) => (module.policies ?? []).map((policy) => {
|
|
24
|
+
const evaluator = policy;
|
|
25
|
+
return [evaluator.policyId, evaluator];
|
|
26
|
+
})));
|
|
27
|
+
const machines = new Map(orderedModules.flatMap((module) => (module.stateMachines ?? []).map((machine) => {
|
|
28
|
+
const definition = machine;
|
|
29
|
+
return [definition.entityType, definition];
|
|
30
|
+
})));
|
|
31
|
+
const views = new Map(orderedModules.flatMap((module) => (module.views ?? []).map((view) => [viewContractKey(view), view])));
|
|
32
|
+
return {
|
|
33
|
+
modules: registered,
|
|
34
|
+
orderedModules,
|
|
35
|
+
resolveAction: (actionId) => actions.get(actionId),
|
|
36
|
+
resolvePolicy: (policyId) => policies.get(policyId),
|
|
37
|
+
resolveStateMachine: (entityType) => machines.get(entityType),
|
|
38
|
+
resolveView: (name, version) => views.get(`${name}@${version}`)
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
function validateIdentifierList(values, label, namespace) {
|
|
42
|
+
for (const value of values ?? []) if (!value) throw new Error(`Module "${namespace}" has an empty ${label} entry.`);
|
|
43
|
+
}
|
|
44
|
+
function assertJsonValue(value, path) {
|
|
45
|
+
if (value === null || typeof value === "string" || typeof value === "boolean") return;
|
|
46
|
+
if (typeof value === "number" && Number.isFinite(value)) return;
|
|
47
|
+
if (Array.isArray(value)) {
|
|
48
|
+
value.forEach((item, index) => assertJsonValue(item, `${path}[${index}]`));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
if (typeof value === "object") {
|
|
52
|
+
for (const [key, child] of Object.entries(value)) assertJsonValue(child, `${path}.${key}`);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
throw new Error(`${path} must contain JSON-serializable values.`);
|
|
56
|
+
}
|
|
57
|
+
function qualifiedObjectType(namespace, type) {
|
|
58
|
+
return `${namespace}.${type}`;
|
|
59
|
+
}
|
|
60
|
+
function validateObjectDefinition(objectType, namespace, context) {
|
|
61
|
+
if (typeof objectType === "string") return;
|
|
62
|
+
if (objectType.schema !== void 0) assertPortableJsonSchema(objectType.schema, `Module "${namespace}" object "${objectType.type}" schema`);
|
|
63
|
+
if (objectType.semantics !== void 0) assertJsonValue(objectType.semantics, `Module "${namespace}" object "${objectType.type}" semantics`);
|
|
64
|
+
const relationNames = /* @__PURE__ */ new Set();
|
|
65
|
+
for (const relation of objectType.relations ?? []) {
|
|
66
|
+
if (!/^[a-z][a-zA-Z0-9]*$/.test(relation.name)) throw new Error(`Module "${namespace}" object "${objectType.type}" has invalid relation name "${relation.name}".`);
|
|
67
|
+
if (relationNames.has(relation.name)) throw new Error(`Module "${namespace}" object "${objectType.type}" has duplicate relation "${relation.name}".`);
|
|
68
|
+
relationNames.add(relation.name);
|
|
69
|
+
if (!/^[a-z][a-z0-9-]*\.[A-Z][a-zA-Z0-9]*$/.test(relation.target)) throw new Error(`Relation "${relation.name}" target "${relation.target}" must be module-qualified.`);
|
|
70
|
+
if (context.availableObjectTypes && !context.availableObjectTypes.has(relation.target)) throw new Error(`Relation "${relation.name}" targets missing object type "${relation.target}".`);
|
|
71
|
+
if (relation.required && relation.onTargetDelete === "set-null") throw new Error(`Required relation "${relation.name}" cannot use onTargetDelete "set-null".`);
|
|
72
|
+
}
|
|
73
|
+
const invariantIds = /* @__PURE__ */ new Set();
|
|
74
|
+
for (const invariant of objectType.invariants ?? []) {
|
|
75
|
+
if (!invariant.id.trim() || !invariant.description.trim()) throw new Error(`Module "${namespace}" object "${objectType.type}" has an invariant without an id or description.`);
|
|
76
|
+
if (invariantIds.has(invariant.id)) throw new Error(`Module "${namespace}" object "${objectType.type}" has duplicate invariant "${invariant.id}".`);
|
|
77
|
+
invariantIds.add(invariant.id);
|
|
78
|
+
if (invariant.required && !invariant.enforcementRef?.trim()) throw new Error(`Required invariant "${invariant.id}" must declare enforcementRef.`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function validateCapabilityWorkflows(module, context) {
|
|
82
|
+
const workflows = module.capability?.workflows ?? [];
|
|
83
|
+
const actionsById = new Map((module.actions ?? []).map((action) => [action.actionId, action]));
|
|
84
|
+
const names = /* @__PURE__ */ new Set();
|
|
85
|
+
for (const workflow of workflows) {
|
|
86
|
+
if (!/^[A-Za-z][A-Za-z0-9_-]*$/.test(workflow.name)) throw new Error(`Module "${module.namespace}" declares invalid workflow name "${workflow.name}".`);
|
|
87
|
+
if (names.has(workflow.name)) throw new Error(`Module "${module.namespace}" declares duplicate workflow "${workflow.name}".`);
|
|
88
|
+
names.add(workflow.name);
|
|
89
|
+
if (!/^[a-z][a-z0-9-]*(\.[a-z][a-z0-9-]*)*$/.test(workflow.taskQueue)) throw new Error(`Module "${module.namespace}" workflow "${workflow.name}" declares invalid task queue "${workflow.taskQueue}".`);
|
|
90
|
+
if (workflow.startedBy !== void 0) {
|
|
91
|
+
if (!(context.plannedEventTypes?.has(workflow.startedBy) ?? (module.eventTypes ?? []).some((eventType) => getEventTypeName(eventType) === workflow.startedBy))) throw new Error(`Module "${module.namespace}" workflow "${workflow.name}" is started by unknown event type "${workflow.startedBy}".`);
|
|
92
|
+
}
|
|
93
|
+
const timerNames = /* @__PURE__ */ new Set();
|
|
94
|
+
for (const timer of workflow.timers ?? []) {
|
|
95
|
+
if (!timer.name.trim() || !timer.configKey.trim()) throw new Error(`Module "${module.namespace}" workflow "${workflow.name}" has a timer without a name or configKey.`);
|
|
96
|
+
if (timerNames.has(timer.name)) throw new Error(`Module "${module.namespace}" workflow "${workflow.name}" declares duplicate timer "${timer.name}".`);
|
|
97
|
+
timerNames.add(timer.name);
|
|
98
|
+
}
|
|
99
|
+
const steps = /* @__PURE__ */ new Set();
|
|
100
|
+
for (const compensation of workflow.compensations ?? []) {
|
|
101
|
+
if (!compensation.step.trim()) throw new Error(`Module "${module.namespace}" workflow "${workflow.name}" has a compensation without a step.`);
|
|
102
|
+
if (steps.has(compensation.step)) throw new Error(`Module "${module.namespace}" workflow "${workflow.name}" declares duplicate compensation for step "${compensation.step}".`);
|
|
103
|
+
steps.add(compensation.step);
|
|
104
|
+
const compensatingAction = actionsById.get(compensation.actionId);
|
|
105
|
+
if (!compensatingAction) throw new Error(`Module "${module.namespace}" workflow "${workflow.name}" compensates step "${compensation.step}" with unknown action "${compensation.actionId}".`);
|
|
106
|
+
if (!compensatingAction.idempotent || compensatingAction.execution?.idempotency === "prohibited") throw new Error(`Module "${module.namespace}" workflow "${workflow.name}" compensates step "${compensation.step}" with non-idempotent action "${compensation.actionId}"; a reversal must be safely repeatable.`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
function validateManifest(module, context = {}) {
|
|
111
|
+
validateModuleNamespace(module.namespace);
|
|
112
|
+
const dependencies = (module.dependencies ?? []).map(getModuleDependencyNamespace);
|
|
113
|
+
const objectTypes = (module.objectTypes ?? []).map(getObjectTypeName);
|
|
114
|
+
const eventTypes = (module.eventTypes ?? []).map(getEventTypeName);
|
|
115
|
+
if (module.capability) {
|
|
116
|
+
if (!module.capability.displayName.trim() || !module.capability.description.trim()) throw new Error(`Module "${module.namespace}" capability requires displayName and description.`);
|
|
117
|
+
for (const namespace of Object.keys(module.capability.extensions ?? {})) if (!/^[a-z][a-z0-9.-]*\.[a-z0-9.-]+\/v[1-9][0-9]*$/.test(namespace)) throw new Error(`Module "${module.namespace}" capability has invalid extension namespace "${namespace}".`);
|
|
118
|
+
for (const port of module.capability.requirements?.ports ?? []) if (!/^[a-z][a-z0-9-]*(?:\.[a-z0-9-]+)*$/.test(port.name)) throw new Error(`Module "${module.namespace}" capability has invalid port requirement "${port.name}".`);
|
|
119
|
+
validateCapabilityWorkflows(module, context);
|
|
120
|
+
}
|
|
121
|
+
for (const eventType of module.eventTypes ?? []) if (typeof eventType !== "string" && eventType.schema) assertPortableJsonSchema(eventType.schema, `Event "${eventType.eventType}" schema`);
|
|
122
|
+
for (const action of module.actions ?? []) {
|
|
123
|
+
if (action.execution?.idempotency === "required" && !action.idempotent) throw new Error(`Action "${action.actionId}" requires idempotency but is not declared idempotent.`);
|
|
124
|
+
if (action.execution?.connectivity === "offline-capturable" && action.execution.idempotency === "prohibited") throw new Error(`Offline action "${action.actionId}" cannot prohibit idempotency.`);
|
|
125
|
+
if (action.execution?.completionDeadlineMs !== void 0 && !(typeof action.execution.completionDeadlineMs === "number" && action.execution.completionDeadlineMs > 0)) throw new Error(`Action "${action.actionId}" completionDeadlineMs must be a positive number of milliseconds.`);
|
|
126
|
+
if (action.execution?.completion === "immediate" && action.execution.completionDeadlineMs !== void 0) throw new Error(`Immediate action "${action.actionId}" cannot declare a completion deadline; nothing external completes it.`);
|
|
127
|
+
}
|
|
128
|
+
for (const view of module.views ?? []) if (view.usage?.collection?.filterSchema) assertPortableJsonSchema(view.usage.collection.filterSchema, `View "${view.name}" filter schema`);
|
|
129
|
+
for (const dependency of dependencies) {
|
|
130
|
+
validateModuleNamespace(dependency);
|
|
131
|
+
if (dependency === module.namespace) throw new Error(`Module "${module.namespace}" cannot depend on itself.`);
|
|
132
|
+
if (context.availableNamespaces && !context.availableNamespaces.has(dependency)) throw new Error(`Module "${module.namespace}" depends on missing module "${dependency}".`);
|
|
133
|
+
}
|
|
134
|
+
validateIdentifierList(objectTypes, "objectTypes", module.namespace);
|
|
135
|
+
validateIdentifierList(module.subjectTypes, "subjectTypes", module.namespace);
|
|
136
|
+
validateIdentifierList(eventTypes, "eventTypes", module.namespace);
|
|
137
|
+
for (const objectType of objectTypes) if (!/^[A-Z][a-zA-Z0-9]*$/.test(objectType)) throw new Error(`Invalid object type: "${objectType}". Object types must be PascalCase alphanumeric.`);
|
|
138
|
+
for (const objectType of module.objectTypes ?? []) {
|
|
139
|
+
if (typeof objectType !== "string") for (const relation of objectType.relations ?? []) {
|
|
140
|
+
const targetNamespace = relation.target.slice(0, relation.target.indexOf("."));
|
|
141
|
+
if (targetNamespace !== module.namespace && !dependencies.includes(targetNamespace)) throw new Error(`Module "${module.namespace}" relation "${relation.name}" targets module "${targetNamespace}" without declaring it as a dependency.`);
|
|
142
|
+
}
|
|
143
|
+
validateObjectDefinition(objectType, module.namespace, context);
|
|
144
|
+
}
|
|
145
|
+
for (const action of module.actions ?? []) {
|
|
146
|
+
assertSurfaceDeclaration(action, `Action "${action?.actionId ?? "unknown"}"`);
|
|
147
|
+
let parameterSchema;
|
|
148
|
+
try {
|
|
149
|
+
parameterSchema = action.schema.toJSONSchema?.();
|
|
150
|
+
} catch {
|
|
151
|
+
parameterSchema = void 0;
|
|
152
|
+
}
|
|
153
|
+
if (parameterSchema !== void 0) assertPortableJsonSchema(parameterSchema, `Action "${action.actionId}" parameters`);
|
|
154
|
+
let resultSchema;
|
|
155
|
+
try {
|
|
156
|
+
resultSchema = action.resultSchema?.toJSONSchema?.();
|
|
157
|
+
} catch {
|
|
158
|
+
resultSchema = void 0;
|
|
159
|
+
}
|
|
160
|
+
if (resultSchema !== void 0) assertPortableJsonSchema(resultSchema, `Action "${action.actionId}" result`);
|
|
161
|
+
if (!/^[a-z][a-z0-9-]*\.[a-z][a-z0-9_]*$/.test(action.actionId)) throw new Error(`Invalid action ID: ${action.actionId}`);
|
|
162
|
+
if (action.namespace !== module.namespace) throw new Error(`Action "${action.actionId}" declares namespace "${action.namespace}" but is registered by module "${module.namespace}".`);
|
|
163
|
+
if (!action.actionId.startsWith(`${module.namespace}.`)) throw new Error(`Action "${action.actionId}" must start with module namespace "${module.namespace}."`);
|
|
164
|
+
if (action.mutatesDomain && action.emitsEvents.length === 0) throw new Error(`Action "${action.actionId}" mutates domain but emits no events. Every mutating action must emit at least one AssetEvent.`);
|
|
165
|
+
if (action.admitSubmission !== void 0 && typeof action.admitSubmission !== "function") throw new Error(`Action "${action.actionId}" declares admitSubmission that is not a function.`);
|
|
166
|
+
}
|
|
167
|
+
const viewKeys = /* @__PURE__ */ new Set();
|
|
168
|
+
for (const view of module.views ?? []) {
|
|
169
|
+
assertSurfaceDeclaration(view, `View "${view?.name ?? "unknown"}"`);
|
|
170
|
+
if (!view.name.startsWith(`${module.namespace}/`) || !/^[a-z][a-z0-9-]*\/[a-z][a-z0-9/_-]*$/.test(view.name)) throw new Error(`View "${view.name}" must start with module namespace "${module.namespace}/" and use lowercase path segments.`);
|
|
171
|
+
if (!view.version.trim()) throw new Error(`View "${view.name}" must declare a version.`);
|
|
172
|
+
const key = `${view.name}@${view.version}`;
|
|
173
|
+
if (viewKeys.has(key)) throw new Error(`Module "${module.namespace}" has duplicate view contract "${key}".`);
|
|
174
|
+
viewKeys.add(key);
|
|
175
|
+
assertPortableJsonSchema(view.shape, `View "${key}" shape`);
|
|
176
|
+
if (view.parameterSchema !== void 0) assertPortableJsonSchema(view.parameterSchema, `View "${key}" parameters`);
|
|
177
|
+
if (!Number.isInteger(view.snapshotVersion) || view.snapshotVersion < 1) throw new Error(`View "${key}" snapshotVersion must be a positive integer.`);
|
|
178
|
+
if ((view.compatibleSnapshotVersions?.some((version) => version !== view.snapshotVersion) ?? false) && !view.upgradeSnapshot) throw new Error(`View "${key}" declares older compatible snapshots but no upgradeSnapshot function.`);
|
|
179
|
+
for (const consumption of view.consumes) {
|
|
180
|
+
const isPlanned = context.plannedEventTypes?.has(consumption.eventType) ?? false;
|
|
181
|
+
const isModuleEvent = eventTypes.includes(consumption.eventType);
|
|
182
|
+
if (!isPlanned && !isModuleEvent) throw new Error(`View "${key}" consumes unknown event type "${consumption.eventType}".`);
|
|
183
|
+
if (consumption.schemaVersions.length === 0 || consumption.schemaVersions.some((version) => !Number.isInteger(version) || version < 1)) throw new Error(`View "${key}" must declare positive consumed schema versions for "${consumption.eventType}".`);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
function sortModulesByDependency(modules, registeredNamespaces = /* @__PURE__ */ new Set()) {
|
|
188
|
+
const modulesByNamespace = /* @__PURE__ */ new Map();
|
|
189
|
+
for (const module of modules) {
|
|
190
|
+
validateModuleNamespace(module.namespace);
|
|
191
|
+
if (modulesByNamespace.has(module.namespace)) throw new Error(`Duplicate FabricModule namespace "${module.namespace}".`);
|
|
192
|
+
modulesByNamespace.set(module.namespace, module);
|
|
193
|
+
}
|
|
194
|
+
const sorted = [];
|
|
195
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
196
|
+
const visited = /* @__PURE__ */ new Set();
|
|
197
|
+
function visit(module, path) {
|
|
198
|
+
if (visited.has(module.namespace)) return;
|
|
199
|
+
if (visiting.has(module.namespace)) throw new Error(`Cyclic Fabric module dependency detected: ${[...path, module.namespace].join(" -> ")}`);
|
|
200
|
+
visiting.add(module.namespace);
|
|
201
|
+
for (const dependency of (module.dependencies ?? []).map(getModuleDependencyNamespace)) {
|
|
202
|
+
const dependencyModule = modulesByNamespace.get(dependency);
|
|
203
|
+
if (!dependencyModule) {
|
|
204
|
+
if (registeredNamespaces.has(dependency)) continue;
|
|
205
|
+
throw new Error(`Module "${module.namespace}" depends on missing module "${dependency}".`);
|
|
206
|
+
}
|
|
207
|
+
visit(dependencyModule, [...path, module.namespace]);
|
|
208
|
+
}
|
|
209
|
+
visiting.delete(module.namespace);
|
|
210
|
+
visited.add(module.namespace);
|
|
211
|
+
sorted.push(module);
|
|
212
|
+
}
|
|
213
|
+
for (const module of modules) visit(module, []);
|
|
214
|
+
return sorted;
|
|
215
|
+
}
|
|
216
|
+
function assertAcyclicRelations(modules) {
|
|
217
|
+
const relationKinds = [
|
|
218
|
+
{
|
|
219
|
+
label: "owned containment",
|
|
220
|
+
include: (relation) => relation.semantics === "owned"
|
|
221
|
+
},
|
|
222
|
+
{
|
|
223
|
+
label: "cascade-delete",
|
|
224
|
+
include: (relation) => relation.onTargetDelete === "cascade"
|
|
225
|
+
},
|
|
226
|
+
{
|
|
227
|
+
label: "required-construction",
|
|
228
|
+
include: (relation) => relation.required === true
|
|
229
|
+
}
|
|
230
|
+
];
|
|
231
|
+
for (const kind of relationKinds) {
|
|
232
|
+
const edges = /* @__PURE__ */ new Map();
|
|
233
|
+
for (const module of modules) for (const objectType of module.objectTypes ?? []) {
|
|
234
|
+
if (typeof objectType === "string") continue;
|
|
235
|
+
const source = qualifiedObjectType(module.namespace, objectType.type);
|
|
236
|
+
edges.set(source, (objectType.relations ?? []).filter(kind.include).map((relation) => relation.target));
|
|
237
|
+
}
|
|
238
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
239
|
+
const visited = /* @__PURE__ */ new Set();
|
|
240
|
+
const visit = (node, path) => {
|
|
241
|
+
if (visiting.has(node)) throw new Error(`${kind.label} relation cycle detected: ${[...path, node].join(" -> ")}`);
|
|
242
|
+
if (visited.has(node)) return;
|
|
243
|
+
visiting.add(node);
|
|
244
|
+
for (const target of edges.get(node) ?? []) visit(target, [...path, node]);
|
|
245
|
+
visiting.delete(node);
|
|
246
|
+
visited.add(node);
|
|
247
|
+
};
|
|
248
|
+
for (const node of edges.keys()) visit(node, []);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
function validateAndOrderFabricModules(modules) {
|
|
252
|
+
const availableNamespaces = new Set(modules.map((module) => module.namespace));
|
|
253
|
+
const plannedEventTypes = new Set(modules.flatMap((module) => (module.eventTypes ?? []).map(getEventTypeName)));
|
|
254
|
+
for (const eventType of createEventContractRegistry().eventTypes()) plannedEventTypes.add(eventType);
|
|
255
|
+
const availableObjectTypes = /* @__PURE__ */ new Set([...modules.flatMap((module) => (module.objectTypes ?? []).map((objectType) => qualifiedObjectType(module.namespace, getObjectTypeName(objectType))))]);
|
|
256
|
+
for (const module of modules) validateManifest(module, {
|
|
257
|
+
availableNamespaces,
|
|
258
|
+
plannedEventTypes,
|
|
259
|
+
availableObjectTypes
|
|
260
|
+
});
|
|
261
|
+
assertAcyclicRelations(modules);
|
|
262
|
+
return sortModulesByDependency(modules);
|
|
263
|
+
}
|
|
264
|
+
/** @deprecated Use createModuleRegistry(); registration is now explicit and instance-scoped. */
|
|
265
|
+
function registerFabricModules(modules) {
|
|
266
|
+
return validateAndOrderFabricModules(modules);
|
|
267
|
+
}
|
|
268
|
+
/** @deprecated Use createModuleRegistry([module]); registration is now explicit and instance-scoped. */
|
|
269
|
+
function registerFabricModule(module) {
|
|
270
|
+
validateAndOrderFabricModules([module]);
|
|
271
|
+
}
|
|
272
|
+
//#endregion
|
|
273
|
+
export { createModuleRegistry, getEventTypeName, getModuleDependencyNamespace, getObjectTypeName, registerFabricModule, registerFabricModules, validateAndOrderFabricModules, validateModuleNamespace };
|
|
274
|
+
|
|
7
275
|
//# sourceMappingURL=index.js.map
|