@sixb/core 0.1.2 → 0.1.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/actions/index.js +19 -17
- package/dist/actions/index.js.map +1 -1
- package/dist/actions/worker.js +4 -4
- package/dist/actions/worker.js.map +1 -1
- package/dist/agents/adapters.d.ts +11 -1
- package/dist/agents/adapters.d.ts.map +1 -1
- package/dist/agents/context-compaction.d.ts +40 -0
- package/dist/agents/context-compaction.d.ts.map +1 -0
- package/dist/agents/context.js +1 -1
- package/dist/agents/errors.d.ts +1 -1
- package/dist/agents/errors.d.ts.map +1 -1
- package/dist/agents/execution.d.ts +3 -0
- package/dist/agents/execution.d.ts.map +1 -1
- package/dist/agents/ids.d.ts +2 -0
- package/dist/agents/ids.d.ts.map +1 -1
- package/dist/agents/index.d.ts +10 -6
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +51 -35
- package/dist/agents/index.js.map +1 -1
- package/dist/agents/request.d.ts.map +1 -1
- package/dist/agents/streams.d.ts +17 -1
- package/dist/agents/streams.d.ts.map +1 -1
- package/dist/agents/streams.js +5 -3
- package/dist/agents/streams.js.map +1 -1
- package/dist/agents/thread-context-projection.d.ts +19 -0
- package/dist/agents/thread-context-projection.d.ts.map +1 -0
- package/dist/agents/tool-definition.d.ts.map +1 -1
- package/dist/agents/tool-result.d.ts +6 -0
- package/dist/agents/tool-result.d.ts.map +1 -0
- package/dist/agents/types.d.ts +46 -1
- package/dist/agents/types.d.ts.map +1 -1
- package/dist/agents/validation.d.ts +2 -2
- package/dist/agents/validation.d.ts.map +1 -1
- package/dist/auth/index.js +11 -5
- package/dist/auth/index.js.map +1 -1
- package/dist/authorization/index.js +6 -2
- package/dist/authorization/index.js.map +1 -1
- package/dist/bootstrap/index.js +33 -31
- package/dist/bootstrap/index.js.map +1 -1
- package/dist/{chunk-ys1nse2v.js → chunk-1wk20wn3.js} +438 -246
- package/dist/{chunk-ys1nse2v.js.map → chunk-1wk20wn3.js.map} +11 -11
- package/dist/{chunk-sa4340y1.js → chunk-1yz3x65y.js} +7 -7
- package/dist/{chunk-gqdd7508.js → chunk-4rh2m6zg.js} +1 -1
- package/dist/{chunk-fmx1sz2h.js → chunk-72q2y8hn.js} +3 -3
- package/dist/{chunk-fmx1sz2h.js.map → chunk-72q2y8hn.js.map} +4 -4
- package/dist/{chunk-nnyp53zt.js → chunk-7gw7mepb.js} +259 -9
- package/dist/chunk-7gw7mepb.js.map +14 -0
- package/dist/{chunk-nten49ta.js → chunk-819wnjz8.js} +11 -5
- package/dist/chunk-819wnjz8.js.map +12 -0
- package/dist/chunk-96swp2wd.js +47 -0
- package/dist/chunk-96swp2wd.js.map +10 -0
- package/dist/{chunk-4x43bkbp.js → chunk-a09jx26t.js} +1 -1
- package/dist/{chunk-st4xgxey.js → chunk-afjpa2hs.js} +205 -48
- package/dist/chunk-afjpa2hs.js.map +45 -0
- package/dist/{chunk-0mbx247x.js → chunk-c43qr6s0.js} +427 -99
- package/dist/chunk-c43qr6s0.js.map +46 -0
- package/dist/{chunk-zg9yryhz.js → chunk-cbkm2vam.js} +3 -3
- package/dist/{chunk-57zpb99z.js → chunk-dm72y8wt.js} +26 -3
- package/dist/chunk-dm72y8wt.js.map +10 -0
- package/dist/chunk-drjqm1aa.js +913 -0
- package/dist/chunk-drjqm1aa.js.map +15 -0
- package/dist/chunk-dysw7nsm.js.map +1 -1
- package/dist/{chunk-8ryen3p3.js → chunk-f6erf2vv.js} +1 -1
- package/dist/{chunk-34bqh420.js → chunk-f83ka50g.js} +188 -44
- package/dist/chunk-f83ka50g.js.map +23 -0
- package/dist/{chunk-bct7hmfc.js → chunk-g13869yf.js} +3 -3
- package/dist/{chunk-0k4avqr2.js → chunk-hbeh8j9w.js} +2 -2
- package/dist/{chunk-qvybnnpe.js → chunk-nzw7sm3b.js} +2 -2
- package/dist/{chunk-k9pts48t.js → chunk-pn8n8sba.js} +16 -15
- package/dist/{chunk-k9pts48t.js.map → chunk-pn8n8sba.js.map} +3 -3
- package/dist/{chunk-63te770v.js → chunk-qewtks41.js} +8 -8
- package/dist/{chunk-63te770v.js.map → chunk-qewtks41.js.map} +2 -2
- package/dist/{chunk-85j5ybfj.js → chunk-rdeagz6b.js} +2 -2
- package/dist/{chunk-85j5ybfj.js.map → chunk-rdeagz6b.js.map} +3 -3
- package/dist/chunk-rhrbz7d4.js +36 -0
- package/dist/chunk-rhrbz7d4.js.map +10 -0
- package/dist/{chunk-bh6k3nc6.js → chunk-rs1wbvy6.js} +1 -1
- package/dist/{chunk-88ppkr54.js → chunk-rte5sm3z.js} +26 -2
- package/dist/chunk-rte5sm3z.js.map +12 -0
- package/dist/{chunk-n8herkry.js → chunk-s31d0qmq.js} +57 -20
- package/dist/{chunk-n8herkry.js.map → chunk-s31d0qmq.js.map} +8 -7
- package/dist/{chunk-7pc8b818.js → chunk-sxwk41qa.js} +1 -1
- package/dist/{chunk-663csy96.js → chunk-t0jjkep3.js} +2 -1
- package/dist/chunk-t0jjkep3.js.map +10 -0
- package/dist/{chunk-c6qd89g5.js → chunk-tek1qwgm.js} +6 -6
- package/dist/{chunk-c6qd89g5.js.map → chunk-tek1qwgm.js.map} +1 -1
- package/dist/{chunk-jaj13078.js → chunk-tkdscva6.js} +3 -33
- package/dist/{chunk-jaj13078.js.map → chunk-tkdscva6.js.map} +3 -4
- package/dist/{chunk-5egfka8j.js → chunk-tycbzedm.js} +2 -2
- package/dist/{chunk-g9t3kdtx.js → chunk-x2yw73hy.js} +1 -1
- package/dist/{chunk-57r1cpxx.js → chunk-xc7hq65b.js} +3 -2
- package/dist/{chunk-57r1cpxx.js.map → chunk-xc7hq65b.js.map} +3 -3
- package/dist/chunk-xdf9yswn.js +133 -0
- package/dist/chunk-xdf9yswn.js.map +11 -0
- package/dist/execution/agent.js +29 -27
- package/dist/execution/agent.js.map +1 -1
- package/dist/execution/primitive.js +29 -27
- package/dist/execution/primitive.js.map +2 -2
- package/dist/execution/request.js +30 -28
- package/dist/execution/request.js.map +2 -2
- package/dist/http/index.js +1 -1
- package/dist/index.d.ts +6 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +60 -58
- package/dist/index.js.map +1 -1
- package/dist/lake-storage/types.d.ts +2 -1
- package/dist/lake-storage/types.d.ts.map +1 -1
- package/dist/materialization/model.d.ts +4 -0
- package/dist/materialization/model.d.ts.map +1 -1
- package/dist/materializer/edits/apply.d.ts +6 -1
- package/dist/materializer/edits/apply.d.ts.map +1 -1
- package/dist/materializer/edits/working-state.d.ts +2 -0
- package/dist/materializer/edits/working-state.d.ts.map +1 -1
- package/dist/materializer/effective/resolve.d.ts +3 -1
- package/dist/materializer/effective/resolve.d.ts.map +1 -1
- package/dist/materializer/execution/work-records.d.ts.map +1 -1
- package/dist/materializer/index.js +19 -17
- package/dist/materializer/index.js.map +1 -1
- package/dist/materializer/projections/replacement-plan.d.ts.map +1 -1
- package/dist/materializer/shared/normalize.d.ts.map +1 -1
- package/dist/models/index.d.ts +40 -0
- package/dist/models/index.d.ts.map +1 -0
- package/dist/objects/execution.d.ts +6 -1
- package/dist/objects/execution.d.ts.map +1 -1
- package/dist/objects/index.js +21 -19
- package/dist/objects/index.js.map +1 -1
- package/dist/objects/link/endpoints.d.ts.map +1 -1
- package/dist/objects/query/executor.d.ts +1 -0
- package/dist/objects/query/executor.d.ts.map +1 -1
- package/dist/objects/query/explain.d.ts +1 -0
- package/dist/objects/query/explain.d.ts.map +1 -1
- package/dist/objects/query/index.d.ts +3 -1
- package/dist/objects/query/index.d.ts.map +1 -1
- package/dist/objects/query/index.js +30 -5
- package/dist/objects/query/index.js.map +1 -1
- package/dist/objects/query/ir.d.ts +14 -1
- package/dist/objects/query/ir.d.ts.map +1 -1
- package/dist/objects/query/links.d.ts +25 -0
- package/dist/objects/query/links.d.ts.map +1 -0
- package/dist/objects/query/normalize.d.ts.map +1 -1
- package/dist/objects/query/planner.d.ts.map +1 -1
- package/dist/objects/query/validate.d.ts +1 -0
- package/dist/objects/query/validate.d.ts.map +1 -1
- package/dist/pipelines/index.js +16 -15
- package/dist/pipelines/index.js.map +1 -1
- package/dist/projections/builders.d.ts +52 -10
- package/dist/projections/builders.d.ts.map +1 -1
- package/dist/projections/index.d.ts +2 -1
- package/dist/projections/index.d.ts.map +1 -1
- package/dist/projections/internal.d.ts +4 -1
- package/dist/projections/internal.d.ts.map +1 -1
- package/dist/projections/internal.js +22 -17
- package/dist/projections/internal.js.map +1 -1
- package/dist/projections/run-dispatch.d.ts +1 -0
- package/dist/projections/run-dispatch.d.ts.map +1 -1
- package/dist/projections/timestamp.d.ts +3 -0
- package/dist/projections/timestamp.d.ts.map +1 -0
- package/dist/projections/types.d.ts +21 -9
- package/dist/projections/types.d.ts.map +1 -1
- package/dist/projections/validation.d.ts +6 -5
- package/dist/projections/validation.d.ts.map +1 -1
- package/dist/query.d.ts +2 -1
- package/dist/query.d.ts.map +1 -1
- package/dist/query.js +2 -2
- package/dist/queues/index.d.ts +1 -1
- package/dist/queues/index.d.ts.map +1 -1
- package/dist/queues/types.d.ts +7 -0
- package/dist/queues/types.d.ts.map +1 -1
- package/dist/runtime/ai-cost.d.ts +8 -0
- package/dist/runtime/ai-cost.d.ts.map +1 -0
- package/dist/runtime/create.d.ts +3 -0
- package/dist/runtime/create.d.ts.map +1 -1
- package/dist/runtime/definitions.d.ts +3 -0
- package/dist/runtime/definitions.d.ts.map +1 -1
- package/dist/runtime/host.d.ts +2 -0
- package/dist/runtime/host.d.ts.map +1 -1
- package/dist/runtime/resolve-definitions.d.ts +2 -0
- package/dist/runtime/resolve-definitions.d.ts.map +1 -1
- package/dist/storage/agents/in-memory.d.ts +22 -4
- package/dist/storage/agents/in-memory.d.ts.map +1 -1
- package/dist/storage/agents/index.d.ts +1 -1
- package/dist/storage/agents/index.d.ts.map +1 -1
- package/dist/storage/agents/provider.d.ts +31 -0
- package/dist/storage/agents/provider.d.ts.map +1 -1
- package/dist/storage/agents/provider.js +22 -7
- package/dist/storage/agents/provider.js.map +1 -1
- package/dist/storage/agents/types.d.ts +75 -4
- package/dist/storage/agents/types.d.ts.map +1 -1
- package/dist/storage/ai-cost/analytics.d.ts +61 -0
- package/dist/storage/ai-cost/analytics.d.ts.map +1 -0
- package/dist/storage/ai-cost/codec.d.ts +14 -0
- package/dist/storage/ai-cost/codec.d.ts.map +1 -0
- package/dist/storage/ai-cost/errors.d.ts +7 -0
- package/dist/storage/ai-cost/errors.d.ts.map +1 -0
- package/dist/storage/ai-cost/in-memory.d.ts +32 -0
- package/dist/storage/ai-cost/in-memory.d.ts.map +1 -0
- package/dist/storage/ai-cost/index.d.ts +6 -0
- package/dist/storage/ai-cost/index.d.ts.map +1 -0
- package/dist/storage/ai-cost/provider.d.ts +7 -0
- package/dist/storage/ai-cost/provider.d.ts.map +1 -0
- package/dist/storage/ai-cost/provider.js +132 -0
- package/dist/storage/ai-cost/provider.js.map +10 -0
- package/dist/storage/ai-cost/types.d.ts +154 -0
- package/dist/storage/ai-cost/types.d.ts.map +1 -0
- package/dist/storage/ai-cost/validation.d.ts +7 -0
- package/dist/storage/ai-cost/validation.d.ts.map +1 -0
- package/dist/storage/ai-usage/in-memory.d.ts +2 -1
- package/dist/storage/ai-usage/in-memory.d.ts.map +1 -1
- package/dist/storage/ai-usage/index.d.ts +1 -1
- package/dist/storage/ai-usage/index.d.ts.map +1 -1
- package/dist/storage/ai-usage/types.d.ts +6 -0
- package/dist/storage/ai-usage/types.d.ts.map +1 -1
- package/dist/storage/in-memory/index.d.ts +5 -0
- package/dist/storage/in-memory/index.d.ts.map +1 -1
- package/dist/storage/index.d.ts +6 -3
- package/dist/storage/index.d.ts.map +1 -1
- package/dist/storage/index.js +33 -21
- package/dist/storage/index.js.map +1 -1
- package/dist/storage/objects/in-memory.d.ts +6 -3
- package/dist/storage/objects/in-memory.d.ts.map +1 -1
- package/dist/storage/objects/index.d.ts +3 -1
- package/dist/storage/objects/index.d.ts.map +1 -1
- package/dist/storage/objects/keys.d.ts +16 -0
- package/dist/storage/objects/keys.d.ts.map +1 -0
- package/dist/storage/objects/types.d.ts +33 -6
- package/dist/storage/objects/types.d.ts.map +1 -1
- package/dist/storage/ontology/in-memory/materializations.d.ts.map +1 -1
- package/dist/storage/ontology/materializations.d.ts +3 -0
- package/dist/storage/ontology/materializations.d.ts.map +1 -1
- package/dist/storage/ontology/provider.js +1 -1
- package/dist/storage/operation-scope.d.ts.map +1 -1
- package/dist/storage/operation-scope.js +1 -1
- package/dist/storage/types.d.ts +2 -0
- package/dist/storage/types.d.ts.map +1 -1
- package/dist/storage/workflow-runs/provider.js +10 -5
- package/dist/storage/workflow-runs/provider.js.map +1 -1
- package/dist/syncs/index.js +16 -15
- package/dist/syncs/index.js.map +1 -1
- package/dist/testing/agent-storage-contract.d.ts +3 -2
- package/dist/testing/agent-storage-contract.d.ts.map +1 -1
- package/dist/testing/ai-cost-storage-contract.d.ts +12 -0
- package/dist/testing/ai-cost-storage-contract.d.ts.map +1 -0
- package/dist/testing/ai-usage-storage-contract.d.ts.map +1 -1
- package/dist/testing/effective-storage-contract.d.ts +1 -1
- package/dist/testing/effective-storage-contract.d.ts.map +1 -1
- package/dist/testing/index.d.ts +1 -0
- package/dist/testing/index.d.ts.map +1 -1
- package/dist/testing/index.js +2525 -1480
- package/dist/testing/index.js.map +10 -9
- package/dist/testing/lake-storage-contract.d.ts.map +1 -1
- package/dist/testing/materializer-storage-contract.d.ts.map +1 -1
- package/dist/testing/object-query-contract.d.ts +1 -1
- package/dist/testing/object-query-contract.d.ts.map +1 -1
- package/dist/webhooks/internal.js +14 -13
- package/dist/webhooks/internal.js.map +2 -2
- package/dist/workers/index.js +12 -2
- package/dist/workers/index.js.map +3 -3
- package/dist/workers/queue-worker.d.ts +2 -0
- package/dist/workers/queue-worker.d.ts.map +1 -1
- package/dist/workflows/execution.d.ts +3 -0
- package/dist/workflows/execution.d.ts.map +1 -1
- package/dist/workflows/index.js +30 -28
- package/dist/workflows/index.js.map +1 -1
- package/package.json +7 -1
- package/src/agents/adapters.ts +64 -23
- package/src/agents/builders.ts +3 -3
- package/src/agents/context-compaction.ts +261 -0
- package/src/agents/errors.ts +2 -2
- package/src/agents/execution.ts +14 -2
- package/src/agents/ids.ts +5 -0
- package/src/agents/index.ts +32 -6
- package/src/agents/request.ts +5 -0
- package/src/agents/streams.ts +56 -0
- package/src/agents/thread-context-projection.ts +93 -0
- package/src/agents/tool-definition.ts +17 -2
- package/src/agents/tool-result.ts +61 -0
- package/src/agents/types.ts +57 -1
- package/src/agents/validation.ts +36 -6
- package/src/http/api-routes.ts +7 -7
- package/src/index.ts +27 -0
- package/src/lake-storage/types.ts +2 -1
- package/src/materialization/model.ts +4 -0
- package/src/materializer/edits/apply.ts +55 -2
- package/src/materializer/edits/operations.ts +8 -1
- package/src/materializer/edits/working-state.ts +7 -0
- package/src/materializer/effective/resolve.ts +78 -9
- package/src/materializer/execution/work-records.ts +3 -1
- package/src/materializer/projections/entry-validator.ts +23 -1
- package/src/materializer/projections/replacement-plan.ts +2 -0
- package/src/materializer/shared/normalize.ts +16 -0
- package/src/materializer/telemetry/append.ts +33 -16
- package/src/models/index.ts +71 -0
- package/src/objects/execution.ts +20 -0
- package/src/objects/link/endpoints.ts +2 -1
- package/src/objects/query/executor.ts +42 -11
- package/src/objects/query/explain.ts +11 -0
- package/src/objects/query/index.ts +6 -0
- package/src/objects/query/ir.ts +16 -0
- package/src/objects/query/links.ts +308 -0
- package/src/objects/query/normalize.ts +40 -1
- package/src/objects/query/planner.ts +5 -0
- package/src/objects/query/validate.ts +58 -2
- package/src/projections/builders.ts +320 -50
- package/src/projections/index.ts +7 -0
- package/src/projections/internal.ts +4 -1
- package/src/projections/ownership.ts +5 -5
- package/src/projections/registry.ts +16 -3
- package/src/projections/revision.ts +35 -5
- package/src/projections/run-dispatch.ts +10 -1
- package/src/projections/timestamp.ts +66 -0
- package/src/projections/types.ts +20 -9
- package/src/projections/validation.ts +85 -19
- package/src/query.ts +2 -0
- package/src/queues/index.ts +1 -0
- package/src/queues/types.ts +8 -0
- package/src/runtime/ai-cost.ts +15 -0
- package/src/runtime/create.ts +4 -0
- package/src/runtime/definitions.ts +3 -0
- package/src/runtime/host.ts +2 -0
- package/src/runtime/resolve-definitions.ts +28 -0
- package/src/storage/agents/in-memory.ts +186 -4
- package/src/storage/agents/index.ts +5 -0
- package/src/storage/agents/provider.ts +225 -0
- package/src/storage/agents/types.ts +82 -3
- package/src/storage/ai-cost/analytics.ts +602 -0
- package/src/storage/ai-cost/codec.ts +136 -0
- package/src/storage/ai-cost/errors.ts +12 -0
- package/src/storage/ai-cost/in-memory.ts +164 -0
- package/src/storage/ai-cost/index.ts +35 -0
- package/src/storage/ai-cost/provider.ts +20 -0
- package/src/storage/ai-cost/types.ts +193 -0
- package/src/storage/ai-cost/validation.ts +337 -0
- package/src/storage/ai-usage/in-memory.ts +23 -0
- package/src/storage/ai-usage/index.ts +1 -0
- package/src/storage/ai-usage/types.ts +10 -0
- package/src/storage/in-memory/index.ts +50 -0
- package/src/storage/index.ts +48 -0
- package/src/storage/objects/in-memory.ts +103 -16
- package/src/storage/objects/index.ts +9 -0
- package/src/storage/objects/keys.ts +36 -0
- package/src/storage/objects/types.ts +34 -6
- package/src/storage/ontology/in-memory/materializations.ts +1 -0
- package/src/storage/ontology/materializations.ts +3 -0
- package/src/storage/ontology/provider-header-validation.ts +2 -2
- package/src/storage/operation-scope.ts +1 -0
- package/src/storage/types.ts +2 -0
- package/src/testing/agent-storage-contract.ts +353 -2
- package/src/testing/ai-cost-storage-contract.ts +320 -0
- package/src/testing/ai-usage-storage-contract.ts +35 -0
- package/src/testing/effective-storage-contract.ts +194 -4
- package/src/testing/index.ts +5 -0
- package/src/testing/lake-storage-contract.ts +56 -0
- package/src/testing/materializer-storage-contract.ts +120 -2
- package/src/testing/object-query-contract.ts +208 -1
- package/src/workers/queue-worker.ts +14 -1
- package/src/workflows/execution.ts +31 -10
- package/dist/agents/prompt.d.ts +0 -15
- package/dist/agents/prompt.d.ts.map +0 -1
- package/dist/chunk-0mbx247x.js.map +0 -43
- package/dist/chunk-34bqh420.js.map +0 -23
- package/dist/chunk-57zpb99z.js.map +0 -10
- package/dist/chunk-663csy96.js.map +0 -10
- package/dist/chunk-6wetht33.js +0 -89
- package/dist/chunk-6wetht33.js.map +0 -10
- package/dist/chunk-88ppkr54.js.map +0 -12
- package/dist/chunk-nnyp53zt.js.map +0 -13
- package/dist/chunk-nten49ta.js.map +0 -12
- package/dist/chunk-st4xgxey.js.map +0 -45
- package/dist/chunk-vp1vc6ee.js +0 -35
- package/dist/chunk-vp1vc6ee.js.map +0 -11
- package/src/agents/prompt.ts +0 -57
- /package/dist/{chunk-sa4340y1.js.map → chunk-1yz3x65y.js.map} +0 -0
- /package/dist/{chunk-gqdd7508.js.map → chunk-4rh2m6zg.js.map} +0 -0
- /package/dist/{chunk-4x43bkbp.js.map → chunk-a09jx26t.js.map} +0 -0
- /package/dist/{chunk-zg9yryhz.js.map → chunk-cbkm2vam.js.map} +0 -0
- /package/dist/{chunk-8ryen3p3.js.map → chunk-f6erf2vv.js.map} +0 -0
- /package/dist/{chunk-bct7hmfc.js.map → chunk-g13869yf.js.map} +0 -0
- /package/dist/{chunk-0k4avqr2.js.map → chunk-hbeh8j9w.js.map} +0 -0
- /package/dist/{chunk-qvybnnpe.js.map → chunk-nzw7sm3b.js.map} +0 -0
- /package/dist/{chunk-bh6k3nc6.js.map → chunk-rs1wbvy6.js.map} +0 -0
- /package/dist/{chunk-7pc8b818.js.map → chunk-sxwk41qa.js.map} +0 -0
- /package/dist/{chunk-5egfka8j.js.map → chunk-tycbzedm.js.map} +0 -0
- /package/dist/{chunk-g9t3kdtx.js.map → chunk-x2yw73hy.js.map} +0 -0
|
@@ -1,4 +1,11 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
ObjectRef,
|
|
3
|
+
ObjectType,
|
|
4
|
+
OntologyRegistry,
|
|
5
|
+
Property,
|
|
6
|
+
Schema,
|
|
7
|
+
ValueType,
|
|
8
|
+
} from "../../ontology"
|
|
2
9
|
import { normalizeDecimalValue } from "../../ontology"
|
|
3
10
|
import { formatUnknownObjectTypeMessage } from "../../ontology/errors"
|
|
4
11
|
import { validatePropertyValue, validateSchemaValue } from "../../ontology/validation"
|
|
@@ -30,11 +37,12 @@ export interface ObjectQueryValidationOptions {
|
|
|
30
37
|
ontology: OntologyRegistry
|
|
31
38
|
maxLimit?: number
|
|
32
39
|
maxPageSize?: number
|
|
40
|
+
maxRefs?: number
|
|
33
41
|
normalize?: boolean
|
|
34
42
|
}
|
|
35
43
|
|
|
36
44
|
type QueryValidationContext = Required<
|
|
37
|
-
Pick<ObjectQueryValidationOptions, "maxLimit" | "maxPageSize">
|
|
45
|
+
Pick<ObjectQueryValidationOptions, "maxLimit" | "maxPageSize" | "maxRefs">
|
|
38
46
|
> & {
|
|
39
47
|
ontology: OntologyRegistry
|
|
40
48
|
valueTypesById: ReadonlyMap<string, ValueType>
|
|
@@ -53,6 +61,7 @@ interface TextFieldResolution {
|
|
|
53
61
|
|
|
54
62
|
const DEFAULT_MAX_LIMIT = 1_000
|
|
55
63
|
const DEFAULT_MAX_PAGE_SIZE = 1_000
|
|
64
|
+
const DEFAULT_MAX_REFS = 1_000
|
|
56
65
|
|
|
57
66
|
export function validateObjectQuery(
|
|
58
67
|
query: ObjectQuery,
|
|
@@ -96,6 +105,7 @@ function createValidationContext(options: ObjectQueryValidationOptions): QueryVa
|
|
|
96
105
|
valueTypesById: options.ontology.getValueTypesById(),
|
|
97
106
|
maxLimit: options.maxLimit ?? DEFAULT_MAX_LIMIT,
|
|
98
107
|
maxPageSize: options.maxPageSize ?? DEFAULT_MAX_PAGE_SIZE,
|
|
108
|
+
maxRefs: options.maxRefs ?? DEFAULT_MAX_REFS,
|
|
99
109
|
issues: [],
|
|
100
110
|
touchedObjectTypeIds: new Set<string>(),
|
|
101
111
|
}
|
|
@@ -125,6 +135,8 @@ function dispatchQueryNode(
|
|
|
125
135
|
switch (query.kind) {
|
|
126
136
|
case "start":
|
|
127
137
|
return validateStart(query.objectTypeId, query.includeSubtypes, path, ctx)
|
|
138
|
+
case "refs":
|
|
139
|
+
return validateRefs(query.refs, path, ctx)
|
|
128
140
|
case "filter": {
|
|
129
141
|
const input = validateQueryNode(query.input, `${path}.input`, ctx)
|
|
130
142
|
const predicate = validatePredicate(query.predicate, input.result, `${path}.predicate`, ctx)
|
|
@@ -199,6 +211,50 @@ function dispatchQueryNode(
|
|
|
199
211
|
}
|
|
200
212
|
}
|
|
201
213
|
|
|
214
|
+
function validateRefs(
|
|
215
|
+
refs: readonly ObjectRef[],
|
|
216
|
+
path: string,
|
|
217
|
+
ctx: QueryValidationContext
|
|
218
|
+
): QueryValidationResult {
|
|
219
|
+
if (refs.length === 0) {
|
|
220
|
+
addIssue(ctx, `${path}.refs`, "empty_refs", "refs must include at least one object reference")
|
|
221
|
+
}
|
|
222
|
+
if (refs.length > ctx.maxRefs) {
|
|
223
|
+
addIssue(
|
|
224
|
+
ctx,
|
|
225
|
+
`${path}.refs`,
|
|
226
|
+
"too_many_refs",
|
|
227
|
+
`refs must include at most ${ctx.maxRefs} object references`
|
|
228
|
+
)
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
const objectTypeIds = new Set<string>()
|
|
232
|
+
refs.forEach((ref, index) => {
|
|
233
|
+
const refPath = `${path}.refs[${index}]`
|
|
234
|
+
if (!ref.objectTypeId) {
|
|
235
|
+
addIssue(ctx, `${refPath}.objectTypeId`, "missing_object_type", "objectTypeId is required")
|
|
236
|
+
} else if (!ctx.ontology.getObjectTypeById(ref.objectTypeId)) {
|
|
237
|
+
addIssue(
|
|
238
|
+
ctx,
|
|
239
|
+
`${refPath}.objectTypeId`,
|
|
240
|
+
"unknown_object_type",
|
|
241
|
+
formatUnknownObjectTypeMessage(ref.objectTypeId)
|
|
242
|
+
)
|
|
243
|
+
} else {
|
|
244
|
+
objectTypeIds.add(ref.objectTypeId)
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
if (!ref.primaryId) {
|
|
248
|
+
addIssue(ctx, `${refPath}.primaryId`, "missing_primary_id", "primaryId is required")
|
|
249
|
+
}
|
|
250
|
+
})
|
|
251
|
+
|
|
252
|
+
return {
|
|
253
|
+
result: { objectTypeIds: [...objectTypeIds] },
|
|
254
|
+
query: { kind: "refs", refs: refs.map((ref) => ({ ...ref })) },
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
202
258
|
function validateStart(
|
|
203
259
|
objectTypeId: string,
|
|
204
260
|
includeSubtypes: boolean | undefined,
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import type {
|
|
8
|
+
DatasetColumnDefinitionOf,
|
|
8
9
|
DatasetColumnNameOf,
|
|
9
10
|
DatasetColumnType,
|
|
10
11
|
DatasetColumnTypeOf,
|
|
@@ -21,7 +22,9 @@ import type {
|
|
|
21
22
|
ObjectProjectionTarget,
|
|
22
23
|
ProjectionDefinition,
|
|
23
24
|
ProjectionTarget,
|
|
25
|
+
SourceEditConflictResolution,
|
|
24
26
|
TelemetryProjectionDefinition,
|
|
27
|
+
TelemetryProjectionPropertyMapping,
|
|
25
28
|
} from "./types"
|
|
26
29
|
import {
|
|
27
30
|
validateAndLowerLinkMapping,
|
|
@@ -153,6 +156,20 @@ type DateLikeDatasetColumnNameOf<TDataset extends DatasetDefinition> =
|
|
|
153
156
|
: never
|
|
154
157
|
}[DatasetColumnNameOf<TDataset>]
|
|
155
158
|
|
|
159
|
+
type TimestampDatasetColumnNameOf<TDataset extends DatasetDefinition> =
|
|
160
|
+
string extends DatasetColumnNameOf<TDataset>
|
|
161
|
+
? string
|
|
162
|
+
: {
|
|
163
|
+
[TColumnName in DatasetColumnNameOf<TDataset>]: DatasetColumnTypeOf<
|
|
164
|
+
TDataset,
|
|
165
|
+
TColumnName
|
|
166
|
+
> extends "timestamp"
|
|
167
|
+
? DatasetColumnDefinitionOf<TDataset, TColumnName> extends { readonly nullable: true }
|
|
168
|
+
? never
|
|
169
|
+
: TColumnName
|
|
170
|
+
: never
|
|
171
|
+
}[DatasetColumnNameOf<TDataset>]
|
|
172
|
+
|
|
156
173
|
type ProjectionMappingFor<TObjectType extends ObjectType, TDataset extends DatasetDefinition> = {
|
|
157
174
|
readonly [TPropertyId in PropertyIdOf<TObjectType>]?: DatasetColumnNameCompatibleWithSchema<
|
|
158
175
|
TDataset,
|
|
@@ -170,6 +187,18 @@ type TelemetryPropertyToken<TObjectTypeId extends string = string> = PropertyTok
|
|
|
170
187
|
Property & { readonly mode: "telemetry" }
|
|
171
188
|
>
|
|
172
189
|
|
|
190
|
+
type TelemetryPropertyOf<TObjectType extends ObjectType> = Extract<
|
|
191
|
+
TObjectType["properties"][number],
|
|
192
|
+
{ readonly mode: "telemetry" }
|
|
193
|
+
>
|
|
194
|
+
|
|
195
|
+
type TelemetryPropertyIdOf<TObjectType extends ObjectType> = TelemetryPropertyOf<TObjectType>["id"]
|
|
196
|
+
|
|
197
|
+
type TelemetryPropertyById<
|
|
198
|
+
TObjectType extends ObjectType,
|
|
199
|
+
TPropertyId extends TelemetryPropertyIdOf<TObjectType>,
|
|
200
|
+
> = Extract<TelemetryPropertyOf<TObjectType>, { readonly id: TPropertyId }>
|
|
201
|
+
|
|
173
202
|
type TelemetryProjectionPointMapping<
|
|
174
203
|
TPropertyToken extends TelemetryPropertyToken,
|
|
175
204
|
TDataset extends DatasetDefinition,
|
|
@@ -187,6 +216,58 @@ type ExactTelemetryProjectionPointMapping<TMapping> = TMapping & {
|
|
|
187
216
|
readonly [TKey in Exclude<keyof TMapping, "objectId" | "at" | "value" | "unit">]: never
|
|
188
217
|
}
|
|
189
218
|
|
|
219
|
+
type TelemetryProjectionPropertyInput<
|
|
220
|
+
TProperty extends Property,
|
|
221
|
+
TDataset extends DatasetDefinition,
|
|
222
|
+
> =
|
|
223
|
+
| DatasetColumnNameCompatibleWithSchema<TDataset, TProperty["schema"]>
|
|
224
|
+
| {
|
|
225
|
+
readonly value: DatasetColumnNameCompatibleWithSchema<TDataset, TProperty["schema"]>
|
|
226
|
+
readonly unit: StringDatasetColumnNameOf<TDataset>
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
type TelemetryProjectionPropertiesMapping<
|
|
230
|
+
TObjectType extends ObjectType,
|
|
231
|
+
TDataset extends DatasetDefinition,
|
|
232
|
+
> = {
|
|
233
|
+
readonly [TPropertyId in TelemetryPropertyIdOf<TObjectType>]?: TelemetryProjectionPropertyInput<
|
|
234
|
+
TelemetryPropertyById<TObjectType, TPropertyId>,
|
|
235
|
+
TDataset
|
|
236
|
+
>
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
type ExactTelemetryProjectionPropertiesMapping<
|
|
240
|
+
TObjectType extends ObjectType,
|
|
241
|
+
TMapping,
|
|
242
|
+
> = TMapping & {
|
|
243
|
+
readonly [TKey in Exclude<keyof TMapping, TelemetryPropertyIdOf<TObjectType>>]: never
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
type ExactTelemetryProjectionPropertyInputs<TMapping> = {
|
|
247
|
+
readonly [TPropertyId in keyof TMapping]: TMapping[TPropertyId] extends object
|
|
248
|
+
? TMapping[TPropertyId] & {
|
|
249
|
+
readonly [TKey in Exclude<keyof TMapping[TPropertyId], "value" | "unit">]: never
|
|
250
|
+
}
|
|
251
|
+
: TMapping[TPropertyId]
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
type NonEmptyTelemetryProjectionProperties<TMapping> = keyof TMapping extends never
|
|
255
|
+
? never
|
|
256
|
+
: TMapping
|
|
257
|
+
|
|
258
|
+
type TelemetryProjectionPropertiesPointMapping<
|
|
259
|
+
TObjectType extends ObjectType,
|
|
260
|
+
TDataset extends DatasetDefinition,
|
|
261
|
+
TProperties,
|
|
262
|
+
> = {
|
|
263
|
+
readonly objectId: StringDatasetColumnNameOf<TDataset>
|
|
264
|
+
readonly at: DateLikeDatasetColumnNameOf<TDataset>
|
|
265
|
+
readonly properties: NonEmptyTelemetryProjectionProperties<
|
|
266
|
+
ExactTelemetryProjectionPropertiesMapping<TObjectType, TProperties> &
|
|
267
|
+
ExactTelemetryProjectionPropertyInputs<TProperties>
|
|
268
|
+
>
|
|
269
|
+
}
|
|
270
|
+
|
|
190
271
|
type ForeignKeyFromSourceProperty = Omit<
|
|
191
272
|
ForeignKeyDescriptor,
|
|
192
273
|
"sourcePropertyId" | "sourceField"
|
|
@@ -239,7 +320,7 @@ type ProjectionForeignKeyTokenInput<
|
|
|
239
320
|
)
|
|
240
321
|
}
|
|
241
322
|
|
|
242
|
-
type ProjectionForeignKeyInput<
|
|
323
|
+
export type ProjectionForeignKeyInput<
|
|
243
324
|
TObjectType extends ObjectType,
|
|
244
325
|
TDataset extends DatasetDefinition,
|
|
245
326
|
TLinkId extends LinkIdOf<TObjectType>,
|
|
@@ -268,28 +349,42 @@ function isForeignKeyDescriptor(value: unknown): value is ForeignKeyDescriptor {
|
|
|
268
349
|
|
|
269
350
|
// ── defineProjection ─────────────────────────────────────────
|
|
270
351
|
|
|
271
|
-
interface
|
|
352
|
+
interface ObjectTypeProjectionSourceBuilder<TObjectType extends ObjectType> {
|
|
272
353
|
fromDataset<const TDataset extends DatasetDefinition>(
|
|
273
354
|
dataset: TDataset
|
|
274
|
-
):
|
|
355
|
+
): ObjectTypeProjectionDatasetBuilder<TObjectType, TDataset>
|
|
275
356
|
}
|
|
276
357
|
|
|
277
|
-
interface
|
|
358
|
+
interface ObjectTypeProjectionDatasetBuilder<
|
|
278
359
|
TObjectType extends ObjectType,
|
|
279
360
|
TDataset extends DatasetDefinition,
|
|
280
361
|
> {
|
|
281
362
|
properties<const TMapping extends ProjectionMappingFor<TObjectType, TDataset>>(
|
|
282
363
|
mapping: ExactProjectionMapping<TObjectType, TMapping>
|
|
283
|
-
):
|
|
364
|
+
): ObjectProjectionBuilder<TObjectType, TDataset>
|
|
365
|
+
points<const TProperties extends TelemetryProjectionPropertiesMapping<TObjectType, TDataset>>(
|
|
366
|
+
mapping: TelemetryProjectionPropertiesPointMapping<TObjectType, TDataset, TProperties>
|
|
367
|
+
): TelemetryProjectionDefinition
|
|
284
368
|
}
|
|
285
369
|
|
|
286
|
-
|
|
370
|
+
export type ObjectProjectionConflictResolution<TDataset extends DatasetDefinition> =
|
|
371
|
+
| { readonly strategy: "editsWin" }
|
|
372
|
+
| {
|
|
373
|
+
readonly strategy: "mostRecent"
|
|
374
|
+
readonly sourceTimestamp: TimestampDatasetColumnNameOf<TDataset>
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
export interface ObjectProjectionBuilder<
|
|
287
378
|
TObjectType extends ObjectType,
|
|
288
379
|
TDataset extends DatasetDefinition,
|
|
289
|
-
> {
|
|
380
|
+
> extends ObjectProjectionDefinition {
|
|
381
|
+
readonly conflictResolution: SourceEditConflictResolution
|
|
290
382
|
withLinks(
|
|
291
383
|
mapping: { [K in LinkIdOf<TObjectType>]?: ProjectionForeignKeyInput<TObjectType, TDataset, K> }
|
|
292
|
-
):
|
|
384
|
+
): ObjectProjectionBuilder<TObjectType, TDataset>
|
|
385
|
+
resolveConflicts(
|
|
386
|
+
resolution: ObjectProjectionConflictResolution<TDataset>
|
|
387
|
+
): ObjectProjectionBuilder<TObjectType, TDataset>
|
|
293
388
|
}
|
|
294
389
|
|
|
295
390
|
/**
|
|
@@ -311,7 +406,7 @@ interface ObjectProjectionLinkBuilder<
|
|
|
311
406
|
export function defineProjection<const TObjectType extends ObjectType>(
|
|
312
407
|
id: string,
|
|
313
408
|
objectType: TObjectType
|
|
314
|
-
):
|
|
409
|
+
): ObjectTypeProjectionSourceBuilder<TObjectType>
|
|
315
410
|
export function defineProjection<
|
|
316
411
|
TObjectTypeId extends string,
|
|
317
412
|
TLinkId extends string,
|
|
@@ -328,72 +423,125 @@ export function defineProjection(
|
|
|
328
423
|
id: string,
|
|
329
424
|
target: ObjectType | LinkToken<string, string, string> | TelemetryPropertyToken
|
|
330
425
|
):
|
|
331
|
-
|
|
|
426
|
+
| ObjectTypeProjectionSourceBuilder<ObjectType>
|
|
332
427
|
| LinkProjectionSourceBuilder
|
|
333
428
|
| TelemetryProjectionSourceBuilder<TelemetryPropertyToken> {
|
|
334
429
|
if ("link" in target) return buildLinkProjection(id, target)
|
|
335
430
|
if ("property" in target) return buildTelemetryProjection(id, target)
|
|
336
|
-
return
|
|
431
|
+
return buildObjectTypeProjection(id, target)
|
|
337
432
|
}
|
|
338
433
|
|
|
339
|
-
function
|
|
434
|
+
function buildObjectTypeProjection<const TObjectType extends ObjectType>(
|
|
340
435
|
id: string,
|
|
341
436
|
objectType: TObjectType
|
|
342
|
-
):
|
|
437
|
+
): ObjectTypeProjectionSourceBuilder<TObjectType> {
|
|
343
438
|
assertNonEmpty(id, "id")
|
|
344
439
|
|
|
345
440
|
return {
|
|
346
441
|
fromDataset<const TDataset extends DatasetDefinition>(
|
|
347
442
|
dataset: TDataset
|
|
348
|
-
):
|
|
443
|
+
): ObjectTypeProjectionDatasetBuilder<TObjectType, TDataset> {
|
|
349
444
|
assertProjectionDataset(dataset)
|
|
350
445
|
const datasetId = dataset.id
|
|
351
446
|
|
|
352
447
|
return {
|
|
353
448
|
properties<const TMapping extends ProjectionMappingFor<TObjectType, TDataset>>(
|
|
354
449
|
mapping: ExactProjectionMapping<TObjectType, TMapping>
|
|
355
|
-
):
|
|
450
|
+
): ObjectProjectionBuilder<TObjectType, TDataset> {
|
|
356
451
|
const propertyMapping = mapping as Record<string, string>
|
|
357
452
|
validatePropertyMapping(objectType, propertyMapping)
|
|
358
453
|
|
|
359
|
-
|
|
360
|
-
_tag: "ObjectProjectionDefinition",
|
|
454
|
+
return objectProjectionBuilder({
|
|
361
455
|
id,
|
|
362
|
-
|
|
456
|
+
objectType,
|
|
363
457
|
datasetId,
|
|
364
|
-
|
|
458
|
+
propertyMapping,
|
|
365
459
|
links: {},
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
return Object.assign(definition, {
|
|
369
|
-
withLinks(
|
|
370
|
-
linkMapping: {
|
|
371
|
-
[K in LinkIdOf<TObjectType>]?: ProjectionForeignKeyInput<TObjectType, TDataset, K>
|
|
372
|
-
}
|
|
373
|
-
): ObjectProjectionDefinition {
|
|
374
|
-
const loweredLinkMapping = lowerForeignKeyMapping(linkMapping)
|
|
375
|
-
const validatedLinks = validateAndLowerLinkMapping(
|
|
376
|
-
objectType,
|
|
377
|
-
loweredLinkMapping,
|
|
378
|
-
propertyMapping
|
|
379
|
-
)
|
|
380
|
-
|
|
381
|
-
return {
|
|
382
|
-
_tag: "ObjectProjectionDefinition",
|
|
383
|
-
id,
|
|
384
|
-
objectTypeId: objectType.id,
|
|
385
|
-
datasetId,
|
|
386
|
-
properties: { ...propertyMapping },
|
|
387
|
-
links: validatedLinks,
|
|
388
|
-
}
|
|
389
|
-
},
|
|
460
|
+
conflictResolution: { strategy: "editsWin" },
|
|
390
461
|
})
|
|
391
462
|
},
|
|
463
|
+
points<
|
|
464
|
+
const TProperties extends TelemetryProjectionPropertiesMapping<TObjectType, TDataset>,
|
|
465
|
+
>(
|
|
466
|
+
mapping: TelemetryProjectionPropertiesPointMapping<TObjectType, TDataset, TProperties>
|
|
467
|
+
): TelemetryProjectionDefinition {
|
|
468
|
+
const pointMapping = lowerTelemetryPropertiesPointMapping(
|
|
469
|
+
objectType,
|
|
470
|
+
mapping as {
|
|
471
|
+
readonly objectId?: string
|
|
472
|
+
readonly at?: string
|
|
473
|
+
readonly properties?: Readonly<Record<string, unknown>>
|
|
474
|
+
}
|
|
475
|
+
)
|
|
476
|
+
return {
|
|
477
|
+
_tag: "TelemetryProjectionDefinition",
|
|
478
|
+
id,
|
|
479
|
+
objectTypeId: objectType.id,
|
|
480
|
+
datasetId,
|
|
481
|
+
objectIdField: pointMapping.objectId,
|
|
482
|
+
atField: pointMapping.at,
|
|
483
|
+
properties: pointMapping.properties,
|
|
484
|
+
}
|
|
485
|
+
},
|
|
392
486
|
}
|
|
393
487
|
},
|
|
394
488
|
}
|
|
395
489
|
}
|
|
396
490
|
|
|
491
|
+
function objectProjectionBuilder<
|
|
492
|
+
TObjectType extends ObjectType,
|
|
493
|
+
TDataset extends DatasetDefinition,
|
|
494
|
+
>(input: {
|
|
495
|
+
readonly id: string
|
|
496
|
+
readonly objectType: TObjectType
|
|
497
|
+
readonly datasetId: string
|
|
498
|
+
readonly propertyMapping: Readonly<Record<string, string>>
|
|
499
|
+
readonly links: Readonly<Record<string, ForeignKeyDescriptor>>
|
|
500
|
+
readonly conflictResolution: SourceEditConflictResolution
|
|
501
|
+
}): ObjectProjectionBuilder<TObjectType, TDataset> {
|
|
502
|
+
const definition: ObjectProjectionDefinition & {
|
|
503
|
+
readonly conflictResolution: SourceEditConflictResolution
|
|
504
|
+
} = {
|
|
505
|
+
_tag: "ObjectProjectionDefinition",
|
|
506
|
+
id: input.id,
|
|
507
|
+
objectTypeId: input.objectType.id,
|
|
508
|
+
datasetId: input.datasetId,
|
|
509
|
+
properties: { ...input.propertyMapping },
|
|
510
|
+
links: { ...input.links },
|
|
511
|
+
conflictResolution: { ...input.conflictResolution },
|
|
512
|
+
}
|
|
513
|
+
|
|
514
|
+
return Object.assign(definition, {
|
|
515
|
+
withLinks(
|
|
516
|
+
linkMapping: {
|
|
517
|
+
[K in LinkIdOf<TObjectType>]?: ProjectionForeignKeyInput<TObjectType, TDataset, K>
|
|
518
|
+
}
|
|
519
|
+
): ObjectProjectionBuilder<TObjectType, TDataset> {
|
|
520
|
+
const loweredLinkMapping = lowerForeignKeyMapping(linkMapping)
|
|
521
|
+
const validatedLinks = validateAndLowerLinkMapping(
|
|
522
|
+
input.objectType,
|
|
523
|
+
loweredLinkMapping,
|
|
524
|
+
input.propertyMapping as Record<string, string>
|
|
525
|
+
)
|
|
526
|
+
return objectProjectionBuilder({ ...input, links: validatedLinks })
|
|
527
|
+
},
|
|
528
|
+
resolveConflicts(
|
|
529
|
+
resolution: ObjectProjectionConflictResolution<TDataset>
|
|
530
|
+
): ObjectProjectionBuilder<TObjectType, TDataset> {
|
|
531
|
+
validateConflictResolution(resolution)
|
|
532
|
+
return objectProjectionBuilder({
|
|
533
|
+
...input,
|
|
534
|
+
conflictResolution: resolution as SourceEditConflictResolution,
|
|
535
|
+
})
|
|
536
|
+
},
|
|
537
|
+
})
|
|
538
|
+
}
|
|
539
|
+
|
|
540
|
+
function validateConflictResolution(resolution: SourceEditConflictResolution): void {
|
|
541
|
+
if (resolution.strategy === "editsWin") return
|
|
542
|
+
assertNonEmpty(resolution.sourceTimestamp, "source timestamp field")
|
|
543
|
+
}
|
|
544
|
+
|
|
397
545
|
// ── Telemetry projection ────────────────────────────────────
|
|
398
546
|
|
|
399
547
|
interface TelemetryProjectionSourceBuilder<TPropertyToken extends TelemetryPropertyToken> {
|
|
@@ -448,12 +596,15 @@ function buildTelemetryProjection<const TPropertyToken extends TelemetryProperty
|
|
|
448
596
|
_tag: "TelemetryProjectionDefinition",
|
|
449
597
|
id,
|
|
450
598
|
objectTypeId: propertyToken.objectTypeId,
|
|
451
|
-
propertyId: propertyToken.id,
|
|
452
599
|
datasetId,
|
|
453
600
|
objectIdField: pointMapping.objectId,
|
|
454
601
|
atField: pointMapping.at,
|
|
455
|
-
|
|
456
|
-
|
|
602
|
+
properties: {
|
|
603
|
+
[propertyToken.id]: {
|
|
604
|
+
valueField: pointMapping.value,
|
|
605
|
+
...(pointMapping.unit !== undefined ? { unitField: pointMapping.unit } : {}),
|
|
606
|
+
},
|
|
607
|
+
},
|
|
457
608
|
}
|
|
458
609
|
},
|
|
459
610
|
}
|
|
@@ -514,6 +665,109 @@ function lowerTelemetryPointMapping(mapping: {
|
|
|
514
665
|
}
|
|
515
666
|
}
|
|
516
667
|
|
|
668
|
+
function lowerTelemetryPropertiesPointMapping(
|
|
669
|
+
objectType: ObjectType,
|
|
670
|
+
mapping: {
|
|
671
|
+
readonly objectId?: string
|
|
672
|
+
readonly at?: string
|
|
673
|
+
readonly properties?: Readonly<Record<string, unknown>>
|
|
674
|
+
}
|
|
675
|
+
): {
|
|
676
|
+
readonly objectId: string
|
|
677
|
+
readonly at: string
|
|
678
|
+
readonly properties: Readonly<Record<string, TelemetryProjectionPropertyMapping>>
|
|
679
|
+
} {
|
|
680
|
+
const allowedKeys = new Set(["objectId", "at", "properties"])
|
|
681
|
+
for (const key of Object.keys(mapping)) {
|
|
682
|
+
if (!allowedKeys.has(key)) {
|
|
683
|
+
throw new ProjectionValidationError(
|
|
684
|
+
`Telemetry projection point mapping contains unknown key '${key}'.`
|
|
685
|
+
)
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
689
|
+
if (mapping.objectId === undefined) {
|
|
690
|
+
throw new ProjectionValidationError("Telemetry projection point mapping requires objectId.")
|
|
691
|
+
}
|
|
692
|
+
if (mapping.at === undefined) {
|
|
693
|
+
throw new ProjectionValidationError("Telemetry projection point mapping requires at.")
|
|
694
|
+
}
|
|
695
|
+
if (mapping.properties === undefined) {
|
|
696
|
+
throw new ProjectionValidationError("Telemetry projection point mapping requires properties.")
|
|
697
|
+
}
|
|
698
|
+
if (!isRecord(mapping.properties)) {
|
|
699
|
+
throw new ProjectionValidationError(
|
|
700
|
+
"Telemetry projection point mapping properties must be an object."
|
|
701
|
+
)
|
|
702
|
+
}
|
|
703
|
+
|
|
704
|
+
assertNonEmpty(mapping.objectId, "objectId field")
|
|
705
|
+
assertNonEmpty(mapping.at, "at field")
|
|
706
|
+
|
|
707
|
+
const propertyEntries = Object.entries(mapping.properties)
|
|
708
|
+
if (propertyEntries.length === 0) {
|
|
709
|
+
throw new ProjectionValidationError(
|
|
710
|
+
"Telemetry projection point mapping requires at least one property."
|
|
711
|
+
)
|
|
712
|
+
}
|
|
713
|
+
|
|
714
|
+
const propertiesById = new Map(objectType.properties.map((property) => [property.id, property]))
|
|
715
|
+
const properties: Record<string, TelemetryProjectionPropertyMapping> = {}
|
|
716
|
+
for (const [propertyId, input] of propertyEntries) {
|
|
717
|
+
const property = propertiesById.get(propertyId)
|
|
718
|
+
if (!property) {
|
|
719
|
+
throw new ProjectionValidationError(
|
|
720
|
+
`Property '${propertyId}' does not exist on object type '${objectType.id}'.`
|
|
721
|
+
)
|
|
722
|
+
}
|
|
723
|
+
if (property.mode !== "telemetry") {
|
|
724
|
+
throw new ProjectionValidationError(
|
|
725
|
+
`Projection property '${objectType.id}.${propertyId}' must be telemetry-enabled.`
|
|
726
|
+
)
|
|
727
|
+
}
|
|
728
|
+
properties[propertyId] = lowerTelemetryPropertyMapping(propertyId, input)
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
return { objectId: mapping.objectId, at: mapping.at, properties }
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
function lowerTelemetryPropertyMapping(
|
|
735
|
+
propertyId: string,
|
|
736
|
+
input: unknown
|
|
737
|
+
): TelemetryProjectionPropertyMapping {
|
|
738
|
+
if (typeof input === "string") {
|
|
739
|
+
assertNonEmpty(input, `property '${propertyId}' value field`)
|
|
740
|
+
return { valueField: input }
|
|
741
|
+
}
|
|
742
|
+
if (!isRecord(input)) {
|
|
743
|
+
throw new ProjectionValidationError(
|
|
744
|
+
`Telemetry projection property '${propertyId}' must map a value column or value/unit columns.`
|
|
745
|
+
)
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
const allowedKeys = new Set(["value", "unit"])
|
|
749
|
+
for (const key of Object.keys(input)) {
|
|
750
|
+
if (!allowedKeys.has(key)) {
|
|
751
|
+
throw new ProjectionValidationError(
|
|
752
|
+
`Telemetry projection property '${propertyId}' contains unknown key '${key}'.`
|
|
753
|
+
)
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
if (typeof input.value !== "string") {
|
|
757
|
+
throw new ProjectionValidationError(
|
|
758
|
+
`Telemetry projection property '${propertyId}' requires a value field.`
|
|
759
|
+
)
|
|
760
|
+
}
|
|
761
|
+
if (typeof input.unit !== "string") {
|
|
762
|
+
throw new ProjectionValidationError(
|
|
763
|
+
`Telemetry projection property '${propertyId}' requires a unit field.`
|
|
764
|
+
)
|
|
765
|
+
}
|
|
766
|
+
assertNonEmpty(input.value, `property '${propertyId}' value field`)
|
|
767
|
+
assertNonEmpty(input.unit, `property '${propertyId}' unit field`)
|
|
768
|
+
return { valueField: input.value, unitField: input.unit }
|
|
769
|
+
}
|
|
770
|
+
|
|
517
771
|
// ── fromForeignKey ───────────────────────────────────────────
|
|
518
772
|
|
|
519
773
|
/**
|
|
@@ -672,10 +926,18 @@ export function isObjectProjectionDefinition(value: unknown): value is ObjectPro
|
|
|
672
926
|
typeof value.objectTypeId === "string" &&
|
|
673
927
|
typeof value.datasetId === "string" &&
|
|
674
928
|
isRecord(value.properties) &&
|
|
675
|
-
isRecord(value.links)
|
|
929
|
+
isRecord(value.links) &&
|
|
930
|
+
isSourceEditConflictResolution(value.conflictResolution)
|
|
676
931
|
)
|
|
677
932
|
}
|
|
678
933
|
|
|
934
|
+
function isSourceEditConflictResolution(value: unknown): boolean {
|
|
935
|
+
if (value === undefined) return true
|
|
936
|
+
if (!isRecord(value) || typeof value.strategy !== "string") return false
|
|
937
|
+
if (value.strategy === "editsWin") return value.sourceTimestamp === undefined
|
|
938
|
+
return value.strategy === "mostRecent" && typeof value.sourceTimestamp === "string"
|
|
939
|
+
}
|
|
940
|
+
|
|
679
941
|
/** Runtime type guard for {@link LinkProjectionDefinition}. */
|
|
680
942
|
export function isLinkProjectionDefinition(value: unknown): value is LinkProjectionDefinition {
|
|
681
943
|
if (!isRecord(value)) return false
|
|
@@ -700,12 +962,20 @@ export function isTelemetryProjectionDefinition(
|
|
|
700
962
|
value._tag === "TelemetryProjectionDefinition" &&
|
|
701
963
|
typeof value.id === "string" &&
|
|
702
964
|
typeof value.objectTypeId === "string" &&
|
|
703
|
-
typeof value.propertyId === "string" &&
|
|
704
965
|
typeof value.datasetId === "string" &&
|
|
705
966
|
typeof value.objectIdField === "string" &&
|
|
706
967
|
typeof value.atField === "string" &&
|
|
707
|
-
|
|
708
|
-
|
|
968
|
+
isTelemetryProjectionProperties(value.properties)
|
|
969
|
+
)
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
function isTelemetryProjectionProperties(value: unknown): boolean {
|
|
973
|
+
if (!isRecord(value) || Object.keys(value).length === 0) return false
|
|
974
|
+
return Object.values(value).every(
|
|
975
|
+
(mapping) =>
|
|
976
|
+
isRecord(mapping) &&
|
|
977
|
+
typeof mapping.valueField === "string" &&
|
|
978
|
+
(mapping.unitField === undefined || typeof mapping.unitField === "string")
|
|
709
979
|
)
|
|
710
980
|
}
|
|
711
981
|
|
package/src/projections/index.ts
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
// ── Builders ─────────────────────────────────────────────────
|
|
2
2
|
|
|
3
|
+
export type {
|
|
4
|
+
ObjectProjectionBuilder,
|
|
5
|
+
ObjectProjectionConflictResolution,
|
|
6
|
+
ProjectionForeignKeyInput,
|
|
7
|
+
} from "./builders"
|
|
3
8
|
export {
|
|
4
9
|
categorizeProjections,
|
|
5
10
|
defineProjection,
|
|
@@ -24,7 +29,9 @@ export type {
|
|
|
24
29
|
ProjectionKind,
|
|
25
30
|
ProjectionTarget,
|
|
26
31
|
ProjectionTargetByKind,
|
|
32
|
+
SourceEditConflictResolution,
|
|
27
33
|
TelemetryProjectionDefinition,
|
|
34
|
+
TelemetryProjectionPropertyMapping,
|
|
28
35
|
} from "./types"
|
|
29
36
|
// ── Validation ───────────────────────────────────────────────
|
|
30
37
|
export {
|
|
@@ -7,7 +7,9 @@ import type { ProjectionDispatchDescriptor } from "./types"
|
|
|
7
7
|
*
|
|
8
8
|
* `projectionTargetOf` derives the object types a projection writes, to record them on the run.
|
|
9
9
|
* `validateTelemetryProjectionFieldMapping` re-checks a telemetry mapping against the dataset schema
|
|
10
|
-
* before writing.
|
|
10
|
+
* before writing. `parseDatasetTimestamp` keeps worker timestamps aligned with the materializer's
|
|
11
|
+
* authoritative validation. These are plumbing, so they live here instead of on the
|
|
12
|
+
* `@sixb/core` root.
|
|
11
13
|
*/
|
|
12
14
|
export { projectionTargetOf } from "./builders"
|
|
13
15
|
export {
|
|
@@ -27,6 +29,7 @@ export {
|
|
|
27
29
|
ProjectionRunDispatcher,
|
|
28
30
|
} from "./run-dispatch"
|
|
29
31
|
export { createProjectionRunId } from "./run-id"
|
|
32
|
+
export { parseDatasetTimestamp } from "./timestamp"
|
|
30
33
|
export { validateTelemetryProjectionFieldMapping } from "./validation"
|
|
31
34
|
|
|
32
35
|
export type { ProjectionDispatchDescriptor, ProjectionMaterializationIdentity, ProjectionRegistry }
|
|
@@ -42,12 +42,12 @@ export function computeProjectionOwnership(
|
|
|
42
42
|
return freezeOwnership({
|
|
43
43
|
objects: [],
|
|
44
44
|
links: [],
|
|
45
|
-
telemetry:
|
|
46
|
-
|
|
45
|
+
telemetry: Object.keys(projection.properties)
|
|
46
|
+
.sort(compareStrings)
|
|
47
|
+
.map((propertyId) => ({
|
|
47
48
|
objectTypeId: projection.objectTypeId,
|
|
48
|
-
propertyId
|
|
49
|
-
},
|
|
50
|
-
],
|
|
49
|
+
propertyId,
|
|
50
|
+
})),
|
|
51
51
|
})
|
|
52
52
|
}
|
|
53
53
|
|