@sixb/core 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +470 -0
- package/dist/actions/builders/define-action.d.ts +7 -0
- package/dist/actions/builders/define-action.d.ts.map +1 -0
- package/dist/actions/builders/params.d.ts +23 -0
- package/dist/actions/builders/params.d.ts.map +1 -0
- package/dist/actions/builders.d.ts +3 -0
- package/dist/actions/builders.d.ts.map +1 -0
- package/dist/actions/commit-edits.d.ts +54 -0
- package/dist/actions/commit-edits.d.ts.map +1 -0
- package/dist/actions/errors.d.ts +9 -0
- package/dist/actions/errors.d.ts.map +1 -0
- package/dist/actions/index.d.ts +14 -0
- package/dist/actions/index.d.ts.map +1 -0
- package/dist/actions/index.js +73 -0
- package/dist/actions/index.js.map +9 -0
- package/dist/actions/read-facade.d.ts +56 -0
- package/dist/actions/read-facade.d.ts.map +1 -0
- package/dist/actions/registry.d.ts +17 -0
- package/dist/actions/registry.d.ts.map +1 -0
- package/dist/actions/request.d.ts +37 -0
- package/dist/actions/request.d.ts.map +1 -0
- package/dist/actions/run-id.d.ts +3 -0
- package/dist/actions/run-id.d.ts.map +1 -0
- package/dist/actions/runtime.d.ts +11 -0
- package/dist/actions/runtime.d.ts.map +1 -0
- package/dist/actions/types/context.d.ts +147 -0
- package/dist/actions/types/context.d.ts.map +1 -0
- package/dist/actions/types/definitions.d.ts +67 -0
- package/dist/actions/types/definitions.d.ts.map +1 -0
- package/dist/actions/types/handlers.d.ts +19 -0
- package/dist/actions/types/handlers.d.ts.map +1 -0
- package/dist/actions/types/params.d.ts +45 -0
- package/dist/actions/types/params.d.ts.map +1 -0
- package/dist/actions/types.d.ts +5 -0
- package/dist/actions/types.d.ts.map +1 -0
- package/dist/actions/validation.d.ts +33 -0
- package/dist/actions/validation.d.ts.map +1 -0
- package/dist/actions/validators.d.ts +8 -0
- package/dist/actions/validators.d.ts.map +1 -0
- package/dist/actions/worker.d.ts +3 -0
- package/dist/actions/worker.d.ts.map +1 -0
- package/dist/actions/worker.js +324 -0
- package/dist/actions/worker.js.map +11 -0
- package/dist/agents/adapters.d.ts +185 -0
- package/dist/agents/adapters.d.ts.map +1 -0
- package/dist/agents/api-gateway.d.ts +21 -0
- package/dist/agents/api-gateway.d.ts.map +1 -0
- package/dist/agents/builders.d.ts +10 -0
- package/dist/agents/builders.d.ts.map +1 -0
- package/dist/agents/context-model.d.ts +4 -0
- package/dist/agents/context-model.d.ts.map +1 -0
- package/dist/agents/context-resolution.d.ts +5 -0
- package/dist/agents/context-resolution.d.ts.map +1 -0
- package/dist/agents/context.d.ts +57 -0
- package/dist/agents/context.d.ts.map +1 -0
- package/dist/agents/context.js +23 -0
- package/dist/agents/context.js.map +9 -0
- package/dist/agents/dispatch.d.ts +36 -0
- package/dist/agents/dispatch.d.ts.map +1 -0
- package/dist/agents/errors.d.ts +27 -0
- package/dist/agents/errors.d.ts.map +1 -0
- package/dist/agents/ids.d.ts +11 -0
- package/dist/agents/ids.d.ts.map +1 -0
- package/dist/agents/index.d.ts +24 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +121 -0
- package/dist/agents/index.js.map +9 -0
- package/dist/agents/message.d.ts +78 -0
- package/dist/agents/message.d.ts.map +1 -0
- package/dist/agents/prompt.d.ts +15 -0
- package/dist/agents/prompt.d.ts.map +1 -0
- package/dist/agents/request.d.ts +42 -0
- package/dist/agents/request.d.ts.map +1 -0
- package/dist/agents/runtime.d.ts +41 -0
- package/dist/agents/runtime.d.ts.map +1 -0
- package/dist/agents/streams.d.ts +72 -0
- package/dist/agents/streams.d.ts.map +1 -0
- package/dist/agents/streams.js +32 -0
- package/dist/agents/streams.js.map +9 -0
- package/dist/agents/types.d.ts +52 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/agents/validation.d.ts +10 -0
- package/dist/agents/validation.d.ts.map +1 -0
- package/dist/auth/access-tokens.d.ts +19 -0
- package/dist/auth/access-tokens.d.ts.map +1 -0
- package/dist/auth/audience.d.ts +8 -0
- package/dist/auth/audience.d.ts.map +1 -0
- package/dist/auth/cookies.d.ts +50 -0
- package/dist/auth/cookies.d.ts.map +1 -0
- package/dist/auth/csrf.d.ts +8 -0
- package/dist/auth/csrf.d.ts.map +1 -0
- package/dist/auth/errors.d.ts +7 -0
- package/dist/auth/errors.d.ts.map +1 -0
- package/dist/auth/index.d.ts +15 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +101 -0
- package/dist/auth/index.js.map +9 -0
- package/dist/auth/runtime.d.ts +129 -0
- package/dist/auth/runtime.d.ts.map +1 -0
- package/dist/auth/session-cache.d.ts +44 -0
- package/dist/auth/session-cache.d.ts.map +1 -0
- package/dist/auth/sessions.d.ts +16 -0
- package/dist/auth/sessions.d.ts.map +1 -0
- package/dist/auth/strategy.d.ts +11 -0
- package/dist/auth/strategy.d.ts.map +1 -0
- package/dist/auth/strategy.js +14 -0
- package/dist/auth/strategy.js.map +9 -0
- package/dist/auth/types.d.ts +460 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/validation.d.ts +26 -0
- package/dist/auth/validation.d.ts.map +1 -0
- package/dist/authorization/application-access.d.ts +18 -0
- package/dist/authorization/application-access.d.ts.map +1 -0
- package/dist/authorization/decision.d.ts +104 -0
- package/dist/authorization/decision.d.ts.map +1 -0
- package/dist/authorization/errors.d.ts +10 -0
- package/dist/authorization/errors.d.ts.map +1 -0
- package/dist/authorization/event-visibility.d.ts +16 -0
- package/dist/authorization/event-visibility.d.ts.map +1 -0
- package/dist/authorization/grant-kinds.d.ts +48 -0
- package/dist/authorization/grant-kinds.d.ts.map +1 -0
- package/dist/authorization/index.d.ts +11 -0
- package/dist/authorization/index.d.ts.map +1 -0
- package/dist/authorization/index.js +48 -0
- package/dist/authorization/index.js.map +9 -0
- package/dist/authorization/resolve.d.ts +28 -0
- package/dist/authorization/resolve.d.ts.map +1 -0
- package/dist/authorization/run-visibility.d.ts +15 -0
- package/dist/authorization/run-visibility.d.ts.map +1 -0
- package/dist/authorization/types.d.ts +46 -0
- package/dist/authorization/types.d.ts.map +1 -0
- package/dist/blob-storage/browser.d.ts +14 -0
- package/dist/blob-storage/browser.d.ts.map +1 -0
- package/dist/blob-storage/browser.js +22 -0
- package/dist/blob-storage/browser.js.map +9 -0
- package/dist/blob-storage/constants.d.ts +10 -0
- package/dist/blob-storage/constants.d.ts.map +1 -0
- package/dist/blob-storage/derive.d.ts +4 -0
- package/dist/blob-storage/derive.d.ts.map +1 -0
- package/dist/blob-storage/errors.d.ts +7 -0
- package/dist/blob-storage/errors.d.ts.map +1 -0
- package/dist/blob-storage/in-memory.d.ts +10 -0
- package/dist/blob-storage/in-memory.d.ts.map +1 -0
- package/dist/blob-storage/index.d.ts +8 -0
- package/dist/blob-storage/index.d.ts.map +1 -0
- package/dist/blob-storage/index.js +44 -0
- package/dist/blob-storage/index.js.map +9 -0
- package/dist/blob-storage/types.d.ts +126 -0
- package/dist/blob-storage/types.d.ts.map +1 -0
- package/dist/blob-storage/utils.d.ts +9 -0
- package/dist/blob-storage/utils.d.ts.map +1 -0
- package/dist/blob-storage/validation.d.ts +6 -0
- package/dist/blob-storage/validation.d.ts.map +1 -0
- package/dist/bootstrap/discovery.d.ts +34 -0
- package/dist/bootstrap/discovery.d.ts.map +1 -0
- package/dist/bootstrap/index.d.ts +4 -0
- package/dist/bootstrap/index.d.ts.map +1 -0
- package/dist/bootstrap/index.js +80 -0
- package/dist/bootstrap/index.js.map +9 -0
- package/dist/bootstrap/ontology-type-manifest.d.ts +22 -0
- package/dist/bootstrap/ontology-type-manifest.d.ts.map +1 -0
- package/dist/broker/errors.d.ts +12 -0
- package/dist/broker/errors.d.ts.map +1 -0
- package/dist/broker/in-memory.d.ts +53 -0
- package/dist/broker/in-memory.d.ts.map +1 -0
- package/dist/broker/index.d.ts +5 -0
- package/dist/broker/index.d.ts.map +1 -0
- package/dist/broker/index.js +15 -0
- package/dist/broker/index.js.map +9 -0
- package/dist/broker/types.d.ts +119 -0
- package/dist/broker/types.d.ts.map +1 -0
- package/dist/chunk-04b07a9q.js +89 -0
- package/dist/chunk-04b07a9q.js.map +10 -0
- package/dist/chunk-0fygrz37.js +354 -0
- package/dist/chunk-0fygrz37.js.map +17 -0
- package/dist/chunk-0psb6kdw.js +989 -0
- package/dist/chunk-0psb6kdw.js.map +15 -0
- package/dist/chunk-1evzqhks.js +76 -0
- package/dist/chunk-1evzqhks.js.map +10 -0
- package/dist/chunk-1vffvydj.js +109 -0
- package/dist/chunk-1vffvydj.js.map +10 -0
- package/dist/chunk-2ab72m2h.js +59 -0
- package/dist/chunk-2ab72m2h.js.map +10 -0
- package/dist/chunk-2gpr6jsz.js +1968 -0
- package/dist/chunk-2gpr6jsz.js.map +13 -0
- package/dist/chunk-2s6sydsh.js +368 -0
- package/dist/chunk-2s6sydsh.js.map +12 -0
- package/dist/chunk-45tw90k7.js +72 -0
- package/dist/chunk-45tw90k7.js.map +11 -0
- package/dist/chunk-4pycxcj3.js +35 -0
- package/dist/chunk-4pycxcj3.js.map +11 -0
- package/dist/chunk-50kv63vj.js +523 -0
- package/dist/chunk-50kv63vj.js.map +12 -0
- package/dist/chunk-51fjndv0.js +17 -0
- package/dist/chunk-51fjndv0.js.map +11 -0
- package/dist/chunk-590dejbp.js +49 -0
- package/dist/chunk-590dejbp.js.map +10 -0
- package/dist/chunk-5yny9z0e.js +60 -0
- package/dist/chunk-5yny9z0e.js.map +10 -0
- package/dist/chunk-6wetht33.js +89 -0
- package/dist/chunk-6wetht33.js.map +10 -0
- package/dist/chunk-74drx9gd.js +362 -0
- package/dist/chunk-74drx9gd.js.map +11 -0
- package/dist/chunk-867jxh7c.js +1156 -0
- package/dist/chunk-867jxh7c.js.map +19 -0
- package/dist/chunk-88ppkr54.js +257 -0
- package/dist/chunk-88ppkr54.js.map +12 -0
- package/dist/chunk-8r8cw2xw.js +373 -0
- package/dist/chunk-8r8cw2xw.js.map +11 -0
- package/dist/chunk-8ydjhh27.js +95 -0
- package/dist/chunk-8ydjhh27.js.map +11 -0
- package/dist/chunk-9dzba0f2.js +43 -0
- package/dist/chunk-9dzba0f2.js.map +10 -0
- package/dist/chunk-aebzcsxr.js +5272 -0
- package/dist/chunk-aebzcsxr.js.map +48 -0
- package/dist/chunk-b49dgvsj.js +49 -0
- package/dist/chunk-b49dgvsj.js.map +10 -0
- package/dist/chunk-btpe64e4.js +554 -0
- package/dist/chunk-btpe64e4.js.map +13 -0
- package/dist/chunk-c3zd880g.js +629 -0
- package/dist/chunk-c3zd880g.js.map +14 -0
- package/dist/chunk-dcgrzj1t.js +2954 -0
- package/dist/chunk-dcgrzj1t.js.map +36 -0
- package/dist/chunk-dhmj53mx.js +501 -0
- package/dist/chunk-dhmj53mx.js.map +16 -0
- package/dist/chunk-dktq02ne.js +16 -0
- package/dist/chunk-dktq02ne.js.map +10 -0
- package/dist/chunk-f2b5e2gf.js +141 -0
- package/dist/chunk-f2b5e2gf.js.map +11 -0
- package/dist/chunk-gqdd7508.js +273 -0
- package/dist/chunk-gqdd7508.js.map +11 -0
- package/dist/chunk-hsv43v58.js +1390 -0
- package/dist/chunk-hsv43v58.js.map +21 -0
- package/dist/chunk-jdwx7vzs.js +454 -0
- package/dist/chunk-jdwx7vzs.js.map +14 -0
- package/dist/chunk-k25jm1x5.js +102 -0
- package/dist/chunk-k25jm1x5.js.map +10 -0
- package/dist/chunk-k41ajtz7.js +352 -0
- package/dist/chunk-k41ajtz7.js.map +13 -0
- package/dist/chunk-k6j72mtt.js +9 -0
- package/dist/chunk-k6j72mtt.js.map +10 -0
- package/dist/chunk-mx84y05q.js +426 -0
- package/dist/chunk-mx84y05q.js.map +11 -0
- package/dist/chunk-nvamz5dv.js +819 -0
- package/dist/chunk-nvamz5dv.js.map +21 -0
- package/dist/chunk-p6r5g77m.js +113 -0
- package/dist/chunk-p6r5g77m.js.map +10 -0
- package/dist/chunk-pv1yad91.js +1165 -0
- package/dist/chunk-pv1yad91.js.map +27 -0
- package/dist/chunk-q4qzq0ea.js +832 -0
- package/dist/chunk-q4qzq0ea.js.map +14 -0
- package/dist/chunk-r65yscvk.js +187 -0
- package/dist/chunk-r65yscvk.js.map +11 -0
- package/dist/chunk-ry24jbr1.js +50 -0
- package/dist/chunk-ry24jbr1.js.map +10 -0
- package/dist/chunk-t358gywy.js +991 -0
- package/dist/chunk-t358gywy.js.map +34 -0
- package/dist/chunk-t72dvahb.js +167 -0
- package/dist/chunk-t72dvahb.js.map +12 -0
- package/dist/chunk-tsk2bxs3.js +1254 -0
- package/dist/chunk-tsk2bxs3.js.map +17 -0
- package/dist/chunk-v5c085yp.js +49 -0
- package/dist/chunk-v5c085yp.js.map +10 -0
- package/dist/chunk-vj723r3p.js +146 -0
- package/dist/chunk-vj723r3p.js.map +12 -0
- package/dist/chunk-wj01s5hr.js +363 -0
- package/dist/chunk-wj01s5hr.js.map +11 -0
- package/dist/chunk-wxhdnwh4.js +37 -0
- package/dist/chunk-wxhdnwh4.js.map +10 -0
- package/dist/chunk-xqbtf4wn.js +170 -0
- package/dist/chunk-xqbtf4wn.js.map +10 -0
- package/dist/chunk-xwnf87e1.js +324 -0
- package/dist/chunk-xwnf87e1.js.map +13 -0
- package/dist/chunk-xz5g49bp.js +239 -0
- package/dist/chunk-xz5g49bp.js.map +11 -0
- package/dist/chunk-y64skrwp.js +19 -0
- package/dist/chunk-y64skrwp.js.map +9 -0
- package/dist/chunk-ya6brh8a.js +136 -0
- package/dist/chunk-ya6brh8a.js.map +11 -0
- package/dist/chunk-yt8wphsx.js +12 -0
- package/dist/chunk-yt8wphsx.js.map +10 -0
- package/dist/chunk-yvef9xwc.js +3842 -0
- package/dist/chunk-yvef9xwc.js.map +44 -0
- package/dist/chunk-yxss87qa.js +821 -0
- package/dist/chunk-yxss87qa.js.map +14 -0
- package/dist/connectors/builders.d.ts +10 -0
- package/dist/connectors/builders.d.ts.map +1 -0
- package/dist/connectors/errors.d.ts +14 -0
- package/dist/connectors/errors.d.ts.map +1 -0
- package/dist/connectors/index.d.ts +5 -0
- package/dist/connectors/index.d.ts.map +1 -0
- package/dist/connectors/runtime.d.ts +13 -0
- package/dist/connectors/runtime.d.ts.map +1 -0
- package/dist/connectors/types.d.ts +39 -0
- package/dist/connectors/types.d.ts.map +1 -0
- package/dist/datasets/builders.d.ts +54 -0
- package/dist/datasets/builders.d.ts.map +1 -0
- package/dist/datasets/errors.d.ts +4 -0
- package/dist/datasets/errors.d.ts.map +1 -0
- package/dist/datasets/index.d.ts +5 -0
- package/dist/datasets/index.d.ts.map +1 -0
- package/dist/datasets/types.d.ts +23 -0
- package/dist/datasets/types.d.ts.map +1 -0
- package/dist/datasets/validation.d.ts +8 -0
- package/dist/datasets/validation.d.ts.map +1 -0
- package/dist/edits/errors.d.ts +4 -0
- package/dist/edits/errors.d.ts.map +1 -0
- package/dist/edits/index.d.ts +4 -0
- package/dist/edits/index.d.ts.map +1 -0
- package/dist/edits/index.js +14 -0
- package/dist/edits/index.js.map +9 -0
- package/dist/edits/normalize.d.ts +14 -0
- package/dist/edits/normalize.d.ts.map +1 -0
- package/dist/edits/properties.d.ts +25 -0
- package/dist/edits/properties.d.ts.map +1 -0
- package/dist/edits/recorder.d.ts +4 -0
- package/dist/edits/recorder.d.ts.map +1 -0
- package/dist/edits/types.d.ts +159 -0
- package/dist/edits/types.d.ts.map +1 -0
- package/dist/error-reporting/capability.d.ts +57 -0
- package/dist/error-reporting/capability.d.ts.map +1 -0
- package/dist/error-reporting/internal.d.ts +4 -0
- package/dist/error-reporting/internal.d.ts.map +1 -0
- package/dist/error-reporting/internal.js +24 -0
- package/dist/error-reporting/internal.js.map +9 -0
- package/dist/error-reporting/normalize.d.ts +3 -0
- package/dist/error-reporting/normalize.d.ts.map +1 -0
- package/dist/error-reporting/reporter.d.ts +10 -0
- package/dist/error-reporting/reporter.d.ts.map +1 -0
- package/dist/error-reporting/types.d.ts +112 -0
- package/dist/error-reporting/types.d.ts.map +1 -0
- package/dist/events/definitions.d.ts +76 -0
- package/dist/events/definitions.d.ts.map +1 -0
- package/dist/events/envelope.d.ts +56 -0
- package/dist/events/envelope.d.ts.map +1 -0
- package/dist/events/errors.d.ts +8 -0
- package/dist/events/errors.d.ts.map +1 -0
- package/dist/events/index.d.ts +11 -0
- package/dist/events/index.d.ts.map +1 -0
- package/dist/events/index.js +68 -0
- package/dist/events/index.js.map +9 -0
- package/dist/events/outbox-dispatcher.d.ts +82 -0
- package/dist/events/outbox-dispatcher.d.ts.map +1 -0
- package/dist/events/property-changes.d.ts +16 -0
- package/dist/events/property-changes.d.ts.map +1 -0
- package/dist/events/runtime.d.ts +87 -0
- package/dist/events/runtime.d.ts.map +1 -0
- package/dist/events/scope.d.ts +25 -0
- package/dist/events/scope.d.ts.map +1 -0
- package/dist/events/scope.js +10 -0
- package/dist/events/scope.js.map +9 -0
- package/dist/events/selectors/builder.d.ts +64 -0
- package/dist/events/selectors/builder.d.ts.map +1 -0
- package/dist/events/selectors/index.d.ts +5 -0
- package/dist/events/selectors/index.d.ts.map +1 -0
- package/dist/events/selectors/index.js +15 -0
- package/dist/events/selectors/index.js.map +9 -0
- package/dist/events/selectors/predicate.d.ts +5 -0
- package/dist/events/selectors/predicate.d.ts.map +1 -0
- package/dist/events/selectors/types.d.ts +141 -0
- package/dist/events/selectors/types.d.ts.map +1 -0
- package/dist/events/toStoredEvent.d.ts +10 -0
- package/dist/events/toStoredEvent.d.ts.map +1 -0
- package/dist/events/types/actions.d.ts +39 -0
- package/dist/events/types/actions.d.ts.map +1 -0
- package/dist/events/types/datasets.d.ts +20 -0
- package/dist/events/types/datasets.d.ts.map +1 -0
- package/dist/events/types/index.d.ts +137 -0
- package/dist/events/types/index.d.ts.map +1 -0
- package/dist/events/types/links.d.ts +37 -0
- package/dist/events/types/links.d.ts.map +1 -0
- package/dist/events/types/objects.d.ts +33 -0
- package/dist/events/types/objects.d.ts.map +1 -0
- package/dist/events/types/pipelines.d.ts +59 -0
- package/dist/events/types/pipelines.d.ts.map +1 -0
- package/dist/events/types/rules.d.ts +28 -0
- package/dist/events/types/rules.d.ts.map +1 -0
- package/dist/events/types/schedules.d.ts +14 -0
- package/dist/events/types/schedules.d.ts.map +1 -0
- package/dist/events/types/syncs.d.ts +25 -0
- package/dist/events/types/syncs.d.ts.map +1 -0
- package/dist/events/types/telemetry.d.ts +17 -0
- package/dist/events/types/telemetry.d.ts.map +1 -0
- package/dist/events/types/workflows.d.ts +150 -0
- package/dist/events/types/workflows.d.ts.map +1 -0
- package/dist/http/api-routes.d.ts +24 -0
- package/dist/http/api-routes.d.ts.map +1 -0
- package/dist/http/index.d.ts +4 -0
- package/dist/http/index.d.ts.map +1 -0
- package/dist/http/index.js +16 -0
- package/dist/http/index.js.map +9 -0
- package/dist/http/route-pattern.d.ts +14 -0
- package/dist/http/route-pattern.d.ts.map +1 -0
- package/dist/index.d.ts +70 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +430 -0
- package/dist/index.js.map +9 -0
- package/dist/json.d.ts +14 -0
- package/dist/json.d.ts.map +1 -0
- package/dist/lake-storage/definition-updates.d.ts +40 -0
- package/dist/lake-storage/definition-updates.d.ts.map +1 -0
- package/dist/lake-storage/errors.d.ts +7 -0
- package/dist/lake-storage/errors.d.ts.map +1 -0
- package/dist/lake-storage/in-memory.d.ts +25 -0
- package/dist/lake-storage/in-memory.d.ts.map +1 -0
- package/dist/lake-storage/index.d.ts +9 -0
- package/dist/lake-storage/index.d.ts.map +1 -0
- package/dist/lake-storage/index.js +24 -0
- package/dist/lake-storage/index.js.map +9 -0
- package/dist/lake-storage/sql-transforms.d.ts +45 -0
- package/dist/lake-storage/sql-transforms.d.ts.map +1 -0
- package/dist/lake-storage/types.d.ts +114 -0
- package/dist/lake-storage/types.d.ts.map +1 -0
- package/dist/logging/console-logger.d.ts +17 -0
- package/dist/logging/console-logger.d.ts.map +1 -0
- package/dist/logging/index.d.ts +5 -0
- package/dist/logging/index.d.ts.map +1 -0
- package/dist/logging/index.js +45 -0
- package/dist/logging/index.js.map +9 -0
- package/dist/logging/record.d.ts +10 -0
- package/dist/logging/record.d.ts.map +1 -0
- package/dist/logging/run-logger.d.ts +61 -0
- package/dist/logging/run-logger.d.ts.map +1 -0
- package/dist/logging/runtime.d.ts +87 -0
- package/dist/logging/runtime.d.ts.map +1 -0
- package/dist/logging/stream.d.ts +24 -0
- package/dist/logging/stream.d.ts.map +1 -0
- package/dist/logging/types.d.ts +82 -0
- package/dist/logging/types.d.ts.map +1 -0
- package/dist/logging/types.js +27 -0
- package/dist/logging/types.js.map +9 -0
- package/dist/maintenance/index.d.ts +3 -0
- package/dist/maintenance/index.d.ts.map +1 -0
- package/dist/maintenance/ontology-maintenance.d.ts +48 -0
- package/dist/maintenance/ontology-maintenance.d.ts.map +1 -0
- package/dist/maintenance/types.d.ts +53 -0
- package/dist/maintenance/types.d.ts.map +1 -0
- package/dist/materialization/dataset-watermark.d.ts +5 -0
- package/dist/materialization/dataset-watermark.d.ts.map +1 -0
- package/dist/materialization/errors.d.ts +37 -0
- package/dist/materialization/errors.d.ts.map +1 -0
- package/dist/materialization/events.d.ts +57 -0
- package/dist/materialization/events.d.ts.map +1 -0
- package/dist/materialization/identity.d.ts +8 -0
- package/dist/materialization/identity.d.ts.map +1 -0
- package/dist/materialization/index.d.ts +13 -0
- package/dist/materialization/index.d.ts.map +1 -0
- package/dist/materialization/index.js +56 -0
- package/dist/materialization/index.js.map +9 -0
- package/dist/materialization/model.d.ts +342 -0
- package/dist/materialization/model.d.ts.map +1 -0
- package/dist/materialization/refs.d.ts +24 -0
- package/dist/materialization/refs.d.ts.map +1 -0
- package/dist/materializer/context.d.ts +34 -0
- package/dist/materializer/context.d.ts.map +1 -0
- package/dist/materializer/edits/apply.d.ts +35 -0
- package/dist/materializer/edits/apply.d.ts.map +1 -0
- package/dist/materializer/edits/commit.d.ts +4 -0
- package/dist/materializer/edits/commit.d.ts.map +1 -0
- package/dist/materializer/edits/execution-units.d.ts +14 -0
- package/dist/materializer/edits/execution-units.d.ts.map +1 -0
- package/dist/materializer/edits/load-state.d.ts +6 -0
- package/dist/materializer/edits/load-state.d.ts.map +1 -0
- package/dist/materializer/edits/operations.d.ts +32 -0
- package/dist/materializer/edits/operations.d.ts.map +1 -0
- package/dist/materializer/edits/plan.d.ts +18 -0
- package/dist/materializer/edits/plan.d.ts.map +1 -0
- package/dist/materializer/edits/read-set.d.ts +8 -0
- package/dist/materializer/edits/read-set.d.ts.map +1 -0
- package/dist/materializer/edits/working-state.d.ts +30 -0
- package/dist/materializer/edits/working-state.d.ts.map +1 -0
- package/dist/materializer/effective/build-events.d.ts +26 -0
- package/dist/materializer/effective/build-events.d.ts.map +1 -0
- package/dist/materializer/effective/diff.d.ts +15 -0
- package/dist/materializer/effective/diff.d.ts.map +1 -0
- package/dist/materializer/effective/load-state.d.ts +7 -0
- package/dist/materializer/effective/load-state.d.ts.map +1 -0
- package/dist/materializer/effective/resolve.d.ts +26 -0
- package/dist/materializer/effective/resolve.d.ts.map +1 -0
- package/dist/materializer/effective/validate.d.ts +11 -0
- package/dist/materializer/effective/validate.d.ts.map +1 -0
- package/dist/materializer/execution/commit-lifecycle.d.ts +8 -0
- package/dist/materializer/execution/commit-lifecycle.d.ts.map +1 -0
- package/dist/materializer/execution/plan-stream.d.ts +8 -0
- package/dist/materializer/execution/plan-stream.d.ts.map +1 -0
- package/dist/materializer/execution/run-correlation.d.ts +19 -0
- package/dist/materializer/execution/run-correlation.d.ts.map +1 -0
- package/dist/materializer/execution/work-executor.d.ts +13 -0
- package/dist/materializer/execution/work-executor.d.ts.map +1 -0
- package/dist/materializer/execution/work-records.d.ts +15 -0
- package/dist/materializer/execution/work-records.d.ts.map +1 -0
- package/dist/materializer/index.d.ts +15 -0
- package/dist/materializer/index.d.ts.map +1 -0
- package/dist/materializer/index.js +134 -0
- package/dist/materializer/index.js.map +9 -0
- package/dist/materializer/materializer.d.ts +27 -0
- package/dist/materializer/materializer.d.ts.map +1 -0
- package/dist/materializer/projections/entry-validator.d.ts +8 -0
- package/dist/materializer/projections/entry-validator.d.ts.map +1 -0
- package/dist/materializer/projections/finish-run.d.ts +4 -0
- package/dist/materializer/projections/finish-run.d.ts.map +1 -0
- package/dist/materializer/projections/replace.d.ts +4 -0
- package/dist/materializer/projections/replace.d.ts.map +1 -0
- package/dist/materializer/projections/replacement-plan.d.ts +14 -0
- package/dist/materializer/projections/replacement-plan.d.ts.map +1 -0
- package/dist/materializer/projections/source-materialization.d.ts +27 -0
- package/dist/materializer/projections/source-materialization.d.ts.map +1 -0
- package/dist/materializer/shared/abort.d.ts +2 -0
- package/dist/materializer/shared/abort.d.ts.map +1 -0
- package/dist/materializer/shared/batching.d.ts +11 -0
- package/dist/materializer/shared/batching.d.ts.map +1 -0
- package/dist/materializer/shared/chunking.d.ts +6 -0
- package/dist/materializer/shared/chunking.d.ts.map +1 -0
- package/dist/materializer/shared/identity.d.ts +38 -0
- package/dist/materializer/shared/identity.d.ts.map +1 -0
- package/dist/materializer/shared/normalize.d.ts +10 -0
- package/dist/materializer/shared/normalize.d.ts.map +1 -0
- package/dist/materializer/shared/projection-run.d.ts +19 -0
- package/dist/materializer/shared/projection-run.d.ts.map +1 -0
- package/dist/materializer/telemetry/append.d.ts +4 -0
- package/dist/materializer/telemetry/append.d.ts.map +1 -0
- package/dist/materializer/telemetry/plan.d.ts +12 -0
- package/dist/materializer/telemetry/plan.d.ts.map +1 -0
- package/dist/objects/action/errors.d.ts +39 -0
- package/dist/objects/action/errors.d.ts.map +1 -0
- package/dist/objects/action/index.d.ts +4 -0
- package/dist/objects/action/index.d.ts.map +1 -0
- package/dist/objects/action/request.d.ts +23 -0
- package/dist/objects/action/request.d.ts.map +1 -0
- package/dist/objects/context/index.d.ts +3 -0
- package/dist/objects/context/index.d.ts.map +1 -0
- package/dist/objects/context/resolve.d.ts +27 -0
- package/dist/objects/context/resolve.d.ts.map +1 -0
- package/dist/objects/context/types.d.ts +28 -0
- package/dist/objects/context/types.d.ts.map +1 -0
- package/dist/objects/contexts.d.ts +45 -0
- package/dist/objects/contexts.d.ts.map +1 -0
- package/dist/objects/errors.d.ts +8 -0
- package/dist/objects/errors.d.ts.map +1 -0
- package/dist/objects/helpers.d.ts +7 -0
- package/dist/objects/helpers.d.ts.map +1 -0
- package/dist/objects/index.d.ts +18 -0
- package/dist/objects/index.d.ts.map +1 -0
- package/dist/objects/index.js +71 -0
- package/dist/objects/index.js.map +9 -0
- package/dist/objects/link/authorization.d.ts +25 -0
- package/dist/objects/link/authorization.d.ts.map +1 -0
- package/dist/objects/link/endpoints.d.ts +28 -0
- package/dist/objects/link/endpoints.d.ts.map +1 -0
- package/dist/objects/link/index.d.ts +4 -0
- package/dist/objects/link/index.d.ts.map +1 -0
- package/dist/objects/link/remove.d.ts +8 -0
- package/dist/objects/link/remove.d.ts.map +1 -0
- package/dist/objects/link/upsert-batch.d.ts +11 -0
- package/dist/objects/link/upsert-batch.d.ts.map +1 -0
- package/dist/objects/link/upsert.d.ts +12 -0
- package/dist/objects/link/upsert.d.ts.map +1 -0
- package/dist/objects/materializer-adapter.d.ts +114 -0
- package/dist/objects/materializer-adapter.d.ts.map +1 -0
- package/dist/objects/object/delete.d.ts +17 -0
- package/dist/objects/object/delete.d.ts.map +1 -0
- package/dist/objects/object/index.d.ts +4 -0
- package/dist/objects/object/index.d.ts.map +1 -0
- package/dist/objects/object/upsert-batch.d.ts +7 -0
- package/dist/objects/object/upsert-batch.d.ts.map +1 -0
- package/dist/objects/object/upsert.d.ts +7 -0
- package/dist/objects/object/upsert.d.ts.map +1 -0
- package/dist/objects/query/errors.d.ts +23 -0
- package/dist/objects/query/errors.d.ts.map +1 -0
- package/dist/objects/query/executor.d.ts +63 -0
- package/dist/objects/query/executor.d.ts.map +1 -0
- package/dist/objects/query/explain-format.d.ts +10 -0
- package/dist/objects/query/explain-format.d.ts.map +1 -0
- package/dist/objects/query/explain.d.ts +26 -0
- package/dist/objects/query/explain.d.ts.map +1 -0
- package/dist/objects/query/index.d.ts +14 -0
- package/dist/objects/query/index.d.ts.map +1 -0
- package/dist/objects/query/index.js +54 -0
- package/dist/objects/query/index.js.map +9 -0
- package/dist/objects/query/ir.d.ts +166 -0
- package/dist/objects/query/ir.d.ts.map +1 -0
- package/dist/objects/query/normalize.d.ts +12 -0
- package/dist/objects/query/normalize.d.ts.map +1 -0
- package/dist/objects/query/planner.d.ts +32 -0
- package/dist/objects/query/planner.d.ts.map +1 -0
- package/dist/objects/query/scalar-values.d.ts +6 -0
- package/dist/objects/query/scalar-values.d.ts.map +1 -0
- package/dist/objects/query/validate.d.ts +23 -0
- package/dist/objects/query/validate.d.ts.map +1 -0
- package/dist/objects/runtime-batch.d.ts +29 -0
- package/dist/objects/runtime-batch.d.ts.map +1 -0
- package/dist/objects/sdk/index.d.ts +3 -0
- package/dist/objects/sdk/index.d.ts.map +1 -0
- package/dist/objects/sdk/object-handle.d.ts +6 -0
- package/dist/objects/sdk/object-handle.d.ts.map +1 -0
- package/dist/objects/sdk/object-set.d.ts +14 -0
- package/dist/objects/sdk/object-set.d.ts.map +1 -0
- package/dist/objects/sdk/query-builder.d.ts +20 -0
- package/dist/objects/sdk/query-builder.d.ts.map +1 -0
- package/dist/objects/sdk/query-executor.d.ts +51 -0
- package/dist/objects/sdk/query-executor.d.ts.map +1 -0
- package/dist/objects/sdk/runtime-query-executor.d.ts +16 -0
- package/dist/objects/sdk/runtime-query-executor.d.ts.map +1 -0
- package/dist/objects/sdk/telemetry-channel.d.ts +6 -0
- package/dist/objects/sdk/telemetry-channel.d.ts.map +1 -0
- package/dist/objects/sdk/where.d.ts +15 -0
- package/dist/objects/sdk/where.d.ts.map +1 -0
- package/dist/objects/service/action-service.d.ts +12 -0
- package/dist/objects/service/action-service.d.ts.map +1 -0
- package/dist/objects/service/index.d.ts +7 -0
- package/dist/objects/service/index.d.ts.map +1 -0
- package/dist/objects/service/link-service.d.ts +26 -0
- package/dist/objects/service/link-service.d.ts.map +1 -0
- package/dist/objects/service/list-service.d.ts +24 -0
- package/dist/objects/service/list-service.d.ts.map +1 -0
- package/dist/objects/service/object-service.d.ts +12 -0
- package/dist/objects/service/object-service.d.ts.map +1 -0
- package/dist/objects/service/telemetry-service.d.ts +12 -0
- package/dist/objects/service/telemetry-service.d.ts.map +1 -0
- package/dist/objects/telemetry/append-batch.d.ts +10 -0
- package/dist/objects/telemetry/append-batch.d.ts.map +1 -0
- package/dist/objects/telemetry/history.d.ts +8 -0
- package/dist/objects/telemetry/history.d.ts.map +1 -0
- package/dist/objects/telemetry/index.d.ts +5 -0
- package/dist/objects/telemetry/index.d.ts.map +1 -0
- package/dist/objects/telemetry/write-batch.d.ts +8 -0
- package/dist/objects/telemetry/write-batch.d.ts.map +1 -0
- package/dist/ontology/builders.d.ts +323 -0
- package/dist/ontology/builders.d.ts.map +1 -0
- package/dist/ontology/decimal.d.ts +28 -0
- package/dist/ontology/decimal.d.ts.map +1 -0
- package/dist/ontology/errors.d.ts +20 -0
- package/dist/ontology/errors.d.ts.map +1 -0
- package/dist/ontology/index.d.ts +23 -0
- package/dist/ontology/index.d.ts.map +1 -0
- package/dist/ontology/index.js +120 -0
- package/dist/ontology/index.js.map +9 -0
- package/dist/ontology/inference/index.d.ts +112 -0
- package/dist/ontology/inference/index.d.ts.map +1 -0
- package/dist/ontology/internal.d.ts +4 -0
- package/dist/ontology/internal.d.ts.map +1 -0
- package/dist/ontology/internal.js +118 -0
- package/dist/ontology/internal.js.map +10 -0
- package/dist/ontology/json-schema.d.ts +9 -0
- package/dist/ontology/json-schema.d.ts.map +1 -0
- package/dist/ontology/refs.d.ts +16 -0
- package/dist/ontology/refs.d.ts.map +1 -0
- package/dist/ontology/registry.d.ts +82 -0
- package/dist/ontology/registry.d.ts.map +1 -0
- package/dist/ontology/tokens.d.ts +54 -0
- package/dist/ontology/tokens.d.ts.map +1 -0
- package/dist/ontology/types.d.ts +402 -0
- package/dist/ontology/types.d.ts.map +1 -0
- package/dist/ontology/units/index.d.ts +74 -0
- package/dist/ontology/units/index.d.ts.map +1 -0
- package/dist/ontology/units/quantitative-types.d.ts +1605 -0
- package/dist/ontology/units/quantitative-types.d.ts.map +1 -0
- package/dist/ontology/units/types.d.ts +26 -0
- package/dist/ontology/units/types.d.ts.map +1 -0
- package/dist/ontology/validation/index.d.ts +7 -0
- package/dist/ontology/validation/index.d.ts.map +1 -0
- package/dist/ontology/validation/links.d.ts +18 -0
- package/dist/ontology/validation/links.d.ts.map +1 -0
- package/dist/ontology/validation/normalize.d.ts +21 -0
- package/dist/ontology/validation/normalize.d.ts.map +1 -0
- package/dist/ontology/validation/properties.d.ts +19 -0
- package/dist/ontology/validation/properties.d.ts.map +1 -0
- package/dist/ontology/validation/query.d.ts +3 -0
- package/dist/ontology/validation/query.d.ts.map +1 -0
- package/dist/ontology/validation/schema.d.ts +7 -0
- package/dist/ontology/validation/schema.d.ts.map +1 -0
- package/dist/ontology/validation/telemetry.d.ts +7 -0
- package/dist/ontology/validation/telemetry.d.ts.map +1 -0
- package/dist/pipelines/builders.d.ts +14 -0
- package/dist/pipelines/builders.d.ts.map +1 -0
- package/dist/pipelines/errors.d.ts +4 -0
- package/dist/pipelines/errors.d.ts.map +1 -0
- package/dist/pipelines/index.d.ts +7 -0
- package/dist/pipelines/index.d.ts.map +1 -0
- package/dist/pipelines/request.d.ts +31 -0
- package/dist/pipelines/request.d.ts.map +1 -0
- package/dist/pipelines/types.d.ts +84 -0
- package/dist/pipelines/types.d.ts.map +1 -0
- package/dist/predicates/builders.d.ts +24 -0
- package/dist/predicates/builders.d.ts.map +1 -0
- package/dist/predicates/evaluate.d.ts +8 -0
- package/dist/predicates/evaluate.d.ts.map +1 -0
- package/dist/predicates/index.d.ts +5 -0
- package/dist/predicates/index.d.ts.map +1 -0
- package/dist/predicates/types.d.ts +69 -0
- package/dist/predicates/types.d.ts.map +1 -0
- package/dist/predicates/validation.d.ts +15 -0
- package/dist/predicates/validation.d.ts.map +1 -0
- package/dist/projections/builders.d.ts +212 -0
- package/dist/projections/builders.d.ts.map +1 -0
- package/dist/projections/errors.d.ts +4 -0
- package/dist/projections/errors.d.ts.map +1 -0
- package/dist/projections/index.d.ts +5 -0
- package/dist/projections/index.d.ts.map +1 -0
- package/dist/projections/internal.d.ts +24 -0
- package/dist/projections/internal.d.ts.map +1 -0
- package/dist/projections/internal.js +26 -0
- package/dist/projections/internal.js.map +9 -0
- package/dist/projections/ownership.d.ts +9 -0
- package/dist/projections/ownership.d.ts.map +1 -0
- package/dist/projections/registry.d.ts +30 -0
- package/dist/projections/registry.d.ts.map +1 -0
- package/dist/projections/revision.d.ts +7 -0
- package/dist/projections/revision.d.ts.map +1 -0
- package/dist/projections/types.d.ts +153 -0
- package/dist/projections/types.d.ts.map +1 -0
- package/dist/projections/validation.d.ts +97 -0
- package/dist/projections/validation.d.ts.map +1 -0
- package/dist/provider-scope.d.ts +12 -0
- package/dist/provider-scope.d.ts.map +1 -0
- package/dist/query.d.ts +17 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +21 -0
- package/dist/query.js.map +9 -0
- package/dist/queues/errors.d.ts +7 -0
- package/dist/queues/errors.d.ts.map +1 -0
- package/dist/queues/in-memory.d.ts +73 -0
- package/dist/queues/in-memory.d.ts.map +1 -0
- package/dist/queues/index.d.ts +5 -0
- package/dist/queues/index.d.ts.map +1 -0
- package/dist/queues/index.js +12 -0
- package/dist/queues/index.js.map +9 -0
- package/dist/queues/types.d.ts +182 -0
- package/dist/queues/types.d.ts.map +1 -0
- package/dist/rules/builders.d.ts +10 -0
- package/dist/rules/builders.d.ts.map +1 -0
- package/dist/rules/dependencies.d.ts +9 -0
- package/dist/rules/dependencies.d.ts.map +1 -0
- package/dist/rules/errors.d.ts +11 -0
- package/dist/rules/errors.d.ts.map +1 -0
- package/dist/rules/index.d.ts +6 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/internal.d.ts +9 -0
- package/dist/rules/internal.d.ts.map +1 -0
- package/dist/rules/internal.js +10 -0
- package/dist/rules/internal.js.map +9 -0
- package/dist/rules/types.d.ts +72 -0
- package/dist/rules/types.d.ts.map +1 -0
- package/dist/rules/validation.d.ts +23 -0
- package/dist/rules/validation.d.ts.map +1 -0
- package/dist/runtime/create.d.ts +68 -0
- package/dist/runtime/create.d.ts.map +1 -0
- package/dist/runtime/errors.d.ts +9 -0
- package/dist/runtime/errors.d.ts.map +1 -0
- package/dist/runtime/index.d.ts +26 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/internal.d.ts +3 -0
- package/dist/runtime/internal.d.ts.map +1 -0
- package/dist/runtime/internal.js +16 -0
- package/dist/runtime/internal.js.map +9 -0
- package/dist/runtime/ontology-mutations.d.ts +16 -0
- package/dist/runtime/ontology-mutations.d.ts.map +1 -0
- package/dist/runtime/scoped.d.ts +158 -0
- package/dist/runtime/scoped.d.ts.map +1 -0
- package/dist/runtime/sixb.d.ts +226 -0
- package/dist/runtime/sixb.d.ts.map +1 -0
- package/dist/runtime/storage-readiness.d.ts +20 -0
- package/dist/runtime/storage-readiness.d.ts.map +1 -0
- package/dist/runtime/types.d.ts +840 -0
- package/dist/runtime/types.d.ts.map +1 -0
- package/dist/sandboxes/errors.d.ts +20 -0
- package/dist/sandboxes/errors.d.ts.map +1 -0
- package/dist/sandboxes/exec.d.ts +17 -0
- package/dist/sandboxes/exec.d.ts.map +1 -0
- package/dist/sandboxes/index.d.ts +5 -0
- package/dist/sandboxes/index.d.ts.map +1 -0
- package/dist/sandboxes/index.js +18 -0
- package/dist/sandboxes/index.js.map +9 -0
- package/dist/sandboxes/sandbox.d.ts +110 -0
- package/dist/sandboxes/sandbox.d.ts.map +1 -0
- package/dist/scheduler/errors.d.ts +7 -0
- package/dist/scheduler/errors.d.ts.map +1 -0
- package/dist/scheduler/index.d.ts +4 -0
- package/dist/scheduler/index.d.ts.map +1 -0
- package/dist/scheduler/index.js +18 -0
- package/dist/scheduler/index.js.map +9 -0
- package/dist/scheduler/runtime.d.ts +32 -0
- package/dist/scheduler/runtime.d.ts.map +1 -0
- package/dist/schedules/builders.d.ts +4 -0
- package/dist/schedules/builders.d.ts.map +1 -0
- package/dist/schedules/cron.d.ts +14 -0
- package/dist/schedules/cron.d.ts.map +1 -0
- package/dist/schedules/errors.d.ts +7 -0
- package/dist/schedules/errors.d.ts.map +1 -0
- package/dist/schedules/index.d.ts +12 -0
- package/dist/schedules/index.d.ts.map +1 -0
- package/dist/schedules/index.js +37 -0
- package/dist/schedules/index.js.map +9 -0
- package/dist/schedules/next-occurrence.d.ts +11 -0
- package/dist/schedules/next-occurrence.d.ts.map +1 -0
- package/dist/schedules/runtime.d.ts +17 -0
- package/dist/schedules/runtime.d.ts.map +1 -0
- package/dist/schedules/types.d.ts +99 -0
- package/dist/schedules/types.d.ts.map +1 -0
- package/dist/schedules/validation.d.ts +13 -0
- package/dist/schedules/validation.d.ts.map +1 -0
- package/dist/security/applications.d.ts +15 -0
- package/dist/security/applications.d.ts.map +1 -0
- package/dist/security/builders.d.ts +20 -0
- package/dist/security/builders.d.ts.map +1 -0
- package/dist/security/errors.d.ts +4 -0
- package/dist/security/errors.d.ts.map +1 -0
- package/dist/security/every.d.ts +68 -0
- package/dist/security/every.d.ts.map +1 -0
- package/dist/security/grants.d.ts +40 -0
- package/dist/security/grants.d.ts.map +1 -0
- package/dist/security/index.d.ts +12 -0
- package/dist/security/index.d.ts.map +1 -0
- package/dist/security/membership-policies.d.ts +17 -0
- package/dist/security/membership-policies.d.ts.map +1 -0
- package/dist/security/runtime.d.ts +16 -0
- package/dist/security/runtime.d.ts.map +1 -0
- package/dist/security/types.d.ts +133 -0
- package/dist/security/types.d.ts.map +1 -0
- package/dist/security/validation.d.ts +36 -0
- package/dist/security/validation.d.ts.map +1 -0
- package/dist/storage/action-runs/errors.d.ts +10 -0
- package/dist/storage/action-runs/errors.d.ts.map +1 -0
- package/dist/storage/action-runs/idempotency.d.ts +10 -0
- package/dist/storage/action-runs/idempotency.d.ts.map +1 -0
- package/dist/storage/action-runs/in-memory.d.ts +28 -0
- package/dist/storage/action-runs/in-memory.d.ts.map +1 -0
- package/dist/storage/action-runs/index.d.ts +6 -0
- package/dist/storage/action-runs/index.d.ts.map +1 -0
- package/dist/storage/action-runs/types.d.ts +138 -0
- package/dist/storage/action-runs/types.d.ts.map +1 -0
- package/dist/storage/agents/errors.d.ts +11 -0
- package/dist/storage/agents/errors.d.ts.map +1 -0
- package/dist/storage/agents/in-memory.d.ts +70 -0
- package/dist/storage/agents/in-memory.d.ts.map +1 -0
- package/dist/storage/agents/index.d.ts +7 -0
- package/dist/storage/agents/index.d.ts.map +1 -0
- package/dist/storage/agents/types.d.ts +295 -0
- package/dist/storage/agents/types.d.ts.map +1 -0
- package/dist/storage/auth/errors.d.ts +10 -0
- package/dist/storage/auth/errors.d.ts.map +1 -0
- package/dist/storage/auth/in-memory/access-tokens.d.ts +32 -0
- package/dist/storage/auth/in-memory/access-tokens.d.ts.map +1 -0
- package/dist/storage/auth/in-memory/auth-storage.d.ts +36 -0
- package/dist/storage/auth/in-memory/auth-storage.d.ts.map +1 -0
- package/dist/storage/auth/in-memory/group-memberships.d.ts +21 -0
- package/dist/storage/auth/in-memory/group-memberships.d.ts.map +1 -0
- package/dist/storage/auth/in-memory/identities.d.ts +17 -0
- package/dist/storage/auth/in-memory/identities.d.ts.map +1 -0
- package/dist/storage/auth/in-memory/index.d.ts +2 -0
- package/dist/storage/auth/in-memory/index.d.ts.map +1 -0
- package/dist/storage/auth/in-memory/invitations.d.ts +28 -0
- package/dist/storage/auth/in-memory/invitations.d.ts.map +1 -0
- package/dist/storage/auth/in-memory/magic-links.d.ts +28 -0
- package/dist/storage/auth/in-memory/magic-links.d.ts.map +1 -0
- package/dist/storage/auth/in-memory/oidc-attempts.d.ts +18 -0
- package/dist/storage/auth/in-memory/oidc-attempts.d.ts.map +1 -0
- package/dist/storage/auth/in-memory/service-account-group-memberships.d.ts +17 -0
- package/dist/storage/auth/in-memory/service-account-group-memberships.d.ts.map +1 -0
- package/dist/storage/auth/in-memory/service-accounts.d.ts +14 -0
- package/dist/storage/auth/in-memory/service-accounts.d.ts.map +1 -0
- package/dist/storage/auth/in-memory/sessions.d.ts +55 -0
- package/dist/storage/auth/in-memory/sessions.d.ts.map +1 -0
- package/dist/storage/auth/in-memory/shared.d.ts +71 -0
- package/dist/storage/auth/in-memory/shared.d.ts.map +1 -0
- package/dist/storage/auth/in-memory/users.d.ts +19 -0
- package/dist/storage/auth/in-memory/users.d.ts.map +1 -0
- package/dist/storage/auth/in-memory.d.ts +2 -0
- package/dist/storage/auth/in-memory.d.ts.map +1 -0
- package/dist/storage/auth/index.d.ts +5 -0
- package/dist/storage/auth/index.d.ts.map +1 -0
- package/dist/storage/auth/types.d.ts +584 -0
- package/dist/storage/auth/types.d.ts.map +1 -0
- package/dist/storage/errors.d.ts +27 -0
- package/dist/storage/errors.d.ts.map +1 -0
- package/dist/storage/file-upload-sessions/errors.d.ts +15 -0
- package/dist/storage/file-upload-sessions/errors.d.ts.map +1 -0
- package/dist/storage/file-upload-sessions/in-memory.d.ts +27 -0
- package/dist/storage/file-upload-sessions/in-memory.d.ts.map +1 -0
- package/dist/storage/file-upload-sessions/index.d.ts +6 -0
- package/dist/storage/file-upload-sessions/index.d.ts.map +1 -0
- package/dist/storage/file-upload-sessions/types.d.ts +53 -0
- package/dist/storage/file-upload-sessions/types.d.ts.map +1 -0
- package/dist/storage/file-upload-sessions/utils.d.ts +11 -0
- package/dist/storage/file-upload-sessions/utils.d.ts.map +1 -0
- package/dist/storage/in-memory/index.d.ts +105 -0
- package/dist/storage/in-memory/index.d.ts.map +1 -0
- package/dist/storage/in-memory/testing.d.ts +8 -0
- package/dist/storage/in-memory/testing.d.ts.map +1 -0
- package/dist/storage/index.d.ts +44 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +144 -0
- package/dist/storage/index.js.map +9 -0
- package/dist/storage/migrations/check-schema.d.ts +19 -0
- package/dist/storage/migrations/check-schema.d.ts.map +1 -0
- package/dist/storage/migrations/index.d.ts +5 -0
- package/dist/storage/migrations/index.d.ts.map +1 -0
- package/dist/storage/migrations/migrate-storage.d.ts +6 -0
- package/dist/storage/migrations/migrate-storage.d.ts.map +1 -0
- package/dist/storage/migrations/migration-set.d.ts +27 -0
- package/dist/storage/migrations/migration-set.d.ts.map +1 -0
- package/dist/storage/migrations/types.d.ts +115 -0
- package/dist/storage/migrations/types.d.ts.map +1 -0
- package/dist/storage/objects/in-memory.d.ts +126 -0
- package/dist/storage/objects/in-memory.d.ts.map +1 -0
- package/dist/storage/objects/index.d.ts +2 -0
- package/dist/storage/objects/index.d.ts.map +1 -0
- package/dist/storage/objects/types.d.ts +222 -0
- package/dist/storage/objects/types.d.ts.map +1 -0
- package/dist/storage/ontology/commits.d.ts +117 -0
- package/dist/storage/ontology/commits.d.ts.map +1 -0
- package/dist/storage/ontology/in-memory/commits.d.ts +12 -0
- package/dist/storage/ontology/in-memory/commits.d.ts.map +1 -0
- package/dist/storage/ontology/in-memory/index.d.ts +36 -0
- package/dist/storage/ontology/in-memory/index.d.ts.map +1 -0
- package/dist/storage/ontology/in-memory/materializations-finalization.d.ts +5 -0
- package/dist/storage/ontology/in-memory/materializations-finalization.d.ts.map +1 -0
- package/dist/storage/ontology/in-memory/materializations-state.d.ts +20 -0
- package/dist/storage/ontology/in-memory/materializations-state.d.ts.map +1 -0
- package/dist/storage/ontology/in-memory/materializations-work.d.ts +6 -0
- package/dist/storage/ontology/in-memory/materializations-work.d.ts.map +1 -0
- package/dist/storage/ontology/in-memory/materializations.d.ts +101 -0
- package/dist/storage/ontology/in-memory/materializations.d.ts.map +1 -0
- package/dist/storage/ontology/in-memory/outbox.d.ts +19 -0
- package/dist/storage/ontology/in-memory/outbox.d.ts.map +1 -0
- package/dist/storage/ontology/in-memory/shared-state.d.ts +48 -0
- package/dist/storage/ontology/in-memory/shared-state.d.ts.map +1 -0
- package/dist/storage/ontology/in-memory/sources.d.ts +23 -0
- package/dist/storage/ontology/in-memory/sources.d.ts.map +1 -0
- package/dist/storage/ontology/in-memory/testing.d.ts +11 -0
- package/dist/storage/ontology/in-memory/testing.d.ts.map +1 -0
- package/dist/storage/ontology/index.d.ts +16 -0
- package/dist/storage/ontology/index.d.ts.map +1 -0
- package/dist/storage/ontology/materializations.d.ts +333 -0
- package/dist/storage/ontology/materializations.d.ts.map +1 -0
- package/dist/storage/ontology/outbox.d.ts +66 -0
- package/dist/storage/ontology/outbox.d.ts.map +1 -0
- package/dist/storage/ontology/provider-header-validation.d.ts +4 -0
- package/dist/storage/ontology/provider-header-validation.d.ts.map +1 -0
- package/dist/storage/ontology/provider-validation.d.ts +6 -0
- package/dist/storage/ontology/provider-validation.d.ts.map +1 -0
- package/dist/storage/ontology/provider-work.d.ts +12 -0
- package/dist/storage/ontology/provider-work.d.ts.map +1 -0
- package/dist/storage/ontology/provider.d.ts +191 -0
- package/dist/storage/ontology/provider.d.ts.map +1 -0
- package/dist/storage/ontology/provider.js +115 -0
- package/dist/storage/ontology/provider.js.map +9 -0
- package/dist/storage/ontology/sources.d.ts +151 -0
- package/dist/storage/ontology/sources.d.ts.map +1 -0
- package/dist/storage/operation-scope.d.ts +32 -0
- package/dist/storage/operation-scope.d.ts.map +1 -0
- package/dist/storage/operation-scope.js +22 -0
- package/dist/storage/operation-scope.js.map +9 -0
- package/dist/storage/pagination.d.ts +11 -0
- package/dist/storage/pagination.d.ts.map +1 -0
- package/dist/storage/pipeline-runs/errors.d.ts +7 -0
- package/dist/storage/pipeline-runs/errors.d.ts.map +1 -0
- package/dist/storage/pipeline-runs/in-memory.d.ts +26 -0
- package/dist/storage/pipeline-runs/in-memory.d.ts.map +1 -0
- package/dist/storage/pipeline-runs/index.d.ts +4 -0
- package/dist/storage/pipeline-runs/index.d.ts.map +1 -0
- package/dist/storage/pipeline-runs/types.d.ts +133 -0
- package/dist/storage/pipeline-runs/types.d.ts.map +1 -0
- package/dist/storage/projection-runs/errors.d.ts +9 -0
- package/dist/storage/projection-runs/errors.d.ts.map +1 -0
- package/dist/storage/projection-runs/in-memory.d.ts +42 -0
- package/dist/storage/projection-runs/in-memory.d.ts.map +1 -0
- package/dist/storage/projection-runs/index.d.ts +5 -0
- package/dist/storage/projection-runs/index.d.ts.map +1 -0
- package/dist/storage/projection-runs/lifecycle.d.ts +93 -0
- package/dist/storage/projection-runs/lifecycle.d.ts.map +1 -0
- package/dist/storage/projection-runs/lifecycle.js +64 -0
- package/dist/storage/projection-runs/lifecycle.js.map +9 -0
- package/dist/storage/projection-runs/types.d.ts +175 -0
- package/dist/storage/projection-runs/types.d.ts.map +1 -0
- package/dist/storage/rules/in-memory.d.ts +26 -0
- package/dist/storage/rules/in-memory.d.ts.map +1 -0
- package/dist/storage/rules/index.d.ts +3 -0
- package/dist/storage/rules/index.d.ts.map +1 -0
- package/dist/storage/rules/types.d.ts +60 -0
- package/dist/storage/rules/types.d.ts.map +1 -0
- package/dist/storage/run-listing.d.ts +36 -0
- package/dist/storage/run-listing.d.ts.map +1 -0
- package/dist/storage/sync-runs/errors.d.ts +8 -0
- package/dist/storage/sync-runs/errors.d.ts.map +1 -0
- package/dist/storage/sync-runs/in-memory.d.ts +16 -0
- package/dist/storage/sync-runs/in-memory.d.ts.map +1 -0
- package/dist/storage/sync-runs/index.d.ts +4 -0
- package/dist/storage/sync-runs/index.d.ts.map +1 -0
- package/dist/storage/sync-runs/types.d.ts +85 -0
- package/dist/storage/sync-runs/types.d.ts.map +1 -0
- package/dist/storage/timeseries/index.d.ts +2 -0
- package/dist/storage/timeseries/index.d.ts.map +1 -0
- package/dist/storage/timeseries/store.d.ts +46 -0
- package/dist/storage/timeseries/store.d.ts.map +1 -0
- package/dist/storage/timeseries/types.d.ts +50 -0
- package/dist/storage/timeseries/types.d.ts.map +1 -0
- package/dist/storage/transaction.d.ts +4 -0
- package/dist/storage/transaction.d.ts.map +1 -0
- package/dist/storage/types.d.ts +78 -0
- package/dist/storage/types.d.ts.map +1 -0
- package/dist/storage/webhook-deliveries/in-memory.d.ts +18 -0
- package/dist/storage/webhook-deliveries/in-memory.d.ts.map +1 -0
- package/dist/storage/webhook-deliveries/index.d.ts +3 -0
- package/dist/storage/webhook-deliveries/index.d.ts.map +1 -0
- package/dist/storage/webhook-deliveries/types.d.ts +43 -0
- package/dist/storage/webhook-deliveries/types.d.ts.map +1 -0
- package/dist/storage/webhook-runs/errors.d.ts +7 -0
- package/dist/storage/webhook-runs/errors.d.ts.map +1 -0
- package/dist/storage/webhook-runs/in-memory.d.ts +16 -0
- package/dist/storage/webhook-runs/in-memory.d.ts.map +1 -0
- package/dist/storage/webhook-runs/index.d.ts +4 -0
- package/dist/storage/webhook-runs/index.d.ts.map +1 -0
- package/dist/storage/webhook-runs/types.d.ts +66 -0
- package/dist/storage/webhook-runs/types.d.ts.map +1 -0
- package/dist/storage/workflow-interventions/errors.d.ts +7 -0
- package/dist/storage/workflow-interventions/errors.d.ts.map +1 -0
- package/dist/storage/workflow-interventions/in-memory.d.ts +18 -0
- package/dist/storage/workflow-interventions/in-memory.d.ts.map +1 -0
- package/dist/storage/workflow-interventions/index.d.ts +4 -0
- package/dist/storage/workflow-interventions/index.d.ts.map +1 -0
- package/dist/storage/workflow-interventions/types.d.ts +94 -0
- package/dist/storage/workflow-interventions/types.d.ts.map +1 -0
- package/dist/storage/workflow-runs/errors.d.ts +7 -0
- package/dist/storage/workflow-runs/errors.d.ts.map +1 -0
- package/dist/storage/workflow-runs/in-memory.d.ts +83 -0
- package/dist/storage/workflow-runs/in-memory.d.ts.map +1 -0
- package/dist/storage/workflow-runs/index.d.ts +4 -0
- package/dist/storage/workflow-runs/index.d.ts.map +1 -0
- package/dist/storage/workflow-runs/types.d.ts +305 -0
- package/dist/storage/workflow-runs/types.d.ts.map +1 -0
- package/dist/syncs/builders.d.ts +9 -0
- package/dist/syncs/builders.d.ts.map +1 -0
- package/dist/syncs/errors.d.ts +4 -0
- package/dist/syncs/errors.d.ts.map +1 -0
- package/dist/syncs/index.d.ts +7 -0
- package/dist/syncs/index.d.ts.map +1 -0
- package/dist/syncs/request.d.ts +41 -0
- package/dist/syncs/request.d.ts.map +1 -0
- package/dist/syncs/types.d.ts +76 -0
- package/dist/syncs/types.d.ts.map +1 -0
- package/dist/testing/agent-storage-contract.d.ts +16 -0
- package/dist/testing/agent-storage-contract.d.ts.map +1 -0
- package/dist/testing/auth-storage-contract.d.ts +16 -0
- package/dist/testing/auth-storage-contract.d.ts.map +1 -0
- package/dist/testing/blob-storage-contract.d.ts +10 -0
- package/dist/testing/blob-storage-contract.d.ts.map +1 -0
- package/dist/testing/broker-contract.d.ts +39 -0
- package/dist/testing/broker-contract.d.ts.map +1 -0
- package/dist/testing/effective-storage-contract.d.ts +7 -0
- package/dist/testing/effective-storage-contract.d.ts.map +1 -0
- package/dist/testing/index.d.ts +15 -0
- package/dist/testing/index.d.ts.map +1 -0
- package/dist/testing/index.js +7000 -0
- package/dist/testing/index.js.map +24 -0
- package/dist/testing/lake-storage-contract.d.ts +29 -0
- package/dist/testing/lake-storage-contract.d.ts.map +1 -0
- package/dist/testing/materialization-failure-contract.d.ts +26 -0
- package/dist/testing/materialization-failure-contract.d.ts.map +1 -0
- package/dist/testing/materializer-fixture.d.ts +35 -0
- package/dist/testing/materializer-fixture.d.ts.map +1 -0
- package/dist/testing/materializer-storage-contract.d.ts +7 -0
- package/dist/testing/materializer-storage-contract.d.ts.map +1 -0
- package/dist/testing/object-query-contract.d.ts +21 -0
- package/dist/testing/object-query-contract.d.ts.map +1 -0
- package/dist/testing/ontology-contract-fixture.d.ts +33 -0
- package/dist/testing/ontology-contract-fixture.d.ts.map +1 -0
- package/dist/testing/ontology-storage-contract.d.ts +21 -0
- package/dist/testing/ontology-storage-contract.d.ts.map +1 -0
- package/dist/testing/projection-run-storage-contract.d.ts +10 -0
- package/dist/testing/projection-run-storage-contract.d.ts.map +1 -0
- package/dist/testing/queues-contract.d.ts +31 -0
- package/dist/testing/queues-contract.d.ts.map +1 -0
- package/dist/testing/sandboxes-contract.d.ts +31 -0
- package/dist/testing/sandboxes-contract.d.ts.map +1 -0
- package/dist/tsconfig.json +5 -0
- package/dist/webhooks/builders.d.ts +41 -0
- package/dist/webhooks/builders.d.ts.map +1 -0
- package/dist/webhooks/connector.d.ts +10 -0
- package/dist/webhooks/connector.d.ts.map +1 -0
- package/dist/webhooks/errors.d.ts +4 -0
- package/dist/webhooks/errors.d.ts.map +1 -0
- package/dist/webhooks/index.d.ts +9 -0
- package/dist/webhooks/index.d.ts.map +1 -0
- package/dist/webhooks/registry.d.ts +7 -0
- package/dist/webhooks/registry.d.ts.map +1 -0
- package/dist/webhooks/types.d.ts +79 -0
- package/dist/webhooks/types.d.ts.map +1 -0
- package/dist/webhooks/unverified.d.ts +57 -0
- package/dist/webhooks/unverified.d.ts.map +1 -0
- package/dist/workers/errors.d.ts +17 -0
- package/dist/workers/errors.d.ts.map +1 -0
- package/dist/workers/index.d.ts +7 -0
- package/dist/workers/index.d.ts.map +1 -0
- package/dist/workers/index.js +506 -0
- package/dist/workers/index.js.map +13 -0
- package/dist/workers/queue-delivery.d.ts +38 -0
- package/dist/workers/queue-delivery.d.ts.map +1 -0
- package/dist/workers/queue-worker.d.ts +30 -0
- package/dist/workers/queue-worker.d.ts.map +1 -0
- package/dist/workers/worker.d.ts +14 -0
- package/dist/workers/worker.d.ts.map +1 -0
- package/dist/workflows/builders.d.ts +27 -0
- package/dist/workflows/builders.d.ts.map +1 -0
- package/dist/workflows/errors.d.ts +11 -0
- package/dist/workflows/errors.d.ts.map +1 -0
- package/dist/workflows/index.d.ts +9 -0
- package/dist/workflows/index.d.ts.map +1 -0
- package/dist/workflows/index.js +108 -0
- package/dist/workflows/index.js.map +9 -0
- package/dist/workflows/request.d.ts +29 -0
- package/dist/workflows/request.d.ts.map +1 -0
- package/dist/workflows/runtime.d.ts +33 -0
- package/dist/workflows/runtime.d.ts.map +1 -0
- package/dist/workflows/snapshot.d.ts +55 -0
- package/dist/workflows/snapshot.d.ts.map +1 -0
- package/dist/workflows/types.d.ts +288 -0
- package/dist/workflows/types.d.ts.map +1 -0
- package/dist/workflows/validation.d.ts +66 -0
- package/dist/workflows/validation.d.ts.map +1 -0
- package/package.json +312 -0
- package/src/actions/builders/define-action.ts +243 -0
- package/src/actions/builders/params.ts +48 -0
- package/src/actions/builders.ts +2 -0
- package/src/actions/commit-edits.ts +110 -0
- package/src/actions/errors.ts +15 -0
- package/src/actions/index.ts +75 -0
- package/src/actions/read-facade.ts +224 -0
- package/src/actions/registry.ts +135 -0
- package/src/actions/request.ts +407 -0
- package/src/actions/run-id.ts +17 -0
- package/src/actions/runtime.ts +31 -0
- package/src/actions/types/context.ts +224 -0
- package/src/actions/types/definitions.ts +181 -0
- package/src/actions/types/handlers.ts +68 -0
- package/src/actions/types/params.ts +82 -0
- package/src/actions/types.ts +4 -0
- package/src/actions/validation.ts +186 -0
- package/src/actions/validators.ts +56 -0
- package/src/actions/worker.ts +2 -0
- package/src/agents/adapters.ts +647 -0
- package/src/agents/api-gateway.ts +57 -0
- package/src/agents/builders.ts +46 -0
- package/src/agents/context-model.ts +41 -0
- package/src/agents/context-resolution.ts +43 -0
- package/src/agents/context.ts +185 -0
- package/src/agents/dispatch.ts +107 -0
- package/src/agents/errors.ts +40 -0
- package/src/agents/ids.ts +24 -0
- package/src/agents/index.ts +122 -0
- package/src/agents/message.ts +91 -0
- package/src/agents/prompt.ts +45 -0
- package/src/agents/request.ts +198 -0
- package/src/agents/runtime.ts +124 -0
- package/src/agents/streams.ts +194 -0
- package/src/agents/types.ts +70 -0
- package/src/agents/validation.ts +151 -0
- package/src/auth/access-tokens.ts +125 -0
- package/src/auth/audience.ts +28 -0
- package/src/auth/cookies.ts +263 -0
- package/src/auth/csrf.ts +41 -0
- package/src/auth/errors.ts +19 -0
- package/src/auth/index.ts +149 -0
- package/src/auth/runtime.ts +1642 -0
- package/src/auth/session-cache.ts +112 -0
- package/src/auth/sessions.ts +55 -0
- package/src/auth/strategy.ts +46 -0
- package/src/auth/types.ts +573 -0
- package/src/auth/validation.ts +241 -0
- package/src/authorization/application-access.ts +34 -0
- package/src/authorization/decision.ts +215 -0
- package/src/authorization/errors.ts +12 -0
- package/src/authorization/event-visibility.ts +99 -0
- package/src/authorization/grant-kinds.ts +149 -0
- package/src/authorization/index.ts +24 -0
- package/src/authorization/resolve.ts +101 -0
- package/src/authorization/run-visibility.ts +78 -0
- package/src/authorization/types.ts +52 -0
- package/src/blob-storage/browser.ts +28 -0
- package/src/blob-storage/constants.ts +9 -0
- package/src/blob-storage/derive.ts +13 -0
- package/src/blob-storage/errors.ts +6 -0
- package/src/blob-storage/in-memory.ts +74 -0
- package/src/blob-storage/index.ts +37 -0
- package/src/blob-storage/types.ts +143 -0
- package/src/blob-storage/utils.ts +126 -0
- package/src/blob-storage/validation.ts +58 -0
- package/src/bootstrap/discovery.ts +507 -0
- package/src/bootstrap/index.ts +26 -0
- package/src/bootstrap/ontology-type-manifest.ts +316 -0
- package/src/broker/errors.ts +15 -0
- package/src/broker/in-memory.ts +511 -0
- package/src/broker/index.ts +12 -0
- package/src/broker/types.ts +129 -0
- package/src/connectors/builders.ts +33 -0
- package/src/connectors/errors.ts +15 -0
- package/src/connectors/index.ts +9 -0
- package/src/connectors/runtime.ts +100 -0
- package/src/connectors/types.ts +64 -0
- package/src/datasets/builders.ts +233 -0
- package/src/datasets/errors.ts +3 -0
- package/src/datasets/index.ts +13 -0
- package/src/datasets/types.ts +52 -0
- package/src/datasets/validation.ts +251 -0
- package/src/edits/errors.ts +6 -0
- package/src/edits/index.ts +24 -0
- package/src/edits/normalize.ts +87 -0
- package/src/edits/properties.ts +153 -0
- package/src/edits/recorder.ts +312 -0
- package/src/edits/types.ts +275 -0
- package/src/error-reporting/capability.ts +160 -0
- package/src/error-reporting/internal.ts +13 -0
- package/src/error-reporting/normalize.ts +35 -0
- package/src/error-reporting/reporter.ts +65 -0
- package/src/error-reporting/types.ts +125 -0
- package/src/events/definitions.ts +241 -0
- package/src/events/envelope.ts +68 -0
- package/src/events/errors.ts +7 -0
- package/src/events/index.ts +167 -0
- package/src/events/outbox-dispatcher.ts +534 -0
- package/src/events/property-changes.ts +9 -0
- package/src/events/runtime.ts +401 -0
- package/src/events/scope.ts +71 -0
- package/src/events/selectors/builder.ts +531 -0
- package/src/events/selectors/index.ts +42 -0
- package/src/events/selectors/predicate.ts +91 -0
- package/src/events/selectors/types.ts +258 -0
- package/src/events/toStoredEvent.ts +35 -0
- package/src/events/types/actions.ts +42 -0
- package/src/events/types/datasets.ts +21 -0
- package/src/events/types/index.ts +206 -0
- package/src/events/types/links.ts +42 -0
- package/src/events/types/objects.ts +38 -0
- package/src/events/types/pipelines.ts +67 -0
- package/src/events/types/rules.ts +31 -0
- package/src/events/types/schedules.ts +15 -0
- package/src/events/types/syncs.ts +27 -0
- package/src/events/types/telemetry.ts +19 -0
- package/src/events/types/workflows.ts +172 -0
- package/src/http/api-routes.ts +384 -0
- package/src/http/index.ts +3 -0
- package/src/http/route-pattern.ts +37 -0
- package/src/index.ts +916 -0
- package/src/json.ts +137 -0
- package/src/lake-storage/definition-updates.ts +263 -0
- package/src/lake-storage/errors.ts +6 -0
- package/src/lake-storage/in-memory.ts +348 -0
- package/src/lake-storage/index.ts +48 -0
- package/src/lake-storage/sql-transforms.ts +67 -0
- package/src/lake-storage/types.ts +135 -0
- package/src/logging/console-logger.ts +63 -0
- package/src/logging/index.ts +43 -0
- package/src/logging/record.ts +126 -0
- package/src/logging/run-logger.ts +350 -0
- package/src/logging/runtime.ts +341 -0
- package/src/logging/stream.ts +38 -0
- package/src/logging/types.ts +156 -0
- package/src/maintenance/index.ts +9 -0
- package/src/maintenance/ontology-maintenance.ts +351 -0
- package/src/maintenance/types.ts +57 -0
- package/src/materialization/dataset-watermark.ts +52 -0
- package/src/materialization/errors.ts +73 -0
- package/src/materialization/events.ts +92 -0
- package/src/materialization/identity.ts +36 -0
- package/src/materialization/index.ts +75 -0
- package/src/materialization/model.ts +394 -0
- package/src/materialization/refs.ts +134 -0
- package/src/materializer/README.md +130 -0
- package/src/materializer/context.ts +75 -0
- package/src/materializer/edits/apply.ts +241 -0
- package/src/materializer/edits/commit.ts +311 -0
- package/src/materializer/edits/execution-units.ts +32 -0
- package/src/materializer/edits/load-state.ts +148 -0
- package/src/materializer/edits/operations.ts +298 -0
- package/src/materializer/edits/plan.ts +192 -0
- package/src/materializer/edits/read-set.ts +79 -0
- package/src/materializer/edits/working-state.ts +171 -0
- package/src/materializer/effective/build-events.ts +197 -0
- package/src/materializer/effective/diff.ts +169 -0
- package/src/materializer/effective/load-state.ts +75 -0
- package/src/materializer/effective/resolve.ts +96 -0
- package/src/materializer/effective/validate.ts +180 -0
- package/src/materializer/execution/commit-lifecycle.ts +57 -0
- package/src/materializer/execution/plan-stream.ts +97 -0
- package/src/materializer/execution/run-correlation.ts +73 -0
- package/src/materializer/execution/work-executor.ts +143 -0
- package/src/materializer/execution/work-records.ts +186 -0
- package/src/materializer/index.ts +109 -0
- package/src/materializer/materializer.ts +64 -0
- package/src/materializer/projections/entry-validator.ts +162 -0
- package/src/materializer/projections/finish-run.ts +194 -0
- package/src/materializer/projections/replace.ts +447 -0
- package/src/materializer/projections/replacement-plan.ts +376 -0
- package/src/materializer/projections/source-materialization.ts +99 -0
- package/src/materializer/shared/abort.ts +7 -0
- package/src/materializer/shared/batching.ts +32 -0
- package/src/materializer/shared/chunking.ts +27 -0
- package/src/materializer/shared/identity.ts +141 -0
- package/src/materializer/shared/normalize.ts +527 -0
- package/src/materializer/shared/projection-run.ts +61 -0
- package/src/materializer/telemetry/append.ts +503 -0
- package/src/materializer/telemetry/plan.ts +363 -0
- package/src/objects/action/errors.ts +56 -0
- package/src/objects/action/index.ts +3 -0
- package/src/objects/action/request.ts +63 -0
- package/src/objects/context/index.ts +6 -0
- package/src/objects/context/resolve.ts +51 -0
- package/src/objects/context/types.ts +31 -0
- package/src/objects/contexts.ts +64 -0
- package/src/objects/errors.ts +7 -0
- package/src/objects/helpers.ts +18 -0
- package/src/objects/index.ts +26 -0
- package/src/objects/link/authorization.ts +26 -0
- package/src/objects/link/endpoints.ts +66 -0
- package/src/objects/link/index.ts +3 -0
- package/src/objects/link/remove.ts +42 -0
- package/src/objects/link/upsert-batch.ts +80 -0
- package/src/objects/link/upsert.ts +56 -0
- package/src/objects/materializer-adapter.ts +307 -0
- package/src/objects/object/delete.ts +47 -0
- package/src/objects/object/index.ts +3 -0
- package/src/objects/object/upsert-batch.ts +57 -0
- package/src/objects/object/upsert.ts +38 -0
- package/src/objects/query/errors.ts +55 -0
- package/src/objects/query/executor.ts +1345 -0
- package/src/objects/query/explain-format.ts +34 -0
- package/src/objects/query/explain.ts +215 -0
- package/src/objects/query/index.ts +77 -0
- package/src/objects/query/ir.ts +211 -0
- package/src/objects/query/normalize.ts +245 -0
- package/src/objects/query/planner.ts +538 -0
- package/src/objects/query/scalar-values.ts +100 -0
- package/src/objects/query/validate.ts +1276 -0
- package/src/objects/runtime-batch.ts +105 -0
- package/src/objects/sdk/index.ts +2 -0
- package/src/objects/sdk/object-handle.ts +139 -0
- package/src/objects/sdk/object-set.ts +224 -0
- package/src/objects/sdk/query-builder.ts +386 -0
- package/src/objects/sdk/query-executor.ts +62 -0
- package/src/objects/sdk/runtime-query-executor.ts +88 -0
- package/src/objects/sdk/telemetry-channel.ts +81 -0
- package/src/objects/sdk/where.ts +87 -0
- package/src/objects/service/action-service.ts +40 -0
- package/src/objects/service/index.ts +6 -0
- package/src/objects/service/link-service.ts +74 -0
- package/src/objects/service/list-service.ts +89 -0
- package/src/objects/service/object-service.ts +28 -0
- package/src/objects/service/telemetry-service.ts +17 -0
- package/src/objects/telemetry/append-batch.ts +74 -0
- package/src/objects/telemetry/history.ts +32 -0
- package/src/objects/telemetry/index.ts +4 -0
- package/src/objects/telemetry/write-batch.ts +52 -0
- package/src/ontology/builders.ts +695 -0
- package/src/ontology/decimal.ts +120 -0
- package/src/ontology/errors.ts +25 -0
- package/src/ontology/index.ts +80 -0
- package/src/ontology/inference/index.ts +215 -0
- package/src/ontology/internal.ts +3 -0
- package/src/ontology/json-schema.ts +123 -0
- package/src/ontology/refs.ts +80 -0
- package/src/ontology/registry.ts +417 -0
- package/src/ontology/tokens.ts +113 -0
- package/src/ontology/types.ts +436 -0
- package/src/ontology/units/index.ts +115 -0
- package/src/ontology/units/quantitative-types.ts +608 -0
- package/src/ontology/units/types.ts +27 -0
- package/src/ontology/validation/index.ts +36 -0
- package/src/ontology/validation/links.ts +126 -0
- package/src/ontology/validation/normalize.ts +215 -0
- package/src/ontology/validation/properties.ts +235 -0
- package/src/ontology/validation/query.ts +300 -0
- package/src/ontology/validation/schema.ts +174 -0
- package/src/ontology/validation/telemetry.ts +53 -0
- package/src/pipelines/builders.ts +155 -0
- package/src/pipelines/errors.ts +3 -0
- package/src/pipelines/index.ts +26 -0
- package/src/pipelines/request.ts +71 -0
- package/src/pipelines/types.ts +199 -0
- package/src/predicates/builders.ts +152 -0
- package/src/predicates/evaluate.ts +107 -0
- package/src/predicates/index.ts +28 -0
- package/src/predicates/types.ts +124 -0
- package/src/predicates/validation.ts +152 -0
- package/src/projections/builders.ts +770 -0
- package/src/projections/errors.ts +3 -0
- package/src/projections/index.ts +32 -0
- package/src/projections/internal.ts +75 -0
- package/src/projections/ownership.ts +134 -0
- package/src/projections/registry.ts +269 -0
- package/src/projections/revision.ts +245 -0
- package/src/projections/types.ts +165 -0
- package/src/projections/validation.ts +531 -0
- package/src/provider-scope.ts +11 -0
- package/src/query.ts +75 -0
- package/src/queues/errors.ts +6 -0
- package/src/queues/in-memory.ts +364 -0
- package/src/queues/index.ts +23 -0
- package/src/queues/types.ts +230 -0
- package/src/rules/builders.ts +126 -0
- package/src/rules/dependencies.ts +76 -0
- package/src/rules/errors.ts +11 -0
- package/src/rules/index.ts +30 -0
- package/src/rules/internal.ts +8 -0
- package/src/rules/types.ts +113 -0
- package/src/rules/validation.ts +153 -0
- package/src/runtime/create.ts +163 -0
- package/src/runtime/errors.ts +8 -0
- package/src/runtime/index.ts +67 -0
- package/src/runtime/internal.ts +7 -0
- package/src/runtime/ontology-mutations.ts +90 -0
- package/src/runtime/scoped.ts +436 -0
- package/src/runtime/sixb.ts +822 -0
- package/src/runtime/storage-readiness.ts +91 -0
- package/src/runtime/types.ts +1401 -0
- package/src/sandboxes/errors.ts +22 -0
- package/src/sandboxes/exec.ts +102 -0
- package/src/sandboxes/index.ts +19 -0
- package/src/sandboxes/sandbox.ts +124 -0
- package/src/scheduler/errors.ts +7 -0
- package/src/scheduler/index.ts +3 -0
- package/src/scheduler/runtime.ts +174 -0
- package/src/schedules/builders.ts +257 -0
- package/src/schedules/cron.ts +166 -0
- package/src/schedules/errors.ts +7 -0
- package/src/schedules/index.ts +44 -0
- package/src/schedules/next-occurrence.ts +217 -0
- package/src/schedules/runtime.ts +241 -0
- package/src/schedules/types.ts +212 -0
- package/src/schedules/validation.ts +398 -0
- package/src/security/applications.ts +11 -0
- package/src/security/builders.ts +128 -0
- package/src/security/errors.ts +3 -0
- package/src/security/every.ts +108 -0
- package/src/security/grants.ts +215 -0
- package/src/security/index.ts +51 -0
- package/src/security/membership-policies.ts +101 -0
- package/src/security/runtime.ts +101 -0
- package/src/security/types.ts +156 -0
- package/src/security/validation.ts +430 -0
- package/src/storage/action-runs/errors.ts +13 -0
- package/src/storage/action-runs/idempotency.ts +68 -0
- package/src/storage/action-runs/in-memory.ts +420 -0
- package/src/storage/action-runs/index.ts +31 -0
- package/src/storage/action-runs/types.ts +169 -0
- package/src/storage/agents/errors.ts +22 -0
- package/src/storage/agents/in-memory.ts +498 -0
- package/src/storage/agents/index.ts +42 -0
- package/src/storage/agents/types.ts +348 -0
- package/src/storage/auth/errors.ts +40 -0
- package/src/storage/auth/in-memory/access-tokens.ts +123 -0
- package/src/storage/auth/in-memory/auth-storage.ts +559 -0
- package/src/storage/auth/in-memory/group-memberships.ts +46 -0
- package/src/storage/auth/in-memory/identities.ts +66 -0
- package/src/storage/auth/in-memory/index.ts +1 -0
- package/src/storage/auth/in-memory/invitations.ts +165 -0
- package/src/storage/auth/in-memory/magic-links.ts +98 -0
- package/src/storage/auth/in-memory/oidc-attempts.ts +75 -0
- package/src/storage/auth/in-memory/service-account-group-memberships.ts +102 -0
- package/src/storage/auth/in-memory/service-accounts.ts +80 -0
- package/src/storage/auth/in-memory/sessions.ts +177 -0
- package/src/storage/auth/in-memory/shared.ts +602 -0
- package/src/storage/auth/in-memory/users.ts +139 -0
- package/src/storage/auth/in-memory.ts +1 -0
- package/src/storage/auth/index.ts +58 -0
- package/src/storage/auth/types.ts +639 -0
- package/src/storage/errors.ts +45 -0
- package/src/storage/file-upload-sessions/errors.ts +24 -0
- package/src/storage/file-upload-sessions/in-memory.ts +161 -0
- package/src/storage/file-upload-sessions/index.ts +19 -0
- package/src/storage/file-upload-sessions/types.ts +61 -0
- package/src/storage/file-upload-sessions/utils.ts +49 -0
- package/src/storage/in-memory/index.ts +297 -0
- package/src/storage/in-memory/testing.ts +21 -0
- package/src/storage/index.ts +489 -0
- package/src/storage/migrations/check-schema.ts +49 -0
- package/src/storage/migrations/index.ts +23 -0
- package/src/storage/migrations/migrate-storage.ts +24 -0
- package/src/storage/migrations/migration-set.ts +270 -0
- package/src/storage/migrations/types.ts +129 -0
- package/src/storage/objects/in-memory.ts +1154 -0
- package/src/storage/objects/index.ts +24 -0
- package/src/storage/objects/types.ts +244 -0
- package/src/storage/ontology/commits.ts +132 -0
- package/src/storage/ontology/in-memory/commits.ts +122 -0
- package/src/storage/ontology/in-memory/index.ts +94 -0
- package/src/storage/ontology/in-memory/materializations-finalization.ts +484 -0
- package/src/storage/ontology/in-memory/materializations-state.ts +183 -0
- package/src/storage/ontology/in-memory/materializations-work.ts +62 -0
- package/src/storage/ontology/in-memory/materializations.ts +1192 -0
- package/src/storage/ontology/in-memory/outbox.ts +227 -0
- package/src/storage/ontology/in-memory/shared-state.ts +161 -0
- package/src/storage/ontology/in-memory/sources.ts +566 -0
- package/src/storage/ontology/in-memory/testing.ts +29 -0
- package/src/storage/ontology/index.ts +119 -0
- package/src/storage/ontology/materializations.ts +414 -0
- package/src/storage/ontology/outbox.ts +79 -0
- package/src/storage/ontology/provider-header-validation.ts +173 -0
- package/src/storage/ontology/provider-validation.ts +36 -0
- package/src/storage/ontology/provider-work.ts +330 -0
- package/src/storage/ontology/provider.ts +852 -0
- package/src/storage/ontology/sources.ts +195 -0
- package/src/storage/operation-scope.ts +248 -0
- package/src/storage/pagination.ts +23 -0
- package/src/storage/pipeline-runs/errors.ts +6 -0
- package/src/storage/pipeline-runs/in-memory.ts +307 -0
- package/src/storage/pipeline-runs/index.ts +19 -0
- package/src/storage/pipeline-runs/types.ts +148 -0
- package/src/storage/projection-runs/errors.ts +15 -0
- package/src/storage/projection-runs/in-memory.ts +321 -0
- package/src/storage/projection-runs/index.ts +36 -0
- package/src/storage/projection-runs/lifecycle.ts +793 -0
- package/src/storage/projection-runs/types.ts +254 -0
- package/src/storage/rules/in-memory.ts +191 -0
- package/src/storage/rules/index.ts +12 -0
- package/src/storage/rules/types.ts +80 -0
- package/src/storage/run-listing.ts +107 -0
- package/src/storage/sync-runs/errors.ts +7 -0
- package/src/storage/sync-runs/in-memory.ts +181 -0
- package/src/storage/sync-runs/index.ts +14 -0
- package/src/storage/sync-runs/types.ts +93 -0
- package/src/storage/timeseries/index.ts +7 -0
- package/src/storage/timeseries/store.ts +214 -0
- package/src/storage/timeseries/types.ts +57 -0
- package/src/storage/transaction.ts +56 -0
- package/src/storage/types.ts +299 -0
- package/src/storage/webhook-deliveries/in-memory.ts +108 -0
- package/src/storage/webhook-deliveries/index.ts +9 -0
- package/src/storage/webhook-deliveries/types.ts +41 -0
- package/src/storage/webhook-runs/errors.ts +6 -0
- package/src/storage/webhook-runs/in-memory.ts +131 -0
- package/src/storage/webhook-runs/index.ts +12 -0
- package/src/storage/webhook-runs/types.ts +69 -0
- package/src/storage/workflow-interventions/errors.ts +6 -0
- package/src/storage/workflow-interventions/in-memory.ts +192 -0
- package/src/storage/workflow-interventions/index.ts +14 -0
- package/src/storage/workflow-interventions/types.ts +100 -0
- package/src/storage/workflow-runs/errors.ts +6 -0
- package/src/storage/workflow-runs/in-memory.ts +777 -0
- package/src/storage/workflow-runs/index.ts +45 -0
- package/src/storage/workflow-runs/types.ts +344 -0
- package/src/syncs/builders.ts +101 -0
- package/src/syncs/errors.ts +3 -0
- package/src/syncs/index.ts +22 -0
- package/src/syncs/request.ts +91 -0
- package/src/syncs/types.ts +136 -0
- package/src/testing/agent-storage-contract.ts +824 -0
- package/src/testing/auth-storage-contract.ts +1932 -0
- package/src/testing/blob-storage-contract.ts +108 -0
- package/src/testing/broker-contract.ts +819 -0
- package/src/testing/effective-storage-contract.ts +182 -0
- package/src/testing/index.ts +65 -0
- package/src/testing/lake-storage-contract.ts +699 -0
- package/src/testing/materialization-failure-contract.ts +66 -0
- package/src/testing/materializer-fixture.ts +119 -0
- package/src/testing/materializer-storage-contract.ts +389 -0
- package/src/testing/object-query-contract.ts +1205 -0
- package/src/testing/ontology-contract-fixture.ts +192 -0
- package/src/testing/ontology-storage-contract.ts +922 -0
- package/src/testing/projection-run-storage-contract.ts +372 -0
- package/src/testing/queues-contract.ts +634 -0
- package/src/testing/sandboxes-contract.ts +404 -0
- package/src/webhooks/builders.ts +154 -0
- package/src/webhooks/connector.ts +19 -0
- package/src/webhooks/errors.ts +3 -0
- package/src/webhooks/index.ts +25 -0
- package/src/webhooks/registry.ts +127 -0
- package/src/webhooks/types.ts +98 -0
- package/src/webhooks/unverified.ts +82 -0
- package/src/workers/errors.ts +25 -0
- package/src/workers/index.ts +6 -0
- package/src/workers/queue-delivery.ts +309 -0
- package/src/workers/queue-worker.ts +260 -0
- package/src/workers/worker.ts +87 -0
- package/src/workflows/builders.ts +471 -0
- package/src/workflows/errors.ts +13 -0
- package/src/workflows/index.ts +94 -0
- package/src/workflows/request.ts +161 -0
- package/src/workflows/runtime.ts +68 -0
- package/src/workflows/snapshot.ts +383 -0
- package/src/workflows/types.ts +781 -0
- package/src/workflows/validation.ts +572 -0
|
@@ -0,0 +1,3842 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
isStorageSerializationFailure
|
|
4
|
+
} from "./chunk-aebzcsxr.js";
|
|
5
|
+
import {
|
|
6
|
+
materializationApplyPhase
|
|
7
|
+
} from "./chunk-q4qzq0ea.js";
|
|
8
|
+
import {
|
|
9
|
+
createCommitId,
|
|
10
|
+
createEventId,
|
|
11
|
+
createRequestHash,
|
|
12
|
+
materializationEventKindOrdinal,
|
|
13
|
+
sha256Canonical
|
|
14
|
+
} from "./chunk-wxhdnwh4.js";
|
|
15
|
+
import {
|
|
16
|
+
assertPinnedDatasetWatermark
|
|
17
|
+
} from "./chunk-9dzba0f2.js";
|
|
18
|
+
import {
|
|
19
|
+
compareLinkRefs,
|
|
20
|
+
compareObjectRefs,
|
|
21
|
+
linkOwnershipKey,
|
|
22
|
+
linkRefKey,
|
|
23
|
+
linkRefSortKey,
|
|
24
|
+
linkScopeKey,
|
|
25
|
+
linkScopeSortKey,
|
|
26
|
+
normalizeLinkRef,
|
|
27
|
+
normalizeObjectRef,
|
|
28
|
+
objectRefKey,
|
|
29
|
+
objectRefSortKey,
|
|
30
|
+
projectionEntityKey,
|
|
31
|
+
telemetryOwnershipKey,
|
|
32
|
+
telemetryPointKey,
|
|
33
|
+
telemetryPointSortKey,
|
|
34
|
+
utf8JsonByteLength
|
|
35
|
+
} from "./chunk-p6r5g77m.js";
|
|
36
|
+
import {
|
|
37
|
+
MaterializationCancellationError,
|
|
38
|
+
MaterializationConflictError,
|
|
39
|
+
MaterializationObjectNotFoundError,
|
|
40
|
+
MaterializationValidationError
|
|
41
|
+
} from "./chunk-ry24jbr1.js";
|
|
42
|
+
import {
|
|
43
|
+
assertKnownProperties,
|
|
44
|
+
normalizeLinkProperties,
|
|
45
|
+
normalizeObjectProperties,
|
|
46
|
+
normalizeSchemaValue,
|
|
47
|
+
validateLinkProperties,
|
|
48
|
+
validateObjectProperties,
|
|
49
|
+
validatePropertyValue,
|
|
50
|
+
validateTelemetryUnit
|
|
51
|
+
} from "./chunk-tsk2bxs3.js";
|
|
52
|
+
import {
|
|
53
|
+
ProjectionValidationError,
|
|
54
|
+
isProjectionDefinition,
|
|
55
|
+
validateProjectionsAtStartup
|
|
56
|
+
} from "./chunk-btpe64e4.js";
|
|
57
|
+
import {
|
|
58
|
+
assertJsonValue,
|
|
59
|
+
cloneJsonValue,
|
|
60
|
+
compareStrings,
|
|
61
|
+
stableJsonStringify
|
|
62
|
+
} from "./chunk-1vffvydj.js";
|
|
63
|
+
// src/projections/revision.ts
|
|
64
|
+
function computeOntologyRevision(ontology) {
|
|
65
|
+
const referencedValueTypeIds = collectOntologyValueTypeDependencies(ontology);
|
|
66
|
+
return sha256Canonical({
|
|
67
|
+
objectTypes: normalizeOntologyObjectTypes(ontology),
|
|
68
|
+
valueTypes: normalizeOntologyValueTypes(ontology, referencedValueTypeIds)
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
function collectOntologyValueTypeDependencies(ontology) {
|
|
72
|
+
const referencedValueTypeIds = new Set;
|
|
73
|
+
for (const objectType of ontology.getObjectTypesById().values()) {
|
|
74
|
+
for (const property of objectType.properties) {
|
|
75
|
+
collectReferencedValueTypeIds(property.schema, referencedValueTypeIds);
|
|
76
|
+
}
|
|
77
|
+
for (const link of objectType.links) {
|
|
78
|
+
for (const property of link.properties ?? []) {
|
|
79
|
+
collectReferencedValueTypeIds(property.schema, referencedValueTypeIds);
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
const pending = [...referencedValueTypeIds];
|
|
84
|
+
const queued = new Set(pending);
|
|
85
|
+
for (let index = 0;index < pending.length; index += 1) {
|
|
86
|
+
const valueType = ontology.getValueTypesById().get(pending[index]);
|
|
87
|
+
if (!valueType)
|
|
88
|
+
continue;
|
|
89
|
+
collectReferencedValueTypeIds(valueType.schema, referencedValueTypeIds);
|
|
90
|
+
for (const valueTypeId of referencedValueTypeIds) {
|
|
91
|
+
if (queued.has(valueTypeId))
|
|
92
|
+
continue;
|
|
93
|
+
queued.add(valueTypeId);
|
|
94
|
+
pending.push(valueTypeId);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return referencedValueTypeIds;
|
|
98
|
+
}
|
|
99
|
+
function normalizeOntologyValueTypes(ontology, referencedValueTypeIds) {
|
|
100
|
+
return [...referencedValueTypeIds].sort(compareStrings).map((valueTypeId) => ontology.getValueTypesById().get(valueTypeId)).filter((valueType) => valueType !== undefined).map((valueType) => ({
|
|
101
|
+
id: valueType.id,
|
|
102
|
+
schema: normalizeSchema(valueType.schema),
|
|
103
|
+
semanticType: valueType.semanticType ?? null
|
|
104
|
+
}));
|
|
105
|
+
}
|
|
106
|
+
function normalizeOntologyObjectTypes(ontology) {
|
|
107
|
+
return [...ontology.getObjectTypesById().values()].sort((left, right) => compareStrings(left.id, right.id)).map((objectType) => ({
|
|
108
|
+
id: objectType.id,
|
|
109
|
+
extends: objectType.extends ?? null,
|
|
110
|
+
parents: [...objectType.parents ?? []].sort(),
|
|
111
|
+
implements: [...objectType.implements ?? []].sort(),
|
|
112
|
+
properties: [...objectType.properties].sort((left, right) => compareStrings(left.id, right.id)).map(normalizeProperty),
|
|
113
|
+
links: [...objectType.links].sort((left, right) => compareStrings(left.id, right.id)).map((link) => ({
|
|
114
|
+
id: link.id,
|
|
115
|
+
targetObjectTypeIds: Array.isArray(link.targetObjectTypeId) ? [...link.targetObjectTypeId].sort() : [link.targetObjectTypeId],
|
|
116
|
+
cardinality: link.cardinality ?? "many",
|
|
117
|
+
properties: [...link.properties ?? []].sort((left, right) => compareStrings(left.id, right.id)).map(normalizeProperty)
|
|
118
|
+
}))
|
|
119
|
+
}));
|
|
120
|
+
}
|
|
121
|
+
function collectReferencedValueTypeIds(schema, valueTypeIds) {
|
|
122
|
+
if (typeof schema === "string" || schema.type === "enum")
|
|
123
|
+
return;
|
|
124
|
+
if (schema.type === "valueTypeRef") {
|
|
125
|
+
valueTypeIds.add(schema.valueTypeId);
|
|
126
|
+
return;
|
|
127
|
+
}
|
|
128
|
+
if (schema.type === "array") {
|
|
129
|
+
collectReferencedValueTypeIds(schema.items, valueTypeIds);
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (schema.type === "map") {
|
|
133
|
+
collectReferencedValueTypeIds(schema.valueSchema, valueTypeIds);
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
for (const field of Object.values(schema.properties)) {
|
|
137
|
+
collectReferencedValueTypeIds(field.schema, valueTypeIds);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
function computeProjectionRevision(projection, dataset) {
|
|
141
|
+
const referencedColumns = projectionColumns(projection);
|
|
142
|
+
const columns = dataset.schema.columns.filter((column) => referencedColumns.has(column.name)).map((column) => ({
|
|
143
|
+
name: column.name,
|
|
144
|
+
type: column.type,
|
|
145
|
+
nullable: column.nullable ?? false
|
|
146
|
+
})).sort((left, right) => compareStrings(left.name, right.name));
|
|
147
|
+
return sha256Canonical({
|
|
148
|
+
mapping: normalizeProjectionDefinition(projection),
|
|
149
|
+
columns
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
function computeProjectionOwnershipHash(ownership) {
|
|
153
|
+
return sha256Canonical(ownership);
|
|
154
|
+
}
|
|
155
|
+
function normalizeProjectionDefinition(projection) {
|
|
156
|
+
if (projection._tag === "ObjectProjectionDefinition") {
|
|
157
|
+
return {
|
|
158
|
+
kind: "object",
|
|
159
|
+
objectTypeId: projection.objectTypeId,
|
|
160
|
+
properties: Object.fromEntries(Object.entries(projection.properties).sort(([left], [right]) => compareStrings(left, right))),
|
|
161
|
+
links: Object.fromEntries(Object.entries(projection.links).sort(([left], [right]) => compareStrings(left, right)).map(([linkId, link]) => [
|
|
162
|
+
linkId,
|
|
163
|
+
{
|
|
164
|
+
linkId: link.linkId,
|
|
165
|
+
sourcePropertyId: link.sourcePropertyId ?? null,
|
|
166
|
+
sourceField: link.sourceField ?? null,
|
|
167
|
+
targetObjectTypeId: link.targetObjectTypeId
|
|
168
|
+
}
|
|
169
|
+
]))
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
if (projection._tag === "LinkProjectionDefinition") {
|
|
173
|
+
return {
|
|
174
|
+
kind: "link",
|
|
175
|
+
sourceObjectTypeId: projection.sourceObjectTypeId,
|
|
176
|
+
linkId: projection.linkId,
|
|
177
|
+
targetObjectTypeId: projection.targetObjectTypeId,
|
|
178
|
+
sourceField: projection.sourceField,
|
|
179
|
+
targetField: projection.targetField
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
return {
|
|
183
|
+
kind: "telemetry",
|
|
184
|
+
objectTypeId: projection.objectTypeId,
|
|
185
|
+
propertyId: projection.propertyId,
|
|
186
|
+
objectIdField: projection.objectIdField,
|
|
187
|
+
atField: projection.atField,
|
|
188
|
+
valueField: projection.valueField,
|
|
189
|
+
unitField: projection.unitField ?? null
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
function projectionColumns(projection) {
|
|
193
|
+
if (projection._tag === "ObjectProjectionDefinition") {
|
|
194
|
+
return new Set([
|
|
195
|
+
...Object.values(projection.properties),
|
|
196
|
+
...Object.values(projection.links).flatMap((link) => link.sourceField === undefined ? [] : [link.sourceField])
|
|
197
|
+
]);
|
|
198
|
+
}
|
|
199
|
+
if (projection._tag === "LinkProjectionDefinition") {
|
|
200
|
+
return new Set([projection.sourceField, projection.targetField]);
|
|
201
|
+
}
|
|
202
|
+
return new Set([
|
|
203
|
+
projection.objectIdField,
|
|
204
|
+
projection.atField,
|
|
205
|
+
projection.valueField,
|
|
206
|
+
...projection.unitField === undefined ? [] : [projection.unitField]
|
|
207
|
+
]);
|
|
208
|
+
}
|
|
209
|
+
function normalizeProperty(property) {
|
|
210
|
+
return {
|
|
211
|
+
id: property.id,
|
|
212
|
+
schema: normalizeSchema(property.schema),
|
|
213
|
+
required: property.required ?? false,
|
|
214
|
+
nullable: property.nullable ?? false,
|
|
215
|
+
primary: property.primary ?? false,
|
|
216
|
+
mode: property.mode ?? "static",
|
|
217
|
+
semanticType: property.semanticType ?? null
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
function normalizeSchema(schema) {
|
|
221
|
+
if (typeof schema === "string")
|
|
222
|
+
return schema;
|
|
223
|
+
if (schema.type === "valueTypeRef") {
|
|
224
|
+
return { type: "valueTypeRef", valueTypeId: schema.valueTypeId };
|
|
225
|
+
}
|
|
226
|
+
if (schema.type === "enum") {
|
|
227
|
+
return {
|
|
228
|
+
type: "enum",
|
|
229
|
+
valueType: schema.valueType,
|
|
230
|
+
values: schema.valueType === "string" ? [...schema.values].sort(compareStrings) : [...schema.values].sort((left, right) => left - right)
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
if (schema.type === "array") {
|
|
234
|
+
return { type: "array", items: normalizeSchema(schema.items) };
|
|
235
|
+
}
|
|
236
|
+
if (schema.type === "map") {
|
|
237
|
+
return {
|
|
238
|
+
type: "map",
|
|
239
|
+
keySchema: schema.keySchema,
|
|
240
|
+
valueSchema: normalizeSchema(schema.valueSchema)
|
|
241
|
+
};
|
|
242
|
+
}
|
|
243
|
+
return {
|
|
244
|
+
type: "object",
|
|
245
|
+
properties: Object.fromEntries(Object.entries(schema.properties).sort(([left], [right]) => compareStrings(left, right)).map(([fieldId, field]) => [fieldId, normalizeField(field)]))
|
|
246
|
+
};
|
|
247
|
+
}
|
|
248
|
+
function normalizeField(field) {
|
|
249
|
+
return {
|
|
250
|
+
schema: normalizeSchema(field.schema),
|
|
251
|
+
required: field.required ?? false,
|
|
252
|
+
nullable: field.nullable ?? false,
|
|
253
|
+
semanticType: field.semanticType ?? null
|
|
254
|
+
};
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// src/projections/registry.ts
|
|
258
|
+
class ProjectionRegistry {
|
|
259
|
+
ontologyRevision;
|
|
260
|
+
objectProjections;
|
|
261
|
+
linkProjections;
|
|
262
|
+
telemetryProjections;
|
|
263
|
+
projectionsById = new Map;
|
|
264
|
+
sourceById = new Map;
|
|
265
|
+
telemetryById = new Map;
|
|
266
|
+
dispatchById = new Map;
|
|
267
|
+
dispatchDescriptors;
|
|
268
|
+
constructor(input) {
|
|
269
|
+
const objectProjections = [];
|
|
270
|
+
const linkProjections = [];
|
|
271
|
+
const telemetryProjections = [];
|
|
272
|
+
for (const projection of input.projections) {
|
|
273
|
+
if (!isProjectionDefinition(projection)) {
|
|
274
|
+
throw new ProjectionValidationError("[Sixb] Invalid projection definition.");
|
|
275
|
+
}
|
|
276
|
+
switch (projection._tag) {
|
|
277
|
+
case "ObjectProjectionDefinition":
|
|
278
|
+
objectProjections.push(deepFreeze(cloneObjectProjectionDefinition(projection)));
|
|
279
|
+
break;
|
|
280
|
+
case "LinkProjectionDefinition":
|
|
281
|
+
linkProjections.push(deepFreeze(cloneLinkProjectionDefinition(projection)));
|
|
282
|
+
break;
|
|
283
|
+
case "TelemetryProjectionDefinition":
|
|
284
|
+
telemetryProjections.push(deepFreeze(cloneTelemetryProjectionDefinition(projection)));
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
this.objectProjections = Object.freeze(objectProjections);
|
|
289
|
+
this.linkProjections = Object.freeze(linkProjections);
|
|
290
|
+
this.telemetryProjections = Object.freeze(telemetryProjections);
|
|
291
|
+
const projections = [
|
|
292
|
+
...this.objectProjections,
|
|
293
|
+
...this.linkProjections,
|
|
294
|
+
...this.telemetryProjections
|
|
295
|
+
];
|
|
296
|
+
assertUniqueProjectionIds(projections);
|
|
297
|
+
const validated = validateProjectionsAtStartup({
|
|
298
|
+
objectProjections: this.objectProjections,
|
|
299
|
+
linkProjections: this.linkProjections,
|
|
300
|
+
telemetryProjections: this.telemetryProjections
|
|
301
|
+
}, input.ontology, input.datasetsById);
|
|
302
|
+
this.ontologyRevision = computeOntologyRevision(input.ontology);
|
|
303
|
+
const dispatchDescriptors = [];
|
|
304
|
+
for (const record of validated.objectProjections) {
|
|
305
|
+
const resolved = createResolvedProjection(record);
|
|
306
|
+
this.sourceById.set(resolved.projectionId, resolved);
|
|
307
|
+
this.projectionsById.set(resolved.projectionId, resolved.definition);
|
|
308
|
+
dispatchDescriptors.push(createDispatchDescriptor(resolved, this.ontologyRevision));
|
|
309
|
+
}
|
|
310
|
+
for (const record of validated.linkProjections) {
|
|
311
|
+
const resolved = createResolvedProjection(record);
|
|
312
|
+
this.sourceById.set(resolved.projectionId, resolved);
|
|
313
|
+
this.projectionsById.set(resolved.projectionId, resolved.definition);
|
|
314
|
+
dispatchDescriptors.push(createDispatchDescriptor(resolved, this.ontologyRevision));
|
|
315
|
+
}
|
|
316
|
+
for (const record of validated.telemetryProjections) {
|
|
317
|
+
const resolved = createResolvedProjection(record);
|
|
318
|
+
this.telemetryById.set(resolved.projectionId, resolved);
|
|
319
|
+
this.projectionsById.set(resolved.projectionId, resolved.definition);
|
|
320
|
+
dispatchDescriptors.push(createDispatchDescriptor(resolved, this.ontologyRevision));
|
|
321
|
+
}
|
|
322
|
+
this.dispatchDescriptors = Object.freeze(dispatchDescriptors);
|
|
323
|
+
for (const descriptor of this.dispatchDescriptors) {
|
|
324
|
+
this.dispatchById.set(descriptor.projectionId, descriptor);
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
listObjectProjections() {
|
|
328
|
+
return this.objectProjections;
|
|
329
|
+
}
|
|
330
|
+
listLinkProjections() {
|
|
331
|
+
return this.linkProjections;
|
|
332
|
+
}
|
|
333
|
+
listTelemetryProjections() {
|
|
334
|
+
return this.telemetryProjections;
|
|
335
|
+
}
|
|
336
|
+
getProjectionById(projectionId) {
|
|
337
|
+
return this.projectionsById.get(projectionId) ?? null;
|
|
338
|
+
}
|
|
339
|
+
getDispatchDescriptors() {
|
|
340
|
+
return this.dispatchDescriptors;
|
|
341
|
+
}
|
|
342
|
+
resolveDispatch(projectionId) {
|
|
343
|
+
const descriptor = this.dispatchById.get(projectionId);
|
|
344
|
+
if (descriptor)
|
|
345
|
+
return descriptor;
|
|
346
|
+
throw new ProjectionValidationError(`[Sixb] Unknown projection '${projectionId}'.`);
|
|
347
|
+
}
|
|
348
|
+
resolveSource(projectionId) {
|
|
349
|
+
const resolved = this.sourceById.get(projectionId);
|
|
350
|
+
if (!resolved) {
|
|
351
|
+
if (this.telemetryById.has(projectionId)) {
|
|
352
|
+
throw new ProjectionValidationError(`[Sixb] Projection '${projectionId}' is telemetry-only and cannot replace source state.`);
|
|
353
|
+
}
|
|
354
|
+
throw new ProjectionValidationError(`[Sixb] Unknown source projection '${projectionId}'.`);
|
|
355
|
+
}
|
|
356
|
+
return resolved;
|
|
357
|
+
}
|
|
358
|
+
resolveTelemetry(projectionId) {
|
|
359
|
+
const resolved = this.telemetryById.get(projectionId);
|
|
360
|
+
if (!resolved) {
|
|
361
|
+
if (this.sourceById.has(projectionId)) {
|
|
362
|
+
throw new ProjectionValidationError(`[Sixb] Projection '${projectionId}' does not own a telemetry source.`);
|
|
363
|
+
}
|
|
364
|
+
throw new ProjectionValidationError(`[Sixb] Unknown telemetry projection '${projectionId}'.`);
|
|
365
|
+
}
|
|
366
|
+
return resolved;
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
function createDispatchDescriptor(resolved, ontologyRevision) {
|
|
370
|
+
const common = {
|
|
371
|
+
projectionId: resolved.projectionId,
|
|
372
|
+
datasetId: resolved.datasetId,
|
|
373
|
+
ontologyRevision,
|
|
374
|
+
projectionRevision: resolved.projectionRevision,
|
|
375
|
+
ownershipHash: resolved.ownershipHash
|
|
376
|
+
};
|
|
377
|
+
switch (resolved.definition._tag) {
|
|
378
|
+
case "ObjectProjectionDefinition":
|
|
379
|
+
return deepFreeze({ ...common, projectionKind: "object", protocol: "replacement" });
|
|
380
|
+
case "LinkProjectionDefinition":
|
|
381
|
+
return deepFreeze({ ...common, projectionKind: "link", protocol: "replacement" });
|
|
382
|
+
case "TelemetryProjectionDefinition":
|
|
383
|
+
return deepFreeze({ ...common, projectionKind: "telemetry", protocol: "telemetry" });
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
function assertUniqueProjectionIds(projections) {
|
|
387
|
+
const ids = new Set;
|
|
388
|
+
for (const projection of projections) {
|
|
389
|
+
if (ids.has(projection.id)) {
|
|
390
|
+
throw new ProjectionValidationError(`[Sixb] Duplicate projection id: ${projection.id}`);
|
|
391
|
+
}
|
|
392
|
+
ids.add(projection.id);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
function createResolvedProjection(validated) {
|
|
396
|
+
const { definition, dataset, ownership } = validated;
|
|
397
|
+
return deepFreeze({
|
|
398
|
+
projectionId: definition.id,
|
|
399
|
+
datasetId: definition.datasetId,
|
|
400
|
+
projectionRevision: computeProjectionRevision(definition, dataset),
|
|
401
|
+
ownershipHash: computeProjectionOwnershipHash(ownership),
|
|
402
|
+
ownership,
|
|
403
|
+
definition
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
function cloneObjectProjectionDefinition(projection) {
|
|
407
|
+
return {
|
|
408
|
+
_tag: projection._tag,
|
|
409
|
+
id: projection.id,
|
|
410
|
+
objectTypeId: projection.objectTypeId,
|
|
411
|
+
datasetId: projection.datasetId,
|
|
412
|
+
properties: { ...projection.properties },
|
|
413
|
+
links: Object.fromEntries(Object.entries(projection.links).map(([linkId, descriptor]) => [
|
|
414
|
+
linkId,
|
|
415
|
+
{
|
|
416
|
+
linkId: descriptor.linkId,
|
|
417
|
+
...descriptor.sourcePropertyId !== undefined ? { sourcePropertyId: descriptor.sourcePropertyId } : {},
|
|
418
|
+
...descriptor.sourceField !== undefined ? { sourceField: descriptor.sourceField } : {},
|
|
419
|
+
targetObjectTypeId: descriptor.targetObjectTypeId
|
|
420
|
+
}
|
|
421
|
+
]))
|
|
422
|
+
};
|
|
423
|
+
}
|
|
424
|
+
function cloneLinkProjectionDefinition(projection) {
|
|
425
|
+
return {
|
|
426
|
+
_tag: "LinkProjectionDefinition",
|
|
427
|
+
id: projection.id,
|
|
428
|
+
linkId: projection.linkId,
|
|
429
|
+
sourceObjectTypeId: projection.sourceObjectTypeId,
|
|
430
|
+
targetObjectTypeId: projection.targetObjectTypeId,
|
|
431
|
+
datasetId: projection.datasetId,
|
|
432
|
+
sourceField: projection.sourceField,
|
|
433
|
+
targetField: projection.targetField
|
|
434
|
+
};
|
|
435
|
+
}
|
|
436
|
+
function cloneTelemetryProjectionDefinition(projection) {
|
|
437
|
+
return {
|
|
438
|
+
_tag: "TelemetryProjectionDefinition",
|
|
439
|
+
id: projection.id,
|
|
440
|
+
objectTypeId: projection.objectTypeId,
|
|
441
|
+
propertyId: projection.propertyId,
|
|
442
|
+
datasetId: projection.datasetId,
|
|
443
|
+
objectIdField: projection.objectIdField,
|
|
444
|
+
atField: projection.atField,
|
|
445
|
+
valueField: projection.valueField,
|
|
446
|
+
...projection.unitField !== undefined ? { unitField: projection.unitField } : {}
|
|
447
|
+
};
|
|
448
|
+
}
|
|
449
|
+
function deepFreeze(value) {
|
|
450
|
+
if (value === null || typeof value !== "object" || Object.isFrozen(value))
|
|
451
|
+
return value;
|
|
452
|
+
for (const child of Object.values(value)) {
|
|
453
|
+
deepFreeze(child);
|
|
454
|
+
}
|
|
455
|
+
return Object.freeze(value);
|
|
456
|
+
}
|
|
457
|
+
// src/materializer/shared/batching.ts
|
|
458
|
+
var DEFAULT_MATERIALIZATION_BATCHING = Object.freeze({
|
|
459
|
+
sourceStageRows: 1000,
|
|
460
|
+
sourceStageBytes: 4 * 1024 * 1024,
|
|
461
|
+
statePageRows: 1000,
|
|
462
|
+
planChunkRows: 1000,
|
|
463
|
+
planChunkBytes: 4 * 1024 * 1024
|
|
464
|
+
});
|
|
465
|
+
function resolveMaterializationBatching(overrides = {}) {
|
|
466
|
+
const resolved = { ...DEFAULT_MATERIALIZATION_BATCHING, ...overrides };
|
|
467
|
+
for (const [name, value] of Object.entries(resolved)) {
|
|
468
|
+
if (!Number.isSafeInteger(value) || value <= 0) {
|
|
469
|
+
throw new MaterializationValidationError(`Materialization batching '${name}' must be a positive safe integer.`);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
return Object.freeze(resolved);
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// src/materializer/shared/identity.ts
|
|
476
|
+
import { randomUUID } from "crypto";
|
|
477
|
+
function createActionIdempotencyKey(runId) {
|
|
478
|
+
return `action:${runId}:edits`;
|
|
479
|
+
}
|
|
480
|
+
function createRuntimeIdempotencyKey(requestId) {
|
|
481
|
+
return `runtime:${requestId}`;
|
|
482
|
+
}
|
|
483
|
+
function projectionIdentityTuple(input) {
|
|
484
|
+
return [
|
|
485
|
+
input.projectionId,
|
|
486
|
+
input.projectionKind,
|
|
487
|
+
input.protocol,
|
|
488
|
+
input.datasetVersion.datasetId,
|
|
489
|
+
input.datasetVersion.versionId,
|
|
490
|
+
input.datasetVersion.createdAt,
|
|
491
|
+
input.ontologyRevision,
|
|
492
|
+
input.projectionRevision,
|
|
493
|
+
input.ownershipHash
|
|
494
|
+
];
|
|
495
|
+
}
|
|
496
|
+
function createProjectionIdempotencyKey(identity) {
|
|
497
|
+
return `projection:replace:${sha256Canonical(projectionIdentityTuple(identity))}`;
|
|
498
|
+
}
|
|
499
|
+
function createRuntimeTelemetryIdempotencyKey(requestId) {
|
|
500
|
+
return `telemetry:runtime:${requestId}`;
|
|
501
|
+
}
|
|
502
|
+
function createProjectionTelemetryIdempotencyKey(identity, batchOrdinal) {
|
|
503
|
+
return `telemetry:projection:${sha256Canonical([
|
|
504
|
+
...projectionIdentityTuple(identity),
|
|
505
|
+
batchOrdinal
|
|
506
|
+
])}`;
|
|
507
|
+
}
|
|
508
|
+
function createCommitIdentity(input) {
|
|
509
|
+
return Object.freeze({
|
|
510
|
+
idempotencyKey: input.idempotencyKey,
|
|
511
|
+
requestHash: createRequestHash(input.normalizedCallerIntent),
|
|
512
|
+
commitId: createCommitId(input.projectId, input.idempotencyKey)
|
|
513
|
+
});
|
|
514
|
+
}
|
|
515
|
+
function timestampCommitIdentity(identity, now = new Date) {
|
|
516
|
+
const committedAt = new Date(now);
|
|
517
|
+
if (Number.isNaN(committedAt.getTime())) {
|
|
518
|
+
throw new MaterializationValidationError("Materialization commit time must be a valid date.");
|
|
519
|
+
}
|
|
520
|
+
return Object.freeze({
|
|
521
|
+
...identity,
|
|
522
|
+
committedAt: committedAt.toISOString()
|
|
523
|
+
});
|
|
524
|
+
}
|
|
525
|
+
function createTimedCommitIdentity(input) {
|
|
526
|
+
return timestampCommitIdentity(createCommitIdentity({
|
|
527
|
+
projectId: input.projectId,
|
|
528
|
+
idempotencyKey: input.idempotencyKey,
|
|
529
|
+
normalizedCallerIntent: input.normalizedCallerIntent
|
|
530
|
+
}), input.now);
|
|
531
|
+
}
|
|
532
|
+
function createProjectionMaterializationId() {
|
|
533
|
+
return randomUUID();
|
|
534
|
+
}
|
|
535
|
+
function createLinkScopeFingerprint(links) {
|
|
536
|
+
return sha256Canonical([...links].sort((left, right) => compareLinkRefs(left.ref, right.ref)).map((link) => ({
|
|
537
|
+
ref: link.ref,
|
|
538
|
+
properties: link.properties ?? {},
|
|
539
|
+
lastCommitId: link.lastCommitId
|
|
540
|
+
})));
|
|
541
|
+
}
|
|
542
|
+
|
|
543
|
+
// src/materializer/context.ts
|
|
544
|
+
function createMaterializerContext(input) {
|
|
545
|
+
if (input.projectId.trim().length === 0) {
|
|
546
|
+
throw new MaterializationValidationError("Materializer project id must be nonblank.");
|
|
547
|
+
}
|
|
548
|
+
if (!input.storage?.ontology) {
|
|
549
|
+
throw new MaterializationValidationError("Storage does not provide ontology capabilities.");
|
|
550
|
+
}
|
|
551
|
+
if (computeOntologyRevision(input.ontology) !== input.projections.ontologyRevision) {
|
|
552
|
+
throw new MaterializationValidationError("Materializer Ontology does not match the Ontology pinned by its projection registry.");
|
|
553
|
+
}
|
|
554
|
+
const dependencies = input.dependencies ?? {};
|
|
555
|
+
const maxSerializationRetries = dependencies.maxSerializationRetries ?? 2;
|
|
556
|
+
if (!Number.isSafeInteger(maxSerializationRetries) || maxSerializationRetries < 0) {
|
|
557
|
+
throw new MaterializationValidationError("Materializer serialization retry count must be a nonnegative safe integer.");
|
|
558
|
+
}
|
|
559
|
+
return {
|
|
560
|
+
projectId: input.projectId,
|
|
561
|
+
ontology: input.ontology,
|
|
562
|
+
projectionRegistry: input.projections,
|
|
563
|
+
storage: input.storage,
|
|
564
|
+
batching: resolveMaterializationBatching(dependencies.batching),
|
|
565
|
+
clock: dependencies.clock ?? (() => new Date),
|
|
566
|
+
materializationId: dependencies.materializationId ?? createProjectionMaterializationId,
|
|
567
|
+
maxSerializationRetries,
|
|
568
|
+
...dependencies.onSerializationRetry !== undefined ? { onSerializationRetry: dependencies.onSerializationRetry } : {},
|
|
569
|
+
...dependencies.observeCoreBuffer !== undefined ? { observeCoreBuffer: dependencies.observeCoreBuffer } : {}
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
// src/materializer/execution/commit-lifecycle.ts
|
|
574
|
+
async function replayCommitRecord(context, identity, storage = context.storage) {
|
|
575
|
+
const existing = await storage.ontology.commits.getByIdempotencyKey({
|
|
576
|
+
projectId: context.projectId,
|
|
577
|
+
idempotencyKey: identity.idempotencyKey
|
|
578
|
+
});
|
|
579
|
+
if (!existing)
|
|
580
|
+
return null;
|
|
581
|
+
if (existing.requestHash !== identity.requestHash) {
|
|
582
|
+
throw new MaterializationConflictError("idempotency", `Idempotency key '${identity.idempotencyKey}' was reused with different intent.`);
|
|
583
|
+
}
|
|
584
|
+
return existing;
|
|
585
|
+
}
|
|
586
|
+
async function replayCommit(context, identity, storage = context.storage) {
|
|
587
|
+
const existing = await replayCommitRecord(context, identity, storage);
|
|
588
|
+
if (!existing)
|
|
589
|
+
return null;
|
|
590
|
+
return { ...structuredClone(existing.result), created: false };
|
|
591
|
+
}
|
|
592
|
+
async function withSerializationRetry(context, run) {
|
|
593
|
+
for (let attempt = 0;; attempt += 1) {
|
|
594
|
+
try {
|
|
595
|
+
return await run();
|
|
596
|
+
} catch (error) {
|
|
597
|
+
if (!isStorageSerializationFailure(error) || attempt >= context.maxSerializationRetries) {
|
|
598
|
+
throw error;
|
|
599
|
+
}
|
|
600
|
+
context.onSerializationRetry?.(attempt + 1, error);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
// src/materializer/effective/build-events.ts
|
|
606
|
+
function buildObjectMaterializationEventDraft(input) {
|
|
607
|
+
const draft = buildObjectEventDraft(input, input.change);
|
|
608
|
+
return orderedDraft(objectRefSortKey(input.change.ref), draft);
|
|
609
|
+
}
|
|
610
|
+
function buildObjectEventDraft(context, change) {
|
|
611
|
+
const base = eventDraftBase(context);
|
|
612
|
+
const partitionKey = `${change.ref.objectTypeId}:${change.ref.primaryId}`;
|
|
613
|
+
if (change.kind === "deleted") {
|
|
614
|
+
return {
|
|
615
|
+
...base,
|
|
616
|
+
type: "object.deleted",
|
|
617
|
+
topic: "objects",
|
|
618
|
+
partitionKey,
|
|
619
|
+
payload: {
|
|
620
|
+
objectTypeId: change.ref.objectTypeId,
|
|
621
|
+
primaryId: change.ref.primaryId,
|
|
622
|
+
propertyChanges: change.propertyChanges
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
}
|
|
626
|
+
const type = objectEventType(change);
|
|
627
|
+
return {
|
|
628
|
+
...base,
|
|
629
|
+
type,
|
|
630
|
+
topic: "objects",
|
|
631
|
+
partitionKey,
|
|
632
|
+
payload: {
|
|
633
|
+
objectTypeId: change.ref.objectTypeId,
|
|
634
|
+
primaryId: change.ref.primaryId,
|
|
635
|
+
properties: change.after.properties,
|
|
636
|
+
propertyChanges: change.propertyChanges
|
|
637
|
+
}
|
|
638
|
+
};
|
|
639
|
+
}
|
|
640
|
+
function objectEventType(change) {
|
|
641
|
+
if (change.kind === "created")
|
|
642
|
+
return "object.created";
|
|
643
|
+
return "object.updated";
|
|
644
|
+
}
|
|
645
|
+
function buildLinkMaterializationEventDraft(input) {
|
|
646
|
+
const draft = buildLinkEventDraft(input, input.change);
|
|
647
|
+
return orderedDraft(linkRefSortKey(input.change.ref), draft);
|
|
648
|
+
}
|
|
649
|
+
function buildLinkEventDraft(context, change) {
|
|
650
|
+
const base = eventDraftBase(context);
|
|
651
|
+
const partitionKey = `${change.ref.source.objectTypeId}:${change.ref.source.primaryId}:${change.ref.linkId}`;
|
|
652
|
+
const commonPayload = {
|
|
653
|
+
sourceTypeId: change.ref.source.objectTypeId,
|
|
654
|
+
sourceId: change.ref.source.primaryId,
|
|
655
|
+
linkId: change.ref.linkId,
|
|
656
|
+
targetTypeId: change.ref.target.objectTypeId,
|
|
657
|
+
targetId: change.ref.target.primaryId,
|
|
658
|
+
propertyChanges: change.propertyChanges
|
|
659
|
+
};
|
|
660
|
+
if (change.kind === "deleted") {
|
|
661
|
+
return {
|
|
662
|
+
...base,
|
|
663
|
+
type: "link.deleted",
|
|
664
|
+
topic: "links",
|
|
665
|
+
partitionKey,
|
|
666
|
+
payload: commonPayload
|
|
667
|
+
};
|
|
668
|
+
}
|
|
669
|
+
const type = linkEventType(change);
|
|
670
|
+
if (change.after.properties === undefined) {
|
|
671
|
+
return { ...base, type, topic: "links", partitionKey, payload: commonPayload };
|
|
672
|
+
}
|
|
673
|
+
return {
|
|
674
|
+
...base,
|
|
675
|
+
type,
|
|
676
|
+
topic: "links",
|
|
677
|
+
partitionKey,
|
|
678
|
+
payload: { ...commonPayload, properties: change.after.properties }
|
|
679
|
+
};
|
|
680
|
+
}
|
|
681
|
+
function linkEventType(change) {
|
|
682
|
+
if (change.kind === "created")
|
|
683
|
+
return "link.created";
|
|
684
|
+
return "link.updated";
|
|
685
|
+
}
|
|
686
|
+
function buildTelemetryMaterializationEventDraft(input) {
|
|
687
|
+
const draft = buildTelemetryEventDraft(input, input.point);
|
|
688
|
+
return orderedDraft(telemetryPointSortKey(input.point.series, input.point.at), draft);
|
|
689
|
+
}
|
|
690
|
+
function buildTelemetryEventDraft(context, point) {
|
|
691
|
+
const base = eventDraftBase(context);
|
|
692
|
+
const partitionKey = `${point.series.object.objectTypeId}:${point.series.object.primaryId}:${point.series.propertyId}`;
|
|
693
|
+
const payload = {
|
|
694
|
+
objectTypeId: point.series.object.objectTypeId,
|
|
695
|
+
objectId: point.series.object.primaryId,
|
|
696
|
+
propertyId: point.series.propertyId,
|
|
697
|
+
value: point.value,
|
|
698
|
+
at: point.at
|
|
699
|
+
};
|
|
700
|
+
if (point.unit === undefined) {
|
|
701
|
+
return { ...base, type: "telemetry.appended", topic: "telemetry", partitionKey, payload };
|
|
702
|
+
}
|
|
703
|
+
return {
|
|
704
|
+
...base,
|
|
705
|
+
type: "telemetry.appended",
|
|
706
|
+
topic: "telemetry",
|
|
707
|
+
partitionKey,
|
|
708
|
+
payload: { ...payload, unit: point.unit }
|
|
709
|
+
};
|
|
710
|
+
}
|
|
711
|
+
function eventDraftBase(context) {
|
|
712
|
+
const base = {
|
|
713
|
+
schemaVersion: 1,
|
|
714
|
+
projectId: context.projectId,
|
|
715
|
+
occurredAt: context.committedAt,
|
|
716
|
+
origin: context.origin,
|
|
717
|
+
commitId: context.commitId
|
|
718
|
+
};
|
|
719
|
+
if (context.actor === undefined)
|
|
720
|
+
return base;
|
|
721
|
+
return { ...base, actor: context.actor };
|
|
722
|
+
}
|
|
723
|
+
function orderedDraft(sortKey, draft) {
|
|
724
|
+
return {
|
|
725
|
+
kindRank: materializationEventKindOrdinal(draft.type),
|
|
726
|
+
sortKey,
|
|
727
|
+
draft
|
|
728
|
+
};
|
|
729
|
+
}
|
|
730
|
+
function sequenceMaterializationEvent(projectId, commitId, commitOrdinal, draft) {
|
|
731
|
+
const sequence = {
|
|
732
|
+
id: createEventId(projectId, commitId, commitOrdinal),
|
|
733
|
+
commitOrdinal
|
|
734
|
+
};
|
|
735
|
+
return { ...draft, ...sequence };
|
|
736
|
+
}
|
|
737
|
+
|
|
738
|
+
// src/materializer/shared/abort.ts
|
|
739
|
+
function throwIfAborted(signal) {
|
|
740
|
+
if (signal?.aborted) {
|
|
741
|
+
throw signal.reason instanceof Error ? signal.reason : new DOMException("Projection replacement aborted", "AbortError");
|
|
742
|
+
}
|
|
743
|
+
}
|
|
744
|
+
|
|
745
|
+
// src/materializer/shared/chunking.ts
|
|
746
|
+
async function* chunkBySize(items, input) {
|
|
747
|
+
let chunk = [];
|
|
748
|
+
let bytes = 0;
|
|
749
|
+
for await (const item of items) {
|
|
750
|
+
const itemBytes = input.byteLength(item);
|
|
751
|
+
if (chunk.length > 0 && bytes + itemBytes > input.maxBytes) {
|
|
752
|
+
yield chunk;
|
|
753
|
+
chunk = [];
|
|
754
|
+
bytes = 0;
|
|
755
|
+
}
|
|
756
|
+
chunk.push(item);
|
|
757
|
+
bytes += itemBytes;
|
|
758
|
+
if (chunk.length >= input.maxRows || bytes >= input.maxBytes) {
|
|
759
|
+
yield chunk;
|
|
760
|
+
chunk = [];
|
|
761
|
+
bytes = 0;
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
if (chunk.length > 0)
|
|
765
|
+
yield chunk;
|
|
766
|
+
}
|
|
767
|
+
|
|
768
|
+
// src/materializer/execution/plan-stream.ts
|
|
769
|
+
async function* planStream(items, batching) {
|
|
770
|
+
for await (const itemsChunk of chunkBySize(items, {
|
|
771
|
+
maxRows: batching.planChunkRows,
|
|
772
|
+
maxBytes: batching.planChunkBytes,
|
|
773
|
+
byteLength: utf8JsonByteLength
|
|
774
|
+
})) {
|
|
775
|
+
const chunk = mutableChunk();
|
|
776
|
+
for (const item of itemsChunk)
|
|
777
|
+
appendItem(chunk, item);
|
|
778
|
+
yield chunk;
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
function mutableChunk() {
|
|
782
|
+
return {
|
|
783
|
+
overrides: { objectUpserts: [], objectDeletes: [], linkUpserts: [], linkDeletes: [] },
|
|
784
|
+
effective: { objectUpserts: [], objectDeletes: [], linkUpserts: [], linkDeletes: [] },
|
|
785
|
+
timeseries: { pointUpserts: [] },
|
|
786
|
+
outbox: []
|
|
787
|
+
};
|
|
788
|
+
}
|
|
789
|
+
function appendItem(chunk, item) {
|
|
790
|
+
switch (item.kind) {
|
|
791
|
+
case "object-override-upsert":
|
|
792
|
+
chunk.overrides.objectUpserts.push(item.value);
|
|
793
|
+
break;
|
|
794
|
+
case "object-override-delete":
|
|
795
|
+
chunk.overrides.objectDeletes.push(item.value);
|
|
796
|
+
break;
|
|
797
|
+
case "link-override-upsert":
|
|
798
|
+
chunk.overrides.linkUpserts.push(item.value);
|
|
799
|
+
break;
|
|
800
|
+
case "link-override-delete":
|
|
801
|
+
chunk.overrides.linkDeletes.push(item.value);
|
|
802
|
+
break;
|
|
803
|
+
case "object-upsert":
|
|
804
|
+
chunk.effective.objectUpserts.push(item.value);
|
|
805
|
+
break;
|
|
806
|
+
case "object-delete":
|
|
807
|
+
chunk.effective.objectDeletes.push(item.value);
|
|
808
|
+
break;
|
|
809
|
+
case "link-upsert":
|
|
810
|
+
chunk.effective.linkUpserts.push(item.value);
|
|
811
|
+
break;
|
|
812
|
+
case "link-delete":
|
|
813
|
+
chunk.effective.linkDeletes.push(item.value);
|
|
814
|
+
break;
|
|
815
|
+
case "point-upsert":
|
|
816
|
+
chunk.timeseries.pointUpserts.push(item.value);
|
|
817
|
+
break;
|
|
818
|
+
case "outbox":
|
|
819
|
+
chunk.outbox.push(item.value);
|
|
820
|
+
break;
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
|
|
824
|
+
// src/materializer/execution/work-records.ts
|
|
825
|
+
function appendObjectOverridePlan(items, working, identity) {
|
|
826
|
+
if (stableJsonStringify(working.originalOverride?.value ?? null) === stableJsonStringify(working.override)) {
|
|
827
|
+
return;
|
|
828
|
+
}
|
|
829
|
+
if (working.override) {
|
|
830
|
+
items.push({
|
|
831
|
+
kind: "object-override-upsert",
|
|
832
|
+
value: {
|
|
833
|
+
ref: working.ref,
|
|
834
|
+
value: working.override,
|
|
835
|
+
expectedLastCommitId: working.originalOverride?.lastCommitId ?? null,
|
|
836
|
+
lastCommitId: identity.commitId,
|
|
837
|
+
updatedAt: identity.committedAt
|
|
838
|
+
}
|
|
839
|
+
});
|
|
840
|
+
} else if (working.originalOverride) {
|
|
841
|
+
items.push({
|
|
842
|
+
kind: "object-override-delete",
|
|
843
|
+
value: { ref: working.ref, expectedLastCommitId: working.originalOverride.lastCommitId }
|
|
844
|
+
});
|
|
845
|
+
}
|
|
846
|
+
}
|
|
847
|
+
function appendLinkOverridePlan(items, working, identity) {
|
|
848
|
+
if (stableJsonStringify(working.originalOverride?.value ?? null) === stableJsonStringify(working.override)) {
|
|
849
|
+
return;
|
|
850
|
+
}
|
|
851
|
+
if (working.override) {
|
|
852
|
+
items.push({
|
|
853
|
+
kind: "link-override-upsert",
|
|
854
|
+
value: {
|
|
855
|
+
ref: working.ref,
|
|
856
|
+
value: working.override,
|
|
857
|
+
expectedLastCommitId: working.originalOverride?.lastCommitId ?? null,
|
|
858
|
+
lastCommitId: identity.commitId,
|
|
859
|
+
updatedAt: identity.committedAt
|
|
860
|
+
}
|
|
861
|
+
});
|
|
862
|
+
} else if (working.originalOverride) {
|
|
863
|
+
items.push({
|
|
864
|
+
kind: "link-override-delete",
|
|
865
|
+
value: { ref: working.ref, expectedLastCommitId: working.originalOverride.lastCommitId }
|
|
866
|
+
});
|
|
867
|
+
}
|
|
868
|
+
}
|
|
869
|
+
function appendObjectEffectivePlan(items, change) {
|
|
870
|
+
if (change.kind === "deleted") {
|
|
871
|
+
items.push({
|
|
872
|
+
kind: "object-delete",
|
|
873
|
+
value: {
|
|
874
|
+
ref: change.ref,
|
|
875
|
+
expected: expectedObject(change.before)
|
|
876
|
+
}
|
|
877
|
+
});
|
|
878
|
+
} else {
|
|
879
|
+
items.push({
|
|
880
|
+
kind: "object-upsert",
|
|
881
|
+
value: {
|
|
882
|
+
row: change.after,
|
|
883
|
+
expected: change.before ? expectedObject(change.before) : { ref: change.ref, exists: false }
|
|
884
|
+
}
|
|
885
|
+
});
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
function appendLinkEffectivePlan(items, change) {
|
|
889
|
+
if (change.kind === "deleted") {
|
|
890
|
+
items.push({
|
|
891
|
+
kind: "link-delete",
|
|
892
|
+
value: {
|
|
893
|
+
ref: change.ref,
|
|
894
|
+
expected: expectedLink(change.before)
|
|
895
|
+
}
|
|
896
|
+
});
|
|
897
|
+
} else {
|
|
898
|
+
items.push({
|
|
899
|
+
kind: "link-upsert",
|
|
900
|
+
value: {
|
|
901
|
+
row: change.after,
|
|
902
|
+
expected: change.before ? expectedLink(change.before) : { ref: change.ref, exists: false }
|
|
903
|
+
}
|
|
904
|
+
});
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
function outboxItem(event, committedAt) {
|
|
908
|
+
const value = {
|
|
909
|
+
envelope: event,
|
|
910
|
+
availableAt: committedAt,
|
|
911
|
+
createdAt: committedAt
|
|
912
|
+
};
|
|
913
|
+
return { kind: "outbox", value };
|
|
914
|
+
}
|
|
915
|
+
function classificationWork(entityKind, identityKey, sortKey) {
|
|
916
|
+
return {
|
|
917
|
+
kind: "classification",
|
|
918
|
+
recordKey: `classification:${entityKind}:${sortKey}`,
|
|
919
|
+
entityKind,
|
|
920
|
+
identityKey
|
|
921
|
+
};
|
|
922
|
+
}
|
|
923
|
+
function planWork(item, sortKey) {
|
|
924
|
+
const applyPhase = materializationApplyPhase(item.kind);
|
|
925
|
+
return {
|
|
926
|
+
kind: "plan",
|
|
927
|
+
recordKey: `plan:${item.kind}:${sortKey}`,
|
|
928
|
+
applyPhase,
|
|
929
|
+
sortKey,
|
|
930
|
+
item
|
|
931
|
+
};
|
|
932
|
+
}
|
|
933
|
+
function eventWork(value) {
|
|
934
|
+
return {
|
|
935
|
+
kind: "event",
|
|
936
|
+
recordKey: `event:${value.kindRank}:${value.sortKey}`,
|
|
937
|
+
eventKindRank: value.kindRank,
|
|
938
|
+
sortKey: value.sortKey,
|
|
939
|
+
draft: value.draft
|
|
940
|
+
};
|
|
941
|
+
}
|
|
942
|
+
function expectedObject(snapshot) {
|
|
943
|
+
return {
|
|
944
|
+
ref: snapshot.ref,
|
|
945
|
+
exists: true,
|
|
946
|
+
version: snapshot.version,
|
|
947
|
+
lastCommitId: snapshot.lastCommitId
|
|
948
|
+
};
|
|
949
|
+
}
|
|
950
|
+
function expectedLink(snapshot) {
|
|
951
|
+
return { ref: snapshot.ref, exists: true, lastCommitId: snapshot.lastCommitId };
|
|
952
|
+
}
|
|
953
|
+
|
|
954
|
+
// src/materializer/execution/work-executor.ts
|
|
955
|
+
async function applyItems(context, storage, session, items, signal) {
|
|
956
|
+
for await (const chunk of planStream(items, context.batching)) {
|
|
957
|
+
throwIfAborted(signal);
|
|
958
|
+
await storage.applyChunk({ session, chunk });
|
|
959
|
+
}
|
|
960
|
+
}
|
|
961
|
+
async function stageWorkBounded(context, storage, session, records) {
|
|
962
|
+
for await (const chunk of chunkBySize(records, {
|
|
963
|
+
maxRows: context.batching.planChunkRows,
|
|
964
|
+
maxBytes: context.batching.planChunkBytes,
|
|
965
|
+
byteLength: utf8JsonByteLength
|
|
966
|
+
})) {
|
|
967
|
+
await storage.stageWork({ session, records: chunk });
|
|
968
|
+
}
|
|
969
|
+
}
|
|
970
|
+
async function drainStagedWork(context, storage, session, signal) {
|
|
971
|
+
let phase = null;
|
|
972
|
+
let pending = [];
|
|
973
|
+
const flush = async () => {
|
|
974
|
+
if (pending.length === 0)
|
|
975
|
+
return;
|
|
976
|
+
await applyItems(context, storage, session, pending, signal);
|
|
977
|
+
pending = [];
|
|
978
|
+
};
|
|
979
|
+
for await (const page of storage.streamWork({
|
|
980
|
+
session,
|
|
981
|
+
order: "apply",
|
|
982
|
+
pageRows: context.batching.planChunkRows
|
|
983
|
+
})) {
|
|
984
|
+
for (const record of page.records) {
|
|
985
|
+
if (record.kind !== "plan") {
|
|
986
|
+
throw new MaterializationValidationError("Provider returned non-plan apply work.");
|
|
987
|
+
}
|
|
988
|
+
if (phase !== null && record.applyPhase !== phase)
|
|
989
|
+
await flush();
|
|
990
|
+
phase = record.applyPhase;
|
|
991
|
+
pending.push(record.item);
|
|
992
|
+
if (pending.length >= context.batching.planChunkRows)
|
|
993
|
+
await flush();
|
|
994
|
+
}
|
|
995
|
+
}
|
|
996
|
+
await flush();
|
|
997
|
+
}
|
|
998
|
+
async function validateStagedCardinality(context, storage, session, signal) {
|
|
999
|
+
let currentScope = null;
|
|
1000
|
+
let occupant = null;
|
|
1001
|
+
for await (const page of storage.streamWork({
|
|
1002
|
+
session,
|
|
1003
|
+
order: "cardinality",
|
|
1004
|
+
pageRows: context.batching.statePageRows
|
|
1005
|
+
})) {
|
|
1006
|
+
throwIfAborted(signal);
|
|
1007
|
+
for (const record of page.records) {
|
|
1008
|
+
if (record.kind !== "cardinality") {
|
|
1009
|
+
throw new MaterializationValidationError("Provider returned non-cardinality cardinality work.");
|
|
1010
|
+
}
|
|
1011
|
+
if (record.scopeSortKey !== currentScope) {
|
|
1012
|
+
currentScope = record.scopeSortKey;
|
|
1013
|
+
occupant = null;
|
|
1014
|
+
}
|
|
1015
|
+
if (!record.occupied)
|
|
1016
|
+
continue;
|
|
1017
|
+
if (occupant && occupant !== record.linkSortKey) {
|
|
1018
|
+
throw new MaterializationValidationError(`Link scope '${record.ref.source.objectTypeId}.${record.ref.linkId}' has cardinality one.`);
|
|
1019
|
+
}
|
|
1020
|
+
occupant = record.linkSortKey;
|
|
1021
|
+
}
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
async function drainStagedEvents(context, storage, session, identity, signal) {
|
|
1025
|
+
let ordinal = 0;
|
|
1026
|
+
for await (const page of storage.streamWork({
|
|
1027
|
+
session,
|
|
1028
|
+
order: "event",
|
|
1029
|
+
pageRows: context.batching.planChunkRows
|
|
1030
|
+
})) {
|
|
1031
|
+
const items = [];
|
|
1032
|
+
for (const record of page.records) {
|
|
1033
|
+
if (record.kind !== "event") {
|
|
1034
|
+
throw new MaterializationValidationError("Provider returned non-event event work.");
|
|
1035
|
+
}
|
|
1036
|
+
const event = sequenceMaterializationEvent(context.projectId, identity.commitId, ordinal++, record.draft);
|
|
1037
|
+
items.push(outboxItem(event, identity.committedAt));
|
|
1038
|
+
}
|
|
1039
|
+
await applyItems(context, storage, session, items, signal);
|
|
1040
|
+
}
|
|
1041
|
+
return ordinal;
|
|
1042
|
+
}
|
|
1043
|
+
|
|
1044
|
+
// src/materializer/shared/normalize.ts
|
|
1045
|
+
function normalizeJsonProperties(properties, label = "Properties") {
|
|
1046
|
+
if (typeof properties !== "object" || properties === null || Array.isArray(properties)) {
|
|
1047
|
+
throw new MaterializationValidationError(`${label} must be a JSON object.`);
|
|
1048
|
+
}
|
|
1049
|
+
const normalized = {};
|
|
1050
|
+
for (const propertyId of Object.keys(properties).sort(compareStrings)) {
|
|
1051
|
+
if (propertyId.trim().length === 0) {
|
|
1052
|
+
throw new MaterializationValidationError(`${label} contains a blank property id.`);
|
|
1053
|
+
}
|
|
1054
|
+
const value = properties[propertyId];
|
|
1055
|
+
try {
|
|
1056
|
+
assertJsonValue(value, `${label}.${propertyId}`);
|
|
1057
|
+
} catch (error) {
|
|
1058
|
+
throw new MaterializationValidationError(error instanceof Error ? error.message : `${label}.${propertyId} must be JSON.`);
|
|
1059
|
+
}
|
|
1060
|
+
normalized[propertyId] = cloneJsonValue(value);
|
|
1061
|
+
}
|
|
1062
|
+
return Object.freeze(normalized);
|
|
1063
|
+
}
|
|
1064
|
+
function normalizeNonblank(value, label) {
|
|
1065
|
+
if (typeof value !== "string" || value.trim().length === 0) {
|
|
1066
|
+
throw new MaterializationValidationError(`${label} must be a nonblank string.`);
|
|
1067
|
+
}
|
|
1068
|
+
return value;
|
|
1069
|
+
}
|
|
1070
|
+
function normalizeEventActor(actor) {
|
|
1071
|
+
if (typeof actor !== "object" || actor === null || Array.isArray(actor)) {
|
|
1072
|
+
throw new MaterializationValidationError("Event actor must be an object.");
|
|
1073
|
+
}
|
|
1074
|
+
if (actor.type !== "user" && actor.type !== "serviceAccount" && actor.type !== "system") {
|
|
1075
|
+
throw new MaterializationValidationError("Event actor type must be 'user', 'serviceAccount', or 'system'.");
|
|
1076
|
+
}
|
|
1077
|
+
return Object.freeze({
|
|
1078
|
+
type: actor.type,
|
|
1079
|
+
id: normalizeNonblank(actor.id, "Event actor id")
|
|
1080
|
+
});
|
|
1081
|
+
}
|
|
1082
|
+
function normalizeTimestamp(value, label) {
|
|
1083
|
+
const milliseconds = Date.parse(value);
|
|
1084
|
+
if (!Number.isFinite(milliseconds)) {
|
|
1085
|
+
throw new MaterializationValidationError(`${label} must be a valid timestamp.`);
|
|
1086
|
+
}
|
|
1087
|
+
return new Date(milliseconds).toISOString();
|
|
1088
|
+
}
|
|
1089
|
+
function normalizePropertyIds(values, label) {
|
|
1090
|
+
const seen = new Set;
|
|
1091
|
+
const normalized = [];
|
|
1092
|
+
for (const value of values) {
|
|
1093
|
+
normalizeNonblank(value, label);
|
|
1094
|
+
if (seen.has(value)) {
|
|
1095
|
+
throw new MaterializationValidationError(`${label} contains duplicate '${value}'.`);
|
|
1096
|
+
}
|
|
1097
|
+
seen.add(value);
|
|
1098
|
+
normalized.push(value);
|
|
1099
|
+
}
|
|
1100
|
+
return Object.freeze(normalized.sort(compareStrings));
|
|
1101
|
+
}
|
|
1102
|
+
function normalizeOperation(operation) {
|
|
1103
|
+
normalizeNonblank(operation.id, "Operation id");
|
|
1104
|
+
if (operation.kind === "object.create" || operation.kind === "object.upsert") {
|
|
1105
|
+
return Object.freeze({
|
|
1106
|
+
id: operation.id,
|
|
1107
|
+
kind: operation.kind,
|
|
1108
|
+
ref: normalizeObjectRef(operation.ref),
|
|
1109
|
+
properties: normalizeJsonProperties(operation.properties)
|
|
1110
|
+
});
|
|
1111
|
+
}
|
|
1112
|
+
if (operation.kind === "object.patch") {
|
|
1113
|
+
const set = normalizeJsonProperties(operation.set, `Operation '${operation.id}' set`);
|
|
1114
|
+
const unset = normalizePropertyIds(operation.unset, `Operation '${operation.id}' unset`);
|
|
1115
|
+
const reset = normalizePropertyIds(operation.reset, `Operation '${operation.id}' reset`);
|
|
1116
|
+
const setIds = new Set(Object.keys(set));
|
|
1117
|
+
for (const propertyId of [...unset, ...reset]) {
|
|
1118
|
+
if (setIds.has(propertyId)) {
|
|
1119
|
+
throw new MaterializationValidationError(`Operation '${operation.id}' property '${propertyId}' appears in set and unset/reset.`);
|
|
1120
|
+
}
|
|
1121
|
+
}
|
|
1122
|
+
for (const propertyId of unset) {
|
|
1123
|
+
if (reset.includes(propertyId)) {
|
|
1124
|
+
throw new MaterializationValidationError(`Operation '${operation.id}' property '${propertyId}' appears in unset and reset.`);
|
|
1125
|
+
}
|
|
1126
|
+
}
|
|
1127
|
+
return Object.freeze({
|
|
1128
|
+
id: operation.id,
|
|
1129
|
+
kind: operation.kind,
|
|
1130
|
+
ref: normalizeObjectRef(operation.ref),
|
|
1131
|
+
set,
|
|
1132
|
+
unset,
|
|
1133
|
+
reset
|
|
1134
|
+
});
|
|
1135
|
+
}
|
|
1136
|
+
if (operation.kind === "object.delete" || operation.kind === "object.restore") {
|
|
1137
|
+
return Object.freeze({
|
|
1138
|
+
id: operation.id,
|
|
1139
|
+
kind: operation.kind,
|
|
1140
|
+
ref: normalizeObjectRef(operation.ref)
|
|
1141
|
+
});
|
|
1142
|
+
}
|
|
1143
|
+
if (operation.kind === "link.upsert") {
|
|
1144
|
+
return Object.freeze({
|
|
1145
|
+
id: operation.id,
|
|
1146
|
+
kind: operation.kind,
|
|
1147
|
+
ref: normalizeLinkRef(operation.ref),
|
|
1148
|
+
...operation.properties !== undefined ? { properties: normalizeJsonProperties(operation.properties) } : {}
|
|
1149
|
+
});
|
|
1150
|
+
}
|
|
1151
|
+
if (operation.kind === "link.delete" || operation.kind === "link.reset") {
|
|
1152
|
+
return Object.freeze({
|
|
1153
|
+
id: operation.id,
|
|
1154
|
+
kind: operation.kind,
|
|
1155
|
+
ref: normalizeLinkRef(operation.ref)
|
|
1156
|
+
});
|
|
1157
|
+
}
|
|
1158
|
+
throw new MaterializationValidationError("Unknown ontology edit operation kind.");
|
|
1159
|
+
}
|
|
1160
|
+
function deduplicateExpectations(values, keyOf, label) {
|
|
1161
|
+
const byKey = new Map;
|
|
1162
|
+
for (const value of values) {
|
|
1163
|
+
const key = keyOf(value);
|
|
1164
|
+
const existing = byKey.get(key);
|
|
1165
|
+
if (existing && stableJsonStringify(existing) !== stableJsonStringify(value)) {
|
|
1166
|
+
throw new MaterializationValidationError(`${label} has contradictory values for ${key}.`);
|
|
1167
|
+
}
|
|
1168
|
+
byKey.set(key, value);
|
|
1169
|
+
}
|
|
1170
|
+
return Object.freeze([...byKey.entries()].sort(([left], [right]) => compareStrings(left, right)).map(([, value]) => value));
|
|
1171
|
+
}
|
|
1172
|
+
function normalizeExpectedObject(value) {
|
|
1173
|
+
const ref = normalizeObjectRef(value.ref);
|
|
1174
|
+
if (!value.exists)
|
|
1175
|
+
return Object.freeze({ ref, exists: false });
|
|
1176
|
+
if (!Number.isSafeInteger(value.version) || value.version < 1) {
|
|
1177
|
+
throw new MaterializationValidationError("Expected object version must be a positive integer.");
|
|
1178
|
+
}
|
|
1179
|
+
return Object.freeze({
|
|
1180
|
+
ref,
|
|
1181
|
+
exists: true,
|
|
1182
|
+
version: value.version,
|
|
1183
|
+
lastCommitId: normalizeNonblank(value.lastCommitId, "Expected object lastCommitId")
|
|
1184
|
+
});
|
|
1185
|
+
}
|
|
1186
|
+
function normalizeExpectedLink(value) {
|
|
1187
|
+
const ref = normalizeLinkRef(value.ref);
|
|
1188
|
+
if (!value.exists)
|
|
1189
|
+
return Object.freeze({ ref, exists: false });
|
|
1190
|
+
return Object.freeze({
|
|
1191
|
+
ref,
|
|
1192
|
+
exists: true,
|
|
1193
|
+
lastCommitId: normalizeNonblank(value.lastCommitId, "Expected link lastCommitId")
|
|
1194
|
+
});
|
|
1195
|
+
}
|
|
1196
|
+
function normalizeExpectedLinkScope(value) {
|
|
1197
|
+
return Object.freeze({
|
|
1198
|
+
source: normalizeObjectRef(value.source),
|
|
1199
|
+
linkId: normalizeNonblank(value.linkId, "Expected link scope link id"),
|
|
1200
|
+
fingerprint: normalizeNonblank(value.fingerprint, "Expected link scope fingerprint")
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1203
|
+
function normalizeOperationGroups(groups, operationIds) {
|
|
1204
|
+
const grouped = new Set;
|
|
1205
|
+
const normalized = groups.map((group) => {
|
|
1206
|
+
if (group.length < 2) {
|
|
1207
|
+
throw new MaterializationValidationError("Operation groups must contain at least two operations.");
|
|
1208
|
+
}
|
|
1209
|
+
const positions = group.map((id) => {
|
|
1210
|
+
const position = operationIds.get(id);
|
|
1211
|
+
if (position === undefined) {
|
|
1212
|
+
throw new MaterializationValidationError(`Operation group references unknown operation id '${id}'.`);
|
|
1213
|
+
}
|
|
1214
|
+
if (grouped.has(id)) {
|
|
1215
|
+
throw new MaterializationValidationError(`Operation id '${id}' appears in more than one operation group.`);
|
|
1216
|
+
}
|
|
1217
|
+
grouped.add(id);
|
|
1218
|
+
return position;
|
|
1219
|
+
});
|
|
1220
|
+
const first = positions[0];
|
|
1221
|
+
if (positions.some((position, index) => position !== first + index)) {
|
|
1222
|
+
throw new MaterializationValidationError("Operation groups must list a contiguous run in operation order.");
|
|
1223
|
+
}
|
|
1224
|
+
return { first, ids: Object.freeze([...group]) };
|
|
1225
|
+
});
|
|
1226
|
+
normalized.sort((left, right) => left.first - right.first);
|
|
1227
|
+
return Object.freeze(normalized.map(({ ids }) => ids));
|
|
1228
|
+
}
|
|
1229
|
+
function normalizeOntologyEditCommit(input) {
|
|
1230
|
+
const operationIds = new Map;
|
|
1231
|
+
const operations = input.operations.map((operation, index) => {
|
|
1232
|
+
const normalized = normalizeOperation(operation);
|
|
1233
|
+
if (operationIds.has(normalized.id)) {
|
|
1234
|
+
throw new MaterializationValidationError(`Duplicate operation id '${normalized.id}'.`);
|
|
1235
|
+
}
|
|
1236
|
+
operationIds.set(normalized.id, index);
|
|
1237
|
+
return normalized;
|
|
1238
|
+
});
|
|
1239
|
+
if (input.mode === "continue") {
|
|
1240
|
+
return Object.freeze({
|
|
1241
|
+
mode: "continue",
|
|
1242
|
+
source: Object.freeze({
|
|
1243
|
+
kind: "runtime",
|
|
1244
|
+
requestId: normalizeNonblank(input.source.requestId, "Runtime request id")
|
|
1245
|
+
}),
|
|
1246
|
+
...input.actor !== undefined ? { actor: normalizeEventActor(input.actor) } : {},
|
|
1247
|
+
operations: Object.freeze(operations),
|
|
1248
|
+
...input.operationGroups !== undefined ? { operationGroups: normalizeOperationGroups(input.operationGroups, operationIds) } : {}
|
|
1249
|
+
});
|
|
1250
|
+
}
|
|
1251
|
+
const source = input.source.kind === "action" ? Object.freeze({
|
|
1252
|
+
kind: "action",
|
|
1253
|
+
actionId: normalizeNonblank(input.source.actionId, "Action id"),
|
|
1254
|
+
runId: normalizeNonblank(input.source.runId, "Action run id")
|
|
1255
|
+
}) : Object.freeze({
|
|
1256
|
+
kind: "runtime",
|
|
1257
|
+
requestId: normalizeNonblank(input.source.requestId, "Runtime request id")
|
|
1258
|
+
});
|
|
1259
|
+
const expectedObjects = input.expectedObjects.map(normalizeExpectedObject);
|
|
1260
|
+
const expectedLinks = input.expectedLinks.map(normalizeExpectedLink);
|
|
1261
|
+
const expectedLinkScopes = input.expectedLinkScopes.map(normalizeExpectedLinkScope);
|
|
1262
|
+
return Object.freeze({
|
|
1263
|
+
mode: "atomic",
|
|
1264
|
+
source,
|
|
1265
|
+
...input.actor !== undefined ? { actor: normalizeEventActor(input.actor) } : {},
|
|
1266
|
+
operations: Object.freeze(operations),
|
|
1267
|
+
expectedObjects: deduplicateExpectations(expectedObjects, (value) => objectRefKey(value.ref), "Expected objects"),
|
|
1268
|
+
expectedLinks: deduplicateExpectations(expectedLinks, (value) => linkRefKey(value.ref), "Expected links"),
|
|
1269
|
+
expectedLinkScopes: deduplicateExpectations(expectedLinkScopes, (value) => linkScopeKey(value.source, value.linkId), "Expected link scopes")
|
|
1270
|
+
});
|
|
1271
|
+
}
|
|
1272
|
+
function normalizeProjectionSourceRef(source) {
|
|
1273
|
+
return Object.freeze({
|
|
1274
|
+
projectionId: normalizeNonblank(source.projectionId, "Projection id")
|
|
1275
|
+
});
|
|
1276
|
+
}
|
|
1277
|
+
function normalizePinnedDatasetVersion(version) {
|
|
1278
|
+
return Object.freeze({
|
|
1279
|
+
datasetId: normalizeNonblank(version.datasetId, "Dataset id"),
|
|
1280
|
+
versionId: normalizeNonblank(version.versionId, "Dataset version id"),
|
|
1281
|
+
createdAt: normalizeTimestamp(version.createdAt, "Dataset version createdAt")
|
|
1282
|
+
});
|
|
1283
|
+
}
|
|
1284
|
+
function normalizeProjectionRunId(runId) {
|
|
1285
|
+
return normalizeNonblank(runId, "Projection run id");
|
|
1286
|
+
}
|
|
1287
|
+
function normalizeProjectionExecution(input) {
|
|
1288
|
+
return Object.freeze({
|
|
1289
|
+
projectionRunId: normalizeProjectionRunId(input.projectionRunId),
|
|
1290
|
+
executionToken: normalizeNonblank(input.executionToken, "Projection execution token")
|
|
1291
|
+
});
|
|
1292
|
+
}
|
|
1293
|
+
function normalizeProjectionEntity(entity) {
|
|
1294
|
+
return entity.kind === "object" ? Object.freeze({ kind: "object", ref: normalizeObjectRef(entity.ref) }) : Object.freeze({ kind: "link", ref: normalizeLinkRef(entity.ref) });
|
|
1295
|
+
}
|
|
1296
|
+
function normalizeProjectionAssertion(assertion) {
|
|
1297
|
+
return assertion.kind === "object" ? Object.freeze({
|
|
1298
|
+
kind: "object",
|
|
1299
|
+
ref: normalizeObjectRef(assertion.ref),
|
|
1300
|
+
properties: normalizeJsonProperties(assertion.properties)
|
|
1301
|
+
}) : Object.freeze({
|
|
1302
|
+
kind: "link",
|
|
1303
|
+
ref: normalizeLinkRef(assertion.ref),
|
|
1304
|
+
...assertion.properties !== undefined ? { properties: normalizeJsonProperties(assertion.properties) } : {}
|
|
1305
|
+
});
|
|
1306
|
+
}
|
|
1307
|
+
function normalizeProjectionSourceEntry(input) {
|
|
1308
|
+
const root = normalizeProjectionEntity(input.root);
|
|
1309
|
+
const seen = new Set;
|
|
1310
|
+
const assertions = input.assertions.map((assertion) => {
|
|
1311
|
+
const normalized = normalizeProjectionAssertion(assertion);
|
|
1312
|
+
const key = projectionEntityKey(normalized);
|
|
1313
|
+
if (seen.has(key)) {
|
|
1314
|
+
throw new MaterializationValidationError(`Projection entry repeats asserted entity ${key}.`);
|
|
1315
|
+
}
|
|
1316
|
+
seen.add(key);
|
|
1317
|
+
return normalized;
|
|
1318
|
+
});
|
|
1319
|
+
const rootKey = projectionEntityKey(root);
|
|
1320
|
+
if (!seen.has(rootKey)) {
|
|
1321
|
+
throw new MaterializationValidationError(`Projection entry must contain an assertion matching root ${rootKey}.`);
|
|
1322
|
+
}
|
|
1323
|
+
if (root.kind === "object") {
|
|
1324
|
+
const objectAssertions = assertions.filter((assertion) => assertion.kind === "object");
|
|
1325
|
+
if (objectAssertions.length !== 1 || projectionEntityKey(objectAssertions[0]) !== rootKey) {
|
|
1326
|
+
throw new MaterializationValidationError("An object projection root must contain exactly its matching object assertion plus links.");
|
|
1327
|
+
}
|
|
1328
|
+
for (const assertion of assertions) {
|
|
1329
|
+
if (assertion.kind === "link" && objectRefKey(assertion.ref.source) !== objectRefKey(root.ref)) {
|
|
1330
|
+
throw new MaterializationValidationError("An object projection root may contain only links sourced from that root.");
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
} else if (assertions.length !== 1 || assertions[0].kind !== "link" || projectionEntityKey(assertions[0]) !== rootKey) {
|
|
1334
|
+
throw new MaterializationValidationError("A link projection root must contain exactly its matching link assertion.");
|
|
1335
|
+
}
|
|
1336
|
+
return Object.freeze({
|
|
1337
|
+
root,
|
|
1338
|
+
assertions: Object.freeze(assertions.sort((left, right) => compareStrings(projectionEntityKey(left), projectionEntityKey(right))))
|
|
1339
|
+
});
|
|
1340
|
+
}
|
|
1341
|
+
function normalizeTelemetrySeries(series) {
|
|
1342
|
+
return Object.freeze({
|
|
1343
|
+
object: normalizeObjectRef(series.object),
|
|
1344
|
+
propertyId: normalizeNonblank(series.propertyId, "Telemetry property id")
|
|
1345
|
+
});
|
|
1346
|
+
}
|
|
1347
|
+
function normalizeTelemetryPoint(point) {
|
|
1348
|
+
try {
|
|
1349
|
+
assertJsonValue(point.value, "Telemetry point value");
|
|
1350
|
+
} catch (error) {
|
|
1351
|
+
throw new MaterializationValidationError(error instanceof Error ? error.message : "Telemetry point value must be JSON.");
|
|
1352
|
+
}
|
|
1353
|
+
return Object.freeze({
|
|
1354
|
+
series: normalizeTelemetrySeries(point.series),
|
|
1355
|
+
value: cloneJsonValue(point.value),
|
|
1356
|
+
...point.unit !== undefined ? { unit: normalizeNonblank(point.unit, "Telemetry point unit") } : {},
|
|
1357
|
+
at: normalizeTimestamp(point.at, "Telemetry point timestamp")
|
|
1358
|
+
});
|
|
1359
|
+
}
|
|
1360
|
+
function normalizeTelemetryAppend(input) {
|
|
1361
|
+
const pointsByKey = new Map;
|
|
1362
|
+
for (const point of input.points) {
|
|
1363
|
+
const normalized = normalizeTelemetryPoint(point);
|
|
1364
|
+
const key = telemetryPointKey(normalized.series, normalized.at);
|
|
1365
|
+
const existing = pointsByKey.get(key);
|
|
1366
|
+
if (input.source.kind === "runtime" && existing && stableJsonStringify(existing) !== stableJsonStringify(normalized)) {
|
|
1367
|
+
throw new MaterializationValidationError(`Conflicting telemetry points for ${key}.`);
|
|
1368
|
+
}
|
|
1369
|
+
pointsByKey.set(key, normalized);
|
|
1370
|
+
}
|
|
1371
|
+
const points = [...pointsByKey.entries()].sort(([left], [right]) => compareStrings(left, right)).map(([, point]) => point);
|
|
1372
|
+
const source = input.source.kind === "runtime" ? Object.freeze({
|
|
1373
|
+
kind: "runtime",
|
|
1374
|
+
requestId: normalizeNonblank(input.source.requestId, "Runtime request id")
|
|
1375
|
+
}) : Object.freeze({
|
|
1376
|
+
kind: "projection",
|
|
1377
|
+
projection: normalizeProjectionSourceRef(input.source.projection),
|
|
1378
|
+
datasetVersion: normalizePinnedDatasetVersion(input.source.datasetVersion),
|
|
1379
|
+
execution: normalizeProjectionExecution(input.source.execution),
|
|
1380
|
+
batchOrdinal: input.source.batchOrdinal,
|
|
1381
|
+
sourceRowCount: input.source.sourceRowCount,
|
|
1382
|
+
sourceRowsSkipped: input.source.sourceRowsSkipped,
|
|
1383
|
+
inputExhausted: input.source.inputExhausted
|
|
1384
|
+
});
|
|
1385
|
+
if (source.kind === "projection") {
|
|
1386
|
+
if (!Number.isSafeInteger(source.batchOrdinal) || source.batchOrdinal < 0) {
|
|
1387
|
+
throw new MaterializationValidationError("Telemetry projection batch ordinal must be a nonnegative safe integer.");
|
|
1388
|
+
}
|
|
1389
|
+
if (!Number.isSafeInteger(source.sourceRowCount) || source.sourceRowCount < 0) {
|
|
1390
|
+
throw new MaterializationValidationError("Telemetry projection sourceRowCount must be a nonnegative safe integer.");
|
|
1391
|
+
}
|
|
1392
|
+
if (!Number.isSafeInteger(source.sourceRowsSkipped) || source.sourceRowsSkipped < 0) {
|
|
1393
|
+
throw new MaterializationValidationError("Telemetry projection sourceRowsSkipped must be a nonnegative safe integer.");
|
|
1394
|
+
}
|
|
1395
|
+
if (source.sourceRowsSkipped > source.sourceRowCount) {
|
|
1396
|
+
throw new MaterializationValidationError("Telemetry projection sourceRowsSkipped cannot exceed sourceRowCount.");
|
|
1397
|
+
}
|
|
1398
|
+
if (typeof source.inputExhausted !== "boolean") {
|
|
1399
|
+
throw new MaterializationValidationError("Telemetry projection inputExhausted must be a boolean.");
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
return Object.freeze({
|
|
1403
|
+
source,
|
|
1404
|
+
...input.actor !== undefined ? { actor: normalizeEventActor(input.actor) } : {},
|
|
1405
|
+
points: Object.freeze(points)
|
|
1406
|
+
});
|
|
1407
|
+
}
|
|
1408
|
+
|
|
1409
|
+
// src/materializer/edits/execution-units.ts
|
|
1410
|
+
function compileEditExecutionUnits(input) {
|
|
1411
|
+
const groupByFirstId = new Map((input.operationGroups ?? []).map((ids) => [ids[0], new Set(ids)]));
|
|
1412
|
+
const units = [];
|
|
1413
|
+
for (let index = 0;index < input.operations.length; ) {
|
|
1414
|
+
const operation = input.operations[index];
|
|
1415
|
+
const groupIds = groupByFirstId.get(operation.id);
|
|
1416
|
+
if (!groupIds) {
|
|
1417
|
+
units.push({ kind: "single", operation });
|
|
1418
|
+
index += 1;
|
|
1419
|
+
continue;
|
|
1420
|
+
}
|
|
1421
|
+
const operations = input.operations.slice(index, index + groupIds.size);
|
|
1422
|
+
units.push({ kind: "atomic-group", operations });
|
|
1423
|
+
index += operations.length;
|
|
1424
|
+
}
|
|
1425
|
+
return units;
|
|
1426
|
+
}
|
|
1427
|
+
|
|
1428
|
+
// src/materializer/effective/load-state.ts
|
|
1429
|
+
async function* oneStateRequest(request) {
|
|
1430
|
+
yield request;
|
|
1431
|
+
}
|
|
1432
|
+
async function loadState(context, storage, session, request) {
|
|
1433
|
+
const result = { objects: [], links: [], linkScopes: [], points: [] };
|
|
1434
|
+
for await (const page of storage.streamState({
|
|
1435
|
+
session,
|
|
1436
|
+
requests: oneStateRequest(request),
|
|
1437
|
+
pageRows: context.batching.statePageRows
|
|
1438
|
+
})) {
|
|
1439
|
+
result.objects.push(...page.objects);
|
|
1440
|
+
result.links.push(...page.links);
|
|
1441
|
+
result.linkScopes.push(...page.linkScopes);
|
|
1442
|
+
result.points.push(...page.points);
|
|
1443
|
+
}
|
|
1444
|
+
return result;
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
// src/materializer/edits/read-set.ts
|
|
1448
|
+
function buildEditReadSet(ontology, operations) {
|
|
1449
|
+
const objects = new Map;
|
|
1450
|
+
const links = new Map;
|
|
1451
|
+
const scopes = new Map;
|
|
1452
|
+
const incidentObjects = new Map;
|
|
1453
|
+
for (const operation of operations) {
|
|
1454
|
+
if (isObjectOperation(operation)) {
|
|
1455
|
+
if (!ontology.getObjectTypeById(operation.ref.objectTypeId))
|
|
1456
|
+
continue;
|
|
1457
|
+
objects.set(objectRefKey(operation.ref), operation.ref);
|
|
1458
|
+
if (operation.kind !== "object.patch") {
|
|
1459
|
+
incidentObjects.set(objectRefKey(operation.ref), operation.ref);
|
|
1460
|
+
}
|
|
1461
|
+
continue;
|
|
1462
|
+
}
|
|
1463
|
+
if (!isKnownLinkRef(ontology, operation.ref))
|
|
1464
|
+
continue;
|
|
1465
|
+
links.set(linkRefKey(operation.ref), operation.ref);
|
|
1466
|
+
objects.set(objectRefKey(operation.ref.source), operation.ref.source);
|
|
1467
|
+
objects.set(objectRefKey(operation.ref.target), operation.ref.target);
|
|
1468
|
+
if (linkCardinality(ontology, operation.ref) === "one") {
|
|
1469
|
+
const scope = { source: operation.ref.source, linkId: operation.ref.linkId };
|
|
1470
|
+
scopes.set(linkScopeKey(scope.source, scope.linkId), scope);
|
|
1471
|
+
}
|
|
1472
|
+
}
|
|
1473
|
+
return {
|
|
1474
|
+
objects: [...objects.values()].sort(compareObjectRefs),
|
|
1475
|
+
links: [...links.values()].sort(compareLinkRefs),
|
|
1476
|
+
linkScopes: [...scopes.values()].sort((left, right) => linkScopeKey(left.source, left.linkId).localeCompare(linkScopeKey(right.source, right.linkId))),
|
|
1477
|
+
incidentObjects: [...incidentObjects.values()].sort(compareObjectRefs),
|
|
1478
|
+
points: []
|
|
1479
|
+
};
|
|
1480
|
+
}
|
|
1481
|
+
function isKnownLinkRef(ontology, ref) {
|
|
1482
|
+
const sourceType = ontology.getObjectTypeById(ref.source.objectTypeId);
|
|
1483
|
+
if (!sourceType || !ontology.getObjectTypeById(ref.target.objectTypeId))
|
|
1484
|
+
return false;
|
|
1485
|
+
const link = sourceType.links.find((candidate) => candidate.id === ref.linkId);
|
|
1486
|
+
return Boolean(link && ontology.isValidLinkTarget(link.targetObjectTypeId, ref.target.objectTypeId));
|
|
1487
|
+
}
|
|
1488
|
+
function linkCardinality(ontology, ref) {
|
|
1489
|
+
const definition = ontology.getObjectTypeById(ref.source.objectTypeId)?.links.find((candidate) => candidate.id === ref.linkId);
|
|
1490
|
+
return definition?.cardinality ?? "many";
|
|
1491
|
+
}
|
|
1492
|
+
function isObjectOperation(operation) {
|
|
1493
|
+
return operation.kind.startsWith("object.");
|
|
1494
|
+
}
|
|
1495
|
+
|
|
1496
|
+
// src/materializer/effective/resolve.ts
|
|
1497
|
+
function resolveEffectiveObject(input) {
|
|
1498
|
+
const properties = resolveObjectAuthority(input.source, input.override);
|
|
1499
|
+
if (!properties)
|
|
1500
|
+
return null;
|
|
1501
|
+
properties[input.primaryPropertyId] = input.ref.primaryId;
|
|
1502
|
+
applyLatestTelemetry(properties, input.latestTelemetry);
|
|
1503
|
+
return { ref: input.ref, properties };
|
|
1504
|
+
}
|
|
1505
|
+
function resolveObjectAuthority(source, override) {
|
|
1506
|
+
switch (override?.kind) {
|
|
1507
|
+
case "delete":
|
|
1508
|
+
return null;
|
|
1509
|
+
case "create":
|
|
1510
|
+
return { ...override.properties };
|
|
1511
|
+
case "patch":
|
|
1512
|
+
if (!source)
|
|
1513
|
+
return null;
|
|
1514
|
+
return applyObjectPatch(source.assertion.properties, override);
|
|
1515
|
+
default:
|
|
1516
|
+
if (!source)
|
|
1517
|
+
return null;
|
|
1518
|
+
return { ...source.assertion.properties };
|
|
1519
|
+
}
|
|
1520
|
+
}
|
|
1521
|
+
function applyObjectPatch(sourceProperties, override) {
|
|
1522
|
+
const properties = { ...sourceProperties, ...override.set };
|
|
1523
|
+
for (const propertyId of override.unset)
|
|
1524
|
+
delete properties[propertyId];
|
|
1525
|
+
return properties;
|
|
1526
|
+
}
|
|
1527
|
+
function applyLatestTelemetry(properties, latestTelemetry) {
|
|
1528
|
+
for (const point of latestTelemetry)
|
|
1529
|
+
properties[point.series.propertyId] = point.value;
|
|
1530
|
+
}
|
|
1531
|
+
function resolveEffectiveLink(input) {
|
|
1532
|
+
if (!input.sourceEndpointExists || !input.targetEndpointExists)
|
|
1533
|
+
return null;
|
|
1534
|
+
if (input.override?.kind === "delete")
|
|
1535
|
+
return null;
|
|
1536
|
+
if (input.override?.kind === "upsert") {
|
|
1537
|
+
return resolvedLink(input.ref, input.override.properties);
|
|
1538
|
+
}
|
|
1539
|
+
if (!input.source)
|
|
1540
|
+
return null;
|
|
1541
|
+
return resolvedLink(input.ref, input.source.assertion.properties);
|
|
1542
|
+
}
|
|
1543
|
+
function resolvedLink(ref, properties) {
|
|
1544
|
+
if (properties === undefined)
|
|
1545
|
+
return { ref };
|
|
1546
|
+
return { ref, properties };
|
|
1547
|
+
}
|
|
1548
|
+
|
|
1549
|
+
// src/materializer/edits/working-state.ts
|
|
1550
|
+
function mergeWorkingState(objects, links, scopes, state) {
|
|
1551
|
+
for (const object of state.objects) {
|
|
1552
|
+
if (!objects.has(objectRefKey(object.ref))) {
|
|
1553
|
+
objects.set(objectRefKey(object.ref), workingObjectFromState(object));
|
|
1554
|
+
}
|
|
1555
|
+
}
|
|
1556
|
+
for (const link of state.links) {
|
|
1557
|
+
if (!links.has(linkRefKey(link.ref))) {
|
|
1558
|
+
links.set(linkRefKey(link.ref), workingLinkFromState(link));
|
|
1559
|
+
}
|
|
1560
|
+
}
|
|
1561
|
+
for (const scope of state.linkScopes) {
|
|
1562
|
+
if (!scopes.has(linkScopeKey(scope.source, scope.linkId))) {
|
|
1563
|
+
scopes.set(linkScopeKey(scope.source, scope.linkId), scope);
|
|
1564
|
+
}
|
|
1565
|
+
}
|
|
1566
|
+
}
|
|
1567
|
+
function workingObjectFromState(object) {
|
|
1568
|
+
return {
|
|
1569
|
+
ref: object.ref,
|
|
1570
|
+
source: object.source,
|
|
1571
|
+
originalOverride: object.override,
|
|
1572
|
+
override: object.override?.value ?? null,
|
|
1573
|
+
before: object.effective,
|
|
1574
|
+
latestTelemetry: [...object.latestTelemetry]
|
|
1575
|
+
};
|
|
1576
|
+
}
|
|
1577
|
+
function workingLinkFromState(link) {
|
|
1578
|
+
return {
|
|
1579
|
+
ref: link.ref,
|
|
1580
|
+
source: link.source,
|
|
1581
|
+
originalOverride: link.override,
|
|
1582
|
+
override: link.override?.value ?? null,
|
|
1583
|
+
before: link.effective
|
|
1584
|
+
};
|
|
1585
|
+
}
|
|
1586
|
+
function resolveObject(ontology, working) {
|
|
1587
|
+
return resolveEffectiveObject({
|
|
1588
|
+
ref: working.ref,
|
|
1589
|
+
primaryPropertyId: ontology.getPrimaryPropertyId(working.ref.objectTypeId),
|
|
1590
|
+
source: working.source,
|
|
1591
|
+
override: working.override,
|
|
1592
|
+
latestTelemetry: working.latestTelemetry
|
|
1593
|
+
});
|
|
1594
|
+
}
|
|
1595
|
+
function resolveLink(ontology, working, objects) {
|
|
1596
|
+
const source = objects.get(objectRefKey(working.ref.source));
|
|
1597
|
+
const target = objects.get(objectRefKey(working.ref.target));
|
|
1598
|
+
return resolveEffectiveLink({
|
|
1599
|
+
ref: working.ref,
|
|
1600
|
+
source: working.source,
|
|
1601
|
+
override: working.override,
|
|
1602
|
+
sourceEndpointExists: Boolean(source && resolveObject(ontology, source)),
|
|
1603
|
+
targetEndpointExists: Boolean(target && resolveObject(ontology, target))
|
|
1604
|
+
});
|
|
1605
|
+
}
|
|
1606
|
+
function distinctCardinalityOneScopes(ontology, links, existing) {
|
|
1607
|
+
const scopes = new Map;
|
|
1608
|
+
for (const state of links) {
|
|
1609
|
+
const definition = ontology.resolveObjectType(state.ref.source.objectTypeId).links.find((candidate) => candidate.id === state.ref.linkId);
|
|
1610
|
+
const key = linkScopeKey(state.ref.source, state.ref.linkId);
|
|
1611
|
+
if (definition?.cardinality === "one" && !existing.has(key)) {
|
|
1612
|
+
scopes.set(key, { source: state.ref.source, linkId: state.ref.linkId });
|
|
1613
|
+
}
|
|
1614
|
+
}
|
|
1615
|
+
return [...scopes.values()];
|
|
1616
|
+
}
|
|
1617
|
+
function validateWorkingCardinality(ontology, objects, links, scopes) {
|
|
1618
|
+
const effectiveByScope = new Map;
|
|
1619
|
+
for (const [scope, snapshot] of scopes) {
|
|
1620
|
+
effectiveByScope.set(scope, {
|
|
1621
|
+
count: snapshot.effectiveCount,
|
|
1622
|
+
source: snapshot.source,
|
|
1623
|
+
linkId: snapshot.linkId
|
|
1624
|
+
});
|
|
1625
|
+
}
|
|
1626
|
+
for (const working of links.values()) {
|
|
1627
|
+
if (!isKnownLinkRef(ontology, working.ref))
|
|
1628
|
+
continue;
|
|
1629
|
+
const scope = linkScopeKey(working.ref.source, working.ref.linkId);
|
|
1630
|
+
const state = effectiveByScope.get(scope);
|
|
1631
|
+
if (!state)
|
|
1632
|
+
continue;
|
|
1633
|
+
const before = working.before ? 1 : 0;
|
|
1634
|
+
const after = resolveLink(ontology, working, objects) ? 1 : 0;
|
|
1635
|
+
state.count += after - before;
|
|
1636
|
+
}
|
|
1637
|
+
for (const { count, source, linkId } of effectiveByScope.values()) {
|
|
1638
|
+
if (count <= 1)
|
|
1639
|
+
continue;
|
|
1640
|
+
const link = ontology.resolveObjectType(source.objectTypeId).links.find((candidate) => candidate.id === linkId);
|
|
1641
|
+
if (link?.cardinality === "one") {
|
|
1642
|
+
throw new MaterializationValidationError(`Link scope '${source.objectTypeId}.${linkId}' has cardinality one.`);
|
|
1643
|
+
}
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
|
|
1647
|
+
// src/materializer/edits/load-state.ts
|
|
1648
|
+
async function loadEditWorkingState(context, storage, session, operations) {
|
|
1649
|
+
const state = {
|
|
1650
|
+
objects: new Map,
|
|
1651
|
+
links: new Map,
|
|
1652
|
+
scopeSnapshots: new Map
|
|
1653
|
+
};
|
|
1654
|
+
const readSet = buildEditReadSet(context.ontology, operations);
|
|
1655
|
+
const explicitLinkKeys = new Set(readSet.links.map(linkRefKey));
|
|
1656
|
+
const incidentLinks = new Map;
|
|
1657
|
+
const ignoredLinks = new Map;
|
|
1658
|
+
const revivingObjects = new Set(operations.filter(isRevivingObjectOperation).map((operation) => objectRefKey(operation.ref)));
|
|
1659
|
+
for await (const page of storage.streamState({
|
|
1660
|
+
session,
|
|
1661
|
+
requests: oneStateRequest(readSet),
|
|
1662
|
+
pageRows: context.batching.statePageRows
|
|
1663
|
+
})) {
|
|
1664
|
+
mergeWorkingState(state.objects, ignoredLinks, state.scopeSnapshots, page);
|
|
1665
|
+
for (const link of page.links) {
|
|
1666
|
+
const key = linkRefKey(link.ref);
|
|
1667
|
+
if (explicitLinkKeys.has(key) && !state.links.has(key)) {
|
|
1668
|
+
state.links.set(key, workingLinkFromState(link));
|
|
1669
|
+
}
|
|
1670
|
+
if (readSet.incidentObjects.length > 0)
|
|
1671
|
+
incidentLinks.set(key, link);
|
|
1672
|
+
}
|
|
1673
|
+
}
|
|
1674
|
+
await mergeIncidentState(context, storage, session, state, [...incidentLinks.values()], revivingObjects);
|
|
1675
|
+
return state;
|
|
1676
|
+
}
|
|
1677
|
+
function isRevivingObjectOperation(operation) {
|
|
1678
|
+
return operation.kind === "object.create" || operation.kind === "object.upsert" || operation.kind === "object.restore";
|
|
1679
|
+
}
|
|
1680
|
+
async function mergeIncidentState(context, storage, session, state, incidentStates, revivingObjects) {
|
|
1681
|
+
const knownIncidentStates = incidentStates.filter((link) => isKnownLinkRef(context.ontology, link.ref));
|
|
1682
|
+
const missingEndpoints = new Map;
|
|
1683
|
+
for (const link of knownIncidentStates) {
|
|
1684
|
+
for (const ref of [link.ref.source, link.ref.target]) {
|
|
1685
|
+
if (!state.objects.has(objectRefKey(ref)))
|
|
1686
|
+
missingEndpoints.set(objectRefKey(ref), ref);
|
|
1687
|
+
}
|
|
1688
|
+
}
|
|
1689
|
+
if (missingEndpoints.size > 0) {
|
|
1690
|
+
await mergeLoadedState(context, storage, session, state, {
|
|
1691
|
+
objects: [...missingEndpoints.values()],
|
|
1692
|
+
links: [],
|
|
1693
|
+
linkScopes: [],
|
|
1694
|
+
incidentObjects: [],
|
|
1695
|
+
points: []
|
|
1696
|
+
});
|
|
1697
|
+
}
|
|
1698
|
+
const relevantStates = knownIncidentStates.filter((link) => {
|
|
1699
|
+
if (link.effective)
|
|
1700
|
+
return true;
|
|
1701
|
+
if (revivingObjects.has(objectRefKey(link.ref.source)) || revivingObjects.has(objectRefKey(link.ref.target))) {
|
|
1702
|
+
return true;
|
|
1703
|
+
}
|
|
1704
|
+
return Boolean(resolveLink(context.ontology, workingLinkFromState(link), state.objects));
|
|
1705
|
+
});
|
|
1706
|
+
const missingScopes = distinctCardinalityOneScopes(context.ontology, relevantStates, state.scopeSnapshots);
|
|
1707
|
+
if (missingScopes.length > 0) {
|
|
1708
|
+
await mergeLoadedState(context, storage, session, state, {
|
|
1709
|
+
objects: [],
|
|
1710
|
+
links: [],
|
|
1711
|
+
linkScopes: missingScopes,
|
|
1712
|
+
incidentObjects: [],
|
|
1713
|
+
points: []
|
|
1714
|
+
});
|
|
1715
|
+
}
|
|
1716
|
+
for (const link of relevantStates) {
|
|
1717
|
+
const key = linkRefKey(link.ref);
|
|
1718
|
+
if (state.links.has(key))
|
|
1719
|
+
continue;
|
|
1720
|
+
state.links.set(key, workingLinkFromState(link));
|
|
1721
|
+
}
|
|
1722
|
+
context.observeCoreBuffer?.("edits.incident-links", state.links.size);
|
|
1723
|
+
}
|
|
1724
|
+
async function mergeLoadedState(context, storage, session, state, request) {
|
|
1725
|
+
const loaded = await loadState(context, storage, session, request);
|
|
1726
|
+
mergeWorkingState(state.objects, state.links, state.scopeSnapshots, loaded);
|
|
1727
|
+
}
|
|
1728
|
+
|
|
1729
|
+
// src/materializer/effective/diff.ts
|
|
1730
|
+
function diffEffectiveObject(input) {
|
|
1731
|
+
if (!input.before) {
|
|
1732
|
+
if (!input.resolved)
|
|
1733
|
+
return null;
|
|
1734
|
+
return createObjectChange(input.resolved, input.commitId, input.committedAt);
|
|
1735
|
+
}
|
|
1736
|
+
if (!input.resolved)
|
|
1737
|
+
return deleteObjectChange(input.before);
|
|
1738
|
+
if (sameProperties(input.before.properties, input.resolved.properties))
|
|
1739
|
+
return null;
|
|
1740
|
+
return updateObjectChange(input.before, input.resolved, input.commitId, input.committedAt);
|
|
1741
|
+
}
|
|
1742
|
+
function createObjectChange(resolved, commitId, committedAt) {
|
|
1743
|
+
const after = {
|
|
1744
|
+
...resolved,
|
|
1745
|
+
version: 1,
|
|
1746
|
+
createdAt: committedAt,
|
|
1747
|
+
updatedAt: committedAt,
|
|
1748
|
+
lastCommitId: commitId
|
|
1749
|
+
};
|
|
1750
|
+
return {
|
|
1751
|
+
kind: "created",
|
|
1752
|
+
ref: after.ref,
|
|
1753
|
+
before: null,
|
|
1754
|
+
after,
|
|
1755
|
+
propertyChanges: propertyChanges({}, after.properties)
|
|
1756
|
+
};
|
|
1757
|
+
}
|
|
1758
|
+
function deleteObjectChange(before) {
|
|
1759
|
+
return {
|
|
1760
|
+
kind: "deleted",
|
|
1761
|
+
ref: before.ref,
|
|
1762
|
+
before,
|
|
1763
|
+
after: null,
|
|
1764
|
+
propertyChanges: propertyChanges(before.properties, {})
|
|
1765
|
+
};
|
|
1766
|
+
}
|
|
1767
|
+
function updateObjectChange(before, resolved, commitId, committedAt) {
|
|
1768
|
+
const after = {
|
|
1769
|
+
...resolved,
|
|
1770
|
+
version: before.version + 1,
|
|
1771
|
+
createdAt: before.createdAt,
|
|
1772
|
+
updatedAt: committedAt,
|
|
1773
|
+
lastCommitId: commitId
|
|
1774
|
+
};
|
|
1775
|
+
return {
|
|
1776
|
+
kind: "updated",
|
|
1777
|
+
ref: after.ref,
|
|
1778
|
+
before,
|
|
1779
|
+
after,
|
|
1780
|
+
propertyChanges: propertyChanges(before.properties, after.properties)
|
|
1781
|
+
};
|
|
1782
|
+
}
|
|
1783
|
+
function diffEffectiveLink(input) {
|
|
1784
|
+
if (!input.before) {
|
|
1785
|
+
if (!input.resolved)
|
|
1786
|
+
return null;
|
|
1787
|
+
return createLinkChange(input.resolved, input.commitId, input.committedAt);
|
|
1788
|
+
}
|
|
1789
|
+
if (!input.resolved)
|
|
1790
|
+
return deleteLinkChange(input.before);
|
|
1791
|
+
if (sameProperties(input.before.properties ?? {}, input.resolved.properties ?? {}))
|
|
1792
|
+
return null;
|
|
1793
|
+
return updateLinkChange(input.before, input.resolved, input.commitId, input.committedAt);
|
|
1794
|
+
}
|
|
1795
|
+
function createLinkChange(resolved, commitId, committedAt) {
|
|
1796
|
+
const after = {
|
|
1797
|
+
...resolved,
|
|
1798
|
+
createdAt: committedAt,
|
|
1799
|
+
updatedAt: committedAt,
|
|
1800
|
+
lastCommitId: commitId
|
|
1801
|
+
};
|
|
1802
|
+
return {
|
|
1803
|
+
kind: "created",
|
|
1804
|
+
ref: after.ref,
|
|
1805
|
+
before: null,
|
|
1806
|
+
after,
|
|
1807
|
+
propertyChanges: propertyChanges({}, after.properties ?? {})
|
|
1808
|
+
};
|
|
1809
|
+
}
|
|
1810
|
+
function deleteLinkChange(before) {
|
|
1811
|
+
return {
|
|
1812
|
+
kind: "deleted",
|
|
1813
|
+
ref: before.ref,
|
|
1814
|
+
before,
|
|
1815
|
+
after: null,
|
|
1816
|
+
propertyChanges: propertyChanges(before.properties ?? {}, {})
|
|
1817
|
+
};
|
|
1818
|
+
}
|
|
1819
|
+
function updateLinkChange(before, resolved, commitId, committedAt) {
|
|
1820
|
+
const after = {
|
|
1821
|
+
...resolved,
|
|
1822
|
+
createdAt: before.createdAt,
|
|
1823
|
+
updatedAt: committedAt,
|
|
1824
|
+
lastCommitId: commitId
|
|
1825
|
+
};
|
|
1826
|
+
return {
|
|
1827
|
+
kind: "updated",
|
|
1828
|
+
ref: after.ref,
|
|
1829
|
+
before,
|
|
1830
|
+
after,
|
|
1831
|
+
propertyChanges: propertyChanges(before.properties ?? {}, after.properties ?? {})
|
|
1832
|
+
};
|
|
1833
|
+
}
|
|
1834
|
+
function sameProperties(left, right) {
|
|
1835
|
+
return stableJsonStringify(left) === stableJsonStringify(right);
|
|
1836
|
+
}
|
|
1837
|
+
function propertyChanges(before, after) {
|
|
1838
|
+
const changes = {};
|
|
1839
|
+
const ids = [...new Set([...Object.keys(before), ...Object.keys(after)])].sort(compareStrings);
|
|
1840
|
+
for (const id of ids) {
|
|
1841
|
+
if (!(id in before))
|
|
1842
|
+
changes[id] = { operation: "created", after: after[id] };
|
|
1843
|
+
else if (!(id in after))
|
|
1844
|
+
changes[id] = { operation: "cleared", before: before[id], after: null };
|
|
1845
|
+
else if (stableJsonStringify(before[id]) !== stableJsonStringify(after[id])) {
|
|
1846
|
+
changes[id] = { operation: "updated", before: before[id], after: after[id] };
|
|
1847
|
+
}
|
|
1848
|
+
}
|
|
1849
|
+
return changes;
|
|
1850
|
+
}
|
|
1851
|
+
|
|
1852
|
+
// src/materializer/effective/validate.ts
|
|
1853
|
+
function validateObjectRef(ontology, ref) {
|
|
1854
|
+
materializationValidation(() => {
|
|
1855
|
+
ontology.resolveObjectType(ref.objectTypeId);
|
|
1856
|
+
});
|
|
1857
|
+
}
|
|
1858
|
+
function validateLinkRef(ontology, ref) {
|
|
1859
|
+
materializationValidation(() => {
|
|
1860
|
+
const sourceType = ontology.resolveObjectType(ref.source.objectTypeId);
|
|
1861
|
+
ontology.resolveObjectType(ref.target.objectTypeId);
|
|
1862
|
+
const link = sourceType.links.find((candidate) => candidate.id === ref.linkId);
|
|
1863
|
+
if (!link)
|
|
1864
|
+
throw new Error(`[Sixb] Unknown link '${ref.source.objectTypeId}.${ref.linkId}'.`);
|
|
1865
|
+
if (!ontology.isValidLinkTarget(link.targetObjectTypeId, ref.target.objectTypeId)) {
|
|
1866
|
+
throw new Error(`[Sixb] Link '${ref.source.objectTypeId}.${ref.linkId}' cannot target '${ref.target.objectTypeId}'.`);
|
|
1867
|
+
}
|
|
1868
|
+
});
|
|
1869
|
+
}
|
|
1870
|
+
function validateObjectAuthorityProperties(ontology, ref, properties) {
|
|
1871
|
+
return materializationValidation(() => {
|
|
1872
|
+
const objectType = ontology.resolveObjectType(ref.objectTypeId);
|
|
1873
|
+
assertKnownProperties(objectType, properties);
|
|
1874
|
+
const primaryId = ontology.getPrimaryPropertyId(ref.objectTypeId);
|
|
1875
|
+
const result = { ...properties };
|
|
1876
|
+
if (primaryId in result) {
|
|
1877
|
+
if (result[primaryId] !== ref.primaryId) {
|
|
1878
|
+
throw new Error(`[Sixb] Primary property '${primaryId}' must match object identity '${ref.primaryId}'.`);
|
|
1879
|
+
}
|
|
1880
|
+
delete result[primaryId];
|
|
1881
|
+
}
|
|
1882
|
+
for (const propertyId of Object.keys(result)) {
|
|
1883
|
+
const property = objectType.properties.find((candidate) => candidate.id === propertyId);
|
|
1884
|
+
if (property.mode === "telemetry") {
|
|
1885
|
+
throw new Error(`[Sixb] Static authority cannot write telemetry property '${ref.objectTypeId}.${propertyId}'.`);
|
|
1886
|
+
}
|
|
1887
|
+
}
|
|
1888
|
+
const valueTypesById = ontology.getValueTypesById();
|
|
1889
|
+
validateObjectProperties(objectType, result, valueTypesById);
|
|
1890
|
+
return normalizeObjectProperties(objectType.properties, result, valueTypesById, objectType.id);
|
|
1891
|
+
});
|
|
1892
|
+
}
|
|
1893
|
+
function validateObjectPatchPropertyIds(ontology, ref, propertyIds, label) {
|
|
1894
|
+
materializationValidation(() => {
|
|
1895
|
+
const objectType = ontology.resolveObjectType(ref.objectTypeId);
|
|
1896
|
+
const primaryId = ontology.getPrimaryPropertyId(ref.objectTypeId);
|
|
1897
|
+
for (const propertyId of propertyIds) {
|
|
1898
|
+
const property = objectType.properties.find((candidate) => candidate.id === propertyId);
|
|
1899
|
+
if (!property) {
|
|
1900
|
+
throw new Error(`[Sixb] Object patch ${label} references unknown property '${ref.objectTypeId}.${propertyId}'.`);
|
|
1901
|
+
}
|
|
1902
|
+
if (propertyId === primaryId) {
|
|
1903
|
+
throw new Error(`[Sixb] Object patch ${label} cannot target primary property '${ref.objectTypeId}.${propertyId}'.`);
|
|
1904
|
+
}
|
|
1905
|
+
if (property.mode === "telemetry") {
|
|
1906
|
+
throw new Error(`[Sixb] Object patch ${label} cannot target telemetry property '${ref.objectTypeId}.${propertyId}'.`);
|
|
1907
|
+
}
|
|
1908
|
+
}
|
|
1909
|
+
});
|
|
1910
|
+
}
|
|
1911
|
+
function validateEffectiveObject(ontology, ref, properties) {
|
|
1912
|
+
materializationValidation(() => {
|
|
1913
|
+
const objectType = ontology.resolveObjectType(ref.objectTypeId);
|
|
1914
|
+
assertKnownProperties(objectType, properties);
|
|
1915
|
+
for (const property of objectType.properties) {
|
|
1916
|
+
if (property.mode !== "telemetry" && property.required && properties[property.id] === undefined) {
|
|
1917
|
+
throw new Error(`[Sixb] Missing required property '${property.id}' for object type '${objectType.id}'`);
|
|
1918
|
+
}
|
|
1919
|
+
}
|
|
1920
|
+
validateObjectProperties(objectType, properties, ontology.getValueTypesById());
|
|
1921
|
+
});
|
|
1922
|
+
}
|
|
1923
|
+
function validateLinkAuthorityProperties(ontology, ref, properties) {
|
|
1924
|
+
return materializationValidation(() => {
|
|
1925
|
+
const objectType = ontology.resolveObjectType(ref.source.objectTypeId);
|
|
1926
|
+
const link = objectType.links.find((candidate) => candidate.id === ref.linkId);
|
|
1927
|
+
if (!link)
|
|
1928
|
+
throw new Error(`[Sixb] Unknown link '${ref.source.objectTypeId}.${ref.linkId}'.`);
|
|
1929
|
+
if (!ontology.isValidLinkTarget(link.targetObjectTypeId, ref.target.objectTypeId)) {
|
|
1930
|
+
throw new Error(`[Sixb] Link '${ref.source.objectTypeId}.${ref.linkId}' cannot target '${ref.target.objectTypeId}'.`);
|
|
1931
|
+
}
|
|
1932
|
+
const valueTypesById = ontology.getValueTypesById();
|
|
1933
|
+
validateLinkProperties(objectType, link, properties, undefined, valueTypesById);
|
|
1934
|
+
return normalizeLinkProperties(objectType, link, properties, valueTypesById);
|
|
1935
|
+
});
|
|
1936
|
+
}
|
|
1937
|
+
function validateTelemetryPoint(ontology, point) {
|
|
1938
|
+
return materializationValidation(() => {
|
|
1939
|
+
const objectType = ontology.resolveObjectType(point.series.object.objectTypeId);
|
|
1940
|
+
const property = objectType.properties.find((candidate) => candidate.id === point.series.propertyId);
|
|
1941
|
+
if (!property || property.mode !== "telemetry") {
|
|
1942
|
+
throw new Error(`[Sixb] Property '${point.series.object.objectTypeId}.${point.series.propertyId}' is not telemetry-enabled.`);
|
|
1943
|
+
}
|
|
1944
|
+
const path = `${objectType.id}.${property.id}`;
|
|
1945
|
+
const valueTypesById = ontology.getValueTypesById();
|
|
1946
|
+
validatePropertyValue(property, point.value, path, valueTypesById);
|
|
1947
|
+
validateTelemetryUnit(property, path, point.unit, valueTypesById);
|
|
1948
|
+
return {
|
|
1949
|
+
...point,
|
|
1950
|
+
value: point.value === null ? null : normalizeSchemaValue(property.schema, point.value, path, valueTypesById)
|
|
1951
|
+
};
|
|
1952
|
+
});
|
|
1953
|
+
}
|
|
1954
|
+
function materializationValidation(run) {
|
|
1955
|
+
try {
|
|
1956
|
+
return run();
|
|
1957
|
+
} catch (error) {
|
|
1958
|
+
if (error instanceof MaterializationValidationError)
|
|
1959
|
+
throw error;
|
|
1960
|
+
throw new MaterializationValidationError(error instanceof Error ? error.message : String(error));
|
|
1961
|
+
}
|
|
1962
|
+
}
|
|
1963
|
+
|
|
1964
|
+
// src/materializer/edits/apply.ts
|
|
1965
|
+
function applyObjectEdit(input) {
|
|
1966
|
+
const current = input.authority;
|
|
1967
|
+
let next;
|
|
1968
|
+
switch (input.operation.kind) {
|
|
1969
|
+
case "object.create":
|
|
1970
|
+
next = applyObjectCreate(input, input.operation);
|
|
1971
|
+
break;
|
|
1972
|
+
case "object.upsert":
|
|
1973
|
+
next = applyObjectUpsert(input, input.operation);
|
|
1974
|
+
break;
|
|
1975
|
+
case "object.patch":
|
|
1976
|
+
next = applyObjectPatch2(input, input.operation);
|
|
1977
|
+
break;
|
|
1978
|
+
case "object.delete":
|
|
1979
|
+
next = applyObjectDelete(input);
|
|
1980
|
+
break;
|
|
1981
|
+
case "object.restore":
|
|
1982
|
+
next = applyObjectRestore(input);
|
|
1983
|
+
break;
|
|
1984
|
+
default:
|
|
1985
|
+
throw new MaterializationValidationError("Expected an object edit operation.");
|
|
1986
|
+
}
|
|
1987
|
+
return transition(current, next);
|
|
1988
|
+
}
|
|
1989
|
+
function applyObjectCreate(input, operation) {
|
|
1990
|
+
if (input.sourceProperties || input.authority) {
|
|
1991
|
+
throw new MaterializationValidationError(`Object create requires complete authority absence for ${operation.ref.objectTypeId}:${operation.ref.primaryId}.`);
|
|
1992
|
+
}
|
|
1993
|
+
return { kind: "create", properties: input.normalizedProperties ?? operation.properties };
|
|
1994
|
+
}
|
|
1995
|
+
function applyObjectUpsert(input, operation) {
|
|
1996
|
+
const properties = input.normalizedProperties ?? operation.properties;
|
|
1997
|
+
const current = input.authority;
|
|
1998
|
+
if (current?.kind === "create") {
|
|
1999
|
+
return { kind: "create", properties: { ...current.properties, ...properties } };
|
|
2000
|
+
}
|
|
2001
|
+
if (current?.kind === "patch") {
|
|
2002
|
+
return mergeUpsertIntoPatch(current, properties, input.sourceProperties !== null);
|
|
2003
|
+
}
|
|
2004
|
+
if (input.sourceProperties)
|
|
2005
|
+
return { kind: "patch", set: properties, unset: [] };
|
|
2006
|
+
return { kind: "create", properties };
|
|
2007
|
+
}
|
|
2008
|
+
function mergeUpsertIntoPatch(current, properties, hasSource) {
|
|
2009
|
+
if (hasSource) {
|
|
2010
|
+
const unset = current.unset.filter((propertyId) => !(propertyId in properties));
|
|
2011
|
+
return { kind: "patch", set: { ...current.set, ...properties }, unset };
|
|
2012
|
+
}
|
|
2013
|
+
const created = { ...current.set };
|
|
2014
|
+
for (const propertyId of current.unset)
|
|
2015
|
+
delete created[propertyId];
|
|
2016
|
+
return { kind: "create", properties: { ...created, ...properties } };
|
|
2017
|
+
}
|
|
2018
|
+
function applyObjectPatch2(input, operation) {
|
|
2019
|
+
const current = input.authority;
|
|
2020
|
+
if (!input.effectiveExists && current?.kind !== "patch") {
|
|
2021
|
+
throw new MaterializationValidationError(`Object patch requires an effective object for ${operation.ref.objectTypeId}:${operation.ref.primaryId}.`);
|
|
2022
|
+
}
|
|
2023
|
+
const setInput = input.normalizedSet ?? operation.set;
|
|
2024
|
+
if (current?.kind === "create" && !input.sourceProperties) {
|
|
2025
|
+
return patchCreatedObject(current, operation, setInput);
|
|
2026
|
+
}
|
|
2027
|
+
return patchOverride(toPatchOverride(current), operation, setInput);
|
|
2028
|
+
}
|
|
2029
|
+
function patchCreatedObject(current, operation, setInput) {
|
|
2030
|
+
const properties = { ...current.properties, ...setInput };
|
|
2031
|
+
for (const propertyId of [...operation.unset, ...operation.reset]) {
|
|
2032
|
+
delete properties[propertyId];
|
|
2033
|
+
}
|
|
2034
|
+
return { kind: "create", properties };
|
|
2035
|
+
}
|
|
2036
|
+
function toPatchOverride(current) {
|
|
2037
|
+
if (current?.kind === "patch")
|
|
2038
|
+
return current;
|
|
2039
|
+
if (current?.kind === "create") {
|
|
2040
|
+
return { kind: "patch", set: { ...current.properties }, unset: [] };
|
|
2041
|
+
}
|
|
2042
|
+
return { kind: "patch", set: {}, unset: [] };
|
|
2043
|
+
}
|
|
2044
|
+
function patchOverride(base, operation, setInput) {
|
|
2045
|
+
const set = { ...base.set };
|
|
2046
|
+
const unset = new Set(base.unset);
|
|
2047
|
+
for (const propertyId of operation.reset) {
|
|
2048
|
+
delete set[propertyId];
|
|
2049
|
+
unset.delete(propertyId);
|
|
2050
|
+
}
|
|
2051
|
+
for (const propertyId of operation.unset) {
|
|
2052
|
+
delete set[propertyId];
|
|
2053
|
+
unset.add(propertyId);
|
|
2054
|
+
}
|
|
2055
|
+
for (const [propertyId, value] of Object.entries(setInput)) {
|
|
2056
|
+
set[propertyId] = value;
|
|
2057
|
+
unset.delete(propertyId);
|
|
2058
|
+
}
|
|
2059
|
+
if (Object.keys(set).length === 0 && unset.size === 0)
|
|
2060
|
+
return null;
|
|
2061
|
+
return { kind: "patch", set, unset: [...unset].sort() };
|
|
2062
|
+
}
|
|
2063
|
+
function applyObjectDelete(input) {
|
|
2064
|
+
if (!input.effectiveExists)
|
|
2065
|
+
return input.authority;
|
|
2066
|
+
if (input.authority?.kind === "create" && !input.sourceProperties)
|
|
2067
|
+
return null;
|
|
2068
|
+
return { kind: "delete" };
|
|
2069
|
+
}
|
|
2070
|
+
function applyObjectRestore(input) {
|
|
2071
|
+
if (input.authority?.kind !== "delete")
|
|
2072
|
+
return input.authority;
|
|
2073
|
+
return null;
|
|
2074
|
+
}
|
|
2075
|
+
function applyLinkEdit(input) {
|
|
2076
|
+
const current = input.authority;
|
|
2077
|
+
let next;
|
|
2078
|
+
switch (input.operation.kind) {
|
|
2079
|
+
case "link.upsert":
|
|
2080
|
+
next = linkUpsertOverride(input);
|
|
2081
|
+
break;
|
|
2082
|
+
case "link.delete":
|
|
2083
|
+
next = linkDeleteOverride(input);
|
|
2084
|
+
break;
|
|
2085
|
+
case "link.reset":
|
|
2086
|
+
next = null;
|
|
2087
|
+
break;
|
|
2088
|
+
default:
|
|
2089
|
+
throw new MaterializationValidationError("Expected a link edit operation.");
|
|
2090
|
+
}
|
|
2091
|
+
return transition(current, next);
|
|
2092
|
+
}
|
|
2093
|
+
function linkUpsertOverride(input) {
|
|
2094
|
+
if (input.normalizedProperties !== undefined) {
|
|
2095
|
+
return { kind: "upsert", properties: input.normalizedProperties };
|
|
2096
|
+
}
|
|
2097
|
+
if (input.operation.kind === "link.upsert" && input.operation.properties !== undefined) {
|
|
2098
|
+
return { kind: "upsert", properties: input.operation.properties };
|
|
2099
|
+
}
|
|
2100
|
+
return { kind: "upsert" };
|
|
2101
|
+
}
|
|
2102
|
+
function linkDeleteOverride(input) {
|
|
2103
|
+
if (!input.effectiveExists)
|
|
2104
|
+
return input.authority;
|
|
2105
|
+
if (input.authority?.kind === "upsert" && !input.hasSource)
|
|
2106
|
+
return null;
|
|
2107
|
+
return { kind: "delete" };
|
|
2108
|
+
}
|
|
2109
|
+
function transition(current, next) {
|
|
2110
|
+
return { next, changed: !sameAuthority(current, next) };
|
|
2111
|
+
}
|
|
2112
|
+
function sameAuthority(left, right) {
|
|
2113
|
+
return stableJsonStringify(left) === stableJsonStringify(right);
|
|
2114
|
+
}
|
|
2115
|
+
|
|
2116
|
+
// src/materializer/edits/operations.ts
|
|
2117
|
+
function undoEditJournal(journal) {
|
|
2118
|
+
for (let index = journal.length - 1;index >= 0; index -= 1) {
|
|
2119
|
+
journal[index]?.restore();
|
|
2120
|
+
}
|
|
2121
|
+
}
|
|
2122
|
+
function applyEditOperation(context, state, operation, identity, journal) {
|
|
2123
|
+
validateOperationRef(context, operation);
|
|
2124
|
+
if (isObjectOperation2(operation)) {
|
|
2125
|
+
return applyObjectOperation(context, state, operation, identity, journal);
|
|
2126
|
+
}
|
|
2127
|
+
return applyLinkOperation(context, state, operation, linkCardinality(context.ontology, operation.ref), journal);
|
|
2128
|
+
}
|
|
2129
|
+
function validateOperationRef(context, operation) {
|
|
2130
|
+
if (isObjectOperation2(operation)) {
|
|
2131
|
+
validateObjectRef(context.ontology, operation.ref);
|
|
2132
|
+
return;
|
|
2133
|
+
}
|
|
2134
|
+
validateLinkRef(context.ontology, operation.ref);
|
|
2135
|
+
}
|
|
2136
|
+
function applyObjectOperation(context, state, operation, identity, journal) {
|
|
2137
|
+
const working = requireWorkingObject(state, operation);
|
|
2138
|
+
const normalized = validateObjectOperation(context, operation);
|
|
2139
|
+
const currentEffective = resolveObject(context.ontology, working);
|
|
2140
|
+
const transition2 = applyObjectEdit({
|
|
2141
|
+
operation,
|
|
2142
|
+
sourceProperties: working.source?.assertion.properties ?? null,
|
|
2143
|
+
authority: working.override,
|
|
2144
|
+
effectiveExists: currentEffective !== null,
|
|
2145
|
+
...normalized
|
|
2146
|
+
});
|
|
2147
|
+
applyObjectTransition(context, state, working, transition2.next, journal);
|
|
2148
|
+
return objectOperationOutcome(operation, working, transition2.changed, context, identity);
|
|
2149
|
+
}
|
|
2150
|
+
function requireWorkingObject(state, operation) {
|
|
2151
|
+
const working = state.objects.get(objectRefKey(operation.ref));
|
|
2152
|
+
if (!working)
|
|
2153
|
+
throw new MaterializationValidationError("Object state was not loaded.");
|
|
2154
|
+
return working;
|
|
2155
|
+
}
|
|
2156
|
+
function validateObjectOperation(context, operation) {
|
|
2157
|
+
switch (operation.kind) {
|
|
2158
|
+
case "object.create":
|
|
2159
|
+
case "object.upsert":
|
|
2160
|
+
return {
|
|
2161
|
+
normalizedProperties: validateObjectAuthorityProperties(context.ontology, operation.ref, operation.properties)
|
|
2162
|
+
};
|
|
2163
|
+
case "object.patch":
|
|
2164
|
+
validateObjectPatchPropertyIds(context.ontology, operation.ref, operation.unset, "unset");
|
|
2165
|
+
validateObjectPatchPropertyIds(context.ontology, operation.ref, operation.reset, "reset");
|
|
2166
|
+
return {
|
|
2167
|
+
normalizedSet: validateObjectAuthorityProperties(context.ontology, operation.ref, operation.set)
|
|
2168
|
+
};
|
|
2169
|
+
case "object.delete":
|
|
2170
|
+
case "object.restore":
|
|
2171
|
+
return {};
|
|
2172
|
+
}
|
|
2173
|
+
}
|
|
2174
|
+
function applyObjectTransition(context, state, working, next, journal) {
|
|
2175
|
+
const previous = working.override;
|
|
2176
|
+
working.override = next;
|
|
2177
|
+
try {
|
|
2178
|
+
const resolved = resolveObject(context.ontology, working);
|
|
2179
|
+
if (resolved)
|
|
2180
|
+
validateEffectiveObject(context.ontology, resolved.ref, resolved.properties);
|
|
2181
|
+
validateWorkingCardinality(context.ontology, state.objects, state.links, state.scopeSnapshots);
|
|
2182
|
+
} catch (error) {
|
|
2183
|
+
working.override = previous;
|
|
2184
|
+
throw error;
|
|
2185
|
+
}
|
|
2186
|
+
journal?.push({
|
|
2187
|
+
restore: () => {
|
|
2188
|
+
working.override = previous;
|
|
2189
|
+
}
|
|
2190
|
+
});
|
|
2191
|
+
}
|
|
2192
|
+
function objectOperationOutcome(operation, working, changed, context, identity) {
|
|
2193
|
+
const outcome = {
|
|
2194
|
+
id: operation.id,
|
|
2195
|
+
ok: true,
|
|
2196
|
+
authority: authorityOutcome(changed)
|
|
2197
|
+
};
|
|
2198
|
+
const resolved = resolveObject(context.ontology, working);
|
|
2199
|
+
if (!resolved)
|
|
2200
|
+
return outcome;
|
|
2201
|
+
const change = diffEffectiveObject({
|
|
2202
|
+
before: working.before,
|
|
2203
|
+
resolved,
|
|
2204
|
+
commitId: identity.commitId,
|
|
2205
|
+
committedAt: identity.committedAt
|
|
2206
|
+
});
|
|
2207
|
+
const object = change?.after ?? working.before;
|
|
2208
|
+
if (!object) {
|
|
2209
|
+
throw new MaterializationValidationError("Effective object outcome could not be resolved.");
|
|
2210
|
+
}
|
|
2211
|
+
return { ...outcome, object };
|
|
2212
|
+
}
|
|
2213
|
+
function applyLinkOperation(context, state, operation, cardinality, journal) {
|
|
2214
|
+
const working = requireWorkingLink(state, operation);
|
|
2215
|
+
validateLinkEndpoints(context, state, operation);
|
|
2216
|
+
const normalizedProperties = validateLinkOperation(context, operation);
|
|
2217
|
+
const currentEffective = resolveLink(context.ontology, working, state.objects);
|
|
2218
|
+
const transitionInput = {
|
|
2219
|
+
operation,
|
|
2220
|
+
hasSource: working.source !== null,
|
|
2221
|
+
authority: working.override,
|
|
2222
|
+
effectiveExists: currentEffective !== null
|
|
2223
|
+
};
|
|
2224
|
+
const transition2 = applyLinkEdit({ ...transitionInput, normalizedProperties });
|
|
2225
|
+
applyLinkTransition(context, state, working, transition2.next, cardinality, journal);
|
|
2226
|
+
return { id: operation.id, ok: true, authority: authorityOutcome(transition2.changed) };
|
|
2227
|
+
}
|
|
2228
|
+
function requireWorkingLink(state, operation) {
|
|
2229
|
+
const working = state.links.get(linkRefKey(operation.ref));
|
|
2230
|
+
if (!working)
|
|
2231
|
+
throw new MaterializationValidationError("Link state was not loaded.");
|
|
2232
|
+
return working;
|
|
2233
|
+
}
|
|
2234
|
+
function validateLinkEndpoints(context, state, operation) {
|
|
2235
|
+
if (operation.kind !== "link.upsert")
|
|
2236
|
+
return;
|
|
2237
|
+
const source = state.objects.get(objectRefKey(operation.ref.source));
|
|
2238
|
+
const target = state.objects.get(objectRefKey(operation.ref.target));
|
|
2239
|
+
const sourceExists = source && resolveObject(context.ontology, source);
|
|
2240
|
+
const targetExists = target && resolveObject(context.ontology, target);
|
|
2241
|
+
if (sourceExists && targetExists)
|
|
2242
|
+
return;
|
|
2243
|
+
throw new MaterializationValidationError("Link upsert requires both endpoints to be effective.");
|
|
2244
|
+
}
|
|
2245
|
+
function validateLinkOperation(context, operation) {
|
|
2246
|
+
if (operation.kind !== "link.upsert")
|
|
2247
|
+
return;
|
|
2248
|
+
return validateLinkAuthorityProperties(context.ontology, operation.ref, operation.properties);
|
|
2249
|
+
}
|
|
2250
|
+
function applyLinkTransition(context, state, working, next, cardinality, journal) {
|
|
2251
|
+
const previous = working.override;
|
|
2252
|
+
working.override = next;
|
|
2253
|
+
try {
|
|
2254
|
+
if (cardinality === "one") {
|
|
2255
|
+
validateWorkingCardinality(context.ontology, state.objects, state.links, state.scopeSnapshots);
|
|
2256
|
+
}
|
|
2257
|
+
} catch (error) {
|
|
2258
|
+
working.override = previous;
|
|
2259
|
+
throw error;
|
|
2260
|
+
}
|
|
2261
|
+
journal?.push({
|
|
2262
|
+
restore: () => {
|
|
2263
|
+
working.override = previous;
|
|
2264
|
+
}
|
|
2265
|
+
});
|
|
2266
|
+
}
|
|
2267
|
+
function authorityOutcome(changed) {
|
|
2268
|
+
if (changed)
|
|
2269
|
+
return "changed";
|
|
2270
|
+
return "unchanged";
|
|
2271
|
+
}
|
|
2272
|
+
function isObjectOperation2(operation) {
|
|
2273
|
+
switch (operation.kind) {
|
|
2274
|
+
case "object.create":
|
|
2275
|
+
case "object.upsert":
|
|
2276
|
+
case "object.patch":
|
|
2277
|
+
case "object.delete":
|
|
2278
|
+
case "object.restore":
|
|
2279
|
+
return true;
|
|
2280
|
+
case "link.upsert":
|
|
2281
|
+
case "link.delete":
|
|
2282
|
+
case "link.reset":
|
|
2283
|
+
return false;
|
|
2284
|
+
}
|
|
2285
|
+
}
|
|
2286
|
+
|
|
2287
|
+
// src/materializer/edits/plan.ts
|
|
2288
|
+
async function stageEditPlan(context, storage, session, state, planContext) {
|
|
2289
|
+
validateWorkingCardinality(context.ontology, state.objects, state.links, state.scopeSnapshots);
|
|
2290
|
+
const objectChanges = [];
|
|
2291
|
+
for (const working of sortedObjects(state.objects)) {
|
|
2292
|
+
const change = await stageObjectPlan(context, storage, session, working, planContext);
|
|
2293
|
+
if (change)
|
|
2294
|
+
objectChanges.push(change);
|
|
2295
|
+
}
|
|
2296
|
+
const linkChanges = [];
|
|
2297
|
+
for (const working of sortedLinks(state.links)) {
|
|
2298
|
+
const change = await stageLinkPlan(context, storage, session, state.objects, working, planContext);
|
|
2299
|
+
if (change)
|
|
2300
|
+
linkChanges.push(change);
|
|
2301
|
+
}
|
|
2302
|
+
return { objects: objectChanges, links: linkChanges };
|
|
2303
|
+
}
|
|
2304
|
+
async function stageObjectPlan(context, storage, session, working, planContext) {
|
|
2305
|
+
const items = [];
|
|
2306
|
+
appendObjectOverridePlan(items, working, planContext.identity);
|
|
2307
|
+
const resolved = resolveObject(context.ontology, working);
|
|
2308
|
+
if (resolved)
|
|
2309
|
+
validateEffectiveObject(context.ontology, resolved.ref, resolved.properties);
|
|
2310
|
+
const change = diffEffectiveObject({
|
|
2311
|
+
before: working.before,
|
|
2312
|
+
resolved,
|
|
2313
|
+
commitId: planContext.identity.commitId,
|
|
2314
|
+
committedAt: planContext.identity.committedAt
|
|
2315
|
+
});
|
|
2316
|
+
if (change)
|
|
2317
|
+
appendObjectEffectivePlan(items, change);
|
|
2318
|
+
const sortKey = objectRefSortKey(working.ref);
|
|
2319
|
+
const work = [
|
|
2320
|
+
classificationWork("object", objectRefKey(working.ref), sortKey),
|
|
2321
|
+
...items.map((item) => planWork(item, sortKey))
|
|
2322
|
+
];
|
|
2323
|
+
if (change) {
|
|
2324
|
+
work.push(eventWork(buildObjectEvent(context, planContext, change)));
|
|
2325
|
+
}
|
|
2326
|
+
await stageWorkBounded(context, storage, session, work);
|
|
2327
|
+
return change;
|
|
2328
|
+
}
|
|
2329
|
+
async function stageLinkPlan(context, storage, session, objects, working, planContext) {
|
|
2330
|
+
const items = [];
|
|
2331
|
+
appendLinkOverridePlan(items, working, planContext.identity);
|
|
2332
|
+
const resolved = resolveLink(context.ontology, working, objects);
|
|
2333
|
+
const change = diffEffectiveLink({
|
|
2334
|
+
before: working.before,
|
|
2335
|
+
resolved,
|
|
2336
|
+
commitId: planContext.identity.commitId,
|
|
2337
|
+
committedAt: planContext.identity.committedAt
|
|
2338
|
+
});
|
|
2339
|
+
if (change)
|
|
2340
|
+
appendLinkEffectivePlan(items, change);
|
|
2341
|
+
const sortKey = linkRefSortKey(working.ref);
|
|
2342
|
+
const work = [
|
|
2343
|
+
classificationWork("link", linkRefKey(working.ref), sortKey),
|
|
2344
|
+
...items.map((item) => planWork(item, sortKey))
|
|
2345
|
+
];
|
|
2346
|
+
if (change) {
|
|
2347
|
+
work.push(eventWork(buildLinkEvent(context, planContext, change)));
|
|
2348
|
+
}
|
|
2349
|
+
await stageWorkBounded(context, storage, session, work);
|
|
2350
|
+
return change;
|
|
2351
|
+
}
|
|
2352
|
+
function buildObjectEvent(context, planContext, change) {
|
|
2353
|
+
const eventContext = materializationEventContext(context, planContext);
|
|
2354
|
+
return buildObjectMaterializationEventDraft({ ...eventContext, change });
|
|
2355
|
+
}
|
|
2356
|
+
function buildLinkEvent(context, planContext, change) {
|
|
2357
|
+
const eventContext = materializationEventContext(context, planContext);
|
|
2358
|
+
return buildLinkMaterializationEventDraft({ ...eventContext, change });
|
|
2359
|
+
}
|
|
2360
|
+
function materializationEventContext(context, planContext) {
|
|
2361
|
+
const base = {
|
|
2362
|
+
projectId: context.projectId,
|
|
2363
|
+
commitId: planContext.identity.commitId,
|
|
2364
|
+
committedAt: planContext.identity.committedAt,
|
|
2365
|
+
origin: planContext.origin
|
|
2366
|
+
};
|
|
2367
|
+
if (planContext.actor === undefined)
|
|
2368
|
+
return base;
|
|
2369
|
+
return { ...base, actor: planContext.actor };
|
|
2370
|
+
}
|
|
2371
|
+
function sortedObjects(objects) {
|
|
2372
|
+
return [...objects.values()].sort((left, right) => compareObjectRefs(left.ref, right.ref));
|
|
2373
|
+
}
|
|
2374
|
+
function sortedLinks(links) {
|
|
2375
|
+
return [...links.values()].sort((left, right) => compareLinkRefs(left.ref, right.ref));
|
|
2376
|
+
}
|
|
2377
|
+
|
|
2378
|
+
// src/materializer/edits/commit.ts
|
|
2379
|
+
async function commitEdits(context, raw) {
|
|
2380
|
+
const command = prepareEditCommit(context, raw);
|
|
2381
|
+
const replay = await replayEditCommit(context, command);
|
|
2382
|
+
if (replay)
|
|
2383
|
+
return replay;
|
|
2384
|
+
return executeEditCommit(context, command);
|
|
2385
|
+
}
|
|
2386
|
+
function prepareEditCommit(context, raw) {
|
|
2387
|
+
const input = normalizeOntologyEditCommit(raw);
|
|
2388
|
+
const idempotencyKey = editIdempotencyKey(input);
|
|
2389
|
+
const identity = createTimedCommitIdentity({
|
|
2390
|
+
projectId: context.projectId,
|
|
2391
|
+
idempotencyKey,
|
|
2392
|
+
normalizedCallerIntent: input,
|
|
2393
|
+
now: context.clock()
|
|
2394
|
+
});
|
|
2395
|
+
return { input, identity, origin: input.source };
|
|
2396
|
+
}
|
|
2397
|
+
function editIdempotencyKey(input) {
|
|
2398
|
+
if (input.source.kind === "action") {
|
|
2399
|
+
return createActionIdempotencyKey(input.source.runId);
|
|
2400
|
+
}
|
|
2401
|
+
return createRuntimeIdempotencyKey(input.source.requestId);
|
|
2402
|
+
}
|
|
2403
|
+
async function lockActionRunForMaterialization(storage, projectId, input) {
|
|
2404
|
+
if (input.source.kind !== "action")
|
|
2405
|
+
return;
|
|
2406
|
+
if (!storage.actionRuns) {
|
|
2407
|
+
throw new MaterializationValidationError("Storage does not provide Action run capabilities required by this commit.");
|
|
2408
|
+
}
|
|
2409
|
+
await storage.actionRuns.lockForMaterialization({
|
|
2410
|
+
projectId,
|
|
2411
|
+
actionId: input.source.actionId,
|
|
2412
|
+
runId: input.source.runId
|
|
2413
|
+
});
|
|
2414
|
+
}
|
|
2415
|
+
function replayEditCommit(context, command) {
|
|
2416
|
+
return replayCommit(context, command.identity);
|
|
2417
|
+
}
|
|
2418
|
+
async function executeEditCommit(context, command) {
|
|
2419
|
+
return withSerializationRetry(context, () => context.storage.transaction((storage) => executeEditTransaction(context, storage, command), {
|
|
2420
|
+
isolation: "serializable"
|
|
2421
|
+
}));
|
|
2422
|
+
}
|
|
2423
|
+
async function executeEditTransaction(context, storage, command) {
|
|
2424
|
+
await lockActionRunForMaterialization(storage, context.projectId, command.input);
|
|
2425
|
+
const replay = await replayCommit(context, command.identity, storage);
|
|
2426
|
+
if (replay)
|
|
2427
|
+
return replay;
|
|
2428
|
+
const session = await beginEditMaterialization(context, storage, command);
|
|
2429
|
+
const workingState = await loadEditWorkingState(context, storage.ontology.materializations, session, command.input.operations);
|
|
2430
|
+
const outcomes = applyEditOperations(context, workingState, command);
|
|
2431
|
+
const changes = await stageEditPlan(context, storage.ontology.materializations, session, workingState, editPlanContext(command));
|
|
2432
|
+
await drainStagedWork(context, storage.ontology.materializations, session);
|
|
2433
|
+
const eventCount = await drainStagedEvents(context, storage.ontology.materializations, session, command.identity);
|
|
2434
|
+
const result = {
|
|
2435
|
+
kind: "edit",
|
|
2436
|
+
commitId: command.identity.commitId,
|
|
2437
|
+
created: true,
|
|
2438
|
+
eventCount,
|
|
2439
|
+
committedAt: command.identity.committedAt,
|
|
2440
|
+
outcomes,
|
|
2441
|
+
changes
|
|
2442
|
+
};
|
|
2443
|
+
return finalizeEditMaterialization(storage, session, result);
|
|
2444
|
+
}
|
|
2445
|
+
async function beginEditMaterialization(context, storage, command) {
|
|
2446
|
+
const commit = buildEditCommit(context, command);
|
|
2447
|
+
return storage.ontology.materializations.begin({
|
|
2448
|
+
commit,
|
|
2449
|
+
expected: {
|
|
2450
|
+
sources: [],
|
|
2451
|
+
...editExpectations(command.input),
|
|
2452
|
+
points: []
|
|
2453
|
+
}
|
|
2454
|
+
});
|
|
2455
|
+
}
|
|
2456
|
+
function buildEditCommit(context, command) {
|
|
2457
|
+
const commit = {
|
|
2458
|
+
projectId: context.projectId,
|
|
2459
|
+
id: command.identity.commitId,
|
|
2460
|
+
idempotencyKey: command.identity.idempotencyKey,
|
|
2461
|
+
requestHash: command.identity.requestHash,
|
|
2462
|
+
origin: command.origin,
|
|
2463
|
+
ontologyRevision: context.projectionRegistry.ontologyRevision,
|
|
2464
|
+
intent: {
|
|
2465
|
+
kind: "edit",
|
|
2466
|
+
mode: command.input.mode,
|
|
2467
|
+
operationCount: command.input.operations.length
|
|
2468
|
+
},
|
|
2469
|
+
committedAt: command.identity.committedAt
|
|
2470
|
+
};
|
|
2471
|
+
if (command.input.actor === undefined)
|
|
2472
|
+
return commit;
|
|
2473
|
+
return { ...commit, actor: command.input.actor };
|
|
2474
|
+
}
|
|
2475
|
+
function editExpectations(input) {
|
|
2476
|
+
if (input.mode === "atomic") {
|
|
2477
|
+
return {
|
|
2478
|
+
objects: input.expectedObjects,
|
|
2479
|
+
links: input.expectedLinks,
|
|
2480
|
+
linkScopes: input.expectedLinkScopes
|
|
2481
|
+
};
|
|
2482
|
+
}
|
|
2483
|
+
return { objects: [], links: [], linkScopes: [] };
|
|
2484
|
+
}
|
|
2485
|
+
function applyEditOperations(context, state, command) {
|
|
2486
|
+
const outcomes = [];
|
|
2487
|
+
const units = compileEditExecutionUnits(command.input);
|
|
2488
|
+
for (const unit of units) {
|
|
2489
|
+
outcomes.push(...applyEditExecutionUnit(context, state, command, unit));
|
|
2490
|
+
}
|
|
2491
|
+
return outcomes;
|
|
2492
|
+
}
|
|
2493
|
+
function applyEditExecutionUnit(context, state, command, unit) {
|
|
2494
|
+
if (unit.kind === "atomic-group") {
|
|
2495
|
+
return applyEditOperationGroup(context, state, command, unit.operations);
|
|
2496
|
+
}
|
|
2497
|
+
return [applyOneEditOperation(context, state, unit.operation, command)];
|
|
2498
|
+
}
|
|
2499
|
+
function applyOneEditOperation(context, state, operation, command) {
|
|
2500
|
+
try {
|
|
2501
|
+
return applyEditOperation(context, state, operation, command.identity);
|
|
2502
|
+
} catch (error) {
|
|
2503
|
+
if (!isRecoverableEditValidation(command.input, error))
|
|
2504
|
+
throw error;
|
|
2505
|
+
return { id: operation.id, ok: false, error: { code: "validation", message: error.message } };
|
|
2506
|
+
}
|
|
2507
|
+
}
|
|
2508
|
+
function applyEditOperationGroup(context, state, command, group) {
|
|
2509
|
+
const journal = [];
|
|
2510
|
+
const applied = [];
|
|
2511
|
+
for (const operation of group) {
|
|
2512
|
+
let outcome;
|
|
2513
|
+
try {
|
|
2514
|
+
outcome = applyEditOperation(context, state, operation, command.identity, journal);
|
|
2515
|
+
} catch (error) {
|
|
2516
|
+
if (!isRecoverableEditValidation(command.input, error))
|
|
2517
|
+
throw error;
|
|
2518
|
+
undoEditJournal(journal);
|
|
2519
|
+
return failedEditGroup(group, error.message);
|
|
2520
|
+
}
|
|
2521
|
+
if (!outcome.ok) {
|
|
2522
|
+
undoEditJournal(journal);
|
|
2523
|
+
return failedEditGroup(group, outcome.error.message);
|
|
2524
|
+
}
|
|
2525
|
+
applied.push(outcome);
|
|
2526
|
+
}
|
|
2527
|
+
return applied;
|
|
2528
|
+
}
|
|
2529
|
+
function failedEditGroup(group, message) {
|
|
2530
|
+
return group.map((operation) => ({
|
|
2531
|
+
id: operation.id,
|
|
2532
|
+
ok: false,
|
|
2533
|
+
error: { code: "validation", message }
|
|
2534
|
+
}));
|
|
2535
|
+
}
|
|
2536
|
+
function isRecoverableEditValidation(input, error) {
|
|
2537
|
+
if (input.mode === "atomic")
|
|
2538
|
+
return false;
|
|
2539
|
+
return error instanceof MaterializationValidationError;
|
|
2540
|
+
}
|
|
2541
|
+
function editPlanContext(command) {
|
|
2542
|
+
const context = { identity: command.identity, origin: command.origin };
|
|
2543
|
+
if (command.input.actor === undefined)
|
|
2544
|
+
return context;
|
|
2545
|
+
return { ...context, actor: command.input.actor };
|
|
2546
|
+
}
|
|
2547
|
+
async function finalizeEditMaterialization(storage, session, result) {
|
|
2548
|
+
const applied = await storage.ontology.materializations.finalize({
|
|
2549
|
+
session,
|
|
2550
|
+
finalization: { sourceActivations: [], result }
|
|
2551
|
+
});
|
|
2552
|
+
return applied.commit.result;
|
|
2553
|
+
}
|
|
2554
|
+
|
|
2555
|
+
// src/materializer/execution/run-correlation.ts
|
|
2556
|
+
async function lockProjectionRunForMaterialization(storage, input) {
|
|
2557
|
+
const projectionRuns = storage.projectionRuns;
|
|
2558
|
+
if (!projectionRuns) {
|
|
2559
|
+
throw new MaterializationValidationError(input.capabilityErrorMessage ?? "Storage transaction does not provide projection run capabilities.");
|
|
2560
|
+
}
|
|
2561
|
+
const run = await projectionRuns.lockForMaterialization({
|
|
2562
|
+
id: input.projectionRunId,
|
|
2563
|
+
projectId: input.projectId,
|
|
2564
|
+
executionToken: input.executionToken,
|
|
2565
|
+
identity: input.identity
|
|
2566
|
+
});
|
|
2567
|
+
assertProjectionRunTargets(run, input.resolved);
|
|
2568
|
+
return { projectionRuns, run };
|
|
2569
|
+
}
|
|
2570
|
+
function assertProjectionRunTargets(run, resolved) {
|
|
2571
|
+
if (projectionRunTargetsMatch(run, resolved.definition))
|
|
2572
|
+
return;
|
|
2573
|
+
throw new MaterializationConflictError("run-correlation", `Projection run '${run.id}' target object types do not match projection '${resolved.projectionId}'.`);
|
|
2574
|
+
}
|
|
2575
|
+
function projectionRunTargetsMatch(run, definition) {
|
|
2576
|
+
switch (definition._tag) {
|
|
2577
|
+
case "ObjectProjectionDefinition":
|
|
2578
|
+
case "TelemetryProjectionDefinition":
|
|
2579
|
+
return "objectTypeId" in run.target && run.target.objectTypeId === definition.objectTypeId;
|
|
2580
|
+
case "LinkProjectionDefinition":
|
|
2581
|
+
return "sourceObjectTypeId" in run.target && run.target.sourceObjectTypeId === definition.sourceObjectTypeId && run.target.targetObjectTypeId === definition.targetObjectTypeId;
|
|
2582
|
+
}
|
|
2583
|
+
}
|
|
2584
|
+
|
|
2585
|
+
// src/materializer/shared/projection-run.ts
|
|
2586
|
+
function createProjectionRunMaterializationIdentity(input) {
|
|
2587
|
+
const base = {
|
|
2588
|
+
projectionId: input.resolved.projectionId,
|
|
2589
|
+
datasetVersion: input.datasetVersion,
|
|
2590
|
+
ontologyRevision: input.ontologyRevision,
|
|
2591
|
+
projectionRevision: input.resolved.projectionRevision,
|
|
2592
|
+
ownershipHash: input.resolved.ownershipHash
|
|
2593
|
+
};
|
|
2594
|
+
switch (input.resolved.definition._tag) {
|
|
2595
|
+
case "ObjectProjectionDefinition":
|
|
2596
|
+
return { ...base, projectionKind: "object", protocol: "replacement" };
|
|
2597
|
+
case "LinkProjectionDefinition":
|
|
2598
|
+
return { ...base, projectionKind: "link", protocol: "replacement" };
|
|
2599
|
+
case "TelemetryProjectionDefinition":
|
|
2600
|
+
return { ...base, projectionKind: "telemetry", protocol: "telemetry" };
|
|
2601
|
+
default:
|
|
2602
|
+
throw new MaterializationValidationError("Expected a supported projection definition.");
|
|
2603
|
+
}
|
|
2604
|
+
}
|
|
2605
|
+
|
|
2606
|
+
// src/materializer/projections/finish-run.ts
|
|
2607
|
+
async function finishProjectionRun(context, raw) {
|
|
2608
|
+
const command = prepareProjectionRunFinish(context, raw);
|
|
2609
|
+
await withSerializationRetry(context, () => context.storage.transaction((storage) => finishProjectionRunTransaction(storage, command), {
|
|
2610
|
+
isolation: "serializable"
|
|
2611
|
+
}));
|
|
2612
|
+
}
|
|
2613
|
+
function prepareProjectionRunFinish(context, raw) {
|
|
2614
|
+
assertValidTerminalDecision(raw);
|
|
2615
|
+
const source = normalizeProjectionSourceRef(raw.source);
|
|
2616
|
+
const datasetVersion = normalizePinnedDatasetVersion(raw.datasetVersion);
|
|
2617
|
+
const execution = normalizeProjectionExecution(raw.execution);
|
|
2618
|
+
const resolved = raw.protocol === "replacement" ? context.projectionRegistry.resolveSource(source.projectionId) : context.projectionRegistry.resolveTelemetry(source.projectionId);
|
|
2619
|
+
if (resolved.datasetId !== datasetVersion.datasetId) {
|
|
2620
|
+
throw new MaterializationValidationError(`Projection '${resolved.projectionId}' requires dataset '${resolved.datasetId}'.`);
|
|
2621
|
+
}
|
|
2622
|
+
const identity = createProjectionRunMaterializationIdentity({
|
|
2623
|
+
resolved,
|
|
2624
|
+
datasetVersion,
|
|
2625
|
+
ontologyRevision: context.projectionRegistry.ontologyRevision
|
|
2626
|
+
});
|
|
2627
|
+
return {
|
|
2628
|
+
projectId: context.projectId,
|
|
2629
|
+
input: { ...raw, source, datasetVersion, execution },
|
|
2630
|
+
identity,
|
|
2631
|
+
resolved,
|
|
2632
|
+
finishedAt: context.clock()
|
|
2633
|
+
};
|
|
2634
|
+
}
|
|
2635
|
+
async function finishProjectionRunTransaction(storage, command) {
|
|
2636
|
+
const { projectionRuns } = await lockProjectionRunForMaterialization(storage, {
|
|
2637
|
+
projectId: command.projectId,
|
|
2638
|
+
projectionRunId: command.input.execution.projectionRunId,
|
|
2639
|
+
executionToken: command.input.execution.executionToken,
|
|
2640
|
+
identity: command.identity,
|
|
2641
|
+
resolved: command.resolved
|
|
2642
|
+
});
|
|
2643
|
+
if (command.input.protocol === "replacement") {
|
|
2644
|
+
await assertReplacementTerminalDecision(storage, command);
|
|
2645
|
+
}
|
|
2646
|
+
await projectionRuns.finish({
|
|
2647
|
+
id: command.input.execution.projectionRunId,
|
|
2648
|
+
projectId: command.projectId,
|
|
2649
|
+
executionToken: command.input.execution.executionToken,
|
|
2650
|
+
identity: command.identity,
|
|
2651
|
+
...terminalDecision(command.input),
|
|
2652
|
+
finishedAt: command.finishedAt
|
|
2653
|
+
});
|
|
2654
|
+
}
|
|
2655
|
+
function assertValidTerminalDecision(input) {
|
|
2656
|
+
if (input.protocol !== "replacement" && input.protocol !== "telemetry") {
|
|
2657
|
+
throw new MaterializationValidationError("Projection finish protocol is invalid.");
|
|
2658
|
+
}
|
|
2659
|
+
if (input.status !== "succeeded" && input.status !== "failed" && input.status !== "cancelled") {
|
|
2660
|
+
throw new MaterializationValidationError("Projection finish status must be terminal.");
|
|
2661
|
+
}
|
|
2662
|
+
const inputExhausted = "inputExhausted" in input ? input.inputExhausted : undefined;
|
|
2663
|
+
if (input.status === "succeeded" && input.protocol === "telemetry") {
|
|
2664
|
+
if (inputExhausted === true)
|
|
2665
|
+
return;
|
|
2666
|
+
throw new MaterializationValidationError("Telemetry projection success requires an explicit exhausted-input acknowledgement.");
|
|
2667
|
+
}
|
|
2668
|
+
if (inputExhausted !== undefined) {
|
|
2669
|
+
throw new MaterializationValidationError("Only telemetry projection success can acknowledge exhausted input.");
|
|
2670
|
+
}
|
|
2671
|
+
}
|
|
2672
|
+
function terminalDecision(input) {
|
|
2673
|
+
if (input.status !== "succeeded") {
|
|
2674
|
+
return {
|
|
2675
|
+
protocol: input.protocol,
|
|
2676
|
+
status: input.status,
|
|
2677
|
+
...input.errorMessage === undefined ? {} : { errorMessage: input.errorMessage }
|
|
2678
|
+
};
|
|
2679
|
+
}
|
|
2680
|
+
if (input.protocol === "telemetry") {
|
|
2681
|
+
return { protocol: "telemetry", status: "succeeded", inputExhausted: true };
|
|
2682
|
+
}
|
|
2683
|
+
return { protocol: "replacement", status: "succeeded" };
|
|
2684
|
+
}
|
|
2685
|
+
async function assertReplacementTerminalDecision(storage, command) {
|
|
2686
|
+
const commit = await storage.ontology.commits.getByOrigin({
|
|
2687
|
+
projectId: command.projectId,
|
|
2688
|
+
origin: {
|
|
2689
|
+
kind: "projection",
|
|
2690
|
+
projectionRunId: command.input.execution.projectionRunId
|
|
2691
|
+
}
|
|
2692
|
+
});
|
|
2693
|
+
if (command.input.status === "succeeded") {
|
|
2694
|
+
if (!commit) {
|
|
2695
|
+
throw new MaterializationConflictError("run-correlation", `Projection replacement run '${command.input.execution.projectionRunId}' cannot succeed before its ontology commit exists.`);
|
|
2696
|
+
}
|
|
2697
|
+
assertReplacementCommitCorrelation(commit, command);
|
|
2698
|
+
return;
|
|
2699
|
+
}
|
|
2700
|
+
if (commit) {
|
|
2701
|
+
throw new MaterializationConflictError("run-correlation", `Projection replacement run '${command.input.execution.projectionRunId}' cannot finish as '${command.input.status}' after its ontology commit exists.`);
|
|
2702
|
+
}
|
|
2703
|
+
}
|
|
2704
|
+
function assertReplacementCommitCorrelation(commit, command) {
|
|
2705
|
+
const { input, identity } = command;
|
|
2706
|
+
if (commit.origin.kind !== "projection" || commit.intent.kind !== "projection" || commit.result.kind !== "projection" || commit.origin.projectionRunId !== input.execution.projectionRunId || commit.origin.projectionId !== input.source.projectionId || commit.intent.source.projectionId !== input.source.projectionId || !datasetVersionsEqual(commit.intent.datasetVersion, input.datasetVersion) || commit.ontologyRevision !== identity.ontologyRevision || commit.projectionRevision !== identity.projectionRevision || commit.ownershipHash !== identity.ownershipHash) {
|
|
2707
|
+
throw new MaterializationConflictError("run-correlation", `Projection replacement run '${input.execution.projectionRunId}' commit identity does not match.`);
|
|
2708
|
+
}
|
|
2709
|
+
}
|
|
2710
|
+
function datasetVersionsEqual(left, right) {
|
|
2711
|
+
return left.datasetId === right.datasetId && left.versionId === right.versionId && left.createdAt === right.createdAt;
|
|
2712
|
+
}
|
|
2713
|
+
|
|
2714
|
+
// src/materializer/projections/entry-validator.ts
|
|
2715
|
+
function createProjectionEntryValidator(ontology, resolved) {
|
|
2716
|
+
const policy = createValidationPolicy(resolved);
|
|
2717
|
+
return (entry) => validateProjectionEntry(ontology, resolved, policy, entry);
|
|
2718
|
+
}
|
|
2719
|
+
function createValidationPolicy(resolved) {
|
|
2720
|
+
const ownedProperties = new Map(resolved.ownership.objects.map((object) => [object.objectTypeId, new Set(object.propertyIds)]));
|
|
2721
|
+
const ownedLinks = new Set(resolved.ownership.links.map((link) => linkOwnershipKey(link.sourceObjectTypeId, link.linkId)));
|
|
2722
|
+
if (resolved.definition._tag === "ObjectProjectionDefinition") {
|
|
2723
|
+
return {
|
|
2724
|
+
expectedRootKind: "object",
|
|
2725
|
+
expectedRootDescription: "an object",
|
|
2726
|
+
ownedProperties,
|
|
2727
|
+
ownedLinks
|
|
2728
|
+
};
|
|
2729
|
+
}
|
|
2730
|
+
return {
|
|
2731
|
+
expectedRootKind: "link",
|
|
2732
|
+
expectedRootDescription: "a link",
|
|
2733
|
+
ownedProperties,
|
|
2734
|
+
ownedLinks
|
|
2735
|
+
};
|
|
2736
|
+
}
|
|
2737
|
+
function validateProjectionEntry(ontology, resolved, policy, entry) {
|
|
2738
|
+
validateProjectionRoot(resolved, policy, entry);
|
|
2739
|
+
return {
|
|
2740
|
+
root: entry.root,
|
|
2741
|
+
assertions: entry.assertions.map((assertion) => validateProjectionAssertion(ontology, resolved, policy, assertion))
|
|
2742
|
+
};
|
|
2743
|
+
}
|
|
2744
|
+
function validateProjectionRoot(resolved, policy, entry) {
|
|
2745
|
+
if (entry.root.kind === policy.expectedRootKind)
|
|
2746
|
+
return;
|
|
2747
|
+
throw new MaterializationValidationError(`Projection '${resolved.projectionId}' requires ${policy.expectedRootDescription} root.`);
|
|
2748
|
+
}
|
|
2749
|
+
function validateProjectionAssertion(ontology, resolved, policy, assertion) {
|
|
2750
|
+
if (assertion.kind === "object") {
|
|
2751
|
+
return validateObjectAssertion(ontology, resolved, policy, assertion);
|
|
2752
|
+
}
|
|
2753
|
+
return validateLinkAssertion(ontology, resolved, policy, assertion);
|
|
2754
|
+
}
|
|
2755
|
+
function validateObjectAssertion(ontology, resolved, policy, assertion) {
|
|
2756
|
+
if (resolved.definition._tag !== "ObjectProjectionDefinition" || assertion.ref.objectTypeId !== resolved.definition.objectTypeId) {
|
|
2757
|
+
throw new MaterializationValidationError("Projection asserted an object outside its owned type.");
|
|
2758
|
+
}
|
|
2759
|
+
const properties = validateObjectAuthorityProperties(ontology, assertion.ref, assertion.properties);
|
|
2760
|
+
const owned = policy.ownedProperties.get(assertion.ref.objectTypeId) ?? new Set;
|
|
2761
|
+
for (const propertyId of Object.keys(properties)) {
|
|
2762
|
+
if (owned.has(propertyId))
|
|
2763
|
+
continue;
|
|
2764
|
+
throw new MaterializationValidationError(`Projection '${resolved.projectionId}' asserted unowned property '${assertion.ref.objectTypeId}.${propertyId}'.`);
|
|
2765
|
+
}
|
|
2766
|
+
return { ...assertion, properties };
|
|
2767
|
+
}
|
|
2768
|
+
function validateLinkAssertion(ontology, resolved, policy, assertion) {
|
|
2769
|
+
const ownershipKey = linkOwnershipKey(assertion.ref.source.objectTypeId, assertion.ref.linkId);
|
|
2770
|
+
if (!policy.ownedLinks.has(ownershipKey)) {
|
|
2771
|
+
throw new MaterializationValidationError("Projection asserted a link outside its owned scope.");
|
|
2772
|
+
}
|
|
2773
|
+
const expectedTargetTypeId = projectionLinkTargetType(resolved, assertion);
|
|
2774
|
+
if (expectedTargetTypeId !== assertion.ref.target.objectTypeId) {
|
|
2775
|
+
throw new MaterializationValidationError(`Projection '${resolved.projectionId}' asserted link target type '${assertion.ref.target.objectTypeId}' outside its mapping.`);
|
|
2776
|
+
}
|
|
2777
|
+
validateLinkAuthorityProperties(ontology, assertion.ref, assertion.properties);
|
|
2778
|
+
if (assertion.properties !== undefined) {
|
|
2779
|
+
throw new MaterializationValidationError(`Projection '${resolved.projectionId}' does not map link assertion properties.`);
|
|
2780
|
+
}
|
|
2781
|
+
return { ...assertion };
|
|
2782
|
+
}
|
|
2783
|
+
function projectionLinkTargetType(resolved, assertion) {
|
|
2784
|
+
if (resolved.definition._tag === "LinkProjectionDefinition") {
|
|
2785
|
+
return resolved.definition.targetObjectTypeId;
|
|
2786
|
+
}
|
|
2787
|
+
if (resolved.definition._tag === "ObjectProjectionDefinition") {
|
|
2788
|
+
return resolved.definition.links[assertion.ref.linkId]?.targetObjectTypeId;
|
|
2789
|
+
}
|
|
2790
|
+
return;
|
|
2791
|
+
}
|
|
2792
|
+
|
|
2793
|
+
// src/materializer/projections/replacement-plan.ts
|
|
2794
|
+
async function planProjectionReplacement(context, storage, session, input) {
|
|
2795
|
+
const counts = emptyCounts();
|
|
2796
|
+
if (input.projectionKind === "object") {
|
|
2797
|
+
await planObjectReplacement(context, storage, session, input, counts);
|
|
2798
|
+
}
|
|
2799
|
+
await planLinkReplacement(context, storage, session, input, counts);
|
|
2800
|
+
await validateStagedCardinality(context, storage, session, input.signal);
|
|
2801
|
+
return counts;
|
|
2802
|
+
}
|
|
2803
|
+
async function planObjectReplacement(context, storage, session, input, counts) {
|
|
2804
|
+
for await (const page of storage.streamSourceReplacementState({
|
|
2805
|
+
session,
|
|
2806
|
+
source: input.source,
|
|
2807
|
+
candidateMaterializationId: input.materializationId,
|
|
2808
|
+
entityKind: "object",
|
|
2809
|
+
pageRows: context.batching.statePageRows
|
|
2810
|
+
})) {
|
|
2811
|
+
throwIfAborted(input.signal);
|
|
2812
|
+
const work = planObjectPage(context, input, page, counts);
|
|
2813
|
+
await stageWorkBounded(context, storage, session, work);
|
|
2814
|
+
}
|
|
2815
|
+
}
|
|
2816
|
+
function planObjectPage(context, input, page, counts) {
|
|
2817
|
+
const work = [];
|
|
2818
|
+
for (const state of page.objects) {
|
|
2819
|
+
work.push(...planReplacementObject(context, input, state, counts));
|
|
2820
|
+
}
|
|
2821
|
+
return work;
|
|
2822
|
+
}
|
|
2823
|
+
function planReplacementObject(context, input, state, counts) {
|
|
2824
|
+
const resolved = resolveReplacementObject(context, state);
|
|
2825
|
+
if (resolved)
|
|
2826
|
+
validateEffectiveObject(context.ontology, resolved.ref, resolved.properties);
|
|
2827
|
+
const change = diffEffectiveObject({
|
|
2828
|
+
before: state.effective,
|
|
2829
|
+
resolved,
|
|
2830
|
+
commitId: input.identity.commitId,
|
|
2831
|
+
committedAt: input.identity.committedAt
|
|
2832
|
+
});
|
|
2833
|
+
const sortKey = objectRefSortKey(state.ref);
|
|
2834
|
+
const work = [
|
|
2835
|
+
classificationWork("object", objectRefKey(state.ref), sortKey),
|
|
2836
|
+
{
|
|
2837
|
+
kind: "object-existence",
|
|
2838
|
+
recordKey: `existence:${sortKey}`,
|
|
2839
|
+
ref: state.ref,
|
|
2840
|
+
exists: resolved !== null
|
|
2841
|
+
}
|
|
2842
|
+
];
|
|
2843
|
+
if (Boolean(state.effective) !== Boolean(resolved)) {
|
|
2844
|
+
work.push({ kind: "incident-object", recordKey: `incident:${sortKey}`, ref: state.ref });
|
|
2845
|
+
}
|
|
2846
|
+
if (!change) {
|
|
2847
|
+
counts.objectsUnchanged += 1;
|
|
2848
|
+
return work;
|
|
2849
|
+
}
|
|
2850
|
+
incrementObjectCount(counts, change.kind);
|
|
2851
|
+
appendObjectChangeWork(work, sortKey, context, input, change);
|
|
2852
|
+
return work;
|
|
2853
|
+
}
|
|
2854
|
+
function appendObjectChangeWork(work, sortKey, context, input, change) {
|
|
2855
|
+
const items = [];
|
|
2856
|
+
appendObjectEffectivePlan(items, change);
|
|
2857
|
+
for (const item of items)
|
|
2858
|
+
work.push(planWork(item, sortKey));
|
|
2859
|
+
work.push(eventWork(buildObjectMaterializationEventDraft({
|
|
2860
|
+
projectId: context.projectId,
|
|
2861
|
+
commitId: input.identity.commitId,
|
|
2862
|
+
committedAt: input.identity.committedAt,
|
|
2863
|
+
origin: input.origin,
|
|
2864
|
+
change
|
|
2865
|
+
})));
|
|
2866
|
+
}
|
|
2867
|
+
async function planLinkReplacement(context, storage, session, input, counts) {
|
|
2868
|
+
for await (const page of storage.streamSourceReplacementState({
|
|
2869
|
+
session,
|
|
2870
|
+
source: input.source,
|
|
2871
|
+
candidateMaterializationId: input.materializationId,
|
|
2872
|
+
entityKind: "link",
|
|
2873
|
+
pageRows: context.batching.statePageRows
|
|
2874
|
+
})) {
|
|
2875
|
+
throwIfAborted(input.signal);
|
|
2876
|
+
const endpointExistence = await loadEndpointExistence(context, storage, session, page);
|
|
2877
|
+
const work = planLinkPage(context, input, page, endpointExistence, counts);
|
|
2878
|
+
await stageWorkBounded(context, storage, session, work);
|
|
2879
|
+
}
|
|
2880
|
+
}
|
|
2881
|
+
async function loadEndpointExistence(context, storage, session, page) {
|
|
2882
|
+
const endpointRefs = collectEndpointRefs(page.links);
|
|
2883
|
+
const endpointExistence = new Map;
|
|
2884
|
+
for (const value of await storage.readObjectExistence({
|
|
2885
|
+
session,
|
|
2886
|
+
refs: [...endpointRefs.values()]
|
|
2887
|
+
})) {
|
|
2888
|
+
endpointExistence.set(objectRefKey(value.ref), value.exists);
|
|
2889
|
+
}
|
|
2890
|
+
const missingEndpoints = [...endpointRefs.values()].filter((ref) => !endpointExistence.has(objectRefKey(ref)));
|
|
2891
|
+
if (missingEndpoints.length === 0)
|
|
2892
|
+
return endpointExistence;
|
|
2893
|
+
for await (const endpointPage of storage.streamState({
|
|
2894
|
+
session,
|
|
2895
|
+
requests: oneStateRequest({
|
|
2896
|
+
objects: missingEndpoints,
|
|
2897
|
+
links: [],
|
|
2898
|
+
linkScopes: [],
|
|
2899
|
+
incidentObjects: [],
|
|
2900
|
+
points: []
|
|
2901
|
+
}),
|
|
2902
|
+
pageRows: context.batching.statePageRows
|
|
2903
|
+
})) {
|
|
2904
|
+
for (const endpoint of endpointPage.objects) {
|
|
2905
|
+
endpointExistence.set(objectRefKey(endpoint.ref), endpoint.effective !== null);
|
|
2906
|
+
}
|
|
2907
|
+
}
|
|
2908
|
+
return endpointExistence;
|
|
2909
|
+
}
|
|
2910
|
+
function collectEndpointRefs(links) {
|
|
2911
|
+
const refs = new Map;
|
|
2912
|
+
for (const state of links) {
|
|
2913
|
+
refs.set(objectRefKey(state.ref.source), state.ref.source);
|
|
2914
|
+
refs.set(objectRefKey(state.ref.target), state.ref.target);
|
|
2915
|
+
}
|
|
2916
|
+
return refs;
|
|
2917
|
+
}
|
|
2918
|
+
function planLinkPage(context, input, page, endpointExistence, counts) {
|
|
2919
|
+
const work = [];
|
|
2920
|
+
for (const state of page.links) {
|
|
2921
|
+
work.push(...planReplacementLink(context, input, state, endpointExistence, counts));
|
|
2922
|
+
}
|
|
2923
|
+
return work;
|
|
2924
|
+
}
|
|
2925
|
+
function planReplacementLink(context, input, state, endpointExistence, counts) {
|
|
2926
|
+
const resolved = resolveReplacementLink(state, endpointExistence);
|
|
2927
|
+
const work = cardinalityWork(context, state, resolved !== null);
|
|
2928
|
+
if (!state.diffRequired)
|
|
2929
|
+
return work;
|
|
2930
|
+
const change = diffEffectiveLink({
|
|
2931
|
+
before: state.effective,
|
|
2932
|
+
resolved,
|
|
2933
|
+
commitId: input.identity.commitId,
|
|
2934
|
+
committedAt: input.identity.committedAt
|
|
2935
|
+
});
|
|
2936
|
+
const sortKey = linkRefSortKey(state.ref);
|
|
2937
|
+
work.push(classificationWork("link", linkRefKey(state.ref), sortKey));
|
|
2938
|
+
if (!change) {
|
|
2939
|
+
counts.linksUnchanged += 1;
|
|
2940
|
+
return work;
|
|
2941
|
+
}
|
|
2942
|
+
incrementLinkCount(counts, change.kind);
|
|
2943
|
+
appendLinkChangeWork(work, sortKey, context, input, change);
|
|
2944
|
+
return work;
|
|
2945
|
+
}
|
|
2946
|
+
function resolveReplacementLink(state, endpointExistence) {
|
|
2947
|
+
if (!state.diffRequired)
|
|
2948
|
+
return state.effective;
|
|
2949
|
+
return resolveEffectiveLink({
|
|
2950
|
+
ref: state.ref,
|
|
2951
|
+
source: state.candidateSource,
|
|
2952
|
+
override: state.override?.value ?? null,
|
|
2953
|
+
sourceEndpointExists: endpointExistence.get(objectRefKey(state.ref.source)) ?? false,
|
|
2954
|
+
targetEndpointExists: endpointExistence.get(objectRefKey(state.ref.target)) ?? false
|
|
2955
|
+
});
|
|
2956
|
+
}
|
|
2957
|
+
function cardinalityWork(context, state, occupied) {
|
|
2958
|
+
const definition = context.ontology.resolveObjectType(state.ref.source.objectTypeId).links.find((candidate) => candidate.id === state.ref.linkId);
|
|
2959
|
+
if (definition?.cardinality !== "one")
|
|
2960
|
+
return [];
|
|
2961
|
+
const scopeSortKey = linkScopeSortKey(state.ref.source, state.ref.linkId);
|
|
2962
|
+
const linkSortKey = linkRefSortKey(state.ref);
|
|
2963
|
+
return [
|
|
2964
|
+
{
|
|
2965
|
+
kind: "cardinality",
|
|
2966
|
+
recordKey: `cardinality:${scopeSortKey}:${linkSortKey}`,
|
|
2967
|
+
scopeSortKey,
|
|
2968
|
+
linkSortKey,
|
|
2969
|
+
ref: state.ref,
|
|
2970
|
+
occupied
|
|
2971
|
+
}
|
|
2972
|
+
];
|
|
2973
|
+
}
|
|
2974
|
+
function appendLinkChangeWork(work, sortKey, context, input, change) {
|
|
2975
|
+
const items = [];
|
|
2976
|
+
appendLinkEffectivePlan(items, change);
|
|
2977
|
+
for (const item of items)
|
|
2978
|
+
work.push(planWork(item, sortKey));
|
|
2979
|
+
work.push(eventWork(buildLinkMaterializationEventDraft({
|
|
2980
|
+
projectId: context.projectId,
|
|
2981
|
+
commitId: input.identity.commitId,
|
|
2982
|
+
committedAt: input.identity.committedAt,
|
|
2983
|
+
origin: input.origin,
|
|
2984
|
+
change
|
|
2985
|
+
})));
|
|
2986
|
+
}
|
|
2987
|
+
function resolveReplacementObject(context, state) {
|
|
2988
|
+
return resolveEffectiveObject({
|
|
2989
|
+
ref: state.ref,
|
|
2990
|
+
primaryPropertyId: context.ontology.getPrimaryPropertyId(state.ref.objectTypeId),
|
|
2991
|
+
source: state.candidateSource,
|
|
2992
|
+
override: state.override?.value ?? null,
|
|
2993
|
+
latestTelemetry: state.latestTelemetry
|
|
2994
|
+
});
|
|
2995
|
+
}
|
|
2996
|
+
function emptyCounts() {
|
|
2997
|
+
return {
|
|
2998
|
+
objectsCreated: 0,
|
|
2999
|
+
objectsUpdated: 0,
|
|
3000
|
+
objectsDeleted: 0,
|
|
3001
|
+
objectsUnchanged: 0,
|
|
3002
|
+
linksCreated: 0,
|
|
3003
|
+
linksUpdated: 0,
|
|
3004
|
+
linksDeleted: 0,
|
|
3005
|
+
linksUnchanged: 0
|
|
3006
|
+
};
|
|
3007
|
+
}
|
|
3008
|
+
function incrementObjectCount(counts, kind) {
|
|
3009
|
+
if (kind === "created")
|
|
3010
|
+
counts.objectsCreated += 1;
|
|
3011
|
+
else if (kind === "updated")
|
|
3012
|
+
counts.objectsUpdated += 1;
|
|
3013
|
+
else
|
|
3014
|
+
counts.objectsDeleted += 1;
|
|
3015
|
+
}
|
|
3016
|
+
function incrementLinkCount(counts, kind) {
|
|
3017
|
+
if (kind === "created")
|
|
3018
|
+
counts.linksCreated += 1;
|
|
3019
|
+
else if (kind === "updated")
|
|
3020
|
+
counts.linksUpdated += 1;
|
|
3021
|
+
else
|
|
3022
|
+
counts.linksDeleted += 1;
|
|
3023
|
+
}
|
|
3024
|
+
|
|
3025
|
+
// src/materializer/projections/source-materialization.ts
|
|
3026
|
+
async function stageProjectionMaterialization(context, input) {
|
|
3027
|
+
await context.storage.ontology.sources.beginMaterialization({
|
|
3028
|
+
projectId: context.projectId,
|
|
3029
|
+
source: input.source,
|
|
3030
|
+
materializationId: input.materializationId,
|
|
3031
|
+
execution: input.execution,
|
|
3032
|
+
projectionKind: input.projectionKind,
|
|
3033
|
+
protocol: "replacement",
|
|
3034
|
+
datasetVersion: input.datasetVersion,
|
|
3035
|
+
projectionRevision: input.projectionRevision,
|
|
3036
|
+
ownershipHash: input.ownershipHash,
|
|
3037
|
+
ontologyRevision: context.projectionRegistry.ontologyRevision,
|
|
3038
|
+
createdAt: input.createdAt
|
|
3039
|
+
});
|
|
3040
|
+
let rootCount = 0;
|
|
3041
|
+
let assertionCount = 0;
|
|
3042
|
+
async function* assertions() {
|
|
3043
|
+
for await (const rawEntry of input.entries) {
|
|
3044
|
+
throwIfAborted(input.signal);
|
|
3045
|
+
const entry = input.validateEntry(normalizeProjectionSourceEntry(rawEntry));
|
|
3046
|
+
const stagingOrdinal = rootCount;
|
|
3047
|
+
for (const assertion of entry.assertions) {
|
|
3048
|
+
assertionCount += 1;
|
|
3049
|
+
yield { root: entry.root, assertion, stagingOrdinal };
|
|
3050
|
+
}
|
|
3051
|
+
rootCount += 1;
|
|
3052
|
+
}
|
|
3053
|
+
throwIfAborted(input.signal);
|
|
3054
|
+
}
|
|
3055
|
+
for await (const rows of chunkBySize(assertions(), {
|
|
3056
|
+
maxRows: context.batching.sourceStageRows,
|
|
3057
|
+
maxBytes: context.batching.sourceStageBytes,
|
|
3058
|
+
byteLength: utf8JsonByteLength
|
|
3059
|
+
})) {
|
|
3060
|
+
await context.storage.ontology.sources.stageRows({
|
|
3061
|
+
projectId: context.projectId,
|
|
3062
|
+
source: input.source,
|
|
3063
|
+
materializationId: input.materializationId,
|
|
3064
|
+
execution: input.execution,
|
|
3065
|
+
rows
|
|
3066
|
+
});
|
|
3067
|
+
}
|
|
3068
|
+
await context.storage.ontology.sources.markReady({
|
|
3069
|
+
projectId: context.projectId,
|
|
3070
|
+
source: input.source,
|
|
3071
|
+
materializationId: input.materializationId,
|
|
3072
|
+
execution: input.execution,
|
|
3073
|
+
rootCount,
|
|
3074
|
+
assertionCount,
|
|
3075
|
+
readyAt: context.clock().toISOString()
|
|
3076
|
+
});
|
|
3077
|
+
return { rootCount, assertionCount };
|
|
3078
|
+
}
|
|
3079
|
+
|
|
3080
|
+
// src/materializer/projections/replace.ts
|
|
3081
|
+
async function replaceProjection(context, raw) {
|
|
3082
|
+
const command = prepareProjectionReplacement(context, raw);
|
|
3083
|
+
await assertProjectionExecution(context.storage, context.projectId, command, {
|
|
3084
|
+
capabilityErrorMessage: "Storage does not provide projection run capabilities required by source replacement."
|
|
3085
|
+
});
|
|
3086
|
+
const replay = await replayProjectionCommit(context, command);
|
|
3087
|
+
if (replay)
|
|
3088
|
+
return replay;
|
|
3089
|
+
const candidate = await prepareProjectionCandidate(context, command);
|
|
3090
|
+
try {
|
|
3091
|
+
const ready = await stageProjectionCandidate(context, command, candidate);
|
|
3092
|
+
return await commitProjectionCandidate(context, command, ready);
|
|
3093
|
+
} catch (error) {
|
|
3094
|
+
await abandonFailedCandidate(context, command, candidate, error);
|
|
3095
|
+
throw error;
|
|
3096
|
+
}
|
|
3097
|
+
}
|
|
3098
|
+
function prepareProjectionReplacement(context, raw) {
|
|
3099
|
+
const source = normalizeProjectionSourceRef(raw.source);
|
|
3100
|
+
const datasetVersion = normalizePinnedDatasetVersion(raw.datasetVersion);
|
|
3101
|
+
const execution = normalizeProjectionExecution(raw.execution);
|
|
3102
|
+
const resolved = context.projectionRegistry.resolveSource(source.projectionId);
|
|
3103
|
+
validateProjectionDataset(resolved, datasetVersion);
|
|
3104
|
+
const projectionKind = sourceProjectionKind(resolved);
|
|
3105
|
+
const runIdentity = createProjectionRunMaterializationIdentity({
|
|
3106
|
+
resolved,
|
|
3107
|
+
datasetVersion,
|
|
3108
|
+
ontologyRevision: context.projectionRegistry.ontologyRevision
|
|
3109
|
+
});
|
|
3110
|
+
const identity = createCommitIdentity({
|
|
3111
|
+
projectId: context.projectId,
|
|
3112
|
+
idempotencyKey: createProjectionIdempotencyKey(runIdentity),
|
|
3113
|
+
normalizedCallerIntent: { source, datasetVersion }
|
|
3114
|
+
});
|
|
3115
|
+
const command = {
|
|
3116
|
+
source,
|
|
3117
|
+
datasetVersion,
|
|
3118
|
+
execution,
|
|
3119
|
+
entries: raw.entries,
|
|
3120
|
+
resolved,
|
|
3121
|
+
projectionKind,
|
|
3122
|
+
runIdentity,
|
|
3123
|
+
identity
|
|
3124
|
+
};
|
|
3125
|
+
if (raw.signal === undefined)
|
|
3126
|
+
return command;
|
|
3127
|
+
return { ...command, signal: raw.signal };
|
|
3128
|
+
}
|
|
3129
|
+
function validateProjectionDataset(resolved, datasetVersion) {
|
|
3130
|
+
if (datasetVersion.datasetId === resolved.datasetId)
|
|
3131
|
+
return;
|
|
3132
|
+
throw new MaterializationValidationError(`Projection '${resolved.projectionId}' requires dataset '${resolved.datasetId}'.`);
|
|
3133
|
+
}
|
|
3134
|
+
function sourceProjectionKind(resolved) {
|
|
3135
|
+
if (resolved.definition._tag === "ObjectProjectionDefinition")
|
|
3136
|
+
return "object";
|
|
3137
|
+
return "link";
|
|
3138
|
+
}
|
|
3139
|
+
async function assertProjectionExecution(storage, projectId, command, options = {}) {
|
|
3140
|
+
await lockProjectionRunForMaterialization(storage, {
|
|
3141
|
+
projectId,
|
|
3142
|
+
projectionRunId: command.execution.projectionRunId,
|
|
3143
|
+
executionToken: command.execution.executionToken,
|
|
3144
|
+
identity: command.runIdentity,
|
|
3145
|
+
resolved: command.resolved,
|
|
3146
|
+
...options
|
|
3147
|
+
});
|
|
3148
|
+
}
|
|
3149
|
+
async function replayProjectionCommit(context, command) {
|
|
3150
|
+
const existing = await replayCommitRecord(context, command.identity);
|
|
3151
|
+
if (!existing)
|
|
3152
|
+
return null;
|
|
3153
|
+
return withSerializationRetry(context, () => context.storage.transaction(async (storage) => {
|
|
3154
|
+
await assertProjectionExecution(storage, context.projectId, command);
|
|
3155
|
+
const commit = await replayCommitRecord(context, command.identity, storage);
|
|
3156
|
+
return commit ? projectionReplayResult(commit, command) : null;
|
|
3157
|
+
}, { isolation: "serializable" }));
|
|
3158
|
+
}
|
|
3159
|
+
function projectionReplayResult(commit, command) {
|
|
3160
|
+
if (commit.origin.kind !== "projection" || commit.origin.projectionRunId !== command.execution.projectionRunId || commit.result.kind !== "projection") {
|
|
3161
|
+
throw new MaterializationConflictError("run-correlation", `Projection commit '${commit.id}' belongs to a different logical run.`);
|
|
3162
|
+
}
|
|
3163
|
+
return { ...structuredClone(commit.result), created: false };
|
|
3164
|
+
}
|
|
3165
|
+
async function prepareProjectionCandidate(context, command) {
|
|
3166
|
+
await context.storage.ontology.sources.abandon({
|
|
3167
|
+
kind: "reclaim",
|
|
3168
|
+
projectId: context.projectId,
|
|
3169
|
+
source: command.source,
|
|
3170
|
+
execution: command.execution,
|
|
3171
|
+
abandonedAt: context.clock().toISOString()
|
|
3172
|
+
});
|
|
3173
|
+
const active = await context.storage.ontology.sources.getActive({
|
|
3174
|
+
projectId: context.projectId,
|
|
3175
|
+
source: command.source
|
|
3176
|
+
});
|
|
3177
|
+
validateProjectionWatermark(active, command.datasetVersion);
|
|
3178
|
+
return {
|
|
3179
|
+
materializationId: context.materializationId(),
|
|
3180
|
+
createdAt: context.clock().toISOString(),
|
|
3181
|
+
expectedSource: {
|
|
3182
|
+
source: command.source,
|
|
3183
|
+
activeMaterializationId: active?.materializationId ?? null,
|
|
3184
|
+
lastCommitId: active?.lastCommitId ?? null
|
|
3185
|
+
}
|
|
3186
|
+
};
|
|
3187
|
+
}
|
|
3188
|
+
async function stageProjectionCandidate(context, command, candidate) {
|
|
3189
|
+
const input = {
|
|
3190
|
+
source: command.source,
|
|
3191
|
+
materializationId: candidate.materializationId,
|
|
3192
|
+
execution: command.execution,
|
|
3193
|
+
projectionKind: command.projectionKind,
|
|
3194
|
+
datasetVersion: command.datasetVersion,
|
|
3195
|
+
projectionRevision: command.resolved.projectionRevision,
|
|
3196
|
+
ownershipHash: command.resolved.ownershipHash,
|
|
3197
|
+
createdAt: candidate.createdAt,
|
|
3198
|
+
entries: command.entries,
|
|
3199
|
+
validateEntry: createProjectionEntryValidator(context.ontology, command.resolved)
|
|
3200
|
+
};
|
|
3201
|
+
const staged = await stageCandidateEntries(context, input, command.signal);
|
|
3202
|
+
return {
|
|
3203
|
+
...candidate,
|
|
3204
|
+
staged,
|
|
3205
|
+
identity: timestampCommitIdentity(command.identity, context.clock())
|
|
3206
|
+
};
|
|
3207
|
+
}
|
|
3208
|
+
async function stageCandidateEntries(context, input, signal) {
|
|
3209
|
+
if (signal === undefined)
|
|
3210
|
+
return stageProjectionMaterialization(context, input);
|
|
3211
|
+
return stageProjectionMaterialization(context, { ...input, signal });
|
|
3212
|
+
}
|
|
3213
|
+
async function commitProjectionCandidate(context, command, ready) {
|
|
3214
|
+
return withSerializationRetry(context, () => context.storage.transaction((storage) => executeProjectionTransaction(context, storage, command, ready), { isolation: "serializable" }));
|
|
3215
|
+
}
|
|
3216
|
+
async function executeProjectionTransaction(context, storage, command, ready) {
|
|
3217
|
+
await assertProjectionExecution(storage, context.projectId, command);
|
|
3218
|
+
const replay = await replayCommitRecord(context, command.identity, storage);
|
|
3219
|
+
if (replay)
|
|
3220
|
+
return projectionReplayResult(replay, command);
|
|
3221
|
+
const origin = projectionOrigin(command);
|
|
3222
|
+
throwIfAborted(command.signal);
|
|
3223
|
+
const session = await storage.ontology.materializations.begin({
|
|
3224
|
+
commit: projectionCommit(context.projectId, command, ready.identity, origin),
|
|
3225
|
+
expected: {
|
|
3226
|
+
sources: [ready.expectedSource],
|
|
3227
|
+
objects: [],
|
|
3228
|
+
links: [],
|
|
3229
|
+
linkScopes: [],
|
|
3230
|
+
points: []
|
|
3231
|
+
}
|
|
3232
|
+
});
|
|
3233
|
+
const counts = await planReadyProjection(context, storage.ontology.materializations, session, command, ready, origin);
|
|
3234
|
+
await drainStagedWork(context, storage.ontology.materializations, session, command.signal);
|
|
3235
|
+
const eventCount = await drainStagedEvents(context, storage.ontology.materializations, session, ready.identity, command.signal);
|
|
3236
|
+
const result = {
|
|
3237
|
+
kind: "projection",
|
|
3238
|
+
commitId: ready.identity.commitId,
|
|
3239
|
+
created: true,
|
|
3240
|
+
eventCount,
|
|
3241
|
+
committedAt: ready.identity.committedAt,
|
|
3242
|
+
counts
|
|
3243
|
+
};
|
|
3244
|
+
throwIfAborted(command.signal);
|
|
3245
|
+
return finalizeProjectionMaterialization(storage, session, command, ready, result);
|
|
3246
|
+
}
|
|
3247
|
+
async function finalizeProjectionMaterialization(storage, session, command, ready, result) {
|
|
3248
|
+
const applied = await storage.ontology.materializations.finalize({
|
|
3249
|
+
session,
|
|
3250
|
+
finalization: {
|
|
3251
|
+
sourceActivations: [projectionActivation(command, ready)],
|
|
3252
|
+
result
|
|
3253
|
+
}
|
|
3254
|
+
});
|
|
3255
|
+
return applied.commit.result;
|
|
3256
|
+
}
|
|
3257
|
+
function projectionOrigin(command) {
|
|
3258
|
+
return {
|
|
3259
|
+
kind: "projection",
|
|
3260
|
+
projectionId: command.resolved.projectionId,
|
|
3261
|
+
projectionRunId: command.execution.projectionRunId,
|
|
3262
|
+
datasetId: command.datasetVersion.datasetId,
|
|
3263
|
+
datasetVersionId: command.datasetVersion.versionId
|
|
3264
|
+
};
|
|
3265
|
+
}
|
|
3266
|
+
function projectionCommit(projectId, command, identity, origin) {
|
|
3267
|
+
return {
|
|
3268
|
+
projectId,
|
|
3269
|
+
id: identity.commitId,
|
|
3270
|
+
idempotencyKey: identity.idempotencyKey,
|
|
3271
|
+
requestHash: identity.requestHash,
|
|
3272
|
+
origin,
|
|
3273
|
+
ontologyRevision: command.runIdentity.ontologyRevision,
|
|
3274
|
+
projectionRevision: command.runIdentity.projectionRevision,
|
|
3275
|
+
ownershipHash: command.runIdentity.ownershipHash,
|
|
3276
|
+
intent: { kind: "projection", source: command.source, datasetVersion: command.datasetVersion },
|
|
3277
|
+
committedAt: identity.committedAt
|
|
3278
|
+
};
|
|
3279
|
+
}
|
|
3280
|
+
async function planReadyProjection(context, storage, session, command, ready, origin) {
|
|
3281
|
+
const input = {
|
|
3282
|
+
source: command.source,
|
|
3283
|
+
materializationId: ready.materializationId,
|
|
3284
|
+
projectionKind: command.projectionKind,
|
|
3285
|
+
identity: ready.identity,
|
|
3286
|
+
origin
|
|
3287
|
+
};
|
|
3288
|
+
if (command.signal === undefined) {
|
|
3289
|
+
return planProjectionReplacement(context, storage, session, input);
|
|
3290
|
+
}
|
|
3291
|
+
return planProjectionReplacement(context, storage, session, {
|
|
3292
|
+
...input,
|
|
3293
|
+
signal: command.signal
|
|
3294
|
+
});
|
|
3295
|
+
}
|
|
3296
|
+
function projectionActivation(command, ready) {
|
|
3297
|
+
return {
|
|
3298
|
+
source: command.source,
|
|
3299
|
+
materializationId: ready.materializationId,
|
|
3300
|
+
execution: command.execution,
|
|
3301
|
+
projectionKind: command.projectionKind,
|
|
3302
|
+
protocol: "replacement",
|
|
3303
|
+
datasetVersion: command.datasetVersion,
|
|
3304
|
+
projectionRevision: command.runIdentity.projectionRevision,
|
|
3305
|
+
ownershipHash: command.runIdentity.ownershipHash,
|
|
3306
|
+
ontologyRevision: command.runIdentity.ontologyRevision,
|
|
3307
|
+
expected: ready.expectedSource,
|
|
3308
|
+
lastCommitId: ready.identity.commitId,
|
|
3309
|
+
updatedAt: ready.identity.committedAt
|
|
3310
|
+
};
|
|
3311
|
+
}
|
|
3312
|
+
async function abandonFailedCandidate(context, command, candidate, error) {
|
|
3313
|
+
if (!shouldAbandonCandidate(error))
|
|
3314
|
+
return;
|
|
3315
|
+
await context.storage.ontology.sources.abandon({
|
|
3316
|
+
kind: "candidate",
|
|
3317
|
+
projectId: context.projectId,
|
|
3318
|
+
source: command.source,
|
|
3319
|
+
materializationId: candidate.materializationId,
|
|
3320
|
+
execution: command.execution,
|
|
3321
|
+
abandonedAt: context.clock().toISOString()
|
|
3322
|
+
});
|
|
3323
|
+
}
|
|
3324
|
+
function shouldAbandonCandidate(error) {
|
|
3325
|
+
if (error instanceof MaterializationValidationError)
|
|
3326
|
+
return true;
|
|
3327
|
+
if (error instanceof MaterializationCancellationError)
|
|
3328
|
+
return true;
|
|
3329
|
+
return error instanceof MaterializationConflictError && error.kind === "run-correlation";
|
|
3330
|
+
}
|
|
3331
|
+
function validateProjectionWatermark(active, next) {
|
|
3332
|
+
if (!active)
|
|
3333
|
+
return;
|
|
3334
|
+
assertPinnedDatasetWatermark(active.datasetVersion, next, "Projection replacement");
|
|
3335
|
+
}
|
|
3336
|
+
|
|
3337
|
+
// src/materializer/telemetry/plan.ts
|
|
3338
|
+
async function planTelemetryAppend(context, storage, session, input, identity, origin) {
|
|
3339
|
+
const counts = emptyTelemetryCounts();
|
|
3340
|
+
const planContext = { input, identity, origin };
|
|
3341
|
+
const objects = await loadTelemetryObjects(context, storage, session, input.points);
|
|
3342
|
+
const existingPoints = await loadExistingPoints(context, storage, session, input.points);
|
|
3343
|
+
for (const group of telemetryObjectGroups(input.points)) {
|
|
3344
|
+
const storedObject = objects.get(objectRefKey(group.objectRef));
|
|
3345
|
+
if (!storedObject?.effective) {
|
|
3346
|
+
throw new MaterializationObjectNotFoundError(group.objectRef.objectTypeId, group.objectRef.primaryId);
|
|
3347
|
+
}
|
|
3348
|
+
await planTelemetryObject(context, storage, session, planContext, group, workingObjectFromState(storedObject), existingPoints, counts);
|
|
3349
|
+
}
|
|
3350
|
+
return counts;
|
|
3351
|
+
}
|
|
3352
|
+
function* telemetryObjectGroups(points) {
|
|
3353
|
+
let start = 0;
|
|
3354
|
+
while (start < points.length) {
|
|
3355
|
+
const objectRef = points[start].series.object;
|
|
3356
|
+
const objectKey = objectRefKey(objectRef);
|
|
3357
|
+
let end = start + 1;
|
|
3358
|
+
while (end < points.length && objectRefKey(points[end].series.object) === objectKey) {
|
|
3359
|
+
end += 1;
|
|
3360
|
+
}
|
|
3361
|
+
yield { objectRef, start, end };
|
|
3362
|
+
start = end;
|
|
3363
|
+
}
|
|
3364
|
+
}
|
|
3365
|
+
async function planTelemetryObject(context, storage, session, planContext, group, working, existingPoints, counts) {
|
|
3366
|
+
const latest = new Map(working.latestTelemetry.map((point) => [point.series.propertyId, point]));
|
|
3367
|
+
for (let start = group.start;start < group.end; start += context.batching.statePageRows) {
|
|
3368
|
+
const end = Math.min(group.end, start + context.batching.statePageRows);
|
|
3369
|
+
const points = planContext.input.points.slice(start, end);
|
|
3370
|
+
const work = planTelemetryChunk(context, planContext, points, existingPoints, latest, counts);
|
|
3371
|
+
await stageWorkBounded(context, storage, session, work);
|
|
3372
|
+
}
|
|
3373
|
+
working.latestTelemetry = [...latest.values()];
|
|
3374
|
+
await stageTelemetryObjectPlan(context, storage, session, planContext, working, counts);
|
|
3375
|
+
}
|
|
3376
|
+
async function loadTelemetryObjects(context, storage, session, points) {
|
|
3377
|
+
const refs = new Map;
|
|
3378
|
+
for (const point of points)
|
|
3379
|
+
refs.set(objectRefKey(point.series.object), point.series.object);
|
|
3380
|
+
const objectState = await loadState(context, storage, session, {
|
|
3381
|
+
objects: [...refs.values()],
|
|
3382
|
+
links: [],
|
|
3383
|
+
linkScopes: [],
|
|
3384
|
+
incidentObjects: [],
|
|
3385
|
+
points: []
|
|
3386
|
+
});
|
|
3387
|
+
return new Map(objectState.objects.map((object) => [objectRefKey(object.ref), object]));
|
|
3388
|
+
}
|
|
3389
|
+
function planTelemetryChunk(context, planContext, points, existingPoints, latest, counts) {
|
|
3390
|
+
const work = [];
|
|
3391
|
+
for (const point of points) {
|
|
3392
|
+
work.push(...planTelemetryPoint(context, planContext, point, existingPoints, latest, counts));
|
|
3393
|
+
}
|
|
3394
|
+
return work;
|
|
3395
|
+
}
|
|
3396
|
+
async function loadExistingPoints(context, storage, session, points) {
|
|
3397
|
+
const existingPoints = new Map;
|
|
3398
|
+
for await (const page of storage.streamState({
|
|
3399
|
+
session,
|
|
3400
|
+
requests: oneStateRequest({
|
|
3401
|
+
objects: [],
|
|
3402
|
+
links: [],
|
|
3403
|
+
linkScopes: [],
|
|
3404
|
+
incidentObjects: [],
|
|
3405
|
+
points: points.map((point) => ({ series: point.series, at: point.at }))
|
|
3406
|
+
}),
|
|
3407
|
+
pageRows: context.batching.statePageRows
|
|
3408
|
+
})) {
|
|
3409
|
+
for (const existing of page.points) {
|
|
3410
|
+
existingPoints.set(telemetryPointKey(existing.series, existing.at), existing);
|
|
3411
|
+
}
|
|
3412
|
+
}
|
|
3413
|
+
context.observeCoreBuffer?.("telemetry.existing-points", existingPoints.size);
|
|
3414
|
+
return existingPoints;
|
|
3415
|
+
}
|
|
3416
|
+
function planTelemetryPoint(context, planContext, point, existingPoints, latest, counts) {
|
|
3417
|
+
const identityKey = telemetryPointKey(point.series, point.at);
|
|
3418
|
+
const sortKey = telemetryPointSortKey(point.series, point.at);
|
|
3419
|
+
const existing = existingPoints.get(identityKey);
|
|
3420
|
+
const unchanged = telemetryPointUnchanged(existing, point);
|
|
3421
|
+
const work = [classificationWork("point", identityKey, sortKey)];
|
|
3422
|
+
if (unchanged) {
|
|
3423
|
+
counts.pointsUnchanged += 1;
|
|
3424
|
+
} else {
|
|
3425
|
+
countTelemetryPointChange(counts, existing);
|
|
3426
|
+
work.push(planWork(telemetryPointUpsert(point, existing, planContext.identity), sortKey));
|
|
3427
|
+
work.push(eventWork(buildTelemetryEvent(context, planContext, point)));
|
|
3428
|
+
}
|
|
3429
|
+
updateLatestPoint(latest, point, existing, unchanged, planContext.identity);
|
|
3430
|
+
return work;
|
|
3431
|
+
}
|
|
3432
|
+
function telemetryPointUnchanged(existing, point) {
|
|
3433
|
+
if (!existing)
|
|
3434
|
+
return false;
|
|
3435
|
+
return stableJsonStringify({ value: existing.value, unit: existing.unit ?? null }) === stableJsonStringify({ value: point.value, unit: point.unit ?? null });
|
|
3436
|
+
}
|
|
3437
|
+
function countTelemetryPointChange(counts, existing) {
|
|
3438
|
+
if (existing)
|
|
3439
|
+
counts.pointsUpdated += 1;
|
|
3440
|
+
else
|
|
3441
|
+
counts.pointsCreated += 1;
|
|
3442
|
+
}
|
|
3443
|
+
function telemetryPointUpsert(point, existing, identity) {
|
|
3444
|
+
const storedPoint = {
|
|
3445
|
+
series: point.series,
|
|
3446
|
+
value: point.value,
|
|
3447
|
+
at: point.at,
|
|
3448
|
+
lastCommitId: identity.commitId
|
|
3449
|
+
};
|
|
3450
|
+
const pointWithUnit = storedTelemetryPointWithUnit(storedPoint, point.unit);
|
|
3451
|
+
return {
|
|
3452
|
+
kind: "point-upsert",
|
|
3453
|
+
value: {
|
|
3454
|
+
point: pointWithUnit,
|
|
3455
|
+
expected: {
|
|
3456
|
+
series: point.series,
|
|
3457
|
+
at: point.at,
|
|
3458
|
+
lastCommitId: existing?.lastCommitId ?? null
|
|
3459
|
+
}
|
|
3460
|
+
}
|
|
3461
|
+
};
|
|
3462
|
+
}
|
|
3463
|
+
function storedTelemetryPointWithUnit(point, unit) {
|
|
3464
|
+
if (unit === undefined)
|
|
3465
|
+
return point;
|
|
3466
|
+
return { ...point, unit };
|
|
3467
|
+
}
|
|
3468
|
+
function buildTelemetryEvent(context, planContext, point) {
|
|
3469
|
+
const eventContext = telemetryEventContext(context, planContext);
|
|
3470
|
+
return buildTelemetryMaterializationEventDraft({ ...eventContext, point });
|
|
3471
|
+
}
|
|
3472
|
+
function updateLatestPoint(latest, point, existing, unchanged, identity) {
|
|
3473
|
+
const current = latest.get(point.series.propertyId);
|
|
3474
|
+
if (current && point.at < current.at)
|
|
3475
|
+
return;
|
|
3476
|
+
let lastCommitId = identity.commitId;
|
|
3477
|
+
if (unchanged && existing)
|
|
3478
|
+
lastCommitId = existing.lastCommitId;
|
|
3479
|
+
const storedPoint = {
|
|
3480
|
+
series: point.series,
|
|
3481
|
+
value: point.value,
|
|
3482
|
+
at: point.at,
|
|
3483
|
+
lastCommitId
|
|
3484
|
+
};
|
|
3485
|
+
if (point.unit === undefined) {
|
|
3486
|
+
latest.set(point.series.propertyId, storedPoint);
|
|
3487
|
+
return;
|
|
3488
|
+
}
|
|
3489
|
+
latest.set(point.series.propertyId, { ...storedPoint, unit: point.unit });
|
|
3490
|
+
}
|
|
3491
|
+
async function stageTelemetryObjectPlan(context, storage, session, planContext, working, counts) {
|
|
3492
|
+
const resolved = resolveObject(context.ontology, working);
|
|
3493
|
+
if (resolved)
|
|
3494
|
+
validateEffectiveObject(context.ontology, resolved.ref, resolved.properties);
|
|
3495
|
+
const change = diffEffectiveObject({
|
|
3496
|
+
before: working.before,
|
|
3497
|
+
resolved,
|
|
3498
|
+
commitId: planContext.identity.commitId,
|
|
3499
|
+
committedAt: planContext.identity.committedAt
|
|
3500
|
+
});
|
|
3501
|
+
const sortKey = objectRefSortKey(working.ref);
|
|
3502
|
+
const work = [
|
|
3503
|
+
classificationWork("object", objectRefKey(working.ref), sortKey)
|
|
3504
|
+
];
|
|
3505
|
+
if (change) {
|
|
3506
|
+
counts.latestObjectsChanged += 1;
|
|
3507
|
+
const items = [];
|
|
3508
|
+
appendObjectEffectivePlan(items, change);
|
|
3509
|
+
work.push(...items.map((item) => planWork(item, sortKey)));
|
|
3510
|
+
const eventContext = telemetryEventContext(context, planContext);
|
|
3511
|
+
work.push(eventWork(buildObjectMaterializationEventDraft({ ...eventContext, change })));
|
|
3512
|
+
}
|
|
3513
|
+
await stageWorkBounded(context, storage, session, work);
|
|
3514
|
+
}
|
|
3515
|
+
function telemetryEventContext(context, planContext) {
|
|
3516
|
+
const eventContext = {
|
|
3517
|
+
projectId: context.projectId,
|
|
3518
|
+
commitId: planContext.identity.commitId,
|
|
3519
|
+
committedAt: planContext.identity.committedAt,
|
|
3520
|
+
origin: planContext.origin
|
|
3521
|
+
};
|
|
3522
|
+
if (planContext.input.actor === undefined)
|
|
3523
|
+
return eventContext;
|
|
3524
|
+
return { ...eventContext, actor: planContext.input.actor };
|
|
3525
|
+
}
|
|
3526
|
+
function emptyTelemetryCounts() {
|
|
3527
|
+
return {
|
|
3528
|
+
pointsCreated: 0,
|
|
3529
|
+
pointsUpdated: 0,
|
|
3530
|
+
pointsUnchanged: 0,
|
|
3531
|
+
latestObjectsChanged: 0
|
|
3532
|
+
};
|
|
3533
|
+
}
|
|
3534
|
+
|
|
3535
|
+
// src/materializer/telemetry/append.ts
|
|
3536
|
+
async function appendTelemetry(context, raw) {
|
|
3537
|
+
const command = prepareTelemetryAppend(context, raw);
|
|
3538
|
+
if (command.kind === "runtime") {
|
|
3539
|
+
const replay = await replayCommit(context, command.identity);
|
|
3540
|
+
if (replay)
|
|
3541
|
+
return replay;
|
|
3542
|
+
}
|
|
3543
|
+
return executeTelemetryCommit(context, command);
|
|
3544
|
+
}
|
|
3545
|
+
function prepareTelemetryAppend(context, raw) {
|
|
3546
|
+
const rawInputPointCount = raw.points.length;
|
|
3547
|
+
const input = normalizeTelemetryAppend({
|
|
3548
|
+
...raw,
|
|
3549
|
+
points: raw.points.map((point) => validateTelemetryPoint(context.ontology, point))
|
|
3550
|
+
});
|
|
3551
|
+
const inputPointCount = telemetryInputPointCount(input, rawInputPointCount);
|
|
3552
|
+
validateTelemetryBatch(input, inputPointCount);
|
|
3553
|
+
const ontologyRevision = context.projectionRegistry.ontologyRevision;
|
|
3554
|
+
if (input.source.kind === "runtime") {
|
|
3555
|
+
return prepareRuntimeTelemetry(context, input, input.source, inputPointCount, ontologyRevision);
|
|
3556
|
+
}
|
|
3557
|
+
return prepareProjectionTelemetry(context, input, input.source, inputPointCount, ontologyRevision);
|
|
3558
|
+
}
|
|
3559
|
+
function telemetryInputPointCount(input, rawInputPointCount) {
|
|
3560
|
+
if (input.source.kind === "projection")
|
|
3561
|
+
return rawInputPointCount;
|
|
3562
|
+
return input.points.length;
|
|
3563
|
+
}
|
|
3564
|
+
function validateTelemetryBatch(input, inputPointCount) {
|
|
3565
|
+
if (input.source.kind === "projection") {
|
|
3566
|
+
if (input.source.sourceRowCount === 0) {
|
|
3567
|
+
throw new MaterializationValidationError("Projection telemetry batches must consume at least one source row; an empty dataset produces no batch commit.");
|
|
3568
|
+
}
|
|
3569
|
+
if (input.source.sourceRowCount !== inputPointCount + input.source.sourceRowsSkipped) {
|
|
3570
|
+
throw new MaterializationValidationError("Projection telemetry sourceRowCount must equal input points plus skipped rows.");
|
|
3571
|
+
}
|
|
3572
|
+
}
|
|
3573
|
+
}
|
|
3574
|
+
function prepareRuntimeTelemetry(context, input, source, inputPointCount, ontologyRevision) {
|
|
3575
|
+
const identity = createTimedCommitIdentity({
|
|
3576
|
+
projectId: context.projectId,
|
|
3577
|
+
idempotencyKey: createRuntimeTelemetryIdempotencyKey(source.requestId),
|
|
3578
|
+
normalizedCallerIntent: input,
|
|
3579
|
+
now: context.clock()
|
|
3580
|
+
});
|
|
3581
|
+
return { kind: "runtime", input, source, inputPointCount, ontologyRevision, identity };
|
|
3582
|
+
}
|
|
3583
|
+
function prepareProjectionTelemetry(context, input, source, inputPointCount, ontologyRevision) {
|
|
3584
|
+
const resolvedProjection = context.projectionRegistry.resolveTelemetry(source.projection.projectionId);
|
|
3585
|
+
validateTelemetryProjectionDataset(resolvedProjection, source);
|
|
3586
|
+
validateTelemetryOwnership(resolvedProjection, input);
|
|
3587
|
+
const runIdentity = createProjectionRunMaterializationIdentity({
|
|
3588
|
+
resolved: resolvedProjection,
|
|
3589
|
+
datasetVersion: source.datasetVersion,
|
|
3590
|
+
ontologyRevision
|
|
3591
|
+
});
|
|
3592
|
+
const identity = createTimedCommitIdentity({
|
|
3593
|
+
projectId: context.projectId,
|
|
3594
|
+
idempotencyKey: createProjectionTelemetryIdempotencyKey(runIdentity, source.batchOrdinal),
|
|
3595
|
+
normalizedCallerIntent: projectionTelemetryCallerIntent(input, source, inputPointCount),
|
|
3596
|
+
now: context.clock()
|
|
3597
|
+
});
|
|
3598
|
+
return {
|
|
3599
|
+
kind: "projection",
|
|
3600
|
+
input,
|
|
3601
|
+
source,
|
|
3602
|
+
inputPointCount,
|
|
3603
|
+
ontologyRevision,
|
|
3604
|
+
identity,
|
|
3605
|
+
resolvedProjection,
|
|
3606
|
+
runIdentity
|
|
3607
|
+
};
|
|
3608
|
+
}
|
|
3609
|
+
function validateTelemetryProjectionDataset(resolved, source) {
|
|
3610
|
+
if (resolved.datasetId === source.datasetVersion.datasetId)
|
|
3611
|
+
return;
|
|
3612
|
+
throw new MaterializationValidationError(`Telemetry projection '${resolved.projectionId}' requires dataset '${resolved.datasetId}'.`);
|
|
3613
|
+
}
|
|
3614
|
+
function validateTelemetryOwnership(resolved, input) {
|
|
3615
|
+
const ownedSeries = new Set(resolved.ownership.telemetry.map(({ objectTypeId, propertyId }) => telemetryOwnershipKey(objectTypeId, propertyId)));
|
|
3616
|
+
for (const point of input.points) {
|
|
3617
|
+
const scope = telemetryOwnershipKey(point.series.object.objectTypeId, point.series.propertyId);
|
|
3618
|
+
if (ownedSeries.has(scope))
|
|
3619
|
+
continue;
|
|
3620
|
+
throw new MaterializationValidationError(`Telemetry projection '${resolved.projectionId}' does not own series '${point.series.object.objectTypeId}.${point.series.propertyId}'.`);
|
|
3621
|
+
}
|
|
3622
|
+
}
|
|
3623
|
+
function projectionTelemetryCallerIntent(input, source, inputPointCount) {
|
|
3624
|
+
const intent = {
|
|
3625
|
+
source: {
|
|
3626
|
+
kind: "projection",
|
|
3627
|
+
projection: source.projection,
|
|
3628
|
+
datasetVersion: source.datasetVersion,
|
|
3629
|
+
batchOrdinal: source.batchOrdinal,
|
|
3630
|
+
sourceRowCount: source.sourceRowCount,
|
|
3631
|
+
sourceRowsSkipped: source.sourceRowsSkipped,
|
|
3632
|
+
inputExhausted: source.inputExhausted
|
|
3633
|
+
},
|
|
3634
|
+
inputPointCount,
|
|
3635
|
+
points: input.points
|
|
3636
|
+
};
|
|
3637
|
+
if (input.actor === undefined)
|
|
3638
|
+
return intent;
|
|
3639
|
+
return { ...intent, actor: input.actor };
|
|
3640
|
+
}
|
|
3641
|
+
async function assertTelemetryExecution(storage, projectId, command) {
|
|
3642
|
+
if (command.kind === "runtime")
|
|
3643
|
+
return null;
|
|
3644
|
+
const execution = await lockProjectionRunForMaterialization(storage, {
|
|
3645
|
+
projectId,
|
|
3646
|
+
projectionRunId: command.source.execution.projectionRunId,
|
|
3647
|
+
executionToken: command.source.execution.executionToken,
|
|
3648
|
+
identity: command.runIdentity,
|
|
3649
|
+
resolved: command.resolvedProjection,
|
|
3650
|
+
capabilityErrorMessage: "Storage does not provide projection run capabilities required by telemetry projection."
|
|
3651
|
+
});
|
|
3652
|
+
assertTelemetryBatchPosition(execution.run, command.source.batchOrdinal, command.source.sourceRowCount, command.source.inputExhausted);
|
|
3653
|
+
return execution;
|
|
3654
|
+
}
|
|
3655
|
+
function assertTelemetryBatchPosition(run, batchOrdinal, sourceRowCount, inputExhausted) {
|
|
3656
|
+
const checkpoint = run.telemetryCheckpoint;
|
|
3657
|
+
if (!checkpoint) {
|
|
3658
|
+
throw new MaterializationValidationError(`Telemetry projection run '${run.id}' has incomplete checkpoint state.`);
|
|
3659
|
+
}
|
|
3660
|
+
if (batchOrdinal > checkpoint.nextBatchOrdinal) {
|
|
3661
|
+
throw new MaterializationValidationError(`Telemetry projection run '${run.id}' expected batch ordinal ${checkpoint.nextBatchOrdinal}, got ${batchOrdinal}.`);
|
|
3662
|
+
}
|
|
3663
|
+
if (checkpoint.inputExhausted && batchOrdinal >= checkpoint.nextBatchOrdinal) {
|
|
3664
|
+
throw new MaterializationValidationError(`Telemetry projection run '${run.id}' has already exhausted its input.`);
|
|
3665
|
+
}
|
|
3666
|
+
if (sourceRowCount > checkpoint.fixedBatchSize) {
|
|
3667
|
+
throw new MaterializationValidationError(`Telemetry projection run '${run.id}' batch exceeds its fixed size.`);
|
|
3668
|
+
}
|
|
3669
|
+
if (!inputExhausted && sourceRowCount !== checkpoint.fixedBatchSize) {
|
|
3670
|
+
throw new MaterializationValidationError(`Telemetry projection run '${run.id}' cannot advance past a partial non-final batch.`);
|
|
3671
|
+
}
|
|
3672
|
+
}
|
|
3673
|
+
function assertTelemetryReplayCheckpoint(run, batchOrdinal) {
|
|
3674
|
+
if (!run.telemetryCheckpoint || batchOrdinal >= run.telemetryCheckpoint.nextBatchOrdinal) {
|
|
3675
|
+
throw new MaterializationValidationError(`Telemetry commit batch ${batchOrdinal} exists without an advanced run checkpoint.`);
|
|
3676
|
+
}
|
|
3677
|
+
}
|
|
3678
|
+
function telemetryProjectionReplayResult(commit, command) {
|
|
3679
|
+
const origin = commit.origin;
|
|
3680
|
+
if (origin.kind !== "telemetry" || origin.source.kind !== "projection" || origin.source.projectionRunId !== command.source.execution.projectionRunId || origin.source.batchOrdinal !== command.source.batchOrdinal || commit.result.kind !== "telemetry") {
|
|
3681
|
+
throw new MaterializationConflictError("run-correlation", `Telemetry commit '${commit.id}' belongs to a different logical run or batch.`);
|
|
3682
|
+
}
|
|
3683
|
+
return { ...structuredClone(commit.result), created: false };
|
|
3684
|
+
}
|
|
3685
|
+
async function executeTelemetryCommit(context, command) {
|
|
3686
|
+
return withSerializationRetry(context, () => context.storage.transaction((storage) => executeTelemetryTransaction(context, storage, command), { isolation: "serializable" }));
|
|
3687
|
+
}
|
|
3688
|
+
async function executeTelemetryTransaction(context, storage, command) {
|
|
3689
|
+
const execution = await assertTelemetryExecution(storage, context.projectId, command);
|
|
3690
|
+
const replay = await replayCommitRecord(context, command.identity, storage);
|
|
3691
|
+
if (replay) {
|
|
3692
|
+
if (command.kind === "projection" && execution) {
|
|
3693
|
+
assertTelemetryReplayCheckpoint(execution.run, command.source.batchOrdinal);
|
|
3694
|
+
return telemetryProjectionReplayResult(replay, command);
|
|
3695
|
+
}
|
|
3696
|
+
return { ...structuredClone(replay.result), created: false };
|
|
3697
|
+
}
|
|
3698
|
+
if (command.kind === "projection") {
|
|
3699
|
+
if (!execution?.run.telemetryCheckpoint || execution.run.telemetryCheckpoint.nextBatchOrdinal !== command.source.batchOrdinal) {
|
|
3700
|
+
throw new MaterializationValidationError(`Telemetry projection batch ${command.source.batchOrdinal} is behind its run checkpoint.`);
|
|
3701
|
+
}
|
|
3702
|
+
}
|
|
3703
|
+
const origin = telemetryOrigin(command);
|
|
3704
|
+
const session = await beginTelemetryMaterialization(context, storage, command, origin);
|
|
3705
|
+
const counts = await planTelemetryAppend(context, storage.ontology.materializations, session, command.input, command.identity, origin);
|
|
3706
|
+
await drainStagedWork(context, storage.ontology.materializations, session);
|
|
3707
|
+
const eventCount = await drainStagedEvents(context, storage.ontology.materializations, session, command.identity);
|
|
3708
|
+
const result = {
|
|
3709
|
+
kind: "telemetry",
|
|
3710
|
+
commitId: command.identity.commitId,
|
|
3711
|
+
created: true,
|
|
3712
|
+
eventCount,
|
|
3713
|
+
committedAt: command.identity.committedAt,
|
|
3714
|
+
...counts
|
|
3715
|
+
};
|
|
3716
|
+
return finalizeTelemetryMaterialization(storage, session, command, result, execution?.projectionRuns);
|
|
3717
|
+
}
|
|
3718
|
+
function telemetryOrigin(command) {
|
|
3719
|
+
if (command.kind === "runtime") {
|
|
3720
|
+
return { kind: "telemetry", source: command.source };
|
|
3721
|
+
}
|
|
3722
|
+
return {
|
|
3723
|
+
kind: "telemetry",
|
|
3724
|
+
source: {
|
|
3725
|
+
kind: "projection",
|
|
3726
|
+
projectionId: command.source.projection.projectionId,
|
|
3727
|
+
projectionRunId: command.source.execution.projectionRunId,
|
|
3728
|
+
datasetId: command.source.datasetVersion.datasetId,
|
|
3729
|
+
datasetVersionId: command.source.datasetVersion.versionId,
|
|
3730
|
+
batchOrdinal: command.source.batchOrdinal
|
|
3731
|
+
}
|
|
3732
|
+
};
|
|
3733
|
+
}
|
|
3734
|
+
async function beginTelemetryMaterialization(context, storage, command, origin) {
|
|
3735
|
+
return storage.ontology.materializations.begin({
|
|
3736
|
+
commit: telemetryCommit(context.projectId, command, origin),
|
|
3737
|
+
expected: {
|
|
3738
|
+
sources: [],
|
|
3739
|
+
objects: [],
|
|
3740
|
+
links: [],
|
|
3741
|
+
linkScopes: [],
|
|
3742
|
+
points: []
|
|
3743
|
+
}
|
|
3744
|
+
});
|
|
3745
|
+
}
|
|
3746
|
+
function telemetryCommit(projectId, command, origin) {
|
|
3747
|
+
const base = {
|
|
3748
|
+
projectId,
|
|
3749
|
+
id: command.identity.commitId,
|
|
3750
|
+
idempotencyKey: command.identity.idempotencyKey,
|
|
3751
|
+
requestHash: command.identity.requestHash,
|
|
3752
|
+
origin,
|
|
3753
|
+
ontologyRevision: command.ontologyRevision,
|
|
3754
|
+
intent: telemetryCommitIntent(command),
|
|
3755
|
+
committedAt: command.identity.committedAt
|
|
3756
|
+
};
|
|
3757
|
+
const withActor = telemetryCommitActor(base, command);
|
|
3758
|
+
if (command.kind === "runtime")
|
|
3759
|
+
return withActor;
|
|
3760
|
+
return {
|
|
3761
|
+
...withActor,
|
|
3762
|
+
projectionRevision: command.resolvedProjection.projectionRevision,
|
|
3763
|
+
ownershipHash: command.resolvedProjection.ownershipHash
|
|
3764
|
+
};
|
|
3765
|
+
}
|
|
3766
|
+
function telemetryCommitActor(commit, command) {
|
|
3767
|
+
if (command.input.actor === undefined)
|
|
3768
|
+
return commit;
|
|
3769
|
+
return { ...commit, actor: command.input.actor };
|
|
3770
|
+
}
|
|
3771
|
+
function telemetryCommitIntent(command) {
|
|
3772
|
+
if (command.kind === "runtime") {
|
|
3773
|
+
return {
|
|
3774
|
+
kind: "telemetry",
|
|
3775
|
+
pointCount: command.input.points.length,
|
|
3776
|
+
inputPointCount: command.inputPointCount,
|
|
3777
|
+
source: { kind: "runtime" }
|
|
3778
|
+
};
|
|
3779
|
+
}
|
|
3780
|
+
return {
|
|
3781
|
+
kind: "telemetry",
|
|
3782
|
+
pointCount: command.input.points.length,
|
|
3783
|
+
inputPointCount: command.inputPointCount,
|
|
3784
|
+
source: {
|
|
3785
|
+
kind: "projection",
|
|
3786
|
+
projection: command.source.projection,
|
|
3787
|
+
datasetVersion: command.source.datasetVersion,
|
|
3788
|
+
batchOrdinal: command.source.batchOrdinal,
|
|
3789
|
+
sourceRowCount: command.source.sourceRowCount,
|
|
3790
|
+
sourceRowsSkipped: command.source.sourceRowsSkipped,
|
|
3791
|
+
inputExhausted: command.source.inputExhausted
|
|
3792
|
+
}
|
|
3793
|
+
};
|
|
3794
|
+
}
|
|
3795
|
+
async function finalizeTelemetryMaterialization(storage, session, command, result, projectionRuns) {
|
|
3796
|
+
const applied = await storage.ontology.materializations.finalize({
|
|
3797
|
+
session,
|
|
3798
|
+
finalization: { sourceActivations: [], result }
|
|
3799
|
+
});
|
|
3800
|
+
if (command.kind === "projection") {
|
|
3801
|
+
if (!projectionRuns) {
|
|
3802
|
+
throw new MaterializationValidationError("Expected an asserted telemetry projection run.");
|
|
3803
|
+
}
|
|
3804
|
+
await projectionRuns.advanceTelemetryCheckpoint({
|
|
3805
|
+
id: command.source.execution.projectionRunId,
|
|
3806
|
+
projectId: applied.commit.projectId,
|
|
3807
|
+
executionToken: command.source.execution.executionToken,
|
|
3808
|
+
identity: command.runIdentity,
|
|
3809
|
+
batchOrdinal: command.source.batchOrdinal,
|
|
3810
|
+
batchRowCount: command.source.sourceRowCount,
|
|
3811
|
+
batchRowsSkipped: command.source.sourceRowsSkipped,
|
|
3812
|
+
inputExhausted: command.source.inputExhausted
|
|
3813
|
+
});
|
|
3814
|
+
}
|
|
3815
|
+
return applied.commit.result;
|
|
3816
|
+
}
|
|
3817
|
+
|
|
3818
|
+
// src/materializer/materializer.ts
|
|
3819
|
+
class OntologyMaterializer {
|
|
3820
|
+
edits = { commit: (input) => commitEdits(this.context, input) };
|
|
3821
|
+
projections = {
|
|
3822
|
+
replace: (input) => replaceProjection(this.context, input),
|
|
3823
|
+
finishRun: (input) => finishProjectionRun(this.context, input)
|
|
3824
|
+
};
|
|
3825
|
+
telemetry = { append: (input) => appendTelemetry(this.context, input) };
|
|
3826
|
+
context;
|
|
3827
|
+
constructor(projectId, ontology, projectionRegistry, storage, dependencies = {}) {
|
|
3828
|
+
this.context = createMaterializerContext({
|
|
3829
|
+
projectId,
|
|
3830
|
+
ontology,
|
|
3831
|
+
projections: projectionRegistry,
|
|
3832
|
+
storage,
|
|
3833
|
+
dependencies
|
|
3834
|
+
});
|
|
3835
|
+
}
|
|
3836
|
+
}
|
|
3837
|
+
function createOntologyMaterializer(input) {
|
|
3838
|
+
return new OntologyMaterializer(input.projectId, input.ontology, input.projections, input.storage, input.dependencies);
|
|
3839
|
+
}
|
|
3840
|
+
export { computeOntologyRevision, computeProjectionRevision, computeProjectionOwnershipHash, ProjectionRegistry, createActionIdempotencyKey, createRuntimeIdempotencyKey, createProjectionIdempotencyKey, createRuntimeTelemetryIdempotencyKey, createProjectionTelemetryIdempotencyKey, createCommitIdentity, timestampCommitIdentity, createTimedCommitIdentity, createProjectionMaterializationId, createLinkScopeFingerprint, normalizeJsonProperties, normalizeOntologyEditCommit, normalizeProjectionExecution, normalizeProjectionSourceEntry, normalizeTelemetryAppend, OntologyMaterializer, createOntologyMaterializer };
|
|
3841
|
+
|
|
3842
|
+
//# debugId=B1AC0F5B25E653E764756E2164756E21
|