@fabricorg/platform 0.1.2 → 0.2.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/dist/actions/index.cjs +48 -0
- package/dist/actions/index.cjs.map +1 -0
- package/dist/actions/index.d.cts +116 -0
- package/dist/adapters/index.cjs +28 -0
- package/dist/adapters/index.cjs.map +1 -0
- package/dist/adapters/index.d.cts +83 -0
- package/dist/chunk-7KJHGAZY.cjs +99 -0
- package/dist/chunk-7KJHGAZY.cjs.map +1 -0
- package/dist/chunk-GB2PSZ33.cjs +74 -0
- package/dist/chunk-GB2PSZ33.cjs.map +1 -0
- package/dist/chunk-JAXDEK5Z.cjs +63 -0
- package/dist/chunk-JAXDEK5Z.cjs.map +1 -0
- package/dist/chunk-KQEBNUZI.cjs +70 -0
- package/dist/chunk-KQEBNUZI.cjs.map +1 -0
- package/dist/chunk-LHCSVEFT.cjs +8 -0
- package/dist/chunk-LHCSVEFT.cjs.map +1 -0
- package/dist/chunk-LYX73U3P.cjs +195 -0
- package/dist/chunk-LYX73U3P.cjs.map +1 -0
- package/dist/chunk-LZSE6QGQ.cjs +60 -0
- package/dist/chunk-LZSE6QGQ.cjs.map +1 -0
- package/dist/chunk-NPVIFZQV.cjs +107 -0
- package/dist/chunk-NPVIFZQV.cjs.map +1 -0
- package/dist/chunk-PG5LYTUX.cjs +4 -0
- package/dist/chunk-PG5LYTUX.cjs.map +1 -0
- package/dist/chunk-Q3WYIWCN.cjs +183 -0
- package/dist/chunk-Q3WYIWCN.cjs.map +1 -0
- package/dist/chunk-QETQGAXJ.cjs +35 -0
- package/dist/chunk-QETQGAXJ.cjs.map +1 -0
- package/dist/chunk-SDXDHVTV.cjs +555 -0
- package/dist/chunk-SDXDHVTV.cjs.map +1 -0
- package/dist/chunk-YZKUEC2J.cjs +31 -0
- package/dist/chunk-YZKUEC2J.cjs.map +1 -0
- package/dist/displays/index.cjs +24 -0
- package/dist/displays/index.cjs.map +1 -0
- package/dist/displays/index.d.cts +34 -0
- package/dist/events/index.cjs +36 -0
- package/dist/events/index.cjs.map +1 -0
- package/dist/events/index.d.cts +35 -0
- package/dist/evidence/index.cjs +6 -0
- package/dist/evidence/index.cjs.map +1 -0
- package/dist/evidence/index.d.cts +43 -0
- package/dist/ids/index.cjs +24 -0
- package/dist/ids/index.cjs.map +1 -0
- package/dist/ids/index.d.cts +19 -0
- package/dist/index.cjs +268 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +13 -0
- package/dist/modules/index.cjs +42 -0
- package/dist/modules/index.cjs.map +1 -0
- package/dist/modules/index.d.cts +73 -0
- package/dist/objects/index.cjs +24 -0
- package/dist/objects/index.cjs.map +1 -0
- package/dist/objects/index.d.cts +7 -0
- package/dist/policies/index.cjs +48 -0
- package/dist/policies/index.cjs.map +1 -0
- package/dist/policies/index.d.cts +143 -0
- package/dist/privacy/index.cjs +12 -0
- package/dist/privacy/index.cjs.map +1 -0
- package/dist/privacy/index.d.cts +77 -0
- package/dist/projections/index.cjs +12 -0
- package/dist/projections/index.cjs.map +1 -0
- package/dist/projections/index.d.cts +52 -0
- package/dist/state-machines/index.cjs +32 -0
- package/dist/state-machines/index.cjs.map +1 -0
- package/dist/state-machines/index.d.cts +60 -0
- package/dist/testing/index.cjs +21 -0
- package/dist/testing/index.cjs.map +1 -0
- package/dist/testing/index.d.cts +19 -0
- package/package.json +196 -111
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../privacy/index.ts"],"names":[],"mappings":";;;AAAO,IAAM,+BAAA,GAAkC","file":"chunk-LHCSVEFT.cjs","sourcesContent":["export const PLATFORM_PRIVACY_POLICY_VERSION = \"fabric-platform-privacy-v1\";\n\nexport type RedactionMethod = \"nullify\" | \"mask\" | \"hash\" | \"tokenize\" | \"generalize\" | \"drop\";\n\nexport type PlatformDataClass =\n\t| \"asset_event\"\n\t| \"read_model\"\n\t| \"raw_payload\"\n\t| \"evidence_packet\"\n\t| \"action_evidence\"\n\t| \"access_event\";\n\nexport interface RedactionRule {\n\tfieldPath: string;\n\tmethod: RedactionMethod;\n\treason: string;\n\tdataClass?: PlatformDataClass;\n}\n\nexport interface DataClassificationRule {\n\tfieldPath: string;\n\tclassification: string;\n\tcontainsDirectIdentifier?: boolean;\n\tcontainsSensitiveData?: boolean;\n}\n\nexport interface AnonymizationContext {\n\ttenantId: string;\n\tspaceId?: string | null;\n\tjobId: string;\n\treason: string;\n\tredactedAt?: Date;\n\tpolicyVersion?: string;\n}\n\nexport interface AnonymizationFieldMetadata {\n\tfieldPath: string;\n\tmethod: RedactionMethod;\n\tpolicyVersion: string;\n\tjobId: string;\n\tredactedAt: string;\n\treason: string;\n\tdataClass: PlatformDataClass;\n\tbeforeChecksum: string;\n}\n\nexport interface AnonymizationMetadata {\n\tredactionState: \"anonymized\";\n\tpolicyVersion: string;\n\tjobId: string;\n\tredactedAt: string;\n\treason: string;\n\tdataClass: PlatformDataClass;\n\tredactedFields: AnonymizationFieldMetadata[];\n\tpreservedSemantics: string[];\n}\n\nexport interface AnonymizationResult<TValue> {\n\tvalue: TValue;\n\tmetadata: AnonymizationMetadata;\n}\n\nexport interface AnalyticsDataContractSource {\n\tname: string;\n\tprivacyClass:\n\t\t| \"raw\"\n\t\t| \"operational_pii\"\n\t\t| \"tenant_scoped_tokenized\"\n\t\t| \"anonymized\"\n\t\t| \"aggregated\"\n\t\t| \"differentially_minimized\";\n\tcontainsDirectIdentifiers?: boolean;\n\tcontainsGloballyStablePersonTokens?: boolean;\n\tanonymizationPolicyVersion?: string;\n\tminimumGroupSize?: number;\n}\n\nexport interface AnalyticsDataContract {\n\tcontractId: string;\n\tstatus: \"draft\" | \"accepted\" | \"deprecated\";\n\tcrossTenant: boolean;\n\tacceptedBy?: string;\n\tacceptedAt?: string;\n\tadrReference?: string;\n\tsources: AnalyticsDataContractSource[];\n}\n\nexport interface AnalyticsEligibilityDecision {\n\teligible: boolean;\n\tpolicyVersion: string;\n\treasons: string[];\n}\n\nexport interface RetentionRule {\n\tdataClass: PlatformDataClass;\n\tretainForDays: number;\n\tafterRetention: \"delete\" | \"anonymize\" | \"archive\";\n\tlegalHoldExempt?: boolean;\n}\n"]}
|
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var chunkQETQGAXJ_cjs = require('./chunk-QETQGAXJ.cjs');
|
|
4
|
+
var chunkSDXDHVTV_cjs = require('./chunk-SDXDHVTV.cjs');
|
|
5
|
+
var chunkGB2PSZ33_cjs = require('./chunk-GB2PSZ33.cjs');
|
|
6
|
+
var chunkKQEBNUZI_cjs = require('./chunk-KQEBNUZI.cjs');
|
|
7
|
+
var chunk7KJHGAZY_cjs = require('./chunk-7KJHGAZY.cjs');
|
|
8
|
+
var chunkJAXDEK5Z_cjs = require('./chunk-JAXDEK5Z.cjs');
|
|
9
|
+
|
|
10
|
+
// modules/index.ts
|
|
11
|
+
var registeredModuleNamespaces = /* @__PURE__ */ new Set();
|
|
12
|
+
function getModuleDependencyNamespace(dependency) {
|
|
13
|
+
return typeof dependency === "string" ? dependency : dependency.namespace;
|
|
14
|
+
}
|
|
15
|
+
function getObjectTypeName(objectType) {
|
|
16
|
+
return typeof objectType === "string" ? objectType : objectType.type;
|
|
17
|
+
}
|
|
18
|
+
function getEventTypeName(eventType) {
|
|
19
|
+
return typeof eventType === "string" ? eventType : eventType.eventType;
|
|
20
|
+
}
|
|
21
|
+
function validateModuleNamespace(namespace) {
|
|
22
|
+
if (!namespace) {
|
|
23
|
+
throw new Error("Module namespace cannot be empty");
|
|
24
|
+
}
|
|
25
|
+
if (!/^[a-z][a-z0-9-]*$/.test(namespace)) {
|
|
26
|
+
throw new Error(
|
|
27
|
+
`Invalid module namespace: "${namespace}". Must be lowercase letters, numbers, and hyphens only.`
|
|
28
|
+
);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
function createModuleRegistry(modules = []) {
|
|
32
|
+
const registered = /* @__PURE__ */ new Map();
|
|
33
|
+
for (const module of modules) {
|
|
34
|
+
validateModuleNamespace(module.namespace);
|
|
35
|
+
if (registered.has(module.namespace)) {
|
|
36
|
+
throw new Error(`Duplicate FabricModule namespace "${module.namespace}".`);
|
|
37
|
+
}
|
|
38
|
+
registered.set(module.namespace, module);
|
|
39
|
+
}
|
|
40
|
+
return { modules: registered };
|
|
41
|
+
}
|
|
42
|
+
function validateIdentifierList(values, label, namespace) {
|
|
43
|
+
for (const value of values ?? []) {
|
|
44
|
+
if (!value) {
|
|
45
|
+
throw new Error(`Module "${namespace}" has an empty ${label} entry.`);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
function validateManifest(module, context = {}) {
|
|
50
|
+
validateModuleNamespace(module.namespace);
|
|
51
|
+
const dependencies = (module.dependencies ?? []).map(getModuleDependencyNamespace);
|
|
52
|
+
const objectTypes = (module.objectTypes ?? []).map(getObjectTypeName);
|
|
53
|
+
const eventTypes = (module.eventTypes ?? []).map(getEventTypeName);
|
|
54
|
+
for (const dependency of dependencies) {
|
|
55
|
+
validateModuleNamespace(dependency);
|
|
56
|
+
if (dependency === module.namespace) {
|
|
57
|
+
throw new Error(`Module "${module.namespace}" cannot depend on itself.`);
|
|
58
|
+
}
|
|
59
|
+
if (context.availableNamespaces && !context.availableNamespaces.has(dependency)) {
|
|
60
|
+
throw new Error(`Module "${module.namespace}" depends on missing module "${dependency}".`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
validateIdentifierList(objectTypes, "objectTypes", module.namespace);
|
|
64
|
+
validateIdentifierList(module.subjectTypes, "subjectTypes", module.namespace);
|
|
65
|
+
validateIdentifierList(eventTypes, "eventTypes", module.namespace);
|
|
66
|
+
for (const objectType of objectTypes) {
|
|
67
|
+
if (!/^[A-Z][a-zA-Z0-9]*$/.test(objectType)) {
|
|
68
|
+
throw new Error(
|
|
69
|
+
`Invalid object type: "${objectType}". Object types must be PascalCase alphanumeric.`
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
for (const action of module.actions ?? []) {
|
|
74
|
+
if (!/^[a-z][a-z0-9-]*\.[a-z][a-z0-9_]*$/.test(action.actionId)) {
|
|
75
|
+
throw new Error(`Invalid action ID: ${action.actionId}`);
|
|
76
|
+
}
|
|
77
|
+
if (action.namespace !== module.namespace) {
|
|
78
|
+
throw new Error(
|
|
79
|
+
`Action "${action.actionId}" declares namespace "${action.namespace}" but is registered by module "${module.namespace}".`
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
if (!action.actionId.startsWith(`${module.namespace}.`)) {
|
|
83
|
+
throw new Error(
|
|
84
|
+
`Action "${action.actionId}" must start with module namespace "${module.namespace}."`
|
|
85
|
+
);
|
|
86
|
+
}
|
|
87
|
+
if (action.mutatesDomain && action.emitsEvents.length === 0) {
|
|
88
|
+
throw new Error(
|
|
89
|
+
`Action "${action.actionId}" mutates domain but emits no events. Every mutating action must emit at least one AssetEvent.`
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
for (const descriptor of module.displayRenderers ?? []) {
|
|
94
|
+
const isPlannedEventType = context.plannedEventTypes?.has(descriptor.eventType) ?? false;
|
|
95
|
+
const isModuleEventType = eventTypes.includes(descriptor.eventType);
|
|
96
|
+
if (!chunkJAXDEK5Z_cjs.isValidEventType(descriptor.eventType) && !isModuleEventType && !isPlannedEventType) {
|
|
97
|
+
throw new Error(
|
|
98
|
+
`Display renderer registered for unknown event type "${descriptor.eventType}". Register the event type before adding a display renderer.`
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
function sortModulesByDependency(modules, registeredNamespaces = registeredModuleNamespaces) {
|
|
104
|
+
const modulesByNamespace = /* @__PURE__ */ new Map();
|
|
105
|
+
for (const module of modules) {
|
|
106
|
+
validateModuleNamespace(module.namespace);
|
|
107
|
+
if (modulesByNamespace.has(module.namespace)) {
|
|
108
|
+
throw new Error(`Duplicate Fabric module namespace "${module.namespace}".`);
|
|
109
|
+
}
|
|
110
|
+
modulesByNamespace.set(module.namespace, module);
|
|
111
|
+
}
|
|
112
|
+
const sorted = [];
|
|
113
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
114
|
+
const visited = /* @__PURE__ */ new Set();
|
|
115
|
+
function visit(module, path) {
|
|
116
|
+
if (visited.has(module.namespace)) {
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
if (visiting.has(module.namespace)) {
|
|
120
|
+
throw new Error(
|
|
121
|
+
`Cyclic Fabric module dependency detected: ${[...path, module.namespace].join(" -> ")}`
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
visiting.add(module.namespace);
|
|
125
|
+
for (const dependency of (module.dependencies ?? []).map(getModuleDependencyNamespace)) {
|
|
126
|
+
const dependencyModule = modulesByNamespace.get(dependency);
|
|
127
|
+
if (!dependencyModule) {
|
|
128
|
+
if (registeredNamespaces.has(dependency)) {
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
throw new Error(`Module "${module.namespace}" depends on missing module "${dependency}".`);
|
|
132
|
+
}
|
|
133
|
+
visit(dependencyModule, [...path, module.namespace]);
|
|
134
|
+
}
|
|
135
|
+
visiting.delete(module.namespace);
|
|
136
|
+
visited.add(module.namespace);
|
|
137
|
+
sorted.push(module);
|
|
138
|
+
}
|
|
139
|
+
for (const module of modules) {
|
|
140
|
+
visit(module, []);
|
|
141
|
+
}
|
|
142
|
+
return sorted;
|
|
143
|
+
}
|
|
144
|
+
function registerFabricModule(module) {
|
|
145
|
+
validateManifest(module, { availableNamespaces: registeredModuleNamespaces });
|
|
146
|
+
for (const objectType of module.objectTypes ?? []) {
|
|
147
|
+
chunkQETQGAXJ_cjs.registerObjectType(getObjectTypeName(objectType));
|
|
148
|
+
}
|
|
149
|
+
for (const subjectType of module.subjectTypes ?? []) {
|
|
150
|
+
chunkJAXDEK5Z_cjs.registerSubjectType(subjectType);
|
|
151
|
+
}
|
|
152
|
+
for (const eventType of module.eventTypes ?? []) {
|
|
153
|
+
chunkJAXDEK5Z_cjs.registerEventType(getEventTypeName(eventType));
|
|
154
|
+
}
|
|
155
|
+
for (const policy of module.policies ?? []) {
|
|
156
|
+
chunkSDXDHVTV_cjs.registerPolicyIfMissing(policy);
|
|
157
|
+
}
|
|
158
|
+
for (const machine of module.stateMachines ?? []) {
|
|
159
|
+
chunkGB2PSZ33_cjs.registerStateMachineIfMissing(machine);
|
|
160
|
+
}
|
|
161
|
+
for (const action of module.actions ?? []) {
|
|
162
|
+
chunkKQEBNUZI_cjs.registerActionIfMissing(action);
|
|
163
|
+
}
|
|
164
|
+
for (const descriptor of module.displayRenderers ?? []) {
|
|
165
|
+
chunk7KJHGAZY_cjs.registerDisplayRenderer(descriptor.eventType, descriptor.renderer);
|
|
166
|
+
}
|
|
167
|
+
registeredModuleNamespaces.add(module.namespace);
|
|
168
|
+
}
|
|
169
|
+
function registerFabricModules(modules) {
|
|
170
|
+
const availableNamespaces = /* @__PURE__ */ new Set([
|
|
171
|
+
...registeredModuleNamespaces,
|
|
172
|
+
...modules.map((module) => module.namespace)
|
|
173
|
+
]);
|
|
174
|
+
const plannedEventTypes = new Set(
|
|
175
|
+
modules.flatMap((module) => (module.eventTypes ?? []).map(getEventTypeName))
|
|
176
|
+
);
|
|
177
|
+
for (const module of modules) {
|
|
178
|
+
validateManifest(module, { availableNamespaces, plannedEventTypes });
|
|
179
|
+
}
|
|
180
|
+
const sortedModules = sortModulesByDependency(modules);
|
|
181
|
+
for (const module of sortedModules) {
|
|
182
|
+
registerFabricModule(module);
|
|
183
|
+
}
|
|
184
|
+
return sortedModules;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
exports.createModuleRegistry = createModuleRegistry;
|
|
188
|
+
exports.getEventTypeName = getEventTypeName;
|
|
189
|
+
exports.getModuleDependencyNamespace = getModuleDependencyNamespace;
|
|
190
|
+
exports.getObjectTypeName = getObjectTypeName;
|
|
191
|
+
exports.registerFabricModule = registerFabricModule;
|
|
192
|
+
exports.registerFabricModules = registerFabricModules;
|
|
193
|
+
exports.validateModuleNamespace = validateModuleNamespace;
|
|
194
|
+
//# sourceMappingURL=chunk-LYX73U3P.cjs.map
|
|
195
|
+
//# sourceMappingURL=chunk-LYX73U3P.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../modules/index.ts"],"names":["isValidEventType","registerObjectType","registerSubjectType","registerEventType","registerPolicyIfMissing","registerStateMachineIfMissing","registerActionIfMissing","registerDisplayRenderer"],"mappings":"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","file":"chunk-LYX73U3P.cjs","sourcesContent":["import { registerActionIfMissing, type ActionDefinition } from \"../actions\";\nimport { registerDisplayRenderer, type DisplayRenderer } from \"../displays\";\nimport { isValidEventType, registerEventType, registerSubjectType } from \"../events\";\nimport { registerObjectType } from \"../objects\";\nimport { registerPolicyIfMissing, type PolicyEvaluator } from \"../policies\";\nimport { registerStateMachineIfMissing, type StateMachineDefinition } from \"../state-machines\";\n\nexport interface ModuleDependency {\n\tnamespace: string;\n\tversion?: string;\n\toptional?: boolean;\n}\n\nexport type ModuleDependencyInput = string | ModuleDependency;\n\nexport interface IdPrefixRegistration {\n\tprefix: string;\n\tname: string;\n\tmodule: string;\n}\n\nexport interface EventTypeRegistration {\n\teventType: string;\n\tschemaVersion: number;\n\tdescription?: string;\n}\n\nexport type EventTypeRegistrationInput = string | EventTypeRegistration;\n\nexport interface ObjectTypeRegistration {\n\ttype: string;\n\tdisplayName?: string;\n\tidPrefix?: string;\n\tisCoreModuleType?: boolean;\n}\n\nexport type ObjectTypeRegistrationInput = string | ObjectTypeRegistration;\n\nexport interface ModuleDisplayRendererRegistration {\n\teventType: string;\n\trenderer: (payload: unknown, ctx?: any) => unknown;\n}\n\nexport interface PolicyRegistration {\n\tid: string;\n\tversion?: string;\n\tdescription?: string;\n}\n\nexport interface StateMachineRegistration {\n\tentityType: string;\n\tstates: string[];\n}\n\nexport interface FabricModule<TDb = unknown> {\n\tnamespace: string;\n\tversion?: string;\n\tdisplayName?: string;\n\tdescription?: string;\n\tdependencies?: ModuleDependencyInput[];\n\tobjectTypes?: ObjectTypeRegistrationInput[];\n\tsubjectTypes?: string[];\n\tidPrefixes?: IdPrefixRegistration[];\n\teventTypes?: EventTypeRegistrationInput[];\n\tactions?: ActionDefinition<TDb>[];\n\tpolicies?: unknown[];\n\tstateMachines?: unknown[];\n\tdisplayRenderers?: ModuleDisplayRendererRegistration[];\n\tadapterDefinitions?: unknown[];\n\tpermissions?: unknown[];\n\troles?: unknown[];\n\tredactionRules?: unknown[];\n\tdataClassifications?: unknown[];\n\tretentionRules?: unknown[];\n\tevidenceRenderers?: unknown[];\n}\n\nexport interface ModuleRegistry<TDb = unknown> {\n\tmodules: ReadonlyMap<string, FabricModule<TDb>>;\n}\n\ninterface ModuleValidationContext {\n\tavailableNamespaces?: Set<string>;\n\tplannedEventTypes?: Set<string>;\n}\n\nconst registeredModuleNamespaces = new Set<string>();\n\nexport function getModuleDependencyNamespace(dependency: ModuleDependencyInput): string {\n\treturn typeof dependency === \"string\" ? dependency : dependency.namespace;\n}\n\nexport function getObjectTypeName(objectType: ObjectTypeRegistrationInput): string {\n\treturn typeof objectType === \"string\" ? objectType : objectType.type;\n}\n\nexport function getEventTypeName(eventType: EventTypeRegistrationInput): string {\n\treturn typeof eventType === \"string\" ? eventType : eventType.eventType;\n}\n\nexport function validateModuleNamespace(namespace: string): void {\n\tif (!namespace) {\n\t\tthrow new Error(\"Module namespace cannot be empty\");\n\t}\n\tif (!/^[a-z][a-z0-9-]*$/.test(namespace)) {\n\t\tthrow new Error(\n\t\t\t`Invalid module namespace: \"${namespace}\". Must be lowercase letters, numbers, and hyphens only.`,\n\t\t);\n\t}\n}\n\nexport function createModuleRegistry<TDb = unknown>(\n\tmodules: FabricModule<TDb>[] = [],\n): ModuleRegistry<TDb> {\n\tconst registered = new Map<string, FabricModule<TDb>>();\n\tfor (const module of modules) {\n\t\tvalidateModuleNamespace(module.namespace);\n\t\tif (registered.has(module.namespace)) {\n\t\t\tthrow new Error(`Duplicate FabricModule namespace \"${module.namespace}\".`);\n\t\t}\n\t\tregistered.set(module.namespace, module);\n\t}\n\treturn { modules: registered };\n}\n\nfunction validateIdentifierList(\n\tvalues: string[] | undefined,\n\tlabel: string,\n\tnamespace: string,\n): void {\n\tfor (const value of values ?? []) {\n\t\tif (!value) {\n\t\t\tthrow new Error(`Module \"${namespace}\" has an empty ${label} entry.`);\n\t\t}\n\t}\n}\n\nfunction validateManifest(module: FabricModule<any>, context: ModuleValidationContext = {}): void {\n\tvalidateModuleNamespace(module.namespace);\n\n\tconst dependencies = (module.dependencies ?? []).map(getModuleDependencyNamespace);\n\tconst objectTypes = (module.objectTypes ?? []).map(getObjectTypeName);\n\tconst eventTypes = (module.eventTypes ?? []).map(getEventTypeName);\n\n\tfor (const dependency of dependencies) {\n\t\tvalidateModuleNamespace(dependency);\n\t\tif (dependency === module.namespace) {\n\t\t\tthrow new Error(`Module \"${module.namespace}\" cannot depend on itself.`);\n\t\t}\n\t\tif (context.availableNamespaces && !context.availableNamespaces.has(dependency)) {\n\t\t\tthrow new Error(`Module \"${module.namespace}\" depends on missing module \"${dependency}\".`);\n\t\t}\n\t}\n\n\tvalidateIdentifierList(objectTypes, \"objectTypes\", module.namespace);\n\tvalidateIdentifierList(module.subjectTypes, \"subjectTypes\", module.namespace);\n\tvalidateIdentifierList(eventTypes, \"eventTypes\", module.namespace);\n\n\tfor (const objectType of objectTypes) {\n\t\tif (!/^[A-Z][a-zA-Z0-9]*$/.test(objectType)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid object type: \"${objectType}\". Object types must be PascalCase alphanumeric.`,\n\t\t\t);\n\t\t}\n\t}\n\n\tfor (const action of module.actions ?? []) {\n\t\tif (!/^[a-z][a-z0-9-]*\\.[a-z][a-z0-9_]*$/.test(action.actionId)) {\n\t\t\tthrow new Error(`Invalid action ID: ${action.actionId}`);\n\t\t}\n\n\t\tif (action.namespace !== module.namespace) {\n\t\t\tthrow new Error(\n\t\t\t\t`Action \"${action.actionId}\" declares namespace \"${action.namespace}\" ` +\n\t\t\t\t\t`but is registered by module \"${module.namespace}\".`,\n\t\t\t);\n\t\t}\n\n\t\tif (!action.actionId.startsWith(`${module.namespace}.`)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Action \"${action.actionId}\" must start with module namespace \"${module.namespace}.\"`,\n\t\t\t);\n\t\t}\n\n\t\tif (action.mutatesDomain && action.emitsEvents.length === 0) {\n\t\t\tthrow new Error(\n\t\t\t\t`Action \"${action.actionId}\" mutates domain but emits no events. ` +\n\t\t\t\t\t`Every mutating action must emit at least one AssetEvent.`,\n\t\t\t);\n\t\t}\n\t}\n\n\tfor (const descriptor of module.displayRenderers ?? []) {\n\t\tconst isPlannedEventType = context.plannedEventTypes?.has(descriptor.eventType) ?? false;\n\t\tconst isModuleEventType = eventTypes.includes(descriptor.eventType);\n\t\tif (!isValidEventType(descriptor.eventType) && !isModuleEventType && !isPlannedEventType) {\n\t\t\tthrow new Error(\n\t\t\t\t`Display renderer registered for unknown event type \"${descriptor.eventType}\". ` +\n\t\t\t\t\t`Register the event type before adding a display renderer.`,\n\t\t\t);\n\t\t}\n\t}\n}\n\nfunction sortModulesByDependency(\n\tmodules: FabricModule<any>[],\n\tregisteredNamespaces = registeredModuleNamespaces,\n): FabricModule<any>[] {\n\tconst modulesByNamespace = new Map<string, FabricModule<any>>();\n\n\tfor (const module of modules) {\n\t\tvalidateModuleNamespace(module.namespace);\n\t\tif (modulesByNamespace.has(module.namespace)) {\n\t\t\tthrow new Error(`Duplicate Fabric module namespace \"${module.namespace}\".`);\n\t\t}\n\t\tmodulesByNamespace.set(module.namespace, module);\n\t}\n\n\tconst sorted: FabricModule<any>[] = [];\n\tconst visiting = new Set<string>();\n\tconst visited = new Set<string>();\n\n\tfunction visit(module: FabricModule<any>, path: string[]): void {\n\t\tif (visited.has(module.namespace)) {\n\t\t\treturn;\n\t\t}\n\t\tif (visiting.has(module.namespace)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Cyclic Fabric module dependency detected: ${[...path, module.namespace].join(\" -> \")}`,\n\t\t\t);\n\t\t}\n\n\t\tvisiting.add(module.namespace);\n\t\tfor (const dependency of (module.dependencies ?? []).map(getModuleDependencyNamespace)) {\n\t\t\tconst dependencyModule = modulesByNamespace.get(dependency);\n\t\t\tif (!dependencyModule) {\n\t\t\t\tif (registeredNamespaces.has(dependency)) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tthrow new Error(`Module \"${module.namespace}\" depends on missing module \"${dependency}\".`);\n\t\t\t}\n\t\t\tvisit(dependencyModule, [...path, module.namespace]);\n\t\t}\n\t\tvisiting.delete(module.namespace);\n\t\tvisited.add(module.namespace);\n\t\tsorted.push(module);\n\t}\n\n\tfor (const module of modules) {\n\t\tvisit(module, []);\n\t}\n\n\treturn sorted;\n}\n\nexport function registerFabricModule(module: FabricModule<any>): void {\n\tvalidateManifest(module, { availableNamespaces: registeredModuleNamespaces });\n\n\tfor (const objectType of module.objectTypes ?? []) {\n\t\tregisterObjectType(getObjectTypeName(objectType));\n\t}\n\n\tfor (const subjectType of module.subjectTypes ?? []) {\n\t\tregisterSubjectType(subjectType);\n\t}\n\n\tfor (const eventType of module.eventTypes ?? []) {\n\t\tregisterEventType(getEventTypeName(eventType));\n\t}\n\n\tfor (const policy of module.policies ?? []) {\n\t\tregisterPolicyIfMissing(policy as PolicyEvaluator);\n\t}\n\n\tfor (const machine of module.stateMachines ?? []) {\n\t\tregisterStateMachineIfMissing(machine as StateMachineDefinition);\n\t}\n\n\tfor (const action of module.actions ?? []) {\n\t\tregisterActionIfMissing(action);\n\t}\n\n\tfor (const descriptor of module.displayRenderers ?? []) {\n\t\tregisterDisplayRenderer(descriptor.eventType, descriptor.renderer as DisplayRenderer);\n\t}\n\n\tregisteredModuleNamespaces.add(module.namespace);\n}\n\nexport function registerFabricModules(modules: FabricModule<any>[]): FabricModule<any>[] {\n\tconst availableNamespaces = new Set([\n\t\t...registeredModuleNamespaces,\n\t\t...modules.map((module) => module.namespace),\n\t]);\n\tconst plannedEventTypes = new Set(\n\t\tmodules.flatMap((module) => (module.eventTypes ?? []).map(getEventTypeName)),\n\t);\n\n\tfor (const module of modules) {\n\t\tvalidateManifest(module, { availableNamespaces, plannedEventTypes });\n\t}\n\n\tconst sortedModules = sortModulesByDependency(modules);\n\tfor (const module of sortedModules) {\n\t\tregisterFabricModule(module);\n\t}\n\n\treturn sortedModules;\n}\n"]}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// ids/index.ts
|
|
4
|
+
var CROCKFORD_BASE32 = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
|
|
5
|
+
var FABRIC_ID_PREFIXES = {
|
|
6
|
+
assetEvent: "evt",
|
|
7
|
+
actionInvocation: "act",
|
|
8
|
+
policyEvaluation: "pol",
|
|
9
|
+
adapterInvocation: "adp",
|
|
10
|
+
adapterDeadLetterQueue: "dlq",
|
|
11
|
+
accessEvent: "acc",
|
|
12
|
+
projectionSnapshot: "psn",
|
|
13
|
+
complianceEvidencePacket: "cep"
|
|
14
|
+
};
|
|
15
|
+
var ID_REGEX = /^([a-z][a-z0-9]{1,7})_([0-9A-Z]{26})$/;
|
|
16
|
+
function randomBase32(length) {
|
|
17
|
+
let output = "";
|
|
18
|
+
const randomValues = new Uint8Array(length);
|
|
19
|
+
globalThis.crypto.getRandomValues(randomValues);
|
|
20
|
+
for (const value of randomValues) {
|
|
21
|
+
output += CROCKFORD_BASE32[value % CROCKFORD_BASE32.length];
|
|
22
|
+
}
|
|
23
|
+
return output;
|
|
24
|
+
}
|
|
25
|
+
function createSortableRandomId() {
|
|
26
|
+
let timestamp = Date.now();
|
|
27
|
+
let encodedTime = "";
|
|
28
|
+
for (let index = 0; index < 10; index++) {
|
|
29
|
+
encodedTime = CROCKFORD_BASE32[timestamp % 32] + encodedTime;
|
|
30
|
+
timestamp = Math.floor(timestamp / 32);
|
|
31
|
+
}
|
|
32
|
+
return `${encodedTime}${randomBase32(16)}`;
|
|
33
|
+
}
|
|
34
|
+
function createFabricId(prefix) {
|
|
35
|
+
if (!/^[a-z][a-z0-9]{1,7}$/.test(prefix)) {
|
|
36
|
+
throw new Error(`Invalid Fabric ID prefix: ${prefix}`);
|
|
37
|
+
}
|
|
38
|
+
return `${prefix}_${createSortableRandomId()}`;
|
|
39
|
+
}
|
|
40
|
+
function isFabricId(id, prefix) {
|
|
41
|
+
const match = ID_REGEX.exec(id);
|
|
42
|
+
if (!match) {
|
|
43
|
+
return false;
|
|
44
|
+
}
|
|
45
|
+
return prefix ? match[1] === prefix : true;
|
|
46
|
+
}
|
|
47
|
+
function parseFabricId(id) {
|
|
48
|
+
const match = ID_REGEX.exec(id);
|
|
49
|
+
if (!match) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
return { prefix: match[1], ulid: match[2] };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
exports.FABRIC_ID_PREFIXES = FABRIC_ID_PREFIXES;
|
|
56
|
+
exports.createFabricId = createFabricId;
|
|
57
|
+
exports.isFabricId = isFabricId;
|
|
58
|
+
exports.parseFabricId = parseFabricId;
|
|
59
|
+
//# sourceMappingURL=chunk-LZSE6QGQ.cjs.map
|
|
60
|
+
//# sourceMappingURL=chunk-LZSE6QGQ.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../ids/index.ts"],"names":[],"mappings":";;;AAAA,IAAM,gBAAA,GAAmB,kCAAA;AAElB,IAAM,kBAAA,GAAqB;AAAA,EACjC,UAAA,EAAY,KAAA;AAAA,EACZ,gBAAA,EAAkB,KAAA;AAAA,EAClB,gBAAA,EAAkB,KAAA;AAAA,EAClB,iBAAA,EAAmB,KAAA;AAAA,EACnB,sBAAA,EAAwB,KAAA;AAAA,EACxB,WAAA,EAAa,KAAA;AAAA,EACb,kBAAA,EAAoB,KAAA;AAAA,EACpB,wBAAA,EAA0B;AAC3B;AAIA,IAAM,QAAA,GAAW,uCAAA;AAEjB,SAAS,aAAa,MAAA,EAAwB;AAC7C,EAAA,IAAI,MAAA,GAAS,EAAA;AACb,EAAA,MAAM,YAAA,GAAe,IAAI,UAAA,CAAW,MAAM,CAAA;AAC1C,EAAA,UAAA,CAAW,MAAA,CAAO,gBAAgB,YAAY,CAAA;AAC9C,EAAA,KAAA,MAAW,SAAS,YAAA,EAAc;AACjC,IAAA,MAAA,IAAU,gBAAA,CAAiB,KAAA,GAAQ,gBAAA,CAAiB,MAAM,CAAA;AAAA,EAC3D;AACA,EAAA,OAAO,MAAA;AACR;AAEA,SAAS,sBAAA,GAAiC;AACzC,EAAA,IAAI,SAAA,GAAY,KAAK,GAAA,EAAI;AACzB,EAAA,IAAI,WAAA,GAAc,EAAA;AAClB,EAAA,KAAA,IAAS,KAAA,GAAQ,CAAA,EAAG,KAAA,GAAQ,EAAA,EAAI,KAAA,EAAA,EAAS;AACxC,IAAA,WAAA,GAAc,gBAAA,CAAiB,SAAA,GAAY,EAAE,CAAA,GAAI,WAAA;AACjD,IAAA,SAAA,GAAY,IAAA,CAAK,KAAA,CAAM,SAAA,GAAY,EAAE,CAAA;AAAA,EACtC;AACA,EAAA,OAAO,CAAA,EAAG,WAAW,CAAA,EAAG,YAAA,CAAa,EAAE,CAAC,CAAA,CAAA;AACzC;AAEO,SAAS,eAAe,MAAA,EAAgC;AAC9D,EAAA,IAAI,CAAC,sBAAA,CAAuB,IAAA,CAAK,MAAM,CAAA,EAAG;AACzC,IAAA,MAAM,IAAI,KAAA,CAAM,CAAA,0BAAA,EAA6B,MAAM,CAAA,CAAE,CAAA;AAAA,EACtD;AACA,EAAA,OAAO,CAAA,EAAG,MAAM,CAAA,CAAA,EAAI,sBAAA,EAAwB,CAAA,CAAA;AAC7C;AAEO,SAAS,UAAA,CAAW,IAAY,MAAA,EAAkC;AACxE,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,IAAA,CAAK,EAAE,CAAA;AAC9B,EAAA,IAAI,CAAC,KAAA,EAAO;AACX,IAAA,OAAO,KAAA;AAAA,EACR;AACA,EAAA,OAAO,MAAA,GAAS,KAAA,CAAM,CAAC,CAAA,KAAM,MAAA,GAAS,IAAA;AACvC;AAEO,SAAS,cAAc,EAAA,EAAqD;AAClF,EAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,IAAA,CAAK,EAAE,CAAA;AAC9B,EAAA,IAAI,CAAC,KAAA,EAAO;AACX,IAAA,OAAO,IAAA;AAAA,EACR;AACA,EAAA,OAAO,EAAE,QAAQ,KAAA,CAAM,CAAC,GAAG,IAAA,EAAM,KAAA,CAAM,CAAC,CAAA,EAAE;AAC3C","file":"chunk-LZSE6QGQ.cjs","sourcesContent":["const CROCKFORD_BASE32 = \"0123456789ABCDEFGHJKMNPQRSTVWXYZ\";\n\nexport const FABRIC_ID_PREFIXES = {\n\tassetEvent: \"evt\",\n\tactionInvocation: \"act\",\n\tpolicyEvaluation: \"pol\",\n\tadapterInvocation: \"adp\",\n\tadapterDeadLetterQueue: \"dlq\",\n\taccessEvent: \"acc\",\n\tprojectionSnapshot: \"psn\",\n\tcomplianceEvidencePacket: \"cep\",\n} as const;\n\nexport type FabricIdPrefix = (typeof FABRIC_ID_PREFIXES)[keyof typeof FABRIC_ID_PREFIXES] | string;\n\nconst ID_REGEX = /^([a-z][a-z0-9]{1,7})_([0-9A-Z]{26})$/;\n\nfunction randomBase32(length: number): string {\n\tlet output = \"\";\n\tconst randomValues = new Uint8Array(length);\n\tglobalThis.crypto.getRandomValues(randomValues);\n\tfor (const value of randomValues) {\n\t\toutput += CROCKFORD_BASE32[value % CROCKFORD_BASE32.length];\n\t}\n\treturn output;\n}\n\nfunction createSortableRandomId(): string {\n\tlet timestamp = Date.now();\n\tlet encodedTime = \"\";\n\tfor (let index = 0; index < 10; index++) {\n\t\tencodedTime = CROCKFORD_BASE32[timestamp % 32] + encodedTime;\n\t\ttimestamp = Math.floor(timestamp / 32);\n\t}\n\treturn `${encodedTime}${randomBase32(16)}`;\n}\n\nexport function createFabricId(prefix: FabricIdPrefix): string {\n\tif (!/^[a-z][a-z0-9]{1,7}$/.test(prefix)) {\n\t\tthrow new Error(`Invalid Fabric ID prefix: ${prefix}`);\n\t}\n\treturn `${prefix}_${createSortableRandomId()}`;\n}\n\nexport function isFabricId(id: string, prefix?: FabricIdPrefix): boolean {\n\tconst match = ID_REGEX.exec(id);\n\tif (!match) {\n\t\treturn false;\n\t}\n\treturn prefix ? match[1] === prefix : true;\n}\n\nexport function parseFabricId(id: string): { prefix: string; ulid: string } | null {\n\tconst match = ID_REGEX.exec(id);\n\tif (!match) {\n\t\treturn null;\n\t}\n\treturn { prefix: match[1], ulid: match[2] };\n}\n"]}
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// adapters/index.ts
|
|
4
|
+
function adapterKey(adapterType, operation) {
|
|
5
|
+
return `${adapterType}:${operation}`;
|
|
6
|
+
}
|
|
7
|
+
var MissingAdapterRegistrationError = class extends Error {
|
|
8
|
+
constructor(adapterType, operation) {
|
|
9
|
+
super(`No adapter registered for adapterType "${adapterType}" and operation "${operation}"`);
|
|
10
|
+
this.name = "MissingAdapterRegistrationError";
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
var AdapterRegistry = class {
|
|
14
|
+
adapters = /* @__PURE__ */ new Map();
|
|
15
|
+
register(adapter) {
|
|
16
|
+
const key = adapterKey(adapter.adapterType, adapter.operation);
|
|
17
|
+
if (this.adapters.has(key)) {
|
|
18
|
+
throw new Error(
|
|
19
|
+
`Adapter already registered for adapterType "${adapter.adapterType}" and operation "${adapter.operation}"`
|
|
20
|
+
);
|
|
21
|
+
}
|
|
22
|
+
this.adapters.set(key, adapter);
|
|
23
|
+
}
|
|
24
|
+
resolve(adapterType, operation) {
|
|
25
|
+
return this.adapters.get(adapterKey(adapterType, operation));
|
|
26
|
+
}
|
|
27
|
+
require(adapterType, operation) {
|
|
28
|
+
const adapter = this.resolve(adapterType, operation);
|
|
29
|
+
if (!adapter) {
|
|
30
|
+
throw new MissingAdapterRegistrationError(adapterType, operation);
|
|
31
|
+
}
|
|
32
|
+
return adapter;
|
|
33
|
+
}
|
|
34
|
+
};
|
|
35
|
+
var DEFAULT_RETRY_POLICY = {
|
|
36
|
+
maxAttempts: 3,
|
|
37
|
+
initialDelayMs: 100,
|
|
38
|
+
backoffMultiplier: 2,
|
|
39
|
+
maxDelayMs: 1e3
|
|
40
|
+
};
|
|
41
|
+
var NO_RETRY_POLICY = {
|
|
42
|
+
idempotent: false,
|
|
43
|
+
maxAttempts: 1,
|
|
44
|
+
initialDelayMs: 0,
|
|
45
|
+
backoffMultiplier: 1,
|
|
46
|
+
maxDelayMs: 0
|
|
47
|
+
};
|
|
48
|
+
function resolveAdapterRetryPolicy(policy, defaultIdempotent) {
|
|
49
|
+
const idempotent = policy?.idempotent ?? defaultIdempotent;
|
|
50
|
+
if (!idempotent) {
|
|
51
|
+
return NO_RETRY_POLICY;
|
|
52
|
+
}
|
|
53
|
+
return {
|
|
54
|
+
idempotent: true,
|
|
55
|
+
maxAttempts: Math.max(1, Math.min(policy?.maxAttempts ?? DEFAULT_RETRY_POLICY.maxAttempts, 5)),
|
|
56
|
+
initialDelayMs: Math.max(0, policy?.initialDelayMs ?? DEFAULT_RETRY_POLICY.initialDelayMs),
|
|
57
|
+
backoffMultiplier: Math.max(
|
|
58
|
+
1,
|
|
59
|
+
policy?.backoffMultiplier ?? DEFAULT_RETRY_POLICY.backoffMultiplier
|
|
60
|
+
),
|
|
61
|
+
maxDelayMs: Math.max(0, policy?.maxDelayMs ?? DEFAULT_RETRY_POLICY.maxDelayMs)
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
function getRetryDelayMs(attempt, policy) {
|
|
65
|
+
const exponentialDelay = policy.initialDelayMs * policy.backoffMultiplier ** Math.max(0, attempt - 1);
|
|
66
|
+
return Math.min(exponentialDelay, policy.maxDelayMs);
|
|
67
|
+
}
|
|
68
|
+
async function executeWithAdapterRetry(options) {
|
|
69
|
+
const policy = resolveAdapterRetryPolicy(options.policy, options.defaultIdempotent);
|
|
70
|
+
const sleep = options.sleep ?? ((delayMs) => new Promise((resolve) => setTimeout(resolve, delayMs)));
|
|
71
|
+
let lastError;
|
|
72
|
+
for (let attempt = 1; attempt <= policy.maxAttempts; attempt++) {
|
|
73
|
+
try {
|
|
74
|
+
const result = await options.execute(attempt, policy.maxAttempts);
|
|
75
|
+
if (options.isSuccessful(result)) {
|
|
76
|
+
await options.onAttempt?.({ attempt, result, willRetry: false });
|
|
77
|
+
return result;
|
|
78
|
+
}
|
|
79
|
+
lastError = options.getError(result) ?? "Adapter returned unsuccessful result";
|
|
80
|
+
const willRetry = policy.idempotent && attempt < policy.maxAttempts;
|
|
81
|
+
const nextDelayMs = willRetry ? getRetryDelayMs(attempt, policy) : void 0;
|
|
82
|
+
await options.onAttempt?.({ attempt, result, error: lastError, willRetry, nextDelayMs });
|
|
83
|
+
if (!willRetry) {
|
|
84
|
+
return result;
|
|
85
|
+
}
|
|
86
|
+
await sleep(nextDelayMs ?? 0);
|
|
87
|
+
} catch (error) {
|
|
88
|
+
lastError = error instanceof Error ? error.message : String(error);
|
|
89
|
+
const willRetry = policy.idempotent && attempt < policy.maxAttempts;
|
|
90
|
+
const nextDelayMs = willRetry ? getRetryDelayMs(attempt, policy) : void 0;
|
|
91
|
+
await options.onAttempt?.({ attempt, error: lastError, willRetry, nextDelayMs });
|
|
92
|
+
if (!willRetry) {
|
|
93
|
+
throw error;
|
|
94
|
+
}
|
|
95
|
+
await sleep(nextDelayMs ?? 0);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
throw new Error(lastError ?? "Adapter retry exhausted");
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
exports.AdapterRegistry = AdapterRegistry;
|
|
102
|
+
exports.MissingAdapterRegistrationError = MissingAdapterRegistrationError;
|
|
103
|
+
exports.executeWithAdapterRetry = executeWithAdapterRetry;
|
|
104
|
+
exports.getRetryDelayMs = getRetryDelayMs;
|
|
105
|
+
exports.resolveAdapterRetryPolicy = resolveAdapterRetryPolicy;
|
|
106
|
+
//# sourceMappingURL=chunk-NPVIFZQV.cjs.map
|
|
107
|
+
//# sourceMappingURL=chunk-NPVIFZQV.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../adapters/index.ts"],"names":[],"mappings":"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","file":"chunk-NPVIFZQV.cjs","sourcesContent":["export interface AdapterExecutionContext {\n\ttenantId: string;\n\tspaceId: string;\n\tactionInvocationId: string;\n\tadapterInvocationId: string;\n\tcorrelationId: string;\n\tcausationId?: string;\n\tattempt: number;\n\tmaxAttempts: number;\n}\n\nexport interface AdapterExecutionResult {\n\tsuccess: boolean;\n\tcorrelationId?: string;\n\terror?: string;\n}\n\nexport type AdapterExecutor = (\n\tinput: Record<string, unknown>,\n\tcontext: AdapterExecutionContext,\n) => Promise<AdapterExecutionResult>;\n\nexport interface AdapterRetryPolicy {\n\t/** External calls must explicitly opt into retry by being idempotent. */\n\tidempotent: boolean;\n\t/** Total attempts including the first call. Non-idempotent policies are forced to 1. */\n\tmaxAttempts?: number;\n\t/** First backoff delay in milliseconds. */\n\tinitialDelayMs?: number;\n\t/** Exponential multiplier applied after each failed attempt. */\n\tbackoffMultiplier?: number;\n\t/** Upper bound for any single retry delay in milliseconds. */\n\tmaxDelayMs?: number;\n}\n\nexport interface ResolvedAdapterRetryPolicy {\n\tidempotent: boolean;\n\tmaxAttempts: number;\n\tinitialDelayMs: number;\n\tbackoffMultiplier: number;\n\tmaxDelayMs: number;\n}\n\nexport interface AdapterCircuitBreakerConfig {\n\tmode: \"monitor\" | \"enforce\";\n\tfailureThreshold: number;\n\twindowMs: number;\n\tcooldownMs: number;\n\tminimumSamples?: number;\n}\n\nexport interface AdapterImplementation {\n\tadapterType: string;\n\toperation: string;\n\tvendor: string;\n\t/** Whether this adapter operation can be safely retried by default. */\n\tidempotent: boolean;\n\tretryPolicy?: AdapterRetryPolicy;\n\t/** Defaults to monitor-only; enforce mode must be explicitly configured. */\n\tcircuitBreaker?: AdapterCircuitBreakerConfig;\n\texecute: AdapterExecutor;\n}\n\nexport interface AdapterAttempt<T> {\n\tattempt: number;\n\tresult?: T;\n\terror?: string;\n\twillRetry: boolean;\n\tnextDelayMs?: number;\n}\n\nexport interface ExecuteWithRetryOptions<T> {\n\tpolicy?: AdapterRetryPolicy;\n\tdefaultIdempotent: boolean;\n\texecute: (attempt: number, maxAttempts: number) => Promise<T>;\n\tisSuccessful: (result: T) => boolean;\n\tgetError: (result: T) => string | undefined;\n\tsleep?: (delayMs: number) => Promise<void>;\n\tonAttempt?: (attempt: AdapterAttempt<T>) => Promise<void> | void;\n}\n\nfunction adapterKey(adapterType: string, operation: string): string {\n\treturn `${adapterType}:${operation}`;\n}\n\nexport class MissingAdapterRegistrationError extends Error {\n\tconstructor(adapterType: string, operation: string) {\n\t\tsuper(`No adapter registered for adapterType \"${adapterType}\" and operation \"${operation}\"`);\n\t\tthis.name = \"MissingAdapterRegistrationError\";\n\t}\n}\n\nexport class AdapterRegistry {\n\tprivate readonly adapters = new Map<string, AdapterImplementation>();\n\n\tregister(adapter: AdapterImplementation): void {\n\t\tconst key = adapterKey(adapter.adapterType, adapter.operation);\n\t\tif (this.adapters.has(key)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Adapter already registered for adapterType \"${adapter.adapterType}\" and operation \"${adapter.operation}\"`,\n\t\t\t);\n\t\t}\n\n\t\tthis.adapters.set(key, adapter);\n\t}\n\n\tresolve(adapterType: string, operation: string): AdapterImplementation | undefined {\n\t\treturn this.adapters.get(adapterKey(adapterType, operation));\n\t}\n\n\trequire(adapterType: string, operation: string): AdapterImplementation {\n\t\tconst adapter = this.resolve(adapterType, operation);\n\t\tif (!adapter) {\n\t\t\tthrow new MissingAdapterRegistrationError(adapterType, operation);\n\t\t}\n\n\t\treturn adapter;\n\t}\n}\n\nconst DEFAULT_RETRY_POLICY: ResolvedAdapterRetryPolicy = {\n\tidempotent: true,\n\tmaxAttempts: 3,\n\tinitialDelayMs: 100,\n\tbackoffMultiplier: 2,\n\tmaxDelayMs: 1_000,\n};\n\nconst NO_RETRY_POLICY: ResolvedAdapterRetryPolicy = {\n\tidempotent: false,\n\tmaxAttempts: 1,\n\tinitialDelayMs: 0,\n\tbackoffMultiplier: 1,\n\tmaxDelayMs: 0,\n};\n\nexport function resolveAdapterRetryPolicy(\n\tpolicy: AdapterRetryPolicy | undefined,\n\tdefaultIdempotent: boolean,\n): ResolvedAdapterRetryPolicy {\n\tconst idempotent = policy?.idempotent ?? defaultIdempotent;\n\n\tif (!idempotent) {\n\t\treturn NO_RETRY_POLICY;\n\t}\n\n\treturn {\n\t\tidempotent: true,\n\t\tmaxAttempts: Math.max(1, Math.min(policy?.maxAttempts ?? DEFAULT_RETRY_POLICY.maxAttempts, 5)),\n\t\tinitialDelayMs: Math.max(0, policy?.initialDelayMs ?? DEFAULT_RETRY_POLICY.initialDelayMs),\n\t\tbackoffMultiplier: Math.max(\n\t\t\t1,\n\t\t\tpolicy?.backoffMultiplier ?? DEFAULT_RETRY_POLICY.backoffMultiplier,\n\t\t),\n\t\tmaxDelayMs: Math.max(0, policy?.maxDelayMs ?? DEFAULT_RETRY_POLICY.maxDelayMs),\n\t};\n}\n\nexport function getRetryDelayMs(attempt: number, policy: ResolvedAdapterRetryPolicy): number {\n\tconst exponentialDelay =\n\t\tpolicy.initialDelayMs * policy.backoffMultiplier ** Math.max(0, attempt - 1);\n\n\treturn Math.min(exponentialDelay, policy.maxDelayMs);\n}\n\nexport async function executeWithAdapterRetry<T>(options: ExecuteWithRetryOptions<T>): Promise<T> {\n\tconst policy = resolveAdapterRetryPolicy(options.policy, options.defaultIdempotent);\n\tconst sleep =\n\t\toptions.sleep ?? ((delayMs) => new Promise((resolve) => setTimeout(resolve, delayMs)));\n\tlet lastError: string | undefined;\n\n\tfor (let attempt = 1; attempt <= policy.maxAttempts; attempt++) {\n\t\ttry {\n\t\t\tconst result = await options.execute(attempt, policy.maxAttempts);\n\t\t\tif (options.isSuccessful(result)) {\n\t\t\t\tawait options.onAttempt?.({ attempt, result, willRetry: false });\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tlastError = options.getError(result) ?? \"Adapter returned unsuccessful result\";\n\t\t\tconst willRetry = policy.idempotent && attempt < policy.maxAttempts;\n\t\t\tconst nextDelayMs = willRetry ? getRetryDelayMs(attempt, policy) : undefined;\n\t\t\tawait options.onAttempt?.({ attempt, result, error: lastError, willRetry, nextDelayMs });\n\n\t\t\tif (!willRetry) {\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tawait sleep(nextDelayMs ?? 0);\n\t\t} catch (error) {\n\t\t\tlastError = error instanceof Error ? error.message : String(error);\n\t\t\tconst willRetry = policy.idempotent && attempt < policy.maxAttempts;\n\t\t\tconst nextDelayMs = willRetry ? getRetryDelayMs(attempt, policy) : undefined;\n\t\t\tawait options.onAttempt?.({ attempt, error: lastError, willRetry, nextDelayMs });\n\n\t\t\tif (!willRetry) {\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tawait sleep(nextDelayMs ?? 0);\n\t\t}\n\t}\n\n\tthrow new Error(lastError ?? \"Adapter retry exhausted\");\n}\n"]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-PG5LYTUX.cjs"}
|
|
@@ -0,0 +1,183 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// projections/index.ts
|
|
4
|
+
async function replayEvents({
|
|
5
|
+
events,
|
|
6
|
+
scope,
|
|
7
|
+
initialState,
|
|
8
|
+
snapshot,
|
|
9
|
+
applyEvent
|
|
10
|
+
}) {
|
|
11
|
+
const warnings = [];
|
|
12
|
+
const scopedEvents = filterEventsByScope(await collectEvents(events), scope, warnings);
|
|
13
|
+
const orderedEvents = sortEvents(scopedEvents, isSubjectScoped(scope));
|
|
14
|
+
const uniqueEvents = removeDuplicateEvents(orderedEvents, warnings);
|
|
15
|
+
const resumableEvents = applyCursor(uniqueEvents, snapshot, isSubjectScoped(scope), warnings);
|
|
16
|
+
let state = snapshot?.snapshotData ?? initialState;
|
|
17
|
+
const appliedEvents = [];
|
|
18
|
+
let eventCursor = snapshot?.eventCursor ?? null;
|
|
19
|
+
let eventSequence = snapshot?.eventSequence ?? 0;
|
|
20
|
+
for (const event of resumableEvents) {
|
|
21
|
+
state = await applyEvent(state, event);
|
|
22
|
+
appliedEvents.push(event);
|
|
23
|
+
eventCursor = event.id;
|
|
24
|
+
eventSequence = event.sequence;
|
|
25
|
+
}
|
|
26
|
+
return {
|
|
27
|
+
state,
|
|
28
|
+
appliedEvents,
|
|
29
|
+
warnings,
|
|
30
|
+
eventCursor,
|
|
31
|
+
eventSequence
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
async function collectEvents(events) {
|
|
35
|
+
const collected = [];
|
|
36
|
+
if (Symbol.asyncIterator in events) {
|
|
37
|
+
for await (const event of events) {
|
|
38
|
+
collected.push(event);
|
|
39
|
+
}
|
|
40
|
+
return collected;
|
|
41
|
+
}
|
|
42
|
+
for (const event of events) {
|
|
43
|
+
collected.push(event);
|
|
44
|
+
}
|
|
45
|
+
return collected;
|
|
46
|
+
}
|
|
47
|
+
function filterEventsByScope(events, scope, warnings) {
|
|
48
|
+
if (scope.subjectType && !scope.subjectId || !scope.subjectType && scope.subjectId) {
|
|
49
|
+
warnings.push({
|
|
50
|
+
code: "subject_scope_incomplete",
|
|
51
|
+
message: "Both subjectType and subjectId are required for subject-scoped replay.",
|
|
52
|
+
subjectType: scope.subjectType,
|
|
53
|
+
subjectId: scope.subjectId
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return events.filter((event) => {
|
|
57
|
+
if (event.tenantId !== scope.tenantId || event.spaceId !== scope.spaceId) {
|
|
58
|
+
return false;
|
|
59
|
+
}
|
|
60
|
+
if (scope.subjectType && event.subjectType !== scope.subjectType) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
if (scope.subjectId && event.subjectId !== scope.subjectId) {
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
return true;
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
function removeDuplicateEvents(events, warnings) {
|
|
70
|
+
const seenEventIds = /* @__PURE__ */ new Set();
|
|
71
|
+
const uniqueEvents = [];
|
|
72
|
+
for (const event of events) {
|
|
73
|
+
if (seenEventIds.has(event.id)) {
|
|
74
|
+
warnings.push({
|
|
75
|
+
code: "duplicate_event",
|
|
76
|
+
message: `Duplicate event ${event.id} ignored during replay.`,
|
|
77
|
+
eventId: event.id,
|
|
78
|
+
subjectType: event.subjectType,
|
|
79
|
+
subjectId: event.subjectId
|
|
80
|
+
});
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
seenEventIds.add(event.id);
|
|
84
|
+
uniqueEvents.push(event);
|
|
85
|
+
}
|
|
86
|
+
recordMissingSequenceWarnings(uniqueEvents, warnings);
|
|
87
|
+
return uniqueEvents;
|
|
88
|
+
}
|
|
89
|
+
function recordMissingSequenceWarnings(events, warnings) {
|
|
90
|
+
const lastSequenceBySubject = /* @__PURE__ */ new Map();
|
|
91
|
+
for (const event of events) {
|
|
92
|
+
const subjectKey = `${event.subjectType}:${event.subjectId}`;
|
|
93
|
+
const previousSequence = lastSequenceBySubject.get(subjectKey);
|
|
94
|
+
const expectedSequence = previousSequence === void 0 ? event.sequence : previousSequence + 1;
|
|
95
|
+
if (previousSequence !== void 0 && event.sequence > expectedSequence) {
|
|
96
|
+
warnings.push({
|
|
97
|
+
code: "missing_sequence",
|
|
98
|
+
message: `Missing event sequence for ${subjectKey}: expected ${expectedSequence}, received ${event.sequence}.`,
|
|
99
|
+
eventId: event.id,
|
|
100
|
+
subjectType: event.subjectType,
|
|
101
|
+
subjectId: event.subjectId,
|
|
102
|
+
expectedSequence,
|
|
103
|
+
actualSequence: event.sequence
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
lastSequenceBySubject.set(subjectKey, Math.max(previousSequence ?? event.sequence, event.sequence));
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
function applyCursor(events, snapshot, subjectScoped, warnings) {
|
|
110
|
+
const eventCursor = snapshot?.eventCursor;
|
|
111
|
+
if (eventCursor) {
|
|
112
|
+
const cursorIndex = events.findIndex((event) => event.id === eventCursor);
|
|
113
|
+
if (cursorIndex >= 0) {
|
|
114
|
+
return events.slice(cursorIndex + 1);
|
|
115
|
+
}
|
|
116
|
+
warnings.push({
|
|
117
|
+
code: "cursor_not_found",
|
|
118
|
+
message: `Snapshot cursor ${eventCursor} was not found in the scoped event stream.`,
|
|
119
|
+
eventId: eventCursor
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
if (subjectScoped && snapshot?.eventSequence !== void 0 && snapshot.eventSequence !== null) {
|
|
123
|
+
return events.filter((event) => event.sequence > snapshot.eventSequence);
|
|
124
|
+
}
|
|
125
|
+
return events;
|
|
126
|
+
}
|
|
127
|
+
function sortEvents(events, subjectScoped) {
|
|
128
|
+
return [...events].sort(
|
|
129
|
+
(first, second) => subjectScoped ? compareSubjectEvents(first, second) : compareGlobalEvents(first, second)
|
|
130
|
+
);
|
|
131
|
+
}
|
|
132
|
+
function compareSubjectEvents(first, second) {
|
|
133
|
+
return compareValues(
|
|
134
|
+
[first.sequence, toTimestamp(first.recordedAt), toTimestamp(first.occurredAt), first.id],
|
|
135
|
+
[second.sequence, toTimestamp(second.recordedAt), toTimestamp(second.occurredAt), second.id]
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
function compareGlobalEvents(first, second) {
|
|
139
|
+
return compareValues(
|
|
140
|
+
[
|
|
141
|
+
toTimestamp(first.recordedAt),
|
|
142
|
+
toTimestamp(first.occurredAt),
|
|
143
|
+
first.actionInvocationId,
|
|
144
|
+
first.correlationId,
|
|
145
|
+
first.subjectType,
|
|
146
|
+
first.subjectId,
|
|
147
|
+
first.sequence,
|
|
148
|
+
first.id
|
|
149
|
+
],
|
|
150
|
+
[
|
|
151
|
+
toTimestamp(second.recordedAt),
|
|
152
|
+
toTimestamp(second.occurredAt),
|
|
153
|
+
second.actionInvocationId,
|
|
154
|
+
second.correlationId,
|
|
155
|
+
second.subjectType,
|
|
156
|
+
second.subjectId,
|
|
157
|
+
second.sequence,
|
|
158
|
+
second.id
|
|
159
|
+
]
|
|
160
|
+
);
|
|
161
|
+
}
|
|
162
|
+
function compareValues(firstValues, secondValues) {
|
|
163
|
+
for (const [index, firstValue] of firstValues.entries()) {
|
|
164
|
+
const secondValue = secondValues[index];
|
|
165
|
+
if (firstValue < secondValue) {
|
|
166
|
+
return -1;
|
|
167
|
+
}
|
|
168
|
+
if (firstValue > secondValue) {
|
|
169
|
+
return 1;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
return 0;
|
|
173
|
+
}
|
|
174
|
+
function isSubjectScoped(scope) {
|
|
175
|
+
return Boolean(scope.subjectType && scope.subjectId);
|
|
176
|
+
}
|
|
177
|
+
function toTimestamp(value) {
|
|
178
|
+
return value instanceof Date ? value.getTime() : new Date(value).getTime();
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
exports.replayEvents = replayEvents;
|
|
182
|
+
//# sourceMappingURL=chunk-Q3WYIWCN.cjs.map
|
|
183
|
+
//# sourceMappingURL=chunk-Q3WYIWCN.cjs.map
|