@sixb/core 0.1.4 → 0.1.6
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.d.ts +2 -2
- package/dist/actions/index.d.ts.map +1 -1
- package/dist/actions/index.js +8 -8
- package/dist/actions/read-facade.d.ts +10 -2
- package/dist/actions/read-facade.d.ts.map +1 -1
- package/dist/actions/types/context.d.ts +45 -2
- package/dist/actions/types/context.d.ts.map +1 -1
- package/dist/actions/types/definitions.d.ts +8 -2
- package/dist/actions/types/definitions.d.ts.map +1 -1
- package/dist/agents/index.js +13 -13
- package/dist/agents/types.d.ts +2 -0
- package/dist/agents/types.d.ts.map +1 -1
- package/dist/agents/validation.d.ts.map +1 -1
- package/dist/auth/index.d.ts +1 -1
- package/dist/auth/index.d.ts.map +1 -1
- package/dist/auth/index.js +1 -1
- package/dist/auth/runtime.d.ts.map +1 -1
- package/dist/auth/strategy.d.ts +1 -1
- package/dist/auth/strategy.d.ts.map +1 -1
- package/dist/auth/types.d.ts +13 -0
- package/dist/auth/types.d.ts.map +1 -1
- package/dist/bootstrap/index.js +17 -17
- package/dist/{chunk-tycbzedm.js → chunk-0hc5j867.js} +68 -3
- package/dist/chunk-0hc5j867.js.map +15 -0
- package/dist/{chunk-tkdscva6.js → chunk-1e8m6yn3.js} +6 -1
- package/dist/{chunk-tkdscva6.js.map → chunk-1e8m6yn3.js.map} +4 -4
- package/dist/{chunk-xdf9yswn.js → chunk-1g8negke.js} +1 -1
- package/dist/{chunk-s31d0qmq.js → chunk-5gynx4xn.js} +11 -11
- package/dist/{chunk-s31d0qmq.js.map → chunk-5gynx4xn.js.map} +1 -1
- package/dist/{chunk-pn8n8sba.js → chunk-5sxb1168.js} +7 -11
- package/dist/{chunk-pn8n8sba.js.map → chunk-5sxb1168.js.map} +3 -4
- package/dist/chunk-72q2y8hn.js.map +3 -3
- package/dist/{chunk-cbkm2vam.js → chunk-8gv5z0zm.js} +1 -1
- package/dist/{chunk-tek1qwgm.js → chunk-a44d5zgd.js} +8 -3
- package/dist/{chunk-tek1qwgm.js.map → chunk-a44d5zgd.js.map} +4 -3
- package/dist/{chunk-1yz3x65y.js → chunk-dy311asx.js} +7 -9
- package/dist/{chunk-1yz3x65y.js.map → chunk-dy311asx.js.map} +2 -2
- package/dist/{chunk-rs1wbvy6.js → chunk-e42bc6m3.js} +1 -1
- package/dist/{chunk-a09jx26t.js → chunk-fe5ev6mr.js} +1 -1
- package/dist/{chunk-nzw7sm3b.js → chunk-hceck7dq.js} +1 -1
- package/dist/{chunk-7gw7mepb.js → chunk-md8k0r54.js} +1 -1
- package/dist/{chunk-hbeh8j9w.js → chunk-n4spznws.js} +2 -2
- package/dist/{chunk-afjpa2hs.js → chunk-nkbfrt0c.js} +1 -1
- package/dist/{chunk-c43qr6s0.js → chunk-nva1xkjz.js} +16 -12
- package/dist/{chunk-c43qr6s0.js.map → chunk-nva1xkjz.js.map} +4 -4
- package/dist/{chunk-1wk20wn3.js → chunk-t624af60.js} +37 -35
- package/dist/{chunk-1wk20wn3.js.map → chunk-t624af60.js.map} +4 -4
- package/dist/{chunk-g13869yf.js → chunk-tg5mee00.js} +1 -1
- package/dist/{chunk-sxwk41qa.js → chunk-znagycq7.js} +1 -1
- package/dist/execution/agent.js +13 -13
- package/dist/execution/primitive.js +13 -13
- package/dist/execution/request.js +13 -13
- package/dist/index.d.ts +1 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -21
- package/dist/index.js.map +1 -1
- package/dist/materializer/index.js +6 -6
- package/dist/objects/index.js +9 -9
- package/dist/objects/query/index.js +6 -6
- package/dist/ontology/internal.d.ts +1 -1
- package/dist/ontology/internal.d.ts.map +1 -1
- package/dist/ontology/internal.js +14 -6
- package/dist/ontology/internal.js.map +3 -3
- package/dist/ontology/json-schema.d.ts +10 -0
- package/dist/ontology/json-schema.d.ts.map +1 -1
- package/dist/pipelines/index.js +7 -7
- package/dist/projections/internal.js +5 -5
- package/dist/storage/agents/provider.js +3 -3
- package/dist/storage/index.d.ts +1 -1
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +5 -5
- package/dist/storage/ontology/in-memory/materializations.d.ts +4 -3
- package/dist/storage/ontology/in-memory/materializations.d.ts.map +1 -1
- package/dist/storage/ontology/index.d.ts +1 -1
- package/dist/storage/ontology/index.d.ts.map +1 -1
- package/dist/storage/ontology/materializations.d.ts +7 -3
- package/dist/storage/ontology/materializations.d.ts.map +1 -1
- package/dist/storage/ontology/provider.d.ts +2 -2
- package/dist/storage/ontology/provider.d.ts.map +1 -1
- package/dist/storage/workflow-runs/provider.js +3 -3
- package/dist/syncs/index.js +7 -7
- package/dist/testing/index.js +159 -21
- package/dist/testing/index.js.map +3 -3
- package/dist/testing/materializer-storage-contract.d.ts.map +1 -1
- package/dist/webhooks/internal.js +5 -5
- package/dist/workflows/index.js +14 -14
- package/package.json +1 -1
- package/src/actions/index.ts +10 -1
- package/src/actions/read-facade.ts +125 -3
- package/src/actions/types/context.ts +69 -2
- package/src/actions/types/definitions.ts +24 -2
- package/src/agents/types.ts +2 -0
- package/src/agents/validation.ts +4 -0
- package/src/auth/index.ts +1 -0
- package/src/auth/runtime.ts +8 -0
- package/src/auth/strategy.ts +1 -0
- package/src/auth/types.ts +14 -0
- package/src/index.ts +5 -0
- package/src/ontology/internal.ts +1 -1
- package/src/ontology/json-schema.ts +27 -5
- package/src/storage/index.ts +1 -0
- package/src/storage/ontology/in-memory/materializations.ts +34 -22
- package/src/storage/ontology/index.ts +1 -0
- package/src/storage/ontology/materializations.ts +8 -3
- package/src/storage/ontology/provider.ts +2 -2
- package/src/storage/timeseries/store.ts +6 -6
- package/src/testing/materializer-storage-contract.ts +170 -2
- package/dist/chunk-tycbzedm.js.map +0 -15
- /package/dist/{chunk-xdf9yswn.js.map → chunk-1g8negke.js.map} +0 -0
- /package/dist/{chunk-cbkm2vam.js.map → chunk-8gv5z0zm.js.map} +0 -0
- /package/dist/{chunk-rs1wbvy6.js.map → chunk-e42bc6m3.js.map} +0 -0
- /package/dist/{chunk-a09jx26t.js.map → chunk-fe5ev6mr.js.map} +0 -0
- /package/dist/{chunk-nzw7sm3b.js.map → chunk-hceck7dq.js.map} +0 -0
- /package/dist/{chunk-7gw7mepb.js.map → chunk-md8k0r54.js.map} +0 -0
- /package/dist/{chunk-hbeh8j9w.js.map → chunk-n4spznws.js.map} +0 -0
- /package/dist/{chunk-afjpa2hs.js.map → chunk-nkbfrt0c.js.map} +0 -0
- /package/dist/{chunk-g13869yf.js.map → chunk-tg5mee00.js.map} +0 -0
- /package/dist/{chunk-sxwk41qa.js.map → chunk-znagycq7.js.map} +0 -0
|
@@ -38,6 +38,7 @@ import type {
|
|
|
38
38
|
FinalizeMaterializationInput,
|
|
39
39
|
MaterializationCardinalityOccupantWorkRecord,
|
|
40
40
|
MaterializationEventWorkRecord,
|
|
41
|
+
MaterializationLinkScopeRevision,
|
|
41
42
|
MaterializationLinkScopeState,
|
|
42
43
|
MaterializationLinkState,
|
|
43
44
|
MaterializationObjectExistence,
|
|
@@ -134,7 +135,7 @@ export interface SessionState {
|
|
|
134
135
|
readonly workStreams: Record<StreamMaterializationWorkInput["order"], WorkStreamState>
|
|
135
136
|
workSealed: boolean
|
|
136
137
|
incidentLinksByObject: Map<string, readonly OntologyLinkRef[]> | null
|
|
137
|
-
|
|
138
|
+
linkSlotStates: Map<string, MaterializationLinkScopeState> | null
|
|
138
139
|
readonly objectExistence: Map<string, MaterializationObjectExistenceWorkRecord>
|
|
139
140
|
replacement: ReplacementSessionState | null
|
|
140
141
|
}
|
|
@@ -209,13 +210,13 @@ export class InMemoryOntologyMaterializationStorage implements OntologyMateriali
|
|
|
209
210
|
await this.assertObject(expected, input.commit.projectId)
|
|
210
211
|
for (const expected of input.expected.links)
|
|
211
212
|
await this.assertLink(expected, input.commit.projectId)
|
|
212
|
-
const
|
|
213
|
+
const expectedScopeRevisions = new Map<string, MaterializationLinkScopeRevision>()
|
|
213
214
|
for (const expected of input.expected.linkScopes) {
|
|
214
215
|
const key = linkScopeSortKey(expected.source, expected.linkId)
|
|
215
216
|
const current =
|
|
216
|
-
|
|
217
|
-
this.
|
|
218
|
-
|
|
217
|
+
expectedScopeRevisions.get(key) ??
|
|
218
|
+
this.computeEffectiveLinkScope(input.commit.projectId, expected.source, expected.linkId)
|
|
219
|
+
expectedScopeRevisions.set(key, current)
|
|
219
220
|
if (current.fingerprint !== expected.fingerprint) {
|
|
220
221
|
throw new MaterializationConflictError(
|
|
221
222
|
"effective-state",
|
|
@@ -247,7 +248,7 @@ export class InMemoryOntologyMaterializationStorage implements OntologyMateriali
|
|
|
247
248
|
},
|
|
248
249
|
workSealed: false,
|
|
249
250
|
incidentLinksByObject: null,
|
|
250
|
-
|
|
251
|
+
linkSlotStates: new Map(),
|
|
251
252
|
objectExistence: new Map<string, MaterializationObjectExistenceWorkRecord>(),
|
|
252
253
|
replacement: null,
|
|
253
254
|
}
|
|
@@ -275,7 +276,7 @@ export class InMemoryOntologyMaterializationStorage implements OntologyMateriali
|
|
|
275
276
|
session.appliedPlanItems.length = 0
|
|
276
277
|
session.outboxEnvelopes.clear()
|
|
277
278
|
session.incidentLinksByObject = null
|
|
278
|
-
session.
|
|
279
|
+
session.linkSlotStates = null
|
|
279
280
|
session.objectExistence.clear()
|
|
280
281
|
session.replacement = null
|
|
281
282
|
this.liveSessions.delete(session)
|
|
@@ -329,7 +330,7 @@ export class InMemoryOntologyMaterializationStorage implements OntologyMateriali
|
|
|
329
330
|
linkScopeSortKey(value.source, value.linkId)
|
|
330
331
|
)) {
|
|
331
332
|
this.requireSession(input.session)
|
|
332
|
-
const value = this.
|
|
333
|
+
const value = this.linkSlotState(session, scope.source, scope.linkId)
|
|
333
334
|
// Scope rows are currently only requested for cardinality-one links, so the complete member
|
|
334
335
|
// set is bounded by the ontology invariant. Replacement scope enumeration is flattened in
|
|
335
336
|
// its dedicated stream and never uses this shape.
|
|
@@ -1136,25 +1137,44 @@ export class InMemoryOntologyMaterializationStorage implements OntologyMateriali
|
|
|
1136
1137
|
}
|
|
1137
1138
|
}
|
|
1138
1139
|
|
|
1139
|
-
private
|
|
1140
|
+
private linkSlotState(
|
|
1140
1141
|
session: SessionState,
|
|
1141
1142
|
source: OntologyObjectRef,
|
|
1142
1143
|
linkId: string
|
|
1143
1144
|
): MaterializationLinkScopeState {
|
|
1144
|
-
session.
|
|
1145
|
+
session.linkSlotStates ??= new Map()
|
|
1145
1146
|
const key = linkScopeSortKey(source, linkId)
|
|
1146
|
-
const existing = session.
|
|
1147
|
+
const existing = session.linkSlotStates.get(key)
|
|
1147
1148
|
if (existing) return structuredClone(existing)
|
|
1148
|
-
const computed = this.
|
|
1149
|
-
session.
|
|
1149
|
+
const computed = this.computeLinkSlotState(session.header.commit.projectId, source, linkId)
|
|
1150
|
+
session.linkSlotStates.set(key, computed)
|
|
1150
1151
|
return structuredClone(computed)
|
|
1151
1152
|
}
|
|
1152
1153
|
|
|
1153
|
-
private
|
|
1154
|
+
private computeLinkSlotState(
|
|
1154
1155
|
projectId: string,
|
|
1155
1156
|
source: OntologyObjectRef,
|
|
1156
1157
|
linkId: string
|
|
1157
1158
|
): MaterializationLinkScopeState {
|
|
1159
|
+
const value = this.computeEffectiveLinkScope(projectId, source, linkId)
|
|
1160
|
+
return {
|
|
1161
|
+
...value,
|
|
1162
|
+
sourceAssertion: this.findActiveLinkScopeSource(projectId, source, linkId),
|
|
1163
|
+
override: structuredClone(
|
|
1164
|
+
publicLinkSlotOverride(
|
|
1165
|
+
this.state.linkSlotOverrides.get(
|
|
1166
|
+
projectEntityKey(projectId, linkScopeKey(source, linkId))
|
|
1167
|
+
)
|
|
1168
|
+
)
|
|
1169
|
+
),
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
private computeEffectiveLinkScope(
|
|
1174
|
+
projectId: string,
|
|
1175
|
+
source: OntologyObjectRef,
|
|
1176
|
+
linkId: string
|
|
1177
|
+
): MaterializationLinkScopeRevision & Pick<MaterializationLinkScopeState, "effective"> {
|
|
1158
1178
|
const rows: ObjectLinkRow[] = []
|
|
1159
1179
|
getInMemoryObjectMaterializerAdapter(this.objects).visitExactScopeLinks(
|
|
1160
1180
|
projectId,
|
|
@@ -1177,14 +1197,6 @@ export class InMemoryOntologyMaterializationStorage implements OntologyMateriali
|
|
|
1177
1197
|
const effective = rows.length === 1 ? linkSnapshot(rows[0]!) : null
|
|
1178
1198
|
return {
|
|
1179
1199
|
...finishScopeAccumulator(accumulator),
|
|
1180
|
-
sourceAssertion: this.findActiveLinkScopeSource(projectId, source, linkId),
|
|
1181
|
-
override: structuredClone(
|
|
1182
|
-
publicLinkSlotOverride(
|
|
1183
|
-
this.state.linkSlotOverrides.get(
|
|
1184
|
-
projectEntityKey(projectId, linkScopeKey(source, linkId))
|
|
1185
|
-
)
|
|
1186
|
-
)
|
|
1187
|
-
),
|
|
1188
1200
|
effective,
|
|
1189
1201
|
}
|
|
1190
1202
|
}
|
|
@@ -45,6 +45,7 @@ export type {
|
|
|
45
45
|
MaterializationClassificationWorkRecord,
|
|
46
46
|
MaterializationEventWorkRecord,
|
|
47
47
|
MaterializationIncidentObjectWorkRecord,
|
|
48
|
+
MaterializationLinkScopeRevision,
|
|
48
49
|
MaterializationLinkScopeState,
|
|
49
50
|
MaterializationLinkState,
|
|
50
51
|
MaterializationObjectExistence,
|
|
@@ -77,17 +77,22 @@ export interface MaterializationLinkState {
|
|
|
77
77
|
readonly effective: EffectiveLinkSnapshot | null
|
|
78
78
|
}
|
|
79
79
|
|
|
80
|
-
|
|
80
|
+
/** Revision of the complete effective `(source, linkId)` member set, for either cardinality. */
|
|
81
|
+
export interface MaterializationLinkScopeRevision {
|
|
81
82
|
readonly source: OntologyObjectRef
|
|
82
83
|
readonly linkId: string
|
|
84
|
+
readonly effectiveCount: number
|
|
85
|
+
readonly fingerprint: string
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
/** Cardinality-one slot state used while resolving managed and projected authority. */
|
|
89
|
+
export interface MaterializationLinkScopeState extends MaterializationLinkScopeRevision {
|
|
83
90
|
/** Complete active source value for the link slot. */
|
|
84
91
|
readonly sourceAssertion: StoredSourceLinkAssertion | null
|
|
85
92
|
/** Managed slot authority; absence delegates to source authority. */
|
|
86
93
|
readonly override: StoredLinkSlotOverride | null
|
|
87
94
|
/** The single effective edge, if its endpoints are effective. */
|
|
88
95
|
readonly effective: EffectiveLinkSnapshot | null
|
|
89
|
-
readonly effectiveCount: number
|
|
90
|
-
readonly fingerprint: string
|
|
91
96
|
}
|
|
92
97
|
|
|
93
98
|
export interface MaterializationStatePage {
|
|
@@ -14,7 +14,7 @@ import type { OntologyCommitOriginSelector, OntologyCommitWrite } from "./commit
|
|
|
14
14
|
import type {
|
|
15
15
|
FinalizeMaterializationInput,
|
|
16
16
|
MaterializationEventWorkRecord,
|
|
17
|
-
|
|
17
|
+
MaterializationLinkScopeRevision,
|
|
18
18
|
MaterializationPlanChunk,
|
|
19
19
|
MaterializationPlanHeader,
|
|
20
20
|
MaterializationPlanWorkItem,
|
|
@@ -99,7 +99,7 @@ export function appendScopeSnapshot(
|
|
|
99
99
|
|
|
100
100
|
export function finishScopeAccumulator(
|
|
101
101
|
accumulator: LinkScopeAccumulator
|
|
102
|
-
):
|
|
102
|
+
): MaterializationLinkScopeRevision {
|
|
103
103
|
accumulator.hash.update("]")
|
|
104
104
|
return {
|
|
105
105
|
source: accumulator.source,
|
|
@@ -139,9 +139,10 @@ export class InMemoryTimeseriesStorage implements TimeseriesStorage {
|
|
|
139
139
|
points: readonly TimeseriesPoint[]
|
|
140
140
|
}[]
|
|
141
141
|
> {
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
142
|
+
// Start every read before yielding so one batch observes one in-memory snapshot. The SQL
|
|
143
|
+
// providers get the same guarantee from their single query.
|
|
144
|
+
return Promise.all(
|
|
145
|
+
input.series.map(async (series) => ({
|
|
145
146
|
...series,
|
|
146
147
|
points: await this.getHistory({
|
|
147
148
|
projectId: input.projectId,
|
|
@@ -153,9 +154,8 @@ export class InMemoryTimeseriesStorage implements TimeseriesStorage {
|
|
|
153
154
|
limit: input.limitPerSeries,
|
|
154
155
|
order: input.order,
|
|
155
156
|
}),
|
|
156
|
-
})
|
|
157
|
-
|
|
158
|
-
return results
|
|
157
|
+
}))
|
|
158
|
+
)
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
async getLatest(params: {
|
|
@@ -15,6 +15,7 @@ import { restoreTrustedPrimitiveExecutionScope } from "../execution/durable"
|
|
|
15
15
|
import { createTestingScope } from "../execution/scopes"
|
|
16
16
|
import type { OntologyMaterializer } from "../materializer"
|
|
17
17
|
import {
|
|
18
|
+
createLinkScopeFingerprint,
|
|
18
19
|
createOntologyMaterializer,
|
|
19
20
|
type OntologyEditOperation,
|
|
20
21
|
ProjectionRegistry,
|
|
@@ -42,7 +43,7 @@ const Device = defineObjectType({
|
|
|
42
43
|
prop("name", "string", { required: true }),
|
|
43
44
|
prop("temperature", "double", { mode: "telemetry" }),
|
|
44
45
|
],
|
|
45
|
-
links: [link.self("parent", { cardinality: "one" })],
|
|
46
|
+
links: [link.self("parent", { cardinality: "one" }), link.self("peers", { cardinality: "many" })],
|
|
46
47
|
})
|
|
47
48
|
|
|
48
49
|
const devices = defineDataset("storage_contract_devices", {
|
|
@@ -55,6 +56,9 @@ const devices = defineDataset("storage_contract_devices", {
|
|
|
55
56
|
const readings = defineDataset("storage_contract_readings", {
|
|
56
57
|
schema: [col("device_id", "string"), col("at", "timestamp"), col("value", "float64")],
|
|
57
58
|
})
|
|
59
|
+
const devicePeers = defineDataset("storage_contract_device_peers", {
|
|
60
|
+
schema: [col("source_id", "string"), col("target_id", "string")],
|
|
61
|
+
})
|
|
58
62
|
const ConflictDevice = defineObjectType({
|
|
59
63
|
id: "StorageContractConflictDevice",
|
|
60
64
|
name: "Conflict device",
|
|
@@ -88,6 +92,10 @@ const temperatureProjection = defineProjection(
|
|
|
88
92
|
)
|
|
89
93
|
.fromDataset(readings)
|
|
90
94
|
.points({ objectId: "device_id", at: "at", value: "value" })
|
|
95
|
+
const devicePeersProjection = defineProjection("storage_contract_device_peers", Device.l.peers)
|
|
96
|
+
.fromDataset(devicePeers)
|
|
97
|
+
.sourceField("source_id")
|
|
98
|
+
.targetField("target_id")
|
|
91
99
|
const conflictDeviceProjection = defineProjection(
|
|
92
100
|
"storage_contract_conflict_devices",
|
|
93
101
|
ConflictDevice
|
|
@@ -98,11 +106,17 @@ const conflictDeviceProjection = defineProjection(
|
|
|
98
106
|
|
|
99
107
|
const ontology = new OntologyRegistry({ sources: [Device, ConflictDevice] })
|
|
100
108
|
const projections = new ProjectionRegistry({
|
|
101
|
-
projections: [
|
|
109
|
+
projections: [
|
|
110
|
+
deviceProjection,
|
|
111
|
+
temperatureProjection,
|
|
112
|
+
devicePeersProjection,
|
|
113
|
+
conflictDeviceProjection,
|
|
114
|
+
],
|
|
102
115
|
ontology,
|
|
103
116
|
datasetsById: new Map<string, DatasetDefinition>([
|
|
104
117
|
[devices.id, devices],
|
|
105
118
|
[readings.id, readings],
|
|
119
|
+
[devicePeers.id, devicePeers],
|
|
106
120
|
[conflictDevices.id, conflictDevices],
|
|
107
121
|
]),
|
|
108
122
|
})
|
|
@@ -561,6 +575,160 @@ export function runMaterializerStorageContractSuite<TStorage extends Storage>(
|
|
|
561
575
|
await provider.cleanup?.(createdStorage)
|
|
562
576
|
}
|
|
563
577
|
})
|
|
578
|
+
|
|
579
|
+
test(`${name} fences projected cardinality-many link scopes by fingerprint`, async () => {
|
|
580
|
+
const createdStorage = await provider.createStorage()
|
|
581
|
+
const storage = requireContractStorage(createdStorage)
|
|
582
|
+
let materializationOrdinal = 0
|
|
583
|
+
const materializer = createOntologyMaterializer({
|
|
584
|
+
projectId: "materializer-storage-contract",
|
|
585
|
+
ontology,
|
|
586
|
+
projections,
|
|
587
|
+
storage,
|
|
588
|
+
dependencies: {
|
|
589
|
+
batching: { sourceStageRows: 1, statePageRows: 1, planChunkRows: 1 },
|
|
590
|
+
clock: () => new Date("2026-02-01T12:00:00.000Z"),
|
|
591
|
+
materializationId: () => `many-scope-contract-candidate-${++materializationOrdinal}`,
|
|
592
|
+
},
|
|
593
|
+
})
|
|
594
|
+
const runtimeMaterializer = materializer.withScope(runtimeScope())
|
|
595
|
+
const source = { objectTypeId: Device.id, primaryId: "source" }
|
|
596
|
+
const peer = (primaryId: string) => ({ objectTypeId: Device.id, primaryId })
|
|
597
|
+
const linkRef = (targetId: string) => ({
|
|
598
|
+
source,
|
|
599
|
+
linkId: "peers",
|
|
600
|
+
target: peer(targetId),
|
|
601
|
+
})
|
|
602
|
+
|
|
603
|
+
try {
|
|
604
|
+
await runtimeMaterializer.edits.commit({
|
|
605
|
+
mode: "atomic",
|
|
606
|
+
source: { kind: "runtime", requestId: "many-scope-endpoints" },
|
|
607
|
+
operations: ["source", "peer-a", "peer-b", "peer-c"].map((primaryId) => ({
|
|
608
|
+
id: `create-${primaryId}`,
|
|
609
|
+
kind: "object.create" as const,
|
|
610
|
+
ref: peer(primaryId),
|
|
611
|
+
properties: { name: primaryId },
|
|
612
|
+
})),
|
|
613
|
+
expectedObjects: [],
|
|
614
|
+
expectedLinks: [],
|
|
615
|
+
expectedLinkScopes: [],
|
|
616
|
+
})
|
|
617
|
+
|
|
618
|
+
const datasetVersion = {
|
|
619
|
+
datasetId: devicePeers.id,
|
|
620
|
+
versionId: "many-links-v1",
|
|
621
|
+
createdAt: "2026-02-01T00:00:00.000Z",
|
|
622
|
+
}
|
|
623
|
+
const execution = await claim(storage, {
|
|
624
|
+
runId: "many-links-v1",
|
|
625
|
+
projectionId: devicePeersProjection.id,
|
|
626
|
+
protocol: "replacement",
|
|
627
|
+
datasetVersion,
|
|
628
|
+
})
|
|
629
|
+
const projectedLinks = [linkRef("peer-a"), linkRef("peer-b")]
|
|
630
|
+
await (
|
|
631
|
+
await projectionMaterializer(
|
|
632
|
+
materializer,
|
|
633
|
+
storage,
|
|
634
|
+
devicePeersProjection.id,
|
|
635
|
+
"many-links-v1"
|
|
636
|
+
)
|
|
637
|
+
).projections.replace({
|
|
638
|
+
source: { projectionId: devicePeersProjection.id },
|
|
639
|
+
datasetVersion,
|
|
640
|
+
execution,
|
|
641
|
+
entries: entries(
|
|
642
|
+
projectedLinks.map((ref) => ({
|
|
643
|
+
root: { kind: "link", ref },
|
|
644
|
+
assertions: [{ kind: "link", ref }],
|
|
645
|
+
}))
|
|
646
|
+
),
|
|
647
|
+
})
|
|
648
|
+
|
|
649
|
+
const observedLinks = await storage.objects.listLinks({
|
|
650
|
+
projectId: "materializer-storage-contract",
|
|
651
|
+
objectTypeId: Device.id,
|
|
652
|
+
objectId: source.primaryId,
|
|
653
|
+
linkId: "peers",
|
|
654
|
+
})
|
|
655
|
+
const fingerprint = createLinkScopeFingerprint(
|
|
656
|
+
observedLinks.map((row) => {
|
|
657
|
+
if (row.lastCommitId === undefined) {
|
|
658
|
+
throw new Error("Projected contract link is missing materializer provenance.")
|
|
659
|
+
}
|
|
660
|
+
return {
|
|
661
|
+
ref: linkRef(row.targetId),
|
|
662
|
+
createdAt: row.createdAt.toISOString(),
|
|
663
|
+
updatedAt: row.updatedAt.toISOString(),
|
|
664
|
+
lastCommitId: row.lastCommitId,
|
|
665
|
+
}
|
|
666
|
+
})
|
|
667
|
+
)
|
|
668
|
+
const commitObservation = async (runId: string, name: string) => {
|
|
669
|
+
await queueTestActionRun(storage, {
|
|
670
|
+
id: runId,
|
|
671
|
+
projectId: "materializer-storage-contract",
|
|
672
|
+
actionId: "observePeers",
|
|
673
|
+
subject: { kind: "object", objectTypeId: Device.id, primaryId: source.primaryId },
|
|
674
|
+
params: {},
|
|
675
|
+
idempotencyKey: runId,
|
|
676
|
+
})
|
|
677
|
+
await storage.actionRuns.start({ id: runId, projectId: "materializer-storage-contract" })
|
|
678
|
+
const actionMaterializer = await primitiveMaterializer(materializer, storage, {
|
|
679
|
+
kind: "action",
|
|
680
|
+
id: "observePeers",
|
|
681
|
+
runId,
|
|
682
|
+
})
|
|
683
|
+
return actionMaterializer.edits.commit({
|
|
684
|
+
mode: "atomic",
|
|
685
|
+
source: { kind: "action", actionId: "observePeers", runId },
|
|
686
|
+
operations: [
|
|
687
|
+
{
|
|
688
|
+
id: `record-${runId}`,
|
|
689
|
+
kind: "object.patch",
|
|
690
|
+
ref: source,
|
|
691
|
+
set: { name },
|
|
692
|
+
unset: [],
|
|
693
|
+
reset: [],
|
|
694
|
+
},
|
|
695
|
+
],
|
|
696
|
+
expectedObjects: [],
|
|
697
|
+
expectedLinks: [],
|
|
698
|
+
expectedLinkScopes: [{ source, linkId: "peers", fingerprint }],
|
|
699
|
+
})
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
// Regression guard for G-021: make begin() hydrate the expected scope through the
|
|
703
|
+
// cardinality-one slot reader again and this otherwise unrelated Action commit fails before
|
|
704
|
+
// its already-stable fingerprint can be compared.
|
|
705
|
+
await expect(commitObservation("many-scope-action", "observed peers")).resolves.toMatchObject(
|
|
706
|
+
{ kind: "edit", created: true }
|
|
707
|
+
)
|
|
708
|
+
|
|
709
|
+
await runtimeMaterializer.edits.commit({
|
|
710
|
+
mode: "atomic",
|
|
711
|
+
source: { kind: "runtime", requestId: "many-scope-change" },
|
|
712
|
+
operations: [{ id: "add-peer", kind: "link.upsert", ref: linkRef("peer-c") }],
|
|
713
|
+
expectedObjects: [],
|
|
714
|
+
expectedLinks: [],
|
|
715
|
+
expectedLinkScopes: [],
|
|
716
|
+
})
|
|
717
|
+
|
|
718
|
+
await expect(commitObservation("stale-many-scope-action", "must not commit")).rejects.toThrow(
|
|
719
|
+
"Expected link scope changed"
|
|
720
|
+
)
|
|
721
|
+
expect(
|
|
722
|
+
await storage.objects.getByPrimaryId({
|
|
723
|
+
projectId: "materializer-storage-contract",
|
|
724
|
+
objectTypeId: Device.id,
|
|
725
|
+
primaryId: source.primaryId,
|
|
726
|
+
})
|
|
727
|
+
).toMatchObject({ properties: { name: "observed peers" } })
|
|
728
|
+
} finally {
|
|
729
|
+
await provider.cleanup?.(createdStorage)
|
|
730
|
+
}
|
|
731
|
+
})
|
|
564
732
|
}
|
|
565
733
|
|
|
566
734
|
function runtimeScope() {
|
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"version": 3,
|
|
3
|
-
"sources": ["../src/actions/builders/define-action.ts", "../src/actions/builders/params.ts", "../src/actions/commit-edits.ts", "../src/actions/read-facade.ts", "../src/actions/registry.ts", "../src/actions/validators.ts"],
|
|
4
|
-
"sourcesContent": [
|
|
5
|
-
"import type { ObjectTypeWithPropertyTokens } from \"../../ontology/tokens\"\nimport { ActionDefinitionError, effectsWithoutEditsMessage } from \"../errors\"\nimport type {\n ActionBuilder,\n ActionEditsHandler,\n ActionEffectsHandler,\n ActionParamsConfig,\n ActionValidator,\n ActionWritebackHandler,\n GlobalActionDefinition,\n GlobalActionEditsHandler,\n GlobalActionEffectsHandler,\n GlobalActionPhaseBuilder,\n GlobalActionValidator,\n GlobalActionWritebackHandler,\n ObjectActionDefinition,\n ObjectActionPhaseBuilder,\n} from \"../types\"\nimport { assertNonEmpty } from \"../validation\"\n\ntype ActionOptions = {\n description?: string\n}\n\nexport function defineAction<const TId extends string>(\n id: TId,\n options?: ActionOptions\n): ActionBuilder<TId> {\n assertNonEmpty(id, \"id\")\n\n return asPublicActionType<ActionBuilder<TId>>(createActionBuilder(id, options))\n}\n\nfunction createActionBuilder(id: string, options?: ActionOptions) {\n const builder = {\n params(params: ActionParamsConfig) {\n return createGlobalActionPhaseBuilder(id, params, options)\n },\n on(objectType: ObjectTypeWithPropertyTokens) {\n assertNonEmpty(objectType.id, \"target id\")\n return createObjectActionParamsBuilder(id, objectType, options)\n },\n }\n\n return builder\n}\n\nfunction createGlobalActionPhaseBuilder(\n id: string,\n params: ActionParamsConfig,\n options?: ActionOptions\n): GlobalActionPhaseBuilder<string, ActionParamsConfig> {\n const validators: GlobalActionValidator<Record<string, unknown>>[] = []\n\n const builder = {\n validate(validator: GlobalActionValidator<Record<string, unknown>>) {\n validators.push(validator)\n return builder\n },\n writeback(handler: GlobalActionWritebackHandler<Record<string, unknown>, unknown>) {\n return createGlobalDefinition({\n id,\n params,\n description: options?.description,\n validators,\n writeback: handler,\n })\n },\n edits(handler: GlobalActionEditsHandler<Record<string, unknown>, undefined>) {\n return createGlobalDefinition({\n id,\n params,\n description: options?.description,\n validators,\n edits: handler,\n })\n },\n }\n\n return asPublicActionType<GlobalActionPhaseBuilder<string, ActionParamsConfig>>(builder)\n}\n\nfunction createObjectActionParamsBuilder(\n id: string,\n objectType: ObjectTypeWithPropertyTokens,\n options?: ActionOptions\n) {\n return {\n params(params: ActionParamsConfig) {\n return createObjectActionPhaseBuilder(id, objectType, params, options)\n },\n }\n}\n\nfunction createObjectActionPhaseBuilder(\n id: string,\n objectType: ObjectTypeWithPropertyTokens,\n params: ActionParamsConfig,\n options?: ActionOptions\n): ObjectActionPhaseBuilder<string, ObjectTypeWithPropertyTokens, ActionParamsConfig> {\n const validators: ActionValidator<ObjectTypeWithPropertyTokens, Record<string, unknown>>[] = []\n\n const builder = {\n validate(validator: ActionValidator<ObjectTypeWithPropertyTokens, Record<string, unknown>>) {\n validators.push(validator)\n return builder\n },\n writeback(\n handler: ActionWritebackHandler<\n ObjectTypeWithPropertyTokens,\n Record<string, unknown>,\n unknown\n >\n ) {\n return createObjectDefinition({\n id,\n objectType,\n params,\n description: options?.description,\n validators,\n writeback: handler,\n })\n },\n edits(\n handler: ActionEditsHandler<ObjectTypeWithPropertyTokens, Record<string, unknown>, undefined>\n ) {\n return createObjectDefinition({\n id,\n objectType,\n params,\n description: options?.description,\n validators,\n edits: handler,\n })\n },\n }\n\n return asPublicActionType<\n ObjectActionPhaseBuilder<string, ObjectTypeWithPropertyTokens, ActionParamsConfig>\n >(builder)\n}\n\nfunction createGlobalDefinition(input: {\n readonly id: string\n readonly params: ActionParamsConfig\n readonly description?: string\n readonly validators: readonly unknown[]\n readonly writeback?: unknown\n readonly edits?: unknown\n readonly effects?: unknown\n}): GlobalActionDefinition {\n const definition = {\n kind: \"action\",\n id: input.id,\n binding: { kind: \"global\" },\n params: input.params,\n phases: {\n validate: [...input.validators],\n ...(input.writeback ? { writeback: input.writeback } : {}),\n ...(input.edits ? { edits: input.edits } : {}),\n ...(input.effects ? { effects: input.effects } : {}),\n },\n ...(input.description !== undefined ? { description: input.description } : {}),\n }\n\n return asPublicActionType<GlobalActionDefinition>(\n Object.assign(definition, {\n edits(handler: GlobalActionEditsHandler<Record<string, unknown>, unknown>) {\n return createGlobalDefinition({\n ...input,\n edits: handler,\n })\n },\n effects(handler: GlobalActionEffectsHandler<Record<string, unknown>, unknown>) {\n if (!input.edits) {\n throw new ActionDefinitionError(effectsWithoutEditsMessage(input.id))\n }\n return createGlobalDefinition({\n ...input,\n effects: handler,\n })\n },\n })\n )\n}\n\nfunction createObjectDefinition(input: {\n readonly id: string\n readonly objectType: ObjectTypeWithPropertyTokens\n readonly params: ActionParamsConfig\n readonly description?: string\n readonly validators: readonly unknown[]\n readonly writeback?: unknown\n readonly edits?: unknown\n readonly effects?: unknown\n}): ObjectActionDefinition {\n const definition = {\n kind: \"action\",\n id: input.id,\n binding: { kind: \"object\", objectType: input.objectType },\n params: input.params,\n phases: {\n validate: [...input.validators],\n ...(input.writeback ? { writeback: input.writeback } : {}),\n ...(input.edits ? { edits: input.edits } : {}),\n ...(input.effects ? { effects: input.effects } : {}),\n },\n ...(input.description !== undefined ? { description: input.description } : {}),\n }\n\n return asPublicActionType<ObjectActionDefinition>(\n Object.assign(definition, {\n edits(\n handler: ActionEditsHandler<ObjectTypeWithPropertyTokens, Record<string, unknown>, unknown>\n ) {\n return createObjectDefinition({\n ...input,\n edits: handler,\n })\n },\n effects(\n handler: ActionEffectsHandler<\n ObjectTypeWithPropertyTokens,\n Record<string, unknown>,\n unknown\n >\n ) {\n if (!input.edits) {\n throw new ActionDefinitionError(effectsWithoutEditsMessage(input.id))\n }\n return createObjectDefinition({\n ...input,\n effects: handler,\n })\n },\n })\n )\n}\n\n// Runtime builders are plain objects; public builder types carry phase-order inference.\nfunction asPublicActionType<TPublic>(value: unknown): TPublic {\n return value as TPublic\n}\n",
|
|
6
|
-
"import type { SchemaOrRef } from \"../../ontology\"\nimport type { QuantitativeTypeId } from \"../../ontology/units\"\nimport type { ActionParamConfig } from \"../types\"\n\ntype ActionParamOptions = {\n description?: string\n semanticType?: QuantitativeTypeId\n nullable?: boolean\n}\n\ntype FieldFromOptions<TOptions, TKey extends string, TFallback> =\n TOptions extends Record<TKey, infer TValue>\n ? { [K in TKey]: TValue }\n : { [K in TKey]?: TFallback }\n\ntype ActionParamResult<\n TSchema extends SchemaOrRef,\n TRequired extends boolean,\n TOptions extends ActionParamOptions | undefined,\n> = {\n schema: TSchema\n required: TRequired\n} & FieldFromOptions<TOptions, \"description\", string> &\n FieldFromOptions<TOptions, \"semanticType\", QuantitativeTypeId> &\n FieldFromOptions<TOptions, \"nullable\", boolean>\n\nexport function param<\n const TSchema extends SchemaOrRef,\n const TOptions extends ActionParamOptions | undefined = undefined,\n>(schema: TSchema, options?: TOptions): ActionParamResult<TSchema, true, TOptions> {\n const result: ActionParamConfig & { required: true } = {\n schema,\n required: true,\n ...(options?.description !== undefined ? { description: options.description } : {}),\n ...(options?.semanticType !== undefined ? { semanticType: options.semanticType } : {}),\n ...(options?.nullable !== undefined ? { nullable: options.nullable } : {}),\n }\n return result as ActionParamResult<TSchema, true, TOptions>\n}\n\nexport function optional<const TParam extends ActionParamConfig>(\n paramConfig: TParam\n): Omit<TParam, \"required\"> & { readonly required: false } {\n return {\n ...paramConfig,\n required: false,\n }\n}\n",
|
|
7
|
-
"import type { EditBatch } from \"../edits\"\nimport { lowerEditBatch } from \"../edits\"\nimport type {\n EditCommitResult,\n EffectiveLinkChange,\n EffectiveObjectChange,\n ExpectedLinkRevision,\n ExpectedLinkScopeRevision,\n ExpectedObjectRevision,\n OntologyOperationOutcome,\n} from \"../materializer\"\nimport type { OntologyMutationRuntime } from \"../runtime/ontology-mutations\"\nimport type { Storage } from \"../storage/types\"\nimport { ActionEditCommitError } from \"./errors\"\n\n/** Exact reads an Action handler depended on, protected by row-level CAS at commit time. */\nexport interface ActionReadDependencies {\n readonly objects: readonly ExpectedObjectRevision[]\n readonly links: readonly ExpectedLinkRevision[]\n readonly linkScopes: readonly ExpectedLinkScopeRevision[]\n}\n\nconst NO_READ_DEPENDENCIES: ActionReadDependencies = { objects: [], links: [], linkScopes: [] }\n\nexport interface CommitActionEditsInput {\n readonly mutations: Pick<OntologyMutationRuntime, \"commitEdits\">\n readonly projectId: string\n readonly runId: string\n readonly actionId: string\n readonly batch: EditBatch\n readonly dependencies?: ActionReadDependencies\n}\n\n/** The authoritative ontology commit an Action run produced. */\nexport interface ActionEditCommitResult {\n readonly commitId: string\n readonly created: boolean\n readonly eventCount: number\n readonly outcomes: readonly OntologyOperationOutcome[]\n readonly changes: {\n readonly objects: readonly EffectiveObjectChange[]\n readonly links: readonly EffectiveLinkChange[]\n }\n readonly committedAt: Date\n}\n\nexport interface FindActionEditCommitInput {\n readonly storage: Pick<Storage, \"ontology\">\n readonly projectId: string\n readonly runId: string\n}\n\n/**\n * Commits one Action run's recorded edits as a single atomic ontology commit.\n *\n * The batch lowers to canonical Materializer operations and the Materializer validates the Action run\n * identity, applies managed authority, resolves effective state, writes the authoritative commit, and\n * inserts outbox facts in one transaction. Repeating the call for the same run replays that commit;\n * a divergent request for the same run is a typed idempotency conflict.\n */\nexport async function commitActionEdits(\n input: CommitActionEditsInput\n): Promise<ActionEditCommitResult> {\n const dependencies = input.dependencies ?? NO_READ_DEPENDENCIES\n const commit = await input.mutations.commitEdits({\n mode: \"atomic\",\n source: { kind: \"action\", actionId: input.actionId, runId: input.runId },\n operations: lowerEditBatch(input.batch),\n expectedObjects: dependencies.objects,\n expectedLinks: dependencies.links,\n expectedLinkScopes: dependencies.linkScopes,\n })\n return toActionEditCommitResult(commit)\n}\n\n/**\n * Resolves the authoritative commit an Action run already produced, if any.\n *\n * Resume uses the exact `{ actionRunId }` origin instead of rerunning handlers, so a redelivered run\n * returns the persisted result without recomputing an idempotency hash.\n */\nexport async function findActionEditCommit(\n input: FindActionEditCommitInput\n): Promise<ActionEditCommitResult | null> {\n const record = await input.storage.ontology.commits.getByOrigin({\n projectId: input.projectId,\n origin: { kind: \"action\", actionRunId: input.runId },\n })\n if (!record) return null\n if (record.result.kind !== \"edit\") {\n throw new ActionEditCommitError(\n `[Sixb] Action run '${input.runId}' resolved a '${record.result.kind}' commit instead of an edit commit.`\n )\n }\n return toActionEditCommitResult({ ...record.result, created: false })\n}\n\nfunction toActionEditCommitResult(commit: EditCommitResult): ActionEditCommitResult {\n return {\n commitId: commit.commitId,\n created: commit.created,\n eventCount: commit.eventCount,\n outcomes: commit.outcomes,\n changes: commit.changes,\n committedAt: new Date(commit.committedAt),\n }\n}\n",
|
|
8
|
-
"import { linkRefKey, linkScopeKey, objectRefKey } from \"../materialization/refs\"\nimport type {\n EffectiveLinkSnapshot,\n ExpectedLinkRevision,\n ExpectedLinkScopeRevision,\n ExpectedObjectRevision,\n OntologyLinkRef,\n OntologyObjectRef,\n} from \"../materializer\"\nimport { createLinkScopeFingerprint } from \"../materializer\"\nimport type { ObjectTypeWithPropertyTokens } from \"../ontology/tokens\"\nimport type { ValueType } from \"../ontology/types\"\nimport type { ObjectSetListInput } from \"../runtime/types\"\nimport type { ObjectLinkRow, ObjectRow } from \"../storage\"\nimport type { ActionReadDependencies } from \"./commit-edits\"\nimport type { ActionReadFacade, ActionReadObjectSet } from \"./types\"\n\nexport type ActionReadObjectSetSource = {\n get(id: string): Promise<unknown>\n query(): unknown\n list(input?: ObjectSetListInput): Promise<unknown>\n byId(id: string): {\n get(): Promise<unknown>\n listLinks(link?: { readonly id: string }): Promise<unknown>\n }\n}\n\n/**\n * Records the exact state an Action handler observed while reading.\n *\n * A handler that reads one dependency twice keeps the first observation: the commit must fail when\n * current state no longer matches what the decision was made against, and the later read may already\n * reflect the handler's own intent. Arbitrary query phantoms stay out of this release — `query()` and\n * `list()` results are not turned into dependencies.\n */\nexport class ActionReadRecorder {\n private readonly objects = new Map<string, ExpectedObjectRevision>()\n private readonly links = new Map<string, ExpectedLinkRevision>()\n private readonly linkScopes = new Map<string, ExpectedLinkScopeRevision>()\n\n /** Records a concrete object read, including exact absence. */\n observeObject(ref: OntologyObjectRef, row: ObjectRow | null): void {\n const key = objectRefKey(ref)\n if (this.objects.has(key)) return\n if (!row) {\n this.objects.set(key, { ref, exists: false })\n return\n }\n // Rows without materializer provenance predate the commit ledger and cannot be fenced.\n if (row.lastCommitId === undefined) return\n this.objects.set(key, {\n ref,\n exists: true,\n version: row.version,\n lastCommitId: row.lastCommitId,\n })\n }\n\n /**\n * Records the complete `(source, linkId)` scopes a link listing observed.\n *\n * `linkIds` names every scope the read covered so an empty scope is recorded as an empty\n * fingerprint rather than being silently omitted.\n */\n observeLinkScopes(\n source: OntologyObjectRef,\n linkIds: readonly string[],\n rows: readonly ObjectLinkRow[]\n ): void {\n const snapshotsByLinkId = new Map<string, EffectiveLinkSnapshot[]>()\n for (const linkId of linkIds) snapshotsByLinkId.set(linkId, [])\n /** Scopes holding a row that cannot be fenced, so no expectation may be recorded for them. */\n const unfenceable = new Set<string>()\n\n for (const row of rows) {\n if (row.sourceTypeId !== source.objectTypeId || row.sourceId !== source.primaryId) continue\n const snapshots = snapshotsByLinkId.get(row.linkId)\n if (!snapshots) continue\n const snapshot = toLinkSnapshot(row)\n if (!snapshot) {\n // Same rule `observeObject` applies to rows without materializer provenance: record no\n // expectation at all. A fingerprint computed over the remaining rows would describe a scope\n // the store can never reproduce, turning every such read into a guaranteed conflict.\n unfenceable.add(row.linkId)\n continue\n }\n snapshots.push(snapshot)\n this.observeLink(snapshot.ref, snapshot)\n }\n\n for (const [linkId, snapshots] of snapshotsByLinkId) {\n if (unfenceable.has(linkId)) continue\n const key = linkScopeKey(source, linkId)\n if (this.linkScopes.has(key)) continue\n this.linkScopes.set(key, {\n source,\n linkId,\n fingerprint: createLinkScopeFingerprint(snapshots),\n })\n }\n }\n\n /** Records a concrete link read, including exact absence. */\n observeLink(ref: OntologyLinkRef, snapshot: EffectiveLinkSnapshot | null): void {\n const key = linkRefKey(ref)\n if (this.links.has(key)) return\n this.links.set(\n key,\n snapshot ? { ref, exists: true, lastCommitId: snapshot.lastCommitId } : { ref, exists: false }\n )\n }\n\n dependencies(): ActionReadDependencies {\n return {\n objects: [...this.objects.values()],\n links: [...this.links.values()],\n linkScopes: [...this.linkScopes.values()],\n }\n }\n}\n\nexport interface ActionReadFacadeOptions {\n /** Records what the handler observed, so the commit can be fenced against it. */\n readonly recorder: ActionReadRecorder\n /**\n * Every link the object type carries, inherited links included.\n *\n * Inheritance is resolved by the Ontology registry, not by the imported definition, so an\n * `extends` type would otherwise report only its own links and drop inherited ones from the\n * recorded scopes.\n */\n readonly resolveLinkIds: (objectTypeId: string) => readonly string[]\n}\n\nexport function createActionReadFacade(\n createObjectSet: <const TObjectType extends ObjectTypeWithPropertyTokens>(\n objectType: TObjectType\n ) => ActionReadObjectSetSource,\n options?: ActionReadFacadeOptions\n): ActionReadFacade {\n const facade = {\n objects<const TObjectType extends ObjectTypeWithPropertyTokens>(objectType: TObjectType) {\n return createActionReadObjectSetAdapter<TObjectType>(\n objectType,\n createObjectSet(objectType),\n options\n )\n },\n }\n\n return facade as ActionReadFacade\n}\n\nfunction createActionReadObjectSetAdapter<TObjectType extends ObjectTypeWithPropertyTokens>(\n objectType: TObjectType,\n objectSet: ActionReadObjectSetSource,\n options: ActionReadFacadeOptions | undefined\n): ActionReadObjectSet<TObjectType, readonly ValueType[], ObjectTypeWithPropertyTokens> {\n type TypedReadObjectSet = ActionReadObjectSet<\n TObjectType,\n readonly ValueType[],\n ObjectTypeWithPropertyTokens\n >\n\n async function readObject(id: string, read: () => Promise<unknown>): Promise<unknown> {\n const row = await read()\n options?.recorder.observeObject(\n { objectTypeId: objectType.id, primaryId: id },\n (row ?? null) as ObjectRow | null\n )\n return row\n }\n\n return {\n get(id) {\n return readObject(id, () => objectSet.get(id)) as ReturnType<TypedReadObjectSet[\"get\"]>\n },\n query() {\n return objectSet.query() as ReturnType<TypedReadObjectSet[\"query\"]>\n },\n list(input) {\n return objectSet.list(input) as ReturnType<TypedReadObjectSet[\"list\"]>\n },\n byId(id) {\n const handle = objectSet.byId(id)\n return {\n get() {\n return readObject(id, () => handle.get()) as ReturnType<\n ReturnType<TypedReadObjectSet[\"byId\"]>[\"get\"]\n >\n },\n async listLinks(link) {\n const rows = (await handle.listLinks(link)) as readonly ObjectLinkRow[]\n options?.recorder.observeLinkScopes(\n { objectTypeId: objectType.id, primaryId: id },\n link ? [link.id] : options.resolveLinkIds(objectType.id),\n rows\n )\n return rows as unknown as Awaited<\n ReturnType<ReturnType<TypedReadObjectSet[\"byId\"]>[\"listLinks\"]>\n >\n },\n }\n },\n }\n}\n\nfunction toLinkSnapshot(row: ObjectLinkRow): EffectiveLinkSnapshot | null {\n // Rows without materializer provenance predate the commit ledger and cannot be fenced.\n if (row.lastCommitId === undefined) return null\n return {\n ref: {\n source: { objectTypeId: row.sourceTypeId, primaryId: row.sourceId },\n linkId: row.linkId,\n target: { objectTypeId: row.targetTypeId, primaryId: row.targetId },\n },\n ...(row.properties !== undefined\n ? { properties: row.properties as EffectiveLinkSnapshot[\"properties\"] }\n : {}),\n createdAt: row.createdAt.toISOString(),\n updatedAt: row.updatedAt.toISOString(),\n lastCommitId: row.lastCommitId,\n }\n}\n",
|
|
9
|
-
"import type { ObjectType, OntologyDefinitionCatalog } from \"../ontology\"\nimport {\n ActionDefinitionError,\n effectsWithoutEditsMessage,\n missingActionMutationMessage,\n} from \"./errors\"\nimport type { ActionDefinition, ObjectActionDefinition } from \"./types\"\nimport { isObjectActionDefinition } from \"./validation\"\n\nexport interface ActionDefinitionCatalog {\n list(): readonly ActionDefinition[]\n getById(id: string): ActionDefinition | null\n listGlobal(): readonly ActionDefinition[]\n listForType(type: ObjectType): readonly ObjectActionDefinition[]\n}\n\nexport interface ActionRegistryOptions {\n readonly actions: readonly ActionDefinition[]\n readonly ontology: OntologyDefinitionCatalog\n}\n\nexport class ActionRegistry implements ActionDefinitionCatalog {\n private readonly byId = new Map<string, ActionDefinition>()\n private readonly globalActions: ActionDefinition[] = []\n private readonly byTargetId = new Map<string, ObjectActionDefinition[]>()\n\n private readonly ontology: OntologyDefinitionCatalog\n\n constructor(options: ActionRegistryOptions) {\n this.ontology = options.ontology\n\n for (const action of options.actions) {\n const previous = this.byId.get(action.id)\n if (previous) {\n const chainDuplicate = this.getInheritanceDuplicate(action, previous)\n if (chainDuplicate) {\n throw new ActionDefinitionError(\n `Duplicate action id \"${action.id}\" in inheritance chain of \"${chainDuplicate.objectTypeId}\": defined on both \"${chainDuplicate.firstTargetId}\" and \"${chainDuplicate.secondTargetId}\".`\n )\n }\n\n throw new ActionDefinitionError(\n `Duplicate action id \"${action.id}\" declared in multiple files.`\n )\n }\n\n this.validatePhases(action)\n this.byId.set(action.id, action)\n\n if (!isObjectActionDefinition(action)) {\n this.globalActions.push(action)\n continue\n }\n\n const objectType = action.binding.objectType\n const target = this.ontology.getObjectTypeById(objectType.id)\n if (!target) {\n throw new ActionDefinitionError(\n `Action \"${action.id}\" targets unknown object type \"${objectType.id}\". Add the object type to ontology before registering the action.`\n )\n }\n\n const bucket = this.byTargetId.get(objectType.id) ?? []\n bucket.push(action)\n this.byTargetId.set(objectType.id, bucket)\n }\n }\n\n private validatePhases(action: ActionDefinition): void {\n const hasWriteback = action.phases.writeback !== undefined\n const hasEdits = action.phases.edits !== undefined\n const hasEffects = action.phases.effects !== undefined\n\n if (!hasWriteback && !hasEdits) {\n throw new ActionDefinitionError(missingActionMutationMessage(action.id))\n }\n\n if (hasEffects && !hasEdits) {\n throw new ActionDefinitionError(effectsWithoutEditsMessage(action.id))\n }\n }\n\n list(): readonly ActionDefinition[] {\n return [...this.byId.values()]\n }\n\n getById(id: string): ActionDefinition | null {\n return this.byId.get(id) ?? null\n }\n\n listGlobal(): readonly ActionDefinition[] {\n return [...this.globalActions]\n }\n\n listForType(type: ObjectType): readonly ObjectActionDefinition[] {\n this.ontology.resolveObjectType(type.id)\n\n const seen = new Set<string>()\n const result: ObjectActionDefinition[] = []\n\n for (const ancestor of this.ontology.listAncestorChain(type)) {\n for (const action of this.byTargetId.get(ancestor.id) ?? []) {\n if (seen.has(action.id)) continue\n seen.add(action.id)\n result.push(action)\n }\n }\n\n return result\n }\n\n private getInheritanceDuplicate(\n action: ActionDefinition,\n previous: ActionDefinition\n ): { objectTypeId: string; firstTargetId: string; secondTargetId: string } | null {\n if (!isObjectActionDefinition(action) || !isObjectActionDefinition(previous)) {\n return null\n }\n\n const actionObjectType = action.binding.objectType\n const previousObjectType = previous.binding.objectType\n\n if (actionObjectType.id === previousObjectType.id) {\n return null\n }\n\n const actionChain = this.ontology.listAncestorChain(actionObjectType)\n if (actionChain.some((ancestor) => ancestor.id === previousObjectType.id)) {\n return {\n objectTypeId: actionObjectType.id,\n firstTargetId: previousObjectType.id,\n secondTargetId: actionObjectType.id,\n }\n }\n\n const previousChain = this.ontology.listAncestorChain(previousObjectType)\n if (previousChain.some((ancestor) => ancestor.id === actionObjectType.id)) {\n return {\n objectTypeId: previousObjectType.id,\n firstTargetId: actionObjectType.id,\n secondTargetId: previousObjectType.id,\n }\n }\n\n return null\n }\n}\n",
|
|
10
|
-
"import { ActionValidationError } from \"../objects/action/errors\"\nimport type { ActionDefinition, ActionSubject, ActionTargetObject } from \"./types\"\nimport { isObjectActionDefinition } from \"./validation\"\n\ntype RuntimePhaseHandler = (ctx: unknown) => unknown | Promise<unknown>\n\nexport async function runActionValidators<TBaseContext extends object>(input: {\n readonly action: ActionDefinition\n readonly subject: ActionSubject\n readonly baseContext: TBaseContext\n readonly target?: ActionTargetObject | null\n}): Promise<void> {\n const validators = input.action.phases.validate as readonly RuntimePhaseHandler[]\n if (validators.length === 0) {\n return\n }\n\n if (!isObjectActionDefinition(input.action)) {\n for (const validator of validators) {\n const result = await validator(input.baseContext)\n if (isValidatorErrorResult(result)) {\n throw new ActionValidationError(result.error, {\n actionId: input.action.id,\n subject: input.subject,\n })\n }\n }\n return\n }\n\n if (!input.target) {\n throw new Error(`[Sixb] Action '${input.action.id}' requires an object target.`)\n }\n\n for (const validator of validators) {\n const result = await validator({\n ...input.baseContext,\n target: input.target,\n })\n if (isValidatorErrorResult(result)) {\n throw new ActionValidationError(result.error, {\n actionId: input.action.id,\n subject: input.subject,\n })\n }\n }\n}\n\nfunction isValidatorErrorResult(value: unknown): value is { readonly error: string } {\n return (\n typeof value === \"object\" &&\n value !== null &&\n \"error\" in value &&\n typeof value.error === \"string\"\n )\n}\n"
|
|
11
|
-
],
|
|
12
|
-
"mappings": "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",
|
|
13
|
-
"debugId": "F2505FFF52F07A6564756E2164756E21",
|
|
14
|
-
"names": []
|
|
15
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|