@qlever-llc/trellis 0.8.4 → 0.9.0-rc.10
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/README.md +1 -1
- package/bin/trellis-generate.js +0 -0
- package/esm/auth/browser/login.d.ts.map +1 -1
- package/esm/auth/browser/login.js +46 -3
- package/esm/auth/browser/portal.d.ts.map +1 -1
- package/esm/auth/browser/portal.js +5 -1
- package/esm/auth/browser/session.d.ts +18 -7
- package/esm/auth/browser/session.d.ts.map +1 -1
- package/esm/auth/browser/session.js +47 -11
- package/esm/auth/browser/storage.d.ts +6 -1
- package/esm/auth/browser/storage.d.ts.map +1 -1
- package/esm/auth/browser/storage.js +15 -3
- package/esm/auth/browser.d.ts +2 -2
- package/esm/auth/browser.d.ts.map +1 -1
- package/esm/auth/browser.js +1 -1
- package/esm/auth/device_activation.d.ts +36 -33
- package/esm/auth/device_activation.d.ts.map +1 -1
- package/esm/auth/device_activation.js +26 -22
- package/esm/auth/mod.d.ts +4 -4
- package/esm/auth/mod.d.ts.map +1 -1
- package/esm/auth/mod.js +2 -2
- package/esm/auth/proof.d.ts +3 -1
- package/esm/auth/proof.d.ts.map +1 -1
- package/esm/auth/proof.js +21 -15
- package/esm/auth/protocol.d.ts +2457 -941
- package/esm/auth/protocol.d.ts.map +1 -1
- package/esm/auth/protocol.js +747 -375
- package/esm/auth/schemas.d.ts +25 -4
- package/esm/auth/schemas.d.ts.map +1 -1
- package/esm/auth/schemas.js +14 -4
- package/esm/auth/session_auth.d.ts +1 -1
- package/esm/auth/session_auth.d.ts.map +1 -1
- package/esm/auth/session_auth.js +7 -1
- package/esm/client_connect.d.ts +2 -0
- package/esm/client_connect.d.ts.map +1 -1
- package/esm/client_connect.js +76 -15
- package/esm/contract.d.ts +3 -0
- package/esm/contract.d.ts.map +1 -1
- package/esm/contract_support/mod.d.ts +422 -43
- package/esm/contract_support/mod.d.ts.map +1 -1
- package/esm/contract_support/mod.js +734 -33
- package/esm/contract_support/protocol.d.ts +20 -5
- package/esm/contract_support/protocol.d.ts.map +1 -1
- package/esm/contract_support/protocol.js +18 -10
- package/esm/contract_support/runtime.d.ts +11 -0
- package/esm/contract_support/runtime.d.ts.map +1 -1
- package/esm/contract_support/schema_pointers.d.ts.map +1 -1
- package/esm/contract_support/schema_pointers.js +32 -14
- package/esm/device.d.ts +2 -0
- package/esm/device.d.ts.map +1 -1
- package/esm/device.js +3 -0
- package/esm/errors/AuthError.d.ts +2 -1
- package/esm/errors/AuthError.d.ts.map +1 -1
- package/esm/errors/AuthError.js +8 -3
- package/esm/errors/index.d.ts +4 -4
- package/esm/errors/index.d.ts.map +1 -1
- package/esm/errors/index.js +1 -0
- package/esm/generated-sdk/auth/api.d.ts +27 -9
- package/esm/generated-sdk/auth/api.d.ts.map +1 -1
- package/esm/generated-sdk/auth/api.js +16 -590
- package/esm/generated-sdk/auth/client.d.ts +91 -85
- package/esm/generated-sdk/auth/client.d.ts.map +1 -1
- package/esm/generated-sdk/auth/contract.d.ts +1 -1
- package/esm/generated-sdk/auth/contract.d.ts.map +1 -1
- package/esm/generated-sdk/auth/contract.js +4 -2
- package/esm/generated-sdk/auth/mod.d.ts +1 -0
- package/esm/generated-sdk/auth/mod.d.ts.map +1 -1
- package/esm/generated-sdk/auth/owned_api.d.ts +3 -0
- package/esm/generated-sdk/auth/owned_api.d.ts.map +1 -0
- package/esm/generated-sdk/auth/owned_api.js +594 -0
- package/esm/generated-sdk/auth/schemas.d.ts +9959 -5160
- package/esm/generated-sdk/auth/schemas.d.ts.map +1 -1
- package/esm/generated-sdk/auth/schemas.js +136 -137
- package/esm/generated-sdk/auth/types.d.ts +2418 -1557
- package/esm/generated-sdk/auth/types.d.ts.map +1 -1
- package/esm/generated-sdk/auth/types.js +1 -1
- package/esm/generated-sdk/health/api.d.ts +24 -9
- package/esm/generated-sdk/health/api.d.ts.map +1 -1
- package/esm/generated-sdk/health/api.js +12 -20
- package/esm/generated-sdk/health/client.d.ts +2 -1
- package/esm/generated-sdk/health/client.d.ts.map +1 -1
- package/esm/generated-sdk/health/contract.d.ts.map +1 -1
- package/esm/generated-sdk/health/contract.js +2 -0
- package/esm/generated-sdk/health/owned_api.d.ts +3 -0
- package/esm/generated-sdk/health/owned_api.d.ts.map +1 -0
- package/esm/generated-sdk/health/owned_api.js +16 -0
- package/esm/generated-sdk/health/types.d.ts +2 -0
- package/esm/generated-sdk/health/types.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/api.d.ts +33 -9
- package/esm/generated-sdk/jobs/api.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/api.js +22 -87
- package/esm/generated-sdk/jobs/client.d.ts +9 -2
- package/esm/generated-sdk/jobs/client.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/contract.d.ts +1 -1
- package/esm/generated-sdk/jobs/contract.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/contract.js +4 -2
- package/esm/generated-sdk/jobs/owned_api.d.ts +3 -0
- package/esm/generated-sdk/jobs/owned_api.d.ts.map +1 -0
- package/esm/generated-sdk/jobs/owned_api.js +118 -0
- package/esm/generated-sdk/jobs/schemas.d.ts +336 -123
- package/esm/generated-sdk/jobs/schemas.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/schemas.js +17 -15
- package/esm/generated-sdk/jobs/types.d.ts +144 -34
- package/esm/generated-sdk/jobs/types.d.ts.map +1 -1
- package/esm/generated-sdk/jobs/types.js +36 -1
- package/esm/generated-sdk/state/api.d.ts +27 -9
- package/esm/generated-sdk/state/api.d.ts.map +1 -1
- package/esm/generated-sdk/state/api.js +16 -71
- package/esm/generated-sdk/state/client.d.ts +4 -2
- package/esm/generated-sdk/state/client.d.ts.map +1 -1
- package/esm/generated-sdk/state/contract.d.ts +1 -1
- package/esm/generated-sdk/state/contract.d.ts.map +1 -1
- package/esm/generated-sdk/state/contract.js +4 -2
- package/esm/generated-sdk/state/owned_api.d.ts +3 -0
- package/esm/generated-sdk/state/owned_api.d.ts.map +1 -0
- package/esm/generated-sdk/state/owned_api.js +66 -0
- package/esm/generated-sdk/state/schemas.d.ts +264 -284
- package/esm/generated-sdk/state/schemas.d.ts.map +1 -1
- package/esm/generated-sdk/state/schemas.js +6 -6
- package/esm/generated-sdk/state/types.d.ts +24 -23
- package/esm/generated-sdk/state/types.d.ts.map +1 -1
- package/esm/generated-sdk/state/types.js +1 -1
- package/esm/generated-sdk/trellis-core/api.d.ts +27 -9
- package/esm/generated-sdk/trellis-core/api.d.ts.map +1 -1
- package/esm/generated-sdk/trellis-core/api.js +16 -39
- package/esm/generated-sdk/trellis-core/client.d.ts +5 -2
- package/esm/generated-sdk/trellis-core/client.d.ts.map +1 -1
- package/esm/generated-sdk/trellis-core/contract.d.ts +1 -1
- package/esm/generated-sdk/trellis-core/contract.d.ts.map +1 -1
- package/esm/generated-sdk/trellis-core/contract.js +4 -2
- package/esm/generated-sdk/trellis-core/owned_api.d.ts +3 -0
- package/esm/generated-sdk/trellis-core/owned_api.d.ts.map +1 -0
- package/esm/generated-sdk/trellis-core/owned_api.js +42 -0
- package/esm/generated-sdk/trellis-core/schemas.d.ts +259 -11
- package/esm/generated-sdk/trellis-core/schemas.d.ts.map +1 -1
- package/esm/generated-sdk/trellis-core/schemas.js +5 -3
- package/esm/generated-sdk/trellis-core/types.d.ts +56 -1
- package/esm/generated-sdk/trellis-core/types.d.ts.map +1 -1
- package/esm/generated-sdk/trellis-core/types.js +1 -1
- package/esm/helpers.d.ts.map +1 -1
- package/esm/index.d.ts +4 -3
- package/esm/index.d.ts.map +1 -1
- package/esm/index.js +1 -0
- package/esm/jobs.d.ts +10 -1
- package/esm/jobs.d.ts.map +1 -1
- package/esm/jobs.js +16 -1
- package/esm/kv.d.ts.map +1 -1
- package/esm/kv.js +10 -4
- package/esm/models/auth/rpc/Logout.d.ts +4 -4
- package/esm/models/auth/rpc/Logout.d.ts.map +1 -1
- package/esm/models/auth/rpc/Logout.js +2 -2
- package/esm/models/trellis/Page.d.ts +2 -0
- package/esm/models/trellis/Page.d.ts.map +1 -0
- package/esm/models/trellis/Page.js +1 -0
- package/esm/models/trellis/State.d.ts +1 -0
- package/esm/models/trellis/State.d.ts.map +1 -1
- package/esm/models/trellis/State.js +1 -0
- package/esm/models/trellis/rpc/StateList.d.ts +9 -12
- package/esm/models/trellis/rpc/StateList.d.ts.map +1 -1
- package/esm/models/trellis/rpc/StateList.js +16 -18
- package/esm/npm/src/auth/browser/login.d.ts.map +1 -1
- package/esm/npm/src/auth/browser/login.js +46 -3
- package/esm/npm/src/auth/browser/portal.d.ts.map +1 -1
- package/esm/npm/src/auth/browser/portal.js +5 -1
- package/esm/npm/src/auth/browser/session.d.ts +18 -7
- package/esm/npm/src/auth/browser/session.d.ts.map +1 -1
- package/esm/npm/src/auth/browser/session.js +47 -11
- package/esm/npm/src/auth/browser/storage.d.ts +6 -1
- package/esm/npm/src/auth/browser/storage.d.ts.map +1 -1
- package/esm/npm/src/auth/browser/storage.js +15 -3
- package/esm/npm/src/auth/browser.d.ts +2 -2
- package/esm/npm/src/auth/browser.d.ts.map +1 -1
- package/esm/npm/src/auth/browser.js +1 -1
- package/esm/npm/src/auth/device_activation.d.ts +36 -33
- package/esm/npm/src/auth/device_activation.d.ts.map +1 -1
- package/esm/npm/src/auth/device_activation.js +26 -22
- package/esm/npm/src/auth/mod.d.ts +4 -4
- package/esm/npm/src/auth/mod.d.ts.map +1 -1
- package/esm/npm/src/auth/mod.js +2 -2
- package/esm/npm/src/auth/proof.d.ts +3 -1
- package/esm/npm/src/auth/proof.d.ts.map +1 -1
- package/esm/npm/src/auth/proof.js +21 -15
- package/esm/npm/src/auth/protocol.d.ts +2457 -941
- package/esm/npm/src/auth/protocol.d.ts.map +1 -1
- package/esm/npm/src/auth/protocol.js +747 -375
- package/esm/npm/src/auth/schemas.d.ts +25 -4
- package/esm/npm/src/auth/schemas.d.ts.map +1 -1
- package/esm/npm/src/auth/schemas.js +14 -4
- package/esm/npm/src/auth/session_auth.d.ts +1 -1
- package/esm/npm/src/auth/session_auth.d.ts.map +1 -1
- package/esm/npm/src/auth/session_auth.js +7 -1
- package/esm/npm/src/client_connect.d.ts +2 -0
- package/esm/npm/src/client_connect.d.ts.map +1 -1
- package/esm/npm/src/client_connect.js +76 -15
- package/esm/npm/src/contract.d.ts +3 -0
- package/esm/npm/src/contract.d.ts.map +1 -1
- package/esm/npm/src/contract_support/mod.d.ts +422 -43
- package/esm/npm/src/contract_support/mod.d.ts.map +1 -1
- package/esm/npm/src/contract_support/mod.js +734 -33
- package/esm/npm/src/contract_support/protocol.d.ts +20 -5
- package/esm/npm/src/contract_support/protocol.d.ts.map +1 -1
- package/esm/npm/src/contract_support/protocol.js +18 -10
- package/esm/npm/src/contract_support/runtime.d.ts +11 -0
- package/esm/npm/src/contract_support/runtime.d.ts.map +1 -1
- package/esm/npm/src/contract_support/schema_pointers.d.ts.map +1 -1
- package/esm/npm/src/contract_support/schema_pointers.js +32 -14
- package/esm/npm/src/device/deno.d.ts.map +1 -1
- package/esm/npm/src/device/deno.js +6 -0
- package/esm/npm/src/device.d.ts +2 -0
- package/esm/npm/src/device.d.ts.map +1 -1
- package/esm/npm/src/device.js +3 -0
- package/esm/npm/src/errors/AuthError.d.ts +2 -1
- package/esm/npm/src/errors/AuthError.d.ts.map +1 -1
- package/esm/npm/src/errors/AuthError.js +8 -3
- package/esm/npm/src/errors/index.d.ts +4 -4
- package/esm/npm/src/errors/index.d.ts.map +1 -1
- package/esm/npm/src/errors/index.js +1 -0
- package/esm/npm/src/generate.js +39 -26
- package/esm/npm/src/helpers.d.ts.map +1 -1
- package/esm/npm/src/index.d.ts +4 -3
- package/esm/npm/src/index.d.ts.map +1 -1
- package/esm/npm/src/index.js +1 -0
- package/esm/npm/src/jobs.d.ts +10 -1
- package/esm/npm/src/jobs.d.ts.map +1 -1
- package/esm/npm/src/jobs.js +16 -1
- package/esm/npm/src/kv.d.ts.map +1 -1
- package/esm/npm/src/kv.js +10 -4
- package/esm/npm/src/models/auth/rpc/Logout.d.ts +4 -4
- package/esm/npm/src/models/auth/rpc/Logout.d.ts.map +1 -1
- package/esm/npm/src/models/auth/rpc/Logout.js +2 -2
- package/esm/npm/src/models/trellis/Page.d.ts +2 -0
- package/esm/npm/src/models/trellis/Page.d.ts.map +1 -0
- package/esm/npm/src/models/trellis/Page.js +1 -0
- package/esm/npm/src/models/trellis/State.d.ts +1 -0
- package/esm/npm/src/models/trellis/State.d.ts.map +1 -1
- package/esm/npm/src/models/trellis/State.js +1 -0
- package/esm/npm/src/models/trellis/rpc/StateList.d.ts +9 -12
- package/esm/npm/src/models/trellis/rpc/StateList.d.ts.map +1 -1
- package/esm/npm/src/models/trellis/rpc/StateList.js +16 -18
- package/esm/npm/src/operations.d.ts +16 -7
- package/esm/npm/src/operations.d.ts.map +1 -1
- package/esm/npm/src/operations.js +84 -19
- package/esm/npm/src/runtime_transport.d.ts +2 -0
- package/esm/npm/src/runtime_transport.d.ts.map +1 -1
- package/esm/npm/src/runtime_transport.js +1 -0
- package/esm/npm/src/server/internal_jobs/active-job.d.ts +2 -1
- package/esm/npm/src/server/internal_jobs/active-job.d.ts.map +1 -1
- package/esm/npm/src/server/internal_jobs/active-job.js +3 -0
- package/esm/npm/src/server/internal_jobs/job-manager.d.ts +4 -1
- package/esm/npm/src/server/internal_jobs/job-manager.d.ts.map +1 -1
- package/esm/npm/src/server/internal_jobs/job-manager.js +61 -1
- package/esm/npm/src/server/internal_jobs/projection.js +1 -0
- package/esm/npm/src/server/internal_jobs/runtime-worker.d.ts +13 -1
- package/esm/npm/src/server/internal_jobs/runtime-worker.d.ts.map +1 -1
- package/esm/npm/src/server/internal_jobs/runtime-worker.js +73 -13
- package/esm/npm/src/server/internal_jobs/types.d.ts +19 -0
- package/esm/npm/src/server/internal_jobs/types.d.ts.map +1 -1
- package/esm/npm/src/server/internal_jobs/types.js +10 -0
- package/esm/npm/src/server/runtime.d.ts +1 -0
- package/esm/npm/src/server/runtime.d.ts.map +1 -1
- package/esm/npm/src/server/service.d.ts +10 -1
- package/esm/npm/src/server/service.d.ts.map +1 -1
- package/esm/npm/src/server/service.js +210 -64
- package/esm/npm/src/server/transfer.d.ts.map +1 -1
- package/esm/npm/src/server/transfer.js +4 -0
- package/esm/npm/src/server.d.ts.map +1 -1
- package/esm/npm/src/server.js +337 -34
- package/esm/npm/src/store.d.ts +8 -1
- package/esm/npm/src/store.d.ts.map +1 -1
- package/esm/npm/src/store.js +46 -8
- package/esm/npm/src/transfer.d.ts +3 -0
- package/esm/npm/src/transfer.d.ts.map +1 -1
- package/esm/npm/src/transfer.js +20 -30
- package/esm/npm/src/trellis.d.ts +85 -22
- package/esm/npm/src/trellis.d.ts.map +1 -1
- package/esm/npm/src/trellis.js +525 -61
- package/esm/operations.d.ts +16 -7
- package/esm/operations.d.ts.map +1 -1
- package/esm/operations.js +84 -19
- package/esm/runtime_transport.d.ts +2 -0
- package/esm/runtime_transport.d.ts.map +1 -1
- package/esm/runtime_transport.js +1 -0
- package/esm/store.d.ts +8 -1
- package/esm/store.d.ts.map +1 -1
- package/esm/store.js +46 -8
- package/esm/transfer.d.ts +3 -0
- package/esm/transfer.d.ts.map +1 -1
- package/esm/transfer.js +20 -30
- package/esm/trellis.d.ts +85 -22
- package/esm/trellis.d.ts.map +1 -1
- package/esm/trellis.js +525 -61
- package/package.json +6 -3
- package/script/auth/browser/login.d.ts.map +1 -1
- package/script/auth/browser/login.js +46 -3
- package/script/auth/browser/portal.d.ts.map +1 -1
- package/script/auth/browser/portal.js +5 -1
- package/script/auth/browser/session.d.ts +18 -7
- package/script/auth/browser/session.d.ts.map +1 -1
- package/script/auth/browser/session.js +47 -11
- package/script/auth/browser/storage.d.ts +6 -1
- package/script/auth/browser/storage.d.ts.map +1 -1
- package/script/auth/browser/storage.js +15 -3
- package/script/auth/browser.d.ts +2 -2
- package/script/auth/browser.d.ts.map +1 -1
- package/script/auth/browser.js +2 -1
- package/script/auth/device_activation.d.ts +36 -33
- package/script/auth/device_activation.d.ts.map +1 -1
- package/script/auth/device_activation.js +25 -21
- package/script/auth/mod.d.ts +4 -4
- package/script/auth/mod.d.ts.map +1 -1
- package/script/auth/mod.js +132 -137
- package/script/auth/proof.d.ts +3 -1
- package/script/auth/proof.d.ts.map +1 -1
- package/script/auth/proof.js +21 -15
- package/script/auth/protocol.d.ts +2457 -941
- package/script/auth/protocol.d.ts.map +1 -1
- package/script/auth/protocol.js +749 -377
- package/script/auth/schemas.d.ts +25 -4
- package/script/auth/schemas.d.ts.map +1 -1
- package/script/auth/schemas.js +16 -5
- package/script/auth/session_auth.d.ts +1 -1
- package/script/auth/session_auth.d.ts.map +1 -1
- package/script/auth/session_auth.js +7 -1
- package/script/client_connect.d.ts +2 -0
- package/script/client_connect.d.ts.map +1 -1
- package/script/client_connect.js +76 -15
- package/script/contract.d.ts +3 -0
- package/script/contract.d.ts.map +1 -1
- package/script/contract_support/mod.d.ts +422 -43
- package/script/contract_support/mod.d.ts.map +1 -1
- package/script/contract_support/mod.js +757 -51
- package/script/contract_support/protocol.d.ts +20 -5
- package/script/contract_support/protocol.d.ts.map +1 -1
- package/script/contract_support/protocol.js +20 -11
- package/script/contract_support/runtime.d.ts +11 -0
- package/script/contract_support/runtime.d.ts.map +1 -1
- package/script/contract_support/schema_pointers.d.ts.map +1 -1
- package/script/contract_support/schema_pointers.js +32 -14
- package/script/device.d.ts +2 -0
- package/script/device.d.ts.map +1 -1
- package/script/device.js +3 -0
- package/script/errors/AuthError.d.ts +2 -1
- package/script/errors/AuthError.d.ts.map +1 -1
- package/script/errors/AuthError.js +8 -3
- package/script/errors/index.d.ts +4 -4
- package/script/errors/index.d.ts.map +1 -1
- package/script/errors/index.js +1 -0
- package/script/generated-sdk/auth/api.d.ts +27 -9
- package/script/generated-sdk/auth/api.d.ts.map +1 -1
- package/script/generated-sdk/auth/api.js +17 -591
- package/script/generated-sdk/auth/client.d.ts +91 -85
- package/script/generated-sdk/auth/client.d.ts.map +1 -1
- package/script/generated-sdk/auth/contract.d.ts +1 -1
- package/script/generated-sdk/auth/contract.d.ts.map +1 -1
- package/script/generated-sdk/auth/contract.js +4 -2
- package/script/generated-sdk/auth/mod.d.ts +1 -0
- package/script/generated-sdk/auth/mod.d.ts.map +1 -1
- package/script/generated-sdk/auth/owned_api.d.ts +3 -0
- package/script/generated-sdk/auth/owned_api.d.ts.map +1 -0
- package/script/generated-sdk/auth/owned_api.js +597 -0
- package/script/generated-sdk/auth/schemas.d.ts +9959 -5160
- package/script/generated-sdk/auth/schemas.d.ts.map +1 -1
- package/script/generated-sdk/auth/schemas.js +139 -140
- package/script/generated-sdk/auth/types.d.ts +2418 -1557
- package/script/generated-sdk/auth/types.d.ts.map +1 -1
- package/script/generated-sdk/auth/types.js +1 -1
- package/script/generated-sdk/health/api.d.ts +24 -9
- package/script/generated-sdk/health/api.d.ts.map +1 -1
- package/script/generated-sdk/health/api.js +13 -21
- package/script/generated-sdk/health/client.d.ts +2 -1
- package/script/generated-sdk/health/client.d.ts.map +1 -1
- package/script/generated-sdk/health/contract.d.ts.map +1 -1
- package/script/generated-sdk/health/contract.js +2 -0
- package/script/generated-sdk/health/owned_api.d.ts +3 -0
- package/script/generated-sdk/health/owned_api.d.ts.map +1 -0
- package/script/generated-sdk/health/owned_api.js +19 -0
- package/script/generated-sdk/health/types.d.ts +2 -0
- package/script/generated-sdk/health/types.d.ts.map +1 -1
- package/script/generated-sdk/jobs/api.d.ts +33 -9
- package/script/generated-sdk/jobs/api.d.ts.map +1 -1
- package/script/generated-sdk/jobs/api.js +23 -88
- package/script/generated-sdk/jobs/client.d.ts +9 -2
- package/script/generated-sdk/jobs/client.d.ts.map +1 -1
- package/script/generated-sdk/jobs/contract.d.ts +1 -1
- package/script/generated-sdk/jobs/contract.d.ts.map +1 -1
- package/script/generated-sdk/jobs/contract.js +4 -2
- package/script/generated-sdk/jobs/owned_api.d.ts +3 -0
- package/script/generated-sdk/jobs/owned_api.d.ts.map +1 -0
- package/script/generated-sdk/jobs/owned_api.js +154 -0
- package/script/generated-sdk/jobs/schemas.d.ts +336 -123
- package/script/generated-sdk/jobs/schemas.d.ts.map +1 -1
- package/script/generated-sdk/jobs/schemas.js +18 -16
- package/script/generated-sdk/jobs/types.d.ts +144 -34
- package/script/generated-sdk/jobs/types.d.ts.map +1 -1
- package/script/generated-sdk/jobs/types.js +38 -2
- package/script/generated-sdk/state/api.d.ts +27 -9
- package/script/generated-sdk/state/api.d.ts.map +1 -1
- package/script/generated-sdk/state/api.js +17 -72
- package/script/generated-sdk/state/client.d.ts +4 -2
- package/script/generated-sdk/state/client.d.ts.map +1 -1
- package/script/generated-sdk/state/contract.d.ts +1 -1
- package/script/generated-sdk/state/contract.d.ts.map +1 -1
- package/script/generated-sdk/state/contract.js +4 -2
- package/script/generated-sdk/state/owned_api.d.ts +3 -0
- package/script/generated-sdk/state/owned_api.d.ts.map +1 -0
- package/script/generated-sdk/state/owned_api.js +69 -0
- package/script/generated-sdk/state/schemas.d.ts +264 -284
- package/script/generated-sdk/state/schemas.d.ts.map +1 -1
- package/script/generated-sdk/state/schemas.js +6 -6
- package/script/generated-sdk/state/types.d.ts +24 -23
- package/script/generated-sdk/state/types.d.ts.map +1 -1
- package/script/generated-sdk/state/types.js +1 -1
- package/script/generated-sdk/trellis-core/api.d.ts +27 -9
- package/script/generated-sdk/trellis-core/api.d.ts.map +1 -1
- package/script/generated-sdk/trellis-core/api.js +17 -40
- package/script/generated-sdk/trellis-core/client.d.ts +5 -2
- package/script/generated-sdk/trellis-core/client.d.ts.map +1 -1
- package/script/generated-sdk/trellis-core/contract.d.ts +1 -1
- package/script/generated-sdk/trellis-core/contract.d.ts.map +1 -1
- package/script/generated-sdk/trellis-core/contract.js +4 -2
- package/script/generated-sdk/trellis-core/owned_api.d.ts +3 -0
- package/script/generated-sdk/trellis-core/owned_api.d.ts.map +1 -0
- package/script/generated-sdk/trellis-core/owned_api.js +45 -0
- package/script/generated-sdk/trellis-core/schemas.d.ts +259 -11
- package/script/generated-sdk/trellis-core/schemas.d.ts.map +1 -1
- package/script/generated-sdk/trellis-core/schemas.js +6 -4
- package/script/generated-sdk/trellis-core/types.d.ts +56 -1
- package/script/generated-sdk/trellis-core/types.d.ts.map +1 -1
- package/script/generated-sdk/trellis-core/types.js +1 -1
- package/script/helpers.d.ts.map +1 -1
- package/script/index.d.ts +4 -3
- package/script/index.d.ts.map +1 -1
- package/script/index.js +5 -2
- package/script/jobs.d.ts +10 -1
- package/script/jobs.d.ts.map +1 -1
- package/script/jobs.js +17 -2
- package/script/kv.d.ts.map +1 -1
- package/script/kv.js +10 -4
- package/script/models/auth/rpc/Logout.d.ts +4 -4
- package/script/models/auth/rpc/Logout.d.ts.map +1 -1
- package/script/models/auth/rpc/Logout.js +3 -3
- package/script/models/trellis/Page.d.ts +2 -0
- package/script/models/trellis/Page.d.ts.map +1 -0
- package/script/models/trellis/Page.js +6 -0
- package/script/models/trellis/State.d.ts +1 -0
- package/script/models/trellis/State.d.ts.map +1 -1
- package/script/models/trellis/State.js +1 -0
- package/script/models/trellis/rpc/StateList.d.ts +9 -12
- package/script/models/trellis/rpc/StateList.d.ts.map +1 -1
- package/script/models/trellis/rpc/StateList.js +16 -18
- package/script/npm/src/auth/browser/login.d.ts.map +1 -1
- package/script/npm/src/auth/browser/login.js +46 -3
- package/script/npm/src/auth/browser/portal.d.ts.map +1 -1
- package/script/npm/src/auth/browser/portal.js +5 -1
- package/script/npm/src/auth/browser/session.d.ts +18 -7
- package/script/npm/src/auth/browser/session.d.ts.map +1 -1
- package/script/npm/src/auth/browser/session.js +47 -11
- package/script/npm/src/auth/browser/storage.d.ts +6 -1
- package/script/npm/src/auth/browser/storage.d.ts.map +1 -1
- package/script/npm/src/auth/browser/storage.js +15 -3
- package/script/npm/src/auth/browser.d.ts +2 -2
- package/script/npm/src/auth/browser.d.ts.map +1 -1
- package/script/npm/src/auth/browser.js +2 -1
- package/script/npm/src/auth/device_activation.d.ts +36 -33
- package/script/npm/src/auth/device_activation.d.ts.map +1 -1
- package/script/npm/src/auth/device_activation.js +25 -21
- package/script/npm/src/auth/mod.d.ts +4 -4
- package/script/npm/src/auth/mod.d.ts.map +1 -1
- package/script/npm/src/auth/mod.js +132 -137
- package/script/npm/src/auth/proof.d.ts +3 -1
- package/script/npm/src/auth/proof.d.ts.map +1 -1
- package/script/npm/src/auth/proof.js +21 -15
- package/script/npm/src/auth/protocol.d.ts +2457 -941
- package/script/npm/src/auth/protocol.d.ts.map +1 -1
- package/script/npm/src/auth/protocol.js +749 -377
- package/script/npm/src/auth/schemas.d.ts +25 -4
- package/script/npm/src/auth/schemas.d.ts.map +1 -1
- package/script/npm/src/auth/schemas.js +16 -5
- package/script/npm/src/auth/session_auth.d.ts +1 -1
- package/script/npm/src/auth/session_auth.d.ts.map +1 -1
- package/script/npm/src/auth/session_auth.js +7 -1
- package/script/npm/src/client_connect.d.ts +2 -0
- package/script/npm/src/client_connect.d.ts.map +1 -1
- package/script/npm/src/client_connect.js +76 -15
- package/script/npm/src/contract.d.ts +3 -0
- package/script/npm/src/contract.d.ts.map +1 -1
- package/script/npm/src/contract_support/mod.d.ts +422 -43
- package/script/npm/src/contract_support/mod.d.ts.map +1 -1
- package/script/npm/src/contract_support/mod.js +757 -51
- package/script/npm/src/contract_support/protocol.d.ts +20 -5
- package/script/npm/src/contract_support/protocol.d.ts.map +1 -1
- package/script/npm/src/contract_support/protocol.js +20 -11
- package/script/npm/src/contract_support/runtime.d.ts +11 -0
- package/script/npm/src/contract_support/runtime.d.ts.map +1 -1
- package/script/npm/src/contract_support/schema_pointers.d.ts.map +1 -1
- package/script/npm/src/contract_support/schema_pointers.js +32 -14
- package/script/npm/src/device/deno.d.ts.map +1 -1
- package/script/npm/src/device/deno.js +6 -0
- package/script/npm/src/device.d.ts +2 -0
- package/script/npm/src/device.d.ts.map +1 -1
- package/script/npm/src/device.js +3 -0
- package/script/npm/src/errors/AuthError.d.ts +2 -1
- package/script/npm/src/errors/AuthError.d.ts.map +1 -1
- package/script/npm/src/errors/AuthError.js +8 -3
- package/script/npm/src/errors/index.d.ts +4 -4
- package/script/npm/src/errors/index.d.ts.map +1 -1
- package/script/npm/src/errors/index.js +1 -0
- package/script/npm/src/generate.js +39 -59
- package/script/npm/src/helpers.d.ts.map +1 -1
- package/script/npm/src/index.d.ts +4 -3
- package/script/npm/src/index.d.ts.map +1 -1
- package/script/npm/src/index.js +5 -2
- package/script/npm/src/jobs.d.ts +10 -1
- package/script/npm/src/jobs.d.ts.map +1 -1
- package/script/npm/src/jobs.js +17 -2
- package/script/npm/src/kv.d.ts.map +1 -1
- package/script/npm/src/kv.js +10 -4
- package/script/npm/src/models/auth/rpc/Logout.d.ts +4 -4
- package/script/npm/src/models/auth/rpc/Logout.d.ts.map +1 -1
- package/script/npm/src/models/auth/rpc/Logout.js +3 -3
- package/script/npm/src/models/trellis/Page.d.ts +2 -0
- package/script/npm/src/models/trellis/Page.d.ts.map +1 -0
- package/script/npm/src/models/trellis/Page.js +6 -0
- package/script/npm/src/models/trellis/State.d.ts +1 -0
- package/script/npm/src/models/trellis/State.d.ts.map +1 -1
- package/script/npm/src/models/trellis/State.js +1 -0
- package/script/npm/src/models/trellis/rpc/StateList.d.ts +9 -12
- package/script/npm/src/models/trellis/rpc/StateList.d.ts.map +1 -1
- package/script/npm/src/models/trellis/rpc/StateList.js +16 -18
- package/script/npm/src/operations.d.ts +16 -7
- package/script/npm/src/operations.d.ts.map +1 -1
- package/script/npm/src/operations.js +84 -19
- package/script/npm/src/runtime_transport.d.ts +2 -0
- package/script/npm/src/runtime_transport.d.ts.map +1 -1
- package/script/npm/src/runtime_transport.js +2 -1
- package/script/npm/src/server/internal_jobs/active-job.d.ts +2 -1
- package/script/npm/src/server/internal_jobs/active-job.d.ts.map +1 -1
- package/script/npm/src/server/internal_jobs/active-job.js +3 -0
- package/script/npm/src/server/internal_jobs/job-manager.d.ts +4 -1
- package/script/npm/src/server/internal_jobs/job-manager.d.ts.map +1 -1
- package/script/npm/src/server/internal_jobs/job-manager.js +61 -1
- package/script/npm/src/server/internal_jobs/projection.js +1 -0
- package/script/npm/src/server/internal_jobs/runtime-worker.d.ts +13 -1
- package/script/npm/src/server/internal_jobs/runtime-worker.d.ts.map +1 -1
- package/script/npm/src/server/internal_jobs/runtime-worker.js +74 -13
- package/script/npm/src/server/internal_jobs/types.d.ts +19 -0
- package/script/npm/src/server/internal_jobs/types.d.ts.map +1 -1
- package/script/npm/src/server/internal_jobs/types.js +11 -1
- package/script/npm/src/server/runtime.d.ts +1 -0
- package/script/npm/src/server/runtime.d.ts.map +1 -1
- package/script/npm/src/server/service.d.ts +10 -1
- package/script/npm/src/server/service.d.ts.map +1 -1
- package/script/npm/src/server/service.js +208 -62
- package/script/npm/src/server/transfer.d.ts.map +1 -1
- package/script/npm/src/server/transfer.js +4 -0
- package/script/npm/src/server.d.ts.map +1 -1
- package/script/npm/src/server.js +336 -33
- package/script/npm/src/store.d.ts +8 -1
- package/script/npm/src/store.d.ts.map +1 -1
- package/script/npm/src/store.js +46 -8
- package/script/npm/src/transfer.d.ts +3 -0
- package/script/npm/src/transfer.d.ts.map +1 -1
- package/script/npm/src/transfer.js +19 -29
- package/script/npm/src/trellis.d.ts +85 -22
- package/script/npm/src/trellis.d.ts.map +1 -1
- package/script/npm/src/trellis.js +525 -61
- package/script/operations.d.ts +16 -7
- package/script/operations.d.ts.map +1 -1
- package/script/operations.js +84 -19
- package/script/runtime_transport.d.ts +2 -0
- package/script/runtime_transport.d.ts.map +1 -1
- package/script/runtime_transport.js +2 -1
- package/script/store.d.ts +8 -1
- package/script/store.d.ts.map +1 -1
- package/script/store.js +46 -8
- package/script/transfer.d.ts +3 -0
- package/script/transfer.d.ts.map +1 -1
- package/script/transfer.js +19 -29
- package/script/trellis.d.ts +85 -22
- package/script/trellis.d.ts.map +1 -1
- package/script/trellis.js +525 -61
- package/src/_dnt.polyfills.ts +274 -0
- package/src/_dnt.shims.ts +64 -0
- package/src/auth/browser/login.ts +295 -0
- package/src/auth/browser/portal.ts +75 -0
- package/src/auth/browser/session.ts +197 -0
- package/src/auth/browser/storage.ts +105 -0
- package/src/auth/browser.ts +82 -0
- package/src/auth/device_activation.ts +715 -0
- package/src/auth/keys.ts +116 -0
- package/src/auth/mod.ts +298 -0
- package/src/auth/proof.ts +111 -0
- package/src/auth/protocol.ts +1629 -0
- package/src/auth/schemas.ts +145 -0
- package/src/auth/session_auth.ts +167 -0
- package/src/auth/time.ts +15 -0
- package/src/auth/trellis_id.ts +9 -0
- package/src/auth/types.ts +4 -0
- package/src/auth/utils.ts +87 -0
- package/src/auth.ts +2 -0
- package/src/browser.ts +8 -0
- package/src/client.ts +164 -0
- package/src/client_connect.ts +1328 -0
- package/src/codec.ts +107 -0
- package/src/connection.ts +466 -0
- package/src/contract.ts +84 -0
- package/src/contract_support/canonical.ts +217 -0
- package/src/contract_support/mod.ts +5079 -0
- package/src/contract_support/protocol.ts +213 -0
- package/src/contract_support/runtime.ts +129 -0
- package/src/contract_support/schema_pointers.ts +161 -0
- package/src/contracts.ts +9 -0
- package/src/device/deno.ts +941 -0
- package/src/device.ts +989 -0
- package/src/env.ts +1 -0
- package/src/errors/AuthError.ts +82 -0
- package/src/errors/KVError.ts +47 -0
- package/src/errors/RemoteError.ts +111 -0
- package/src/errors/StoreError.ts +43 -0
- package/src/errors/TransferError.ts +43 -0
- package/src/errors/TransportError.ts +48 -0
- package/src/errors/TrellisError.ts +20 -0
- package/src/errors/ValidationError.ts +80 -0
- package/src/errors/index.ts +195 -0
- package/src/generate.ts +329 -0
- package/src/globals.ts +26 -0
- package/src/health.ts +28 -0
- package/src/helpers.ts +63 -0
- package/src/host/mod.ts +9 -0
- package/src/host/node.ts +9 -0
- package/src/index.ts +233 -0
- package/src/jobs.ts +344 -0
- package/src/kv.ts +564 -0
- package/src/models/auth/rpc/Logout.ts +15 -0
- package/src/models/trellis/Page.ts +6 -0
- package/src/models/trellis/State.ts +55 -0
- package/src/models/trellis/TrellisError.ts +21 -0
- package/src/models/trellis/rpc/StateDelete.ts +13 -0
- package/src/models/trellis/rpc/StateGet.ts +25 -0
- package/src/models/trellis/rpc/StateList.ts +26 -0
- package/src/models/trellis/rpc/StatePut.ts +42 -0
- package/src/operations.ts +1508 -0
- package/src/runtime_transport.ts +132 -0
- package/src/sdk/auth.ts +2 -0
- package/src/sdk/core.ts +2 -0
- package/src/sdk/health.ts +2 -0
- package/src/sdk/jobs.ts +2 -0
- package/src/sdk/state.ts +2 -0
- package/src/server/health.ts +379 -0
- package/src/server/health_rpc.ts +51 -0
- package/src/server/health_schemas.ts +61 -0
- package/src/server/internal_jobs/active-job.ts +115 -0
- package/src/server/internal_jobs/bindings.ts +26 -0
- package/src/server/internal_jobs/cancellation-registry.ts +71 -0
- package/src/server/internal_jobs/heartbeat.ts +120 -0
- package/src/server/internal_jobs/job-manager.ts +456 -0
- package/src/server/internal_jobs/projection.ts +48 -0
- package/src/server/internal_jobs/runtime-worker.ts +741 -0
- package/src/server/internal_jobs/types.ts +124 -0
- package/src/server/runtime.ts +27 -0
- package/src/server/service.ts +2377 -0
- package/src/server/subscription.ts +143 -0
- package/src/server/transfer.ts +962 -0
- package/src/server.ts +1725 -0
- package/src/server_logger.ts +10 -0
- package/src/service/deno.ts +18 -0
- package/src/service/mod.ts +68 -0
- package/src/service/node.ts +18 -0
- package/src/store.ts +658 -0
- package/src/tasks.ts +34 -0
- package/src/telemetry/carrier.ts +35 -0
- package/src/telemetry/core.ts +31 -0
- package/src/telemetry/env.ts +23 -0
- package/src/telemetry/mod.ts +26 -0
- package/src/telemetry/nats.ts +15 -0
- package/src/telemetry/result.ts +20 -0
- package/src/telemetry/trace.ts +39 -0
- package/src/telemetry/trellis.ts +1 -0
- package/src/tracing.ts +28 -0
- package/src/transfer.ts +602 -0
- package/src/trellis.ts +3650 -0
- package/esm/models/trellis/Paginate.d.ts +0 -7
- package/esm/models/trellis/Paginate.d.ts.map +0 -1
- package/esm/models/trellis/Paginate.js +0 -5
- package/esm/npm/src/models/trellis/Paginate.d.ts +0 -7
- package/esm/npm/src/models/trellis/Paginate.d.ts.map +0 -1
- package/esm/npm/src/models/trellis/Paginate.js +0 -5
- package/script/models/trellis/Paginate.d.ts +0 -7
- package/script/models/trellis/Paginate.d.ts.map +0 -1
- package/script/models/trellis/Paginate.js +0 -11
- package/script/npm/src/models/trellis/Paginate.d.ts +0 -7
- package/script/npm/src/models/trellis/Paginate.d.ts.map +0 -1
- package/script/npm/src/models/trellis/Paginate.js +0 -11
|
@@ -0,0 +1,5079 @@
|
|
|
1
|
+
import Type, {
|
|
2
|
+
type Static,
|
|
3
|
+
type TObject,
|
|
4
|
+
type TProperties,
|
|
5
|
+
type TSchema,
|
|
6
|
+
} from "typebox";
|
|
7
|
+
import { Value } from "typebox/value";
|
|
8
|
+
import type { BaseError } from "@qlever-llc/result";
|
|
9
|
+
import type { AuthSessionsMeResponse } from "../auth/protocol.js";
|
|
10
|
+
import { TrellisError } from "../errors/TrellisError.js";
|
|
11
|
+
import type {
|
|
12
|
+
AuthSessionsLogoutInput,
|
|
13
|
+
AuthSessionsLogoutResponse,
|
|
14
|
+
} from "../models/auth/rpc/Logout.js";
|
|
15
|
+
import type {
|
|
16
|
+
StateDeleteInput,
|
|
17
|
+
StateDeleteResponse,
|
|
18
|
+
} from "../models/trellis/rpc/StateDelete.js";
|
|
19
|
+
import type {
|
|
20
|
+
StateGetInput,
|
|
21
|
+
StateGetResponse,
|
|
22
|
+
} from "../models/trellis/rpc/StateGet.js";
|
|
23
|
+
import type {
|
|
24
|
+
StateListInput,
|
|
25
|
+
StateListResponse,
|
|
26
|
+
} from "../models/trellis/rpc/StateList.js";
|
|
27
|
+
import type {
|
|
28
|
+
StatePutInput,
|
|
29
|
+
StatePutResponse,
|
|
30
|
+
} from "../models/trellis/rpc/StatePut.js";
|
|
31
|
+
import {
|
|
32
|
+
canonicalizeJson,
|
|
33
|
+
digestJson,
|
|
34
|
+
isJsonValue,
|
|
35
|
+
type JsonValue,
|
|
36
|
+
sha256Base64urlSync,
|
|
37
|
+
} from "./canonical.js";
|
|
38
|
+
import {
|
|
39
|
+
type EventDesc,
|
|
40
|
+
type FeedDesc,
|
|
41
|
+
type InferRuntimeRpcError,
|
|
42
|
+
type InferSchemaType,
|
|
43
|
+
type OperationDesc,
|
|
44
|
+
type RPCDesc,
|
|
45
|
+
type RpcErrorClass,
|
|
46
|
+
type RuntimeRpcErrorDesc,
|
|
47
|
+
type Schema,
|
|
48
|
+
schema,
|
|
49
|
+
type SchemaLike,
|
|
50
|
+
type SerializableErrorData,
|
|
51
|
+
type TrellisAPI,
|
|
52
|
+
unwrapSchema,
|
|
53
|
+
} from "./runtime.js";
|
|
54
|
+
import {
|
|
55
|
+
assertDataPointersExistAndAreTokenable,
|
|
56
|
+
getSubschemaAtDataPointer,
|
|
57
|
+
type SubjectParam,
|
|
58
|
+
} from "./schema_pointers.js";
|
|
59
|
+
import {
|
|
60
|
+
ContractJobQueueSchema,
|
|
61
|
+
ContractResourcesSchema,
|
|
62
|
+
ContractSchemaRefSchema,
|
|
63
|
+
ContractStateSchema,
|
|
64
|
+
} from "./protocol.js";
|
|
65
|
+
|
|
66
|
+
export {
|
|
67
|
+
ContractJobQueueSchema,
|
|
68
|
+
ContractJobsSchema,
|
|
69
|
+
ContractKvResourceSchema,
|
|
70
|
+
ContractResourceBindingsSchema,
|
|
71
|
+
ContractResourcesSchema,
|
|
72
|
+
ContractSchemaRefSchema,
|
|
73
|
+
ContractStateSchema,
|
|
74
|
+
ContractStateStoreSchema,
|
|
75
|
+
ContractStoreResourceSchema,
|
|
76
|
+
type EventHeader,
|
|
77
|
+
EventHeaderSchema,
|
|
78
|
+
type InstalledServiceContract,
|
|
79
|
+
InstalledServiceContractSchema,
|
|
80
|
+
IsoDateSchema,
|
|
81
|
+
type JobsQueueBinding,
|
|
82
|
+
JobsQueueBindingSchema,
|
|
83
|
+
type JobsResourceBinding,
|
|
84
|
+
JobsResourceBindingSchema,
|
|
85
|
+
type KvResourceBinding,
|
|
86
|
+
KvResourceBindingSchema,
|
|
87
|
+
type PageRequest,
|
|
88
|
+
PageRequestSchema,
|
|
89
|
+
type PageResponse,
|
|
90
|
+
PageResponseSchema,
|
|
91
|
+
type StoreResourceBinding,
|
|
92
|
+
StoreResourceBindingSchema,
|
|
93
|
+
} from "./protocol.js";
|
|
94
|
+
|
|
95
|
+
export const CONTRACT_FORMAT_V1 = "trellis.contract.v1" as const;
|
|
96
|
+
export const CATALOG_FORMAT_V1 = "trellis.catalog.v1" as const;
|
|
97
|
+
|
|
98
|
+
const NonEmptyStringSchema = Type.String({ minLength: 1 });
|
|
99
|
+
const VersionSchema = Type.String({ pattern: "^v[0-9]+$" });
|
|
100
|
+
const PointerStringSchema = Type.String({ pattern: "^/.*" });
|
|
101
|
+
const CapabilityListSchema = Type.Array(NonEmptyStringSchema);
|
|
102
|
+
const JsonSchemaValueSchema = Type.Union([
|
|
103
|
+
Type.Object({}, { additionalProperties: true }),
|
|
104
|
+
Type.Boolean(),
|
|
105
|
+
]);
|
|
106
|
+
|
|
107
|
+
export const ContractCapabilityMetadataSchema = Type.Object({
|
|
108
|
+
displayName: NonEmptyStringSchema,
|
|
109
|
+
description: NonEmptyStringSchema,
|
|
110
|
+
consequence: Type.Optional(NonEmptyStringSchema),
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
export const ContractCapabilitiesSchema = Type.Record(
|
|
114
|
+
NonEmptyStringSchema,
|
|
115
|
+
ContractCapabilityMetadataSchema,
|
|
116
|
+
);
|
|
117
|
+
|
|
118
|
+
export const ContractExportsSchema = Type.Object({
|
|
119
|
+
schemas: Type.Optional(
|
|
120
|
+
Type.Array(NonEmptyStringSchema, { uniqueItems: true }),
|
|
121
|
+
),
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
const ContractUseRpcSchema = Type.Object({
|
|
125
|
+
call: Type.Optional(CapabilityListSchema),
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
const ContractUsePubSubSchema = Type.Object({
|
|
129
|
+
publish: Type.Optional(CapabilityListSchema),
|
|
130
|
+
subscribe: Type.Optional(CapabilityListSchema),
|
|
131
|
+
});
|
|
132
|
+
|
|
133
|
+
const ContractUseFeedSchema = Type.Object({
|
|
134
|
+
subscribe: Type.Optional(CapabilityListSchema),
|
|
135
|
+
});
|
|
136
|
+
|
|
137
|
+
const ContractUseSchema = Type.Object({
|
|
138
|
+
contract: NonEmptyStringSchema,
|
|
139
|
+
rpc: Type.Optional(ContractUseRpcSchema),
|
|
140
|
+
operations: Type.Optional(ContractUseRpcSchema),
|
|
141
|
+
events: Type.Optional(ContractUsePubSubSchema),
|
|
142
|
+
feeds: Type.Optional(ContractUseFeedSchema),
|
|
143
|
+
});
|
|
144
|
+
|
|
145
|
+
const ContractUsesFlatSchema = Type.Record(
|
|
146
|
+
NonEmptyStringSchema,
|
|
147
|
+
ContractUseSchema,
|
|
148
|
+
);
|
|
149
|
+
|
|
150
|
+
export const ContractUsesSchema = Type.Object({
|
|
151
|
+
required: Type.Optional(ContractUsesFlatSchema),
|
|
152
|
+
optional: Type.Optional(ContractUsesFlatSchema),
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
const ContractErrorDeclSchema = Type.Object({
|
|
156
|
+
type: NonEmptyStringSchema,
|
|
157
|
+
schema: Type.Optional(ContractSchemaRefSchema),
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
const ContractErrorRefSchema = Type.Object({
|
|
161
|
+
type: NonEmptyStringSchema,
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
const RpcCapabilitiesSchema = Type.Object({
|
|
165
|
+
call: Type.Optional(CapabilityListSchema),
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
const OperationCapabilitiesSchema = Type.Object({
|
|
169
|
+
call: Type.Optional(CapabilityListSchema),
|
|
170
|
+
read: Type.Optional(CapabilityListSchema),
|
|
171
|
+
cancel: Type.Optional(CapabilityListSchema),
|
|
172
|
+
control: Type.Optional(CapabilityListSchema),
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
const PubSubCapabilitiesSchema = Type.Object({
|
|
176
|
+
publish: Type.Optional(CapabilityListSchema),
|
|
177
|
+
subscribe: Type.Optional(CapabilityListSchema),
|
|
178
|
+
});
|
|
179
|
+
|
|
180
|
+
const FeedCapabilitiesSchema = Type.Object({
|
|
181
|
+
subscribe: Type.Optional(CapabilityListSchema),
|
|
182
|
+
});
|
|
183
|
+
|
|
184
|
+
const RpcTransferSchema = Type.Object({
|
|
185
|
+
direction: Type.Literal("receive"),
|
|
186
|
+
});
|
|
187
|
+
|
|
188
|
+
const OperationTransferSchema = Type.Object({
|
|
189
|
+
direction: Type.Literal("send"),
|
|
190
|
+
store: NonEmptyStringSchema,
|
|
191
|
+
key: PointerStringSchema,
|
|
192
|
+
contentType: Type.Optional(PointerStringSchema),
|
|
193
|
+
metadata: Type.Optional(PointerStringSchema),
|
|
194
|
+
expiresInMs: Type.Optional(Type.Integer({ minimum: 1 })),
|
|
195
|
+
maxBytes: Type.Optional(Type.Integer({ minimum: 1 })),
|
|
196
|
+
});
|
|
197
|
+
|
|
198
|
+
const ContractRpcMethodSchema = Type.Object({
|
|
199
|
+
version: VersionSchema,
|
|
200
|
+
subject: NonEmptyStringSchema,
|
|
201
|
+
input: ContractSchemaRefSchema,
|
|
202
|
+
output: ContractSchemaRefSchema,
|
|
203
|
+
capabilities: Type.Optional(RpcCapabilitiesSchema),
|
|
204
|
+
errors: Type.Optional(Type.Array(ContractErrorRefSchema)),
|
|
205
|
+
transfer: Type.Optional(RpcTransferSchema),
|
|
206
|
+
});
|
|
207
|
+
|
|
208
|
+
const ContractOperationSignalSchema = Type.Object({
|
|
209
|
+
input: ContractSchemaRefSchema,
|
|
210
|
+
});
|
|
211
|
+
|
|
212
|
+
const ContractOperationSchema = Type.Object({
|
|
213
|
+
version: VersionSchema,
|
|
214
|
+
subject: NonEmptyStringSchema,
|
|
215
|
+
input: ContractSchemaRefSchema,
|
|
216
|
+
progress: Type.Optional(ContractSchemaRefSchema),
|
|
217
|
+
output: ContractSchemaRefSchema,
|
|
218
|
+
transfer: Type.Optional(OperationTransferSchema),
|
|
219
|
+
capabilities: Type.Optional(OperationCapabilitiesSchema),
|
|
220
|
+
signals: Type.Optional(
|
|
221
|
+
Type.Record(NonEmptyStringSchema, ContractOperationSignalSchema),
|
|
222
|
+
),
|
|
223
|
+
cancel: Type.Optional(Type.Boolean()),
|
|
224
|
+
});
|
|
225
|
+
|
|
226
|
+
const ContractEventSchema = Type.Object({
|
|
227
|
+
version: VersionSchema,
|
|
228
|
+
subject: NonEmptyStringSchema,
|
|
229
|
+
params: Type.Optional(Type.Array(PointerStringSchema)),
|
|
230
|
+
event: ContractSchemaRefSchema,
|
|
231
|
+
capabilities: Type.Optional(PubSubCapabilitiesSchema),
|
|
232
|
+
});
|
|
233
|
+
|
|
234
|
+
const ContractFeedSchema = Type.Object({
|
|
235
|
+
version: VersionSchema,
|
|
236
|
+
subject: NonEmptyStringSchema,
|
|
237
|
+
input: ContractSchemaRefSchema,
|
|
238
|
+
event: ContractSchemaRefSchema,
|
|
239
|
+
capabilities: Type.Optional(FeedCapabilitiesSchema),
|
|
240
|
+
});
|
|
241
|
+
|
|
242
|
+
export const TrellisContractV1Schema = Type.Object({
|
|
243
|
+
format: Type.Literal(CONTRACT_FORMAT_V1),
|
|
244
|
+
id: NonEmptyStringSchema,
|
|
245
|
+
displayName: NonEmptyStringSchema,
|
|
246
|
+
description: NonEmptyStringSchema,
|
|
247
|
+
kind: Type.Union([
|
|
248
|
+
Type.Literal("service"),
|
|
249
|
+
Type.Literal("app"),
|
|
250
|
+
Type.Literal("device"),
|
|
251
|
+
Type.Literal("agent"),
|
|
252
|
+
]),
|
|
253
|
+
capabilities: Type.Optional(ContractCapabilitiesSchema),
|
|
254
|
+
schemas: Type.Optional(
|
|
255
|
+
Type.Record(NonEmptyStringSchema, JsonSchemaValueSchema),
|
|
256
|
+
),
|
|
257
|
+
exports: Type.Optional(ContractExportsSchema),
|
|
258
|
+
uses: Type.Optional(ContractUsesSchema),
|
|
259
|
+
state: Type.Optional(ContractStateSchema),
|
|
260
|
+
rpc: Type.Optional(
|
|
261
|
+
Type.Record(NonEmptyStringSchema, ContractRpcMethodSchema),
|
|
262
|
+
),
|
|
263
|
+
operations: Type.Optional(
|
|
264
|
+
Type.Record(NonEmptyStringSchema, ContractOperationSchema),
|
|
265
|
+
),
|
|
266
|
+
events: Type.Optional(Type.Record(NonEmptyStringSchema, ContractEventSchema)),
|
|
267
|
+
feeds: Type.Optional(Type.Record(NonEmptyStringSchema, ContractFeedSchema)),
|
|
268
|
+
errors: Type.Optional(
|
|
269
|
+
Type.Record(NonEmptyStringSchema, ContractErrorDeclSchema),
|
|
270
|
+
),
|
|
271
|
+
jobs: Type.Optional(
|
|
272
|
+
Type.Record(NonEmptyStringSchema, ContractJobQueueSchema),
|
|
273
|
+
),
|
|
274
|
+
resources: Type.Optional(ContractResourcesSchema),
|
|
275
|
+
});
|
|
276
|
+
|
|
277
|
+
export const TrellisCatalogV1Schema = Type.Object({
|
|
278
|
+
format: Type.Literal(CATALOG_FORMAT_V1),
|
|
279
|
+
contracts: Type.Array(Type.Object({
|
|
280
|
+
id: NonEmptyStringSchema,
|
|
281
|
+
digest: Type.String({ pattern: "^[A-Za-z0-9_-]+$" }),
|
|
282
|
+
displayName: NonEmptyStringSchema,
|
|
283
|
+
description: NonEmptyStringSchema,
|
|
284
|
+
})),
|
|
285
|
+
});
|
|
286
|
+
|
|
287
|
+
const CONTRACT_MODULE_METADATA = Symbol.for(
|
|
288
|
+
"@qlever-llc/trellis/contracts/contract-module",
|
|
289
|
+
);
|
|
290
|
+
export const CONTRACT_JOBS_METADATA = Symbol.for(
|
|
291
|
+
"@qlever-llc/trellis/contracts/jobs",
|
|
292
|
+
);
|
|
293
|
+
export const CONTRACT_KV_METADATA = Symbol.for(
|
|
294
|
+
"@qlever-llc/trellis/contracts/kv",
|
|
295
|
+
);
|
|
296
|
+
export const CONTRACT_STATE_METADATA = Symbol.for(
|
|
297
|
+
"@qlever-llc/trellis/contracts/state",
|
|
298
|
+
);
|
|
299
|
+
const CONTRACT_ERROR_RUNTIME_METADATA = Symbol.for(
|
|
300
|
+
"@qlever-llc/trellis/contracts/error-runtime",
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
type UnionToIntersection<U> =
|
|
304
|
+
(U extends unknown ? (value: U) => void : never) extends
|
|
305
|
+
(value: infer I) => void ? I
|
|
306
|
+
: never;
|
|
307
|
+
|
|
308
|
+
type Simplify<T> = { [K in keyof T]: T[K] } & {};
|
|
309
|
+
type StringKeyOf<T> = Extract<keyof T, string>;
|
|
310
|
+
type KeysFromList<T> = T extends readonly (infer K)[] ? Extract<K, string>
|
|
311
|
+
: never;
|
|
312
|
+
|
|
313
|
+
type ReservedDefinedErrorFieldName =
|
|
314
|
+
| "id"
|
|
315
|
+
| "type"
|
|
316
|
+
| "message"
|
|
317
|
+
| "context"
|
|
318
|
+
| "traceId"
|
|
319
|
+
| "cause";
|
|
320
|
+
|
|
321
|
+
const RESERVED_DEFINED_ERROR_FIELD_NAMES: ReadonlySet<
|
|
322
|
+
ReservedDefinedErrorFieldName
|
|
323
|
+
> = new Set([
|
|
324
|
+
"id",
|
|
325
|
+
"type",
|
|
326
|
+
"message",
|
|
327
|
+
"context",
|
|
328
|
+
"traceId",
|
|
329
|
+
"cause",
|
|
330
|
+
]);
|
|
331
|
+
|
|
332
|
+
const DEFINED_ERROR_PAYLOAD = Symbol.for(
|
|
333
|
+
"@qlever-llc/trellis/contracts/defined-error-payload",
|
|
334
|
+
);
|
|
335
|
+
|
|
336
|
+
export type ContractManifestMetadata = {
|
|
337
|
+
displayName: string;
|
|
338
|
+
description: string;
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
export type ContractKind = "service" | "app" | "device" | "agent";
|
|
342
|
+
|
|
343
|
+
export type Capability = string;
|
|
344
|
+
export type PlatformCapability = "admin" | "service";
|
|
345
|
+
export type GlobalCapability = `${string}::${string}`;
|
|
346
|
+
export type ContractCapabilityMetadata = {
|
|
347
|
+
displayName: string;
|
|
348
|
+
description: string;
|
|
349
|
+
consequence?: string;
|
|
350
|
+
};
|
|
351
|
+
export type ContractCapabilities = Record<string, ContractCapabilityMetadata>;
|
|
352
|
+
type DeclaredCapabilityName<TCapabilities> = [TCapabilities] extends [undefined]
|
|
353
|
+
? never
|
|
354
|
+
: Extract<keyof NonNullable<TCapabilities>, string>;
|
|
355
|
+
type CapabilityRef<TCapabilities> =
|
|
356
|
+
| DeclaredCapabilityName<TCapabilities>
|
|
357
|
+
| GlobalCapability
|
|
358
|
+
| PlatformCapability;
|
|
359
|
+
export type JsonSchema = JsonValue | boolean;
|
|
360
|
+
|
|
361
|
+
export type ContractSchemaRef<TSchemaName extends string = string> = {
|
|
362
|
+
schema: TSchemaName;
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
function createSchemaRef<
|
|
366
|
+
const TSchemas extends Readonly<Record<string, TSchema>>,
|
|
367
|
+
>(_schemas: TSchemas) {
|
|
368
|
+
void _schemas;
|
|
369
|
+
return <const TName extends keyof TSchemas & string>(
|
|
370
|
+
schemaName: TName,
|
|
371
|
+
): ContractSchemaRef<TName> => ({ schema: schemaName });
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
export type BuiltinContractErrorName =
|
|
375
|
+
| "UnexpectedError"
|
|
376
|
+
| "TransportError"
|
|
377
|
+
| "AuthError"
|
|
378
|
+
| "ValidationError"
|
|
379
|
+
| "KVError"
|
|
380
|
+
| "StoreError"
|
|
381
|
+
| "TransferError";
|
|
382
|
+
|
|
383
|
+
type ErrorNameOf<TErrors> =
|
|
384
|
+
| Extract<keyof NonNullable<TErrors>, string>
|
|
385
|
+
| BuiltinContractErrorName;
|
|
386
|
+
|
|
387
|
+
export type ContractRefBuilder<
|
|
388
|
+
TSchemas extends Readonly<Record<string, TSchema>> | undefined = undefined,
|
|
389
|
+
TErrors extends
|
|
390
|
+
| Readonly<Record<string, ErrorClass>>
|
|
391
|
+
| undefined = undefined,
|
|
392
|
+
> = {
|
|
393
|
+
schema<const TName extends SchemaNameOf<TSchemas>>(
|
|
394
|
+
schemaName: TName,
|
|
395
|
+
): ContractSchemaRef<TName>;
|
|
396
|
+
error<const TName extends ErrorNameOf<TErrors>>(
|
|
397
|
+
errorName: TName,
|
|
398
|
+
): TName;
|
|
399
|
+
capability<const TName extends GlobalCapability | PlatformCapability>(
|
|
400
|
+
capabilityName: TName,
|
|
401
|
+
): TName;
|
|
402
|
+
};
|
|
403
|
+
|
|
404
|
+
export type ContractSchemas = Record<string, JsonSchema>;
|
|
405
|
+
|
|
406
|
+
export type ContractExports<TSchemaName extends string = string> = {
|
|
407
|
+
schemas?: TSchemaName[];
|
|
408
|
+
};
|
|
409
|
+
|
|
410
|
+
export type ContractStateKind = "value" | "map";
|
|
411
|
+
|
|
412
|
+
export type ContractStateStore = {
|
|
413
|
+
kind: ContractStateKind;
|
|
414
|
+
schema: ContractSchemaRef;
|
|
415
|
+
stateVersion?: string;
|
|
416
|
+
acceptedVersions?: Record<string, ContractSchemaRef>;
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
export type ContractState = Record<string, ContractStateStore>;
|
|
420
|
+
|
|
421
|
+
type ContractIdentityFields = {
|
|
422
|
+
id: string;
|
|
423
|
+
displayName: string;
|
|
424
|
+
description: string;
|
|
425
|
+
};
|
|
426
|
+
|
|
427
|
+
export type ContractErrorDecl = {
|
|
428
|
+
type: string;
|
|
429
|
+
schema?: ContractSchemaRef;
|
|
430
|
+
};
|
|
431
|
+
|
|
432
|
+
export type ContractErrorRef = {
|
|
433
|
+
type: string;
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
export type ContractRpcMethod = {
|
|
437
|
+
version: `v${number}`;
|
|
438
|
+
subject: string;
|
|
439
|
+
input: ContractSchemaRef;
|
|
440
|
+
output: ContractSchemaRef;
|
|
441
|
+
transfer?: { direction: "receive" };
|
|
442
|
+
capabilities?: { call?: Capability[] };
|
|
443
|
+
errors?: ContractErrorRef[];
|
|
444
|
+
};
|
|
445
|
+
|
|
446
|
+
export type ContractOperation = {
|
|
447
|
+
version: `v${number}`;
|
|
448
|
+
subject: string;
|
|
449
|
+
input: ContractSchemaRef;
|
|
450
|
+
progress?: ContractSchemaRef;
|
|
451
|
+
output: ContractSchemaRef;
|
|
452
|
+
transfer?: {
|
|
453
|
+
direction: "send";
|
|
454
|
+
store: string;
|
|
455
|
+
key: `/${string}`;
|
|
456
|
+
contentType?: `/${string}`;
|
|
457
|
+
metadata?: `/${string}`;
|
|
458
|
+
expiresInMs?: number;
|
|
459
|
+
maxBytes?: number;
|
|
460
|
+
};
|
|
461
|
+
capabilities?: {
|
|
462
|
+
call?: Capability[];
|
|
463
|
+
read?: Capability[];
|
|
464
|
+
cancel?: Capability[];
|
|
465
|
+
control?: Capability[];
|
|
466
|
+
};
|
|
467
|
+
signals?: Record<string, { input: ContractSchemaRef }>;
|
|
468
|
+
cancel?: boolean;
|
|
469
|
+
};
|
|
470
|
+
|
|
471
|
+
export type ContractEvent = {
|
|
472
|
+
version: `v${number}`;
|
|
473
|
+
subject: string;
|
|
474
|
+
params?: string[];
|
|
475
|
+
event: ContractSchemaRef;
|
|
476
|
+
capabilities?: { publish?: Capability[]; subscribe?: Capability[] };
|
|
477
|
+
};
|
|
478
|
+
|
|
479
|
+
export type ContractFeed = {
|
|
480
|
+
version: `v${number}`;
|
|
481
|
+
subject: string;
|
|
482
|
+
input: ContractSchemaRef;
|
|
483
|
+
event: ContractSchemaRef;
|
|
484
|
+
capabilities?: { subscribe?: Capability[] };
|
|
485
|
+
};
|
|
486
|
+
|
|
487
|
+
export type ContractJobQueueResource = {
|
|
488
|
+
payload: ContractSchemaRef;
|
|
489
|
+
result?: ContractSchemaRef;
|
|
490
|
+
maxDeliver?: number;
|
|
491
|
+
backoffMs?: number[];
|
|
492
|
+
ackWaitMs?: number;
|
|
493
|
+
defaultDeadlineMs?: number;
|
|
494
|
+
progress?: boolean;
|
|
495
|
+
logs?: boolean;
|
|
496
|
+
dlq?: boolean;
|
|
497
|
+
concurrency?: number;
|
|
498
|
+
};
|
|
499
|
+
|
|
500
|
+
export type ContractJobQueue = ContractJobQueueResource;
|
|
501
|
+
|
|
502
|
+
export type ContractJobs = Record<string, ContractJobQueue>;
|
|
503
|
+
|
|
504
|
+
export type ContractKvResource = {
|
|
505
|
+
purpose: string;
|
|
506
|
+
schema: ContractSchemaRef;
|
|
507
|
+
required?: boolean;
|
|
508
|
+
history?: number;
|
|
509
|
+
ttlMs?: number;
|
|
510
|
+
maxValueBytes?: number;
|
|
511
|
+
};
|
|
512
|
+
|
|
513
|
+
export type ContractStoreResource = {
|
|
514
|
+
purpose: string;
|
|
515
|
+
required?: boolean;
|
|
516
|
+
ttlMs?: number;
|
|
517
|
+
maxObjectBytes?: number;
|
|
518
|
+
maxTotalBytes?: number;
|
|
519
|
+
};
|
|
520
|
+
|
|
521
|
+
export type ContractResources = {
|
|
522
|
+
kv?: Record<string, ContractKvResource>;
|
|
523
|
+
store?: Record<string, ContractStoreResource>;
|
|
524
|
+
};
|
|
525
|
+
|
|
526
|
+
export type ContractUsesRpc = {
|
|
527
|
+
call?: string[];
|
|
528
|
+
};
|
|
529
|
+
|
|
530
|
+
export type ContractUsesPubSub = {
|
|
531
|
+
publish?: string[];
|
|
532
|
+
subscribe?: string[];
|
|
533
|
+
};
|
|
534
|
+
|
|
535
|
+
export type ContractUse = {
|
|
536
|
+
contract: string;
|
|
537
|
+
rpc?: ContractUsesRpc;
|
|
538
|
+
operations?: ContractUsesRpc;
|
|
539
|
+
events?: ContractUsesPubSub;
|
|
540
|
+
feeds?: { subscribe?: string[] };
|
|
541
|
+
};
|
|
542
|
+
|
|
543
|
+
type ContractUsesFlat = Record<string, ContractUse>;
|
|
544
|
+
|
|
545
|
+
export type ContractUsesGrouped = {
|
|
546
|
+
required?: Record<string, ContractUse>;
|
|
547
|
+
optional?: Record<string, ContractUse>;
|
|
548
|
+
};
|
|
549
|
+
|
|
550
|
+
export type ContractUses = ContractUsesGrouped;
|
|
551
|
+
|
|
552
|
+
export type TrellisContractV1 = {
|
|
553
|
+
format: typeof CONTRACT_FORMAT_V1;
|
|
554
|
+
id: string;
|
|
555
|
+
displayName: string;
|
|
556
|
+
description: string;
|
|
557
|
+
kind: ContractKind;
|
|
558
|
+
capabilities?: ContractCapabilities;
|
|
559
|
+
schemas?: ContractSchemas;
|
|
560
|
+
exports?: ContractExports;
|
|
561
|
+
state?: ContractState;
|
|
562
|
+
uses?: ContractUses;
|
|
563
|
+
rpc?: Record<string, ContractRpcMethod>;
|
|
564
|
+
operations?: Record<string, ContractOperation>;
|
|
565
|
+
events?: Record<string, ContractEvent>;
|
|
566
|
+
feeds?: Record<string, ContractFeed>;
|
|
567
|
+
errors?: Record<string, ContractErrorDecl>;
|
|
568
|
+
jobs?: ContractJobs;
|
|
569
|
+
resources?: ContractResources;
|
|
570
|
+
};
|
|
571
|
+
|
|
572
|
+
export type TrellisCatalogEntry = {
|
|
573
|
+
id: string;
|
|
574
|
+
digest: string;
|
|
575
|
+
displayName: string;
|
|
576
|
+
description: string;
|
|
577
|
+
};
|
|
578
|
+
|
|
579
|
+
export type TrellisCatalogV1 = {
|
|
580
|
+
format: typeof CATALOG_FORMAT_V1;
|
|
581
|
+
contracts: TrellisCatalogEntry[];
|
|
582
|
+
};
|
|
583
|
+
|
|
584
|
+
export type ContractSourceErrorDecl<TSchemaName extends string = string> = {
|
|
585
|
+
type: string;
|
|
586
|
+
schema?: ContractSchemaRef<TSchemaName>;
|
|
587
|
+
};
|
|
588
|
+
|
|
589
|
+
type ExtractErrorClasses<TErrors> = TErrors extends
|
|
590
|
+
Readonly<Record<string, unknown>> ? {
|
|
591
|
+
[
|
|
592
|
+
K in keyof TErrors as TErrors[K] extends ErrorClass ? K
|
|
593
|
+
: never
|
|
594
|
+
]: Extract<TErrors[K], ErrorClass>;
|
|
595
|
+
}
|
|
596
|
+
: undefined;
|
|
597
|
+
|
|
598
|
+
type ContractErrorRuntimeMarker<
|
|
599
|
+
TClass extends RpcErrorClass = RpcErrorClass,
|
|
600
|
+
> = {
|
|
601
|
+
readonly [CONTRACT_ERROR_RUNTIME_METADATA]: TClass;
|
|
602
|
+
};
|
|
603
|
+
|
|
604
|
+
export type ErrorClass<
|
|
605
|
+
TData extends SerializableErrorData = SerializableErrorData,
|
|
606
|
+
TError extends BaseError = BaseError,
|
|
607
|
+
TRuntimeSchema extends TSchema = TSchema,
|
|
608
|
+
> = RpcErrorClass<TData, TError> & {
|
|
609
|
+
readonly name: string;
|
|
610
|
+
readonly schema: TRuntimeSchema;
|
|
611
|
+
readonly type?: string;
|
|
612
|
+
};
|
|
613
|
+
|
|
614
|
+
type DefinedErrorPayload<TFields extends TProperties> =
|
|
615
|
+
& Static<TObject<TFields>>
|
|
616
|
+
& object;
|
|
617
|
+
|
|
618
|
+
type DefinedErrorData<TType extends string, TFields extends TProperties> =
|
|
619
|
+
& SerializableErrorData
|
|
620
|
+
& { type: TType }
|
|
621
|
+
& DefinedErrorPayload<TFields>;
|
|
622
|
+
|
|
623
|
+
type DefinedErrorSchema = TObject<TProperties>;
|
|
624
|
+
|
|
625
|
+
type DefinedErrorPayloadCarrier<TPayload extends object> = {
|
|
626
|
+
[DEFINED_ERROR_PAYLOAD]: Readonly<TPayload>;
|
|
627
|
+
};
|
|
628
|
+
|
|
629
|
+
export type DefineErrorOptions<
|
|
630
|
+
TType extends string,
|
|
631
|
+
TFields extends TProperties,
|
|
632
|
+
> = {
|
|
633
|
+
type: TType;
|
|
634
|
+
fields: TFields;
|
|
635
|
+
message:
|
|
636
|
+
| string
|
|
637
|
+
| ((payload: Readonly<DefinedErrorPayload<TFields>>) => string);
|
|
638
|
+
};
|
|
639
|
+
|
|
640
|
+
export type DefinedErrorInit<TFields extends TProperties> =
|
|
641
|
+
& DefinedErrorPayload<TFields>
|
|
642
|
+
& ErrorOptions
|
|
643
|
+
& {
|
|
644
|
+
context?: Record<string, unknown>;
|
|
645
|
+
id?: string;
|
|
646
|
+
traceId?: string;
|
|
647
|
+
};
|
|
648
|
+
|
|
649
|
+
export type DefinedErrorInstance<
|
|
650
|
+
TType extends string,
|
|
651
|
+
TFields extends TProperties,
|
|
652
|
+
> =
|
|
653
|
+
& TrellisError<DefinedErrorData<TType, TFields>>
|
|
654
|
+
& DefinedErrorPayloadCarrier<DefinedErrorPayload<TFields>>
|
|
655
|
+
& Readonly<DefinedErrorPayload<TFields>>;
|
|
656
|
+
|
|
657
|
+
export type DefinedErrorClass<
|
|
658
|
+
TType extends string,
|
|
659
|
+
TFields extends TProperties,
|
|
660
|
+
> =
|
|
661
|
+
& ErrorClass<
|
|
662
|
+
DefinedErrorData<TType, TFields>,
|
|
663
|
+
DefinedErrorInstance<TType, TFields>,
|
|
664
|
+
DefinedErrorSchema
|
|
665
|
+
>
|
|
666
|
+
& {
|
|
667
|
+
new (
|
|
668
|
+
options: DefinedErrorInit<TFields>,
|
|
669
|
+
): DefinedErrorInstance<TType, TFields>;
|
|
670
|
+
readonly type: TType;
|
|
671
|
+
readonly schema: DefinedErrorSchema;
|
|
672
|
+
fromSerializable(
|
|
673
|
+
data: DefinedErrorData<TType, TFields>,
|
|
674
|
+
): DefinedErrorInstance<TType, TFields>;
|
|
675
|
+
};
|
|
676
|
+
|
|
677
|
+
function getContractErrorType(errorClass: ErrorClass): string {
|
|
678
|
+
const explicitType = Reflect.get(errorClass, "type");
|
|
679
|
+
return typeof explicitType === "string" ? explicitType : errorClass.name;
|
|
680
|
+
}
|
|
681
|
+
|
|
682
|
+
function isSerializableErrorData(
|
|
683
|
+
value: unknown,
|
|
684
|
+
): value is SerializableErrorData {
|
|
685
|
+
return !!value && typeof value === "object" &&
|
|
686
|
+
typeof (value as { id?: unknown }).id === "string" &&
|
|
687
|
+
typeof (value as { type?: unknown }).type === "string" &&
|
|
688
|
+
typeof (value as { message?: unknown }).message === "string";
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
function isErrorClass(value: unknown): value is ErrorClass {
|
|
692
|
+
return typeof value === "function" &&
|
|
693
|
+
typeof Reflect.get(value, "name") === "string" &&
|
|
694
|
+
typeof Reflect.get(value, "fromSerializable") === "function" &&
|
|
695
|
+
typeof Reflect.get(value, "schema") === "object";
|
|
696
|
+
}
|
|
697
|
+
|
|
698
|
+
function assertNoReservedDefinedErrorFieldNames(fields: TProperties): void {
|
|
699
|
+
for (const fieldName of Object.keys(fields)) {
|
|
700
|
+
if (
|
|
701
|
+
RESERVED_DEFINED_ERROR_FIELD_NAMES.has(
|
|
702
|
+
fieldName as ReservedDefinedErrorFieldName,
|
|
703
|
+
)
|
|
704
|
+
) {
|
|
705
|
+
throw new Error(`Defined error field '${fieldName}' is reserved`);
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
function createDefinedErrorSchema<
|
|
711
|
+
TType extends string,
|
|
712
|
+
TFields extends TProperties,
|
|
713
|
+
>(
|
|
714
|
+
type: TType,
|
|
715
|
+
fields: TFields,
|
|
716
|
+
): DefinedErrorSchema {
|
|
717
|
+
return Type.Object({
|
|
718
|
+
id: Type.String(),
|
|
719
|
+
type: Type.Literal(type),
|
|
720
|
+
message: Type.String(),
|
|
721
|
+
...fields,
|
|
722
|
+
context: Type.Optional(Type.Record(Type.String(), Type.Unknown())),
|
|
723
|
+
traceId: Type.Optional(Type.String()),
|
|
724
|
+
});
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
function definedErrorPayloadFieldNames<TFields extends TProperties>(
|
|
728
|
+
fields: TFields,
|
|
729
|
+
): readonly (keyof DefinedErrorPayload<TFields> & string)[] {
|
|
730
|
+
return Object.keys(fields) as Array<
|
|
731
|
+
keyof DefinedErrorPayload<TFields> & string
|
|
732
|
+
>;
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
function pickDefinedErrorPayload<TPayload extends object>(
|
|
736
|
+
fieldNames: readonly (keyof TPayload & string)[],
|
|
737
|
+
source: TPayload,
|
|
738
|
+
): Readonly<TPayload> {
|
|
739
|
+
return Object.fromEntries(
|
|
740
|
+
fieldNames.map((fieldName) => [fieldName, source[fieldName]]),
|
|
741
|
+
) as TPayload;
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
function definedErrorBaseOptions<TPayload extends object>(
|
|
745
|
+
options: TPayload & {
|
|
746
|
+
context?: Record<string, unknown>;
|
|
747
|
+
id?: string;
|
|
748
|
+
traceId?: string;
|
|
749
|
+
cause?: unknown;
|
|
750
|
+
},
|
|
751
|
+
): ErrorOptions & {
|
|
752
|
+
context?: Record<string, unknown>;
|
|
753
|
+
id?: string;
|
|
754
|
+
traceId?: string;
|
|
755
|
+
} {
|
|
756
|
+
const baseOptions: ErrorOptions & {
|
|
757
|
+
context?: Record<string, unknown>;
|
|
758
|
+
id?: string;
|
|
759
|
+
traceId?: string;
|
|
760
|
+
} = {};
|
|
761
|
+
if (options.cause !== undefined) {
|
|
762
|
+
baseOptions.cause = options.cause;
|
|
763
|
+
}
|
|
764
|
+
if (options.context !== undefined) {
|
|
765
|
+
baseOptions.context = options.context;
|
|
766
|
+
}
|
|
767
|
+
if (options.id !== undefined) {
|
|
768
|
+
baseOptions.id = options.id;
|
|
769
|
+
}
|
|
770
|
+
if (options.traceId !== undefined) {
|
|
771
|
+
baseOptions.traceId = options.traceId;
|
|
772
|
+
}
|
|
773
|
+
return baseOptions;
|
|
774
|
+
}
|
|
775
|
+
|
|
776
|
+
function attachDefinedErrorPayload<
|
|
777
|
+
TError extends TrellisError<SerializableErrorData>,
|
|
778
|
+
TPayload extends object,
|
|
779
|
+
>(
|
|
780
|
+
error: TError & DefinedErrorPayloadCarrier<TPayload>,
|
|
781
|
+
payload: Readonly<TPayload>,
|
|
782
|
+
): TError & Readonly<TPayload> & DefinedErrorPayloadCarrier<TPayload> {
|
|
783
|
+
error[DEFINED_ERROR_PAYLOAD] = payload;
|
|
784
|
+
return Object.assign(error, payload);
|
|
785
|
+
}
|
|
786
|
+
|
|
787
|
+
export type ContractSourceSchemas = Record<string, TSchema>;
|
|
788
|
+
|
|
789
|
+
export type ContractSourceExports<TSchemaName extends string = string> = {
|
|
790
|
+
schemas?: readonly TSchemaName[];
|
|
791
|
+
};
|
|
792
|
+
|
|
793
|
+
export type ContractSourceStateStore<TSchemaName extends string = string> = {
|
|
794
|
+
kind: ContractStateKind;
|
|
795
|
+
schema: ContractSchemaRef<TSchemaName>;
|
|
796
|
+
stateVersion?: string;
|
|
797
|
+
acceptedVersions?: Record<string, ContractSchemaRef<TSchemaName>>;
|
|
798
|
+
};
|
|
799
|
+
|
|
800
|
+
export type ContractSourceState<TSchemaName extends string = string> = Record<
|
|
801
|
+
string,
|
|
802
|
+
ContractSourceStateStore<TSchemaName>
|
|
803
|
+
>;
|
|
804
|
+
|
|
805
|
+
export type ContractSourceRpcMethod<
|
|
806
|
+
TSchemaName extends string = string,
|
|
807
|
+
TErrorName extends string = string,
|
|
808
|
+
TCapability extends string = Capability,
|
|
809
|
+
> = {
|
|
810
|
+
version: `v${number}`;
|
|
811
|
+
input: ContractSchemaRef<TSchemaName>;
|
|
812
|
+
output: ContractSchemaRef<TSchemaName>;
|
|
813
|
+
capabilities?: { call?: readonly TCapability[] };
|
|
814
|
+
transfer?: { direction: "receive" };
|
|
815
|
+
errors?: readonly TErrorName[];
|
|
816
|
+
authRequired?: boolean;
|
|
817
|
+
subject?: string;
|
|
818
|
+
};
|
|
819
|
+
|
|
820
|
+
export type ContractSourceOperation<
|
|
821
|
+
TSchemaName extends string = string,
|
|
822
|
+
TCapability extends string = Capability,
|
|
823
|
+
> = {
|
|
824
|
+
version: `v${number}`;
|
|
825
|
+
input: ContractSchemaRef<TSchemaName>;
|
|
826
|
+
progress?: ContractSchemaRef<TSchemaName>;
|
|
827
|
+
output: ContractSchemaRef<TSchemaName>;
|
|
828
|
+
transfer?: {
|
|
829
|
+
direction: "send";
|
|
830
|
+
store: string;
|
|
831
|
+
key: `/${string}`;
|
|
832
|
+
contentType?: `/${string}`;
|
|
833
|
+
metadata?: `/${string}`;
|
|
834
|
+
expiresInMs?: number;
|
|
835
|
+
maxBytes?: number;
|
|
836
|
+
};
|
|
837
|
+
capabilities?: {
|
|
838
|
+
call?: readonly TCapability[];
|
|
839
|
+
read?: readonly TCapability[];
|
|
840
|
+
cancel?: readonly TCapability[];
|
|
841
|
+
control?: readonly TCapability[];
|
|
842
|
+
};
|
|
843
|
+
signals?: Record<string, { input: ContractSchemaRef<TSchemaName> }>;
|
|
844
|
+
cancel?: boolean;
|
|
845
|
+
subject?: string;
|
|
846
|
+
};
|
|
847
|
+
|
|
848
|
+
export type ContractSourceEvent<
|
|
849
|
+
TSchemaName extends string = string,
|
|
850
|
+
TCapability extends string = Capability,
|
|
851
|
+
> = {
|
|
852
|
+
version: `v${number}`;
|
|
853
|
+
event: ContractSchemaRef<TSchemaName>;
|
|
854
|
+
params?: readonly SubjectParam[];
|
|
855
|
+
capabilities?: {
|
|
856
|
+
publish?: readonly TCapability[];
|
|
857
|
+
subscribe?: readonly TCapability[];
|
|
858
|
+
};
|
|
859
|
+
subject?: string;
|
|
860
|
+
};
|
|
861
|
+
|
|
862
|
+
export type ContractSourceFeed<
|
|
863
|
+
TSchemaName extends string = string,
|
|
864
|
+
TCapability extends string = Capability,
|
|
865
|
+
> = {
|
|
866
|
+
version: `v${number}`;
|
|
867
|
+
input: ContractSchemaRef<TSchemaName>;
|
|
868
|
+
event: ContractSchemaRef<TSchemaName>;
|
|
869
|
+
capabilities?: { subscribe?: readonly TCapability[] };
|
|
870
|
+
subject?: string;
|
|
871
|
+
};
|
|
872
|
+
|
|
873
|
+
export type ContractSourceJobQueue<
|
|
874
|
+
TSchemaName extends string = string,
|
|
875
|
+
> = {
|
|
876
|
+
payload: ContractSchemaRef<TSchemaName>;
|
|
877
|
+
result?: ContractSchemaRef<TSchemaName>;
|
|
878
|
+
maxDeliver?: number;
|
|
879
|
+
backoffMs?: readonly number[];
|
|
880
|
+
ackWaitMs?: number;
|
|
881
|
+
defaultDeadlineMs?: number;
|
|
882
|
+
progress?: boolean;
|
|
883
|
+
logs?: boolean;
|
|
884
|
+
dlq?: boolean;
|
|
885
|
+
concurrency?: number;
|
|
886
|
+
};
|
|
887
|
+
|
|
888
|
+
export type ContractSourceJobs<TSchemaName extends string = string> = Record<
|
|
889
|
+
string,
|
|
890
|
+
ContractSourceJobQueue<TSchemaName>
|
|
891
|
+
>;
|
|
892
|
+
|
|
893
|
+
export type ContractSourceKvResource<TSchemaName extends string = string> = {
|
|
894
|
+
purpose: string;
|
|
895
|
+
schema: ContractSchemaRef<TSchemaName>;
|
|
896
|
+
required?: boolean;
|
|
897
|
+
history?: number;
|
|
898
|
+
ttlMs?: number;
|
|
899
|
+
maxValueBytes?: number;
|
|
900
|
+
};
|
|
901
|
+
|
|
902
|
+
export type ContractSourceStoreResource = {
|
|
903
|
+
purpose: string;
|
|
904
|
+
required?: boolean;
|
|
905
|
+
ttlMs?: number;
|
|
906
|
+
maxObjectBytes?: number;
|
|
907
|
+
maxTotalBytes?: number;
|
|
908
|
+
};
|
|
909
|
+
|
|
910
|
+
export type ContractSourceResources<TSchemaName extends string = string> = {
|
|
911
|
+
kv?: Record<string, ContractSourceKvResource<TSchemaName>>;
|
|
912
|
+
store?: Record<string, ContractSourceStoreResource>;
|
|
913
|
+
};
|
|
914
|
+
|
|
915
|
+
export type ContractSourceUse = {
|
|
916
|
+
contract: string;
|
|
917
|
+
rpc?: { call?: readonly string[] };
|
|
918
|
+
operations?: { call?: readonly string[] };
|
|
919
|
+
events?: { publish?: readonly string[]; subscribe?: readonly string[] };
|
|
920
|
+
feeds?: { subscribe?: readonly string[] };
|
|
921
|
+
};
|
|
922
|
+
|
|
923
|
+
type ContractSourceUsesFlat = Record<string, ContractSourceUse>;
|
|
924
|
+
|
|
925
|
+
export type ContractSourceUsesGrouped = {
|
|
926
|
+
required?: Record<string, ContractSourceUse>;
|
|
927
|
+
optional?: Record<string, ContractSourceUse>;
|
|
928
|
+
};
|
|
929
|
+
|
|
930
|
+
export type ContractSourceUses = ContractSourceUsesGrouped;
|
|
931
|
+
|
|
932
|
+
export type TrellisContractSource = {
|
|
933
|
+
id: string;
|
|
934
|
+
displayName: string;
|
|
935
|
+
description: string;
|
|
936
|
+
kind: ContractKind;
|
|
937
|
+
capabilities?: ContractCapabilities;
|
|
938
|
+
schemas?: ContractSourceSchemas;
|
|
939
|
+
exports?: ContractSourceExports;
|
|
940
|
+
state?: ContractSourceState;
|
|
941
|
+
uses?: ContractSourceUses;
|
|
942
|
+
rpc?: Record<string, ContractSourceRpcMethod>;
|
|
943
|
+
operations?: Record<string, ContractSourceOperation>;
|
|
944
|
+
events?: Record<string, ContractSourceEvent>;
|
|
945
|
+
feeds?: Record<string, ContractSourceFeed>;
|
|
946
|
+
errors?: Record<string, ContractSourceErrorDecl>;
|
|
947
|
+
jobs?: ContractSourceJobs;
|
|
948
|
+
resources?: ContractSourceResources;
|
|
949
|
+
};
|
|
950
|
+
|
|
951
|
+
export type TrellisApiLike = {
|
|
952
|
+
rpc: Record<string, RPCDesc>;
|
|
953
|
+
operations: Record<string, OperationDesc>;
|
|
954
|
+
events: Record<string, EventDesc>;
|
|
955
|
+
feeds?: Record<string, FeedDesc>;
|
|
956
|
+
subjects: Record<string, unknown>;
|
|
957
|
+
};
|
|
958
|
+
|
|
959
|
+
type ApiShape = {
|
|
960
|
+
rpc: Record<string, unknown>;
|
|
961
|
+
operations: Record<string, unknown>;
|
|
962
|
+
events: Record<string, unknown>;
|
|
963
|
+
feeds?: Record<string, unknown>;
|
|
964
|
+
subjects: Record<string, unknown>;
|
|
965
|
+
};
|
|
966
|
+
|
|
967
|
+
export type EmptyApi = {
|
|
968
|
+
rpc: {};
|
|
969
|
+
operations: {};
|
|
970
|
+
events: {};
|
|
971
|
+
feeds?: {};
|
|
972
|
+
subjects: {};
|
|
973
|
+
};
|
|
974
|
+
|
|
975
|
+
type BaselineAuthApi = {
|
|
976
|
+
rpc: {
|
|
977
|
+
"Auth.Sessions.Me": RPCDesc<
|
|
978
|
+
Schema<Record<string, never>>,
|
|
979
|
+
Schema<AuthSessionsMeResponse>
|
|
980
|
+
>;
|
|
981
|
+
"Auth.Sessions.Logout": RPCDesc<
|
|
982
|
+
Schema<AuthSessionsLogoutInput>,
|
|
983
|
+
Schema<AuthSessionsLogoutResponse>
|
|
984
|
+
>;
|
|
985
|
+
};
|
|
986
|
+
operations: {};
|
|
987
|
+
events: {};
|
|
988
|
+
feeds: {};
|
|
989
|
+
subjects: {};
|
|
990
|
+
};
|
|
991
|
+
|
|
992
|
+
type BaselineStateApi = {
|
|
993
|
+
rpc: {
|
|
994
|
+
"State.Get": RPCDesc<Schema<StateGetInput>, Schema<StateGetResponse>>;
|
|
995
|
+
"State.Put": RPCDesc<Schema<StatePutInput>, Schema<StatePutResponse>>;
|
|
996
|
+
"State.Delete": RPCDesc<
|
|
997
|
+
Schema<StateDeleteInput>,
|
|
998
|
+
Schema<StateDeleteResponse>
|
|
999
|
+
>;
|
|
1000
|
+
"State.List": RPCDesc<Schema<StateListInput>, Schema<StateListResponse>>;
|
|
1001
|
+
};
|
|
1002
|
+
operations: {};
|
|
1003
|
+
events: {};
|
|
1004
|
+
feeds: {};
|
|
1005
|
+
subjects: {};
|
|
1006
|
+
};
|
|
1007
|
+
|
|
1008
|
+
type BaselineHealthApi = {
|
|
1009
|
+
rpc: {};
|
|
1010
|
+
operations: {};
|
|
1011
|
+
events: {
|
|
1012
|
+
"Health.Heartbeat": EventDesc<Schema<Record<string, unknown>>>;
|
|
1013
|
+
};
|
|
1014
|
+
feeds: {};
|
|
1015
|
+
subjects: {};
|
|
1016
|
+
};
|
|
1017
|
+
|
|
1018
|
+
export type ContractApiViews<
|
|
1019
|
+
TOwnedApi extends ApiShape,
|
|
1020
|
+
TUsedApi extends ApiShape,
|
|
1021
|
+
TTrellisApi extends ApiShape,
|
|
1022
|
+
> = {
|
|
1023
|
+
owned: TOwnedApi;
|
|
1024
|
+
used: TUsedApi;
|
|
1025
|
+
trellis: TTrellisApi;
|
|
1026
|
+
};
|
|
1027
|
+
|
|
1028
|
+
export type UseSpec<TApi extends ApiShape> = {
|
|
1029
|
+
rpc?: {
|
|
1030
|
+
call?: readonly StringKeyOf<TApi["rpc"]>[];
|
|
1031
|
+
};
|
|
1032
|
+
operations?: {
|
|
1033
|
+
call?: readonly StringKeyOf<TApi["operations"]>[];
|
|
1034
|
+
};
|
|
1035
|
+
events?: {
|
|
1036
|
+
publish?: readonly StringKeyOf<TApi["events"]>[];
|
|
1037
|
+
subscribe?: readonly StringKeyOf<TApi["events"]>[];
|
|
1038
|
+
};
|
|
1039
|
+
feeds?: {
|
|
1040
|
+
subscribe?: readonly StringKeyOf<NonNullable<TApi["feeds"]>>[];
|
|
1041
|
+
};
|
|
1042
|
+
};
|
|
1043
|
+
|
|
1044
|
+
type UseRpcCall<TSpec> =
|
|
1045
|
+
NonNullable<TSpec extends { rpc?: infer TRpc } ? TRpc : never> extends
|
|
1046
|
+
{ call?: infer TCall extends readonly string[] | undefined } ? TCall
|
|
1047
|
+
: never;
|
|
1048
|
+
type UseEventsPublish<TSpec> = NonNullable<
|
|
1049
|
+
TSpec extends { events?: infer TEvents } ? TEvents : never
|
|
1050
|
+
> extends { publish?: infer TPublish extends readonly string[] | undefined }
|
|
1051
|
+
? TPublish
|
|
1052
|
+
: never;
|
|
1053
|
+
type UseOperationsCall<TSpec> = NonNullable<
|
|
1054
|
+
TSpec extends { operations?: infer TOperations } ? TOperations : never
|
|
1055
|
+
> extends { call?: infer TCall extends readonly string[] | undefined } ? TCall
|
|
1056
|
+
: never;
|
|
1057
|
+
type UseEventsSubscribe<TSpec> = NonNullable<
|
|
1058
|
+
TSpec extends { events?: infer TEvents } ? TEvents : never
|
|
1059
|
+
> extends { subscribe?: infer TSubscribe extends readonly string[] | undefined }
|
|
1060
|
+
? TSubscribe
|
|
1061
|
+
: never;
|
|
1062
|
+
type UseFeedsSubscribe<TSpec> = NonNullable<
|
|
1063
|
+
TSpec extends { feeds?: infer TFeeds } ? TFeeds : never
|
|
1064
|
+
> extends { subscribe?: infer TSubscribe extends readonly string[] | undefined }
|
|
1065
|
+
? TSubscribe
|
|
1066
|
+
: never;
|
|
1067
|
+
type ContractModuleMarker<
|
|
1068
|
+
TContractModule = ContractModule<
|
|
1069
|
+
string,
|
|
1070
|
+
TrellisApiLike,
|
|
1071
|
+
TrellisApiLike,
|
|
1072
|
+
TrellisApiLike
|
|
1073
|
+
>,
|
|
1074
|
+
> = {
|
|
1075
|
+
readonly [CONTRACT_MODULE_METADATA]: TContractModule;
|
|
1076
|
+
};
|
|
1077
|
+
|
|
1078
|
+
export type ContractDependencyUse<
|
|
1079
|
+
TContractId extends string,
|
|
1080
|
+
TApi extends ApiShape,
|
|
1081
|
+
TSpec extends UseSpec<TApi> = UseSpec<TApi>,
|
|
1082
|
+
> = {
|
|
1083
|
+
contract: TContractId;
|
|
1084
|
+
readonly [CONTRACT_MODULE_METADATA]?: ContractModule<
|
|
1085
|
+
TContractId,
|
|
1086
|
+
TApi,
|
|
1087
|
+
ApiShape,
|
|
1088
|
+
ApiShape
|
|
1089
|
+
>;
|
|
1090
|
+
rpc?: { call?: UseRpcCall<TSpec> };
|
|
1091
|
+
operations?: { call?: UseOperationsCall<TSpec> };
|
|
1092
|
+
events?: {
|
|
1093
|
+
publish?: UseEventsPublish<TSpec>;
|
|
1094
|
+
subscribe?: UseEventsSubscribe<TSpec>;
|
|
1095
|
+
};
|
|
1096
|
+
feeds?: { subscribe?: UseFeedsSubscribe<TSpec> };
|
|
1097
|
+
};
|
|
1098
|
+
|
|
1099
|
+
type InternalContractDependencyUse<
|
|
1100
|
+
TContractId extends string,
|
|
1101
|
+
TApi extends ApiShape,
|
|
1102
|
+
TSpec extends UseSpec<TApi> = UseSpec<TApi>,
|
|
1103
|
+
> = ContractDependencyUse<TContractId, TApi, TSpec> & ContractModuleMarker;
|
|
1104
|
+
|
|
1105
|
+
type AnyContractDependencyUse = InternalContractDependencyUse<
|
|
1106
|
+
string,
|
|
1107
|
+
TrellisApiLike,
|
|
1108
|
+
UseSpec<TrellisApiLike>
|
|
1109
|
+
>;
|
|
1110
|
+
|
|
1111
|
+
type AuthorContractDependencyUse = ContractDependencyUse<
|
|
1112
|
+
string,
|
|
1113
|
+
ApiShape,
|
|
1114
|
+
UseSpec<ApiShape>
|
|
1115
|
+
>;
|
|
1116
|
+
|
|
1117
|
+
type AuthorContractUsesFlat = Readonly<
|
|
1118
|
+
Record<string, AuthorContractDependencyUse>
|
|
1119
|
+
>;
|
|
1120
|
+
|
|
1121
|
+
type AuthorContractUsesGrouped = {
|
|
1122
|
+
required?: AuthorContractUsesFlat;
|
|
1123
|
+
optional?: AuthorContractUsesFlat;
|
|
1124
|
+
};
|
|
1125
|
+
|
|
1126
|
+
type AuthorContractUses = AuthorContractUsesGrouped;
|
|
1127
|
+
|
|
1128
|
+
export type ContractUseFn<TContractId extends string, TApi extends ApiShape> = <
|
|
1129
|
+
const TSpec extends UseSpec<TApi>,
|
|
1130
|
+
>(spec: TSpec) => ContractDependencyUse<TContractId, TApi, TSpec>;
|
|
1131
|
+
|
|
1132
|
+
type MergeRecordUnion<U> = [U] extends [never] ? {}
|
|
1133
|
+
: Simplify<UnionToIntersection<U>>;
|
|
1134
|
+
|
|
1135
|
+
type SchemaNameOf<TSchemas> = Extract<keyof NonNullable<TSchemas>, string>;
|
|
1136
|
+
|
|
1137
|
+
type ResolveSchemaFromMap<
|
|
1138
|
+
TSchemas,
|
|
1139
|
+
TRef,
|
|
1140
|
+
> = TRef extends { schema: infer TName }
|
|
1141
|
+
? TName extends SchemaNameOf<TSchemas>
|
|
1142
|
+
? NonNullable<TSchemas>[TName] extends TSchema ? Schema<
|
|
1143
|
+
import("./runtime.js").InferSchemaType<NonNullable<TSchemas>[TName]>
|
|
1144
|
+
>
|
|
1145
|
+
: Schema<unknown>
|
|
1146
|
+
: Schema<unknown>
|
|
1147
|
+
: Schema<unknown>;
|
|
1148
|
+
|
|
1149
|
+
type ResolveSchemaTypeFromMap<
|
|
1150
|
+
TSchemas,
|
|
1151
|
+
TRef,
|
|
1152
|
+
> = TRef extends { schema: infer TName }
|
|
1153
|
+
? TName extends SchemaNameOf<TSchemas>
|
|
1154
|
+
? NonNullable<TSchemas>[TName] extends TSchema
|
|
1155
|
+
? InferSchemaType<NonNullable<TSchemas>[TName]>
|
|
1156
|
+
: unknown
|
|
1157
|
+
: unknown
|
|
1158
|
+
: unknown;
|
|
1159
|
+
|
|
1160
|
+
export type ContractJobsMetadata = Record<string, {
|
|
1161
|
+
payload: unknown;
|
|
1162
|
+
result: unknown;
|
|
1163
|
+
}>;
|
|
1164
|
+
export type ContractKvMetadata = Record<string, {
|
|
1165
|
+
required: boolean;
|
|
1166
|
+
value: unknown;
|
|
1167
|
+
schema: TSchema;
|
|
1168
|
+
}>;
|
|
1169
|
+
export type ContractStateMetadata = Record<string, {
|
|
1170
|
+
kind: ContractStateKind;
|
|
1171
|
+
value: unknown;
|
|
1172
|
+
schema: unknown;
|
|
1173
|
+
stateVersion: string;
|
|
1174
|
+
acceptedVersions: Record<string, unknown>;
|
|
1175
|
+
}>;
|
|
1176
|
+
|
|
1177
|
+
type ResolveTypeBoxSchemaFromMap<TSchemas, TRef> = TRef extends {
|
|
1178
|
+
schema: infer TName;
|
|
1179
|
+
}
|
|
1180
|
+
? TName extends SchemaNameOf<TSchemas>
|
|
1181
|
+
? NonNullable<TSchemas>[TName] extends TSchema
|
|
1182
|
+
? NonNullable<TSchemas>[TName]
|
|
1183
|
+
: TSchema
|
|
1184
|
+
: TSchema
|
|
1185
|
+
: TSchema;
|
|
1186
|
+
|
|
1187
|
+
type ProjectedJobs<
|
|
1188
|
+
T extends ContractSourceJobs<string> | undefined,
|
|
1189
|
+
TSchemas,
|
|
1190
|
+
> = T extends ContractSourceJobs<string> ? {
|
|
1191
|
+
[K in keyof T]: {
|
|
1192
|
+
payload: ResolveSchemaTypeFromMap<TSchemas, T[K]["payload"]>;
|
|
1193
|
+
result: ResolveSchemaTypeFromMap<TSchemas, T[K]["result"]>;
|
|
1194
|
+
};
|
|
1195
|
+
}
|
|
1196
|
+
: {};
|
|
1197
|
+
|
|
1198
|
+
type ProjectedState<
|
|
1199
|
+
T extends ContractSourceState<string> | undefined,
|
|
1200
|
+
TSchemas,
|
|
1201
|
+
> = T extends ContractSourceState<string> ? {
|
|
1202
|
+
[K in keyof T]: T[K] extends { kind: infer TKind extends ContractStateKind }
|
|
1203
|
+
? {
|
|
1204
|
+
kind: TKind;
|
|
1205
|
+
value: ResolveSchemaTypeFromMap<TSchemas, T[K]["schema"]>;
|
|
1206
|
+
schema: unknown;
|
|
1207
|
+
stateVersion: T[K] extends
|
|
1208
|
+
{ stateVersion: infer TVersion extends string } ? TVersion
|
|
1209
|
+
: "v1";
|
|
1210
|
+
acceptedVersions: T[K] extends { acceptedVersions: infer TVersions }
|
|
1211
|
+
? TVersions
|
|
1212
|
+
: {};
|
|
1213
|
+
}
|
|
1214
|
+
: never;
|
|
1215
|
+
}
|
|
1216
|
+
: {};
|
|
1217
|
+
|
|
1218
|
+
type ProjectedKvResources<
|
|
1219
|
+
T extends ContractSourceResources<string> | undefined,
|
|
1220
|
+
TSchemas,
|
|
1221
|
+
> = T extends { kv?: infer TKv } ? TKv extends Record<
|
|
1222
|
+
string,
|
|
1223
|
+
{ schema: ContractSchemaRef<string>; required?: boolean }
|
|
1224
|
+
> ? {
|
|
1225
|
+
[K in keyof TKv]: {
|
|
1226
|
+
required: TKv[K] extends { required: infer TRequired extends boolean }
|
|
1227
|
+
? TRequired
|
|
1228
|
+
: true;
|
|
1229
|
+
value: ResolveSchemaTypeFromMap<TSchemas, TKv[K]["schema"]>;
|
|
1230
|
+
schema: ResolveTypeBoxSchemaFromMap<TSchemas, TKv[K]["schema"]>;
|
|
1231
|
+
};
|
|
1232
|
+
}
|
|
1233
|
+
: {}
|
|
1234
|
+
: {};
|
|
1235
|
+
|
|
1236
|
+
type JobsFromSource<T> = T extends { jobs?: infer TJobs }
|
|
1237
|
+
? Extract<TJobs, ContractSourceJobs<string> | undefined>
|
|
1238
|
+
: undefined;
|
|
1239
|
+
type ResourcesFromSource<T> = T extends { resources?: infer TResources }
|
|
1240
|
+
? Extract<TResources, ContractSourceResources<string> | undefined>
|
|
1241
|
+
: undefined;
|
|
1242
|
+
type StateFromSource<T> = T extends { state?: infer TState }
|
|
1243
|
+
? Extract<TState, ContractSourceState<string> | undefined>
|
|
1244
|
+
: undefined;
|
|
1245
|
+
|
|
1246
|
+
type SchemasFromSource<T> = T extends { schemas?: infer TSchemas } ? TSchemas
|
|
1247
|
+
: undefined;
|
|
1248
|
+
|
|
1249
|
+
type RuntimeErrorFromSourceDecl<TDecl, TSchemas> = TDecl extends {
|
|
1250
|
+
type: infer TType extends string;
|
|
1251
|
+
schema?: infer TSchemaRef;
|
|
1252
|
+
}
|
|
1253
|
+
? TDecl extends ContractErrorRuntimeMarker<infer TClass>
|
|
1254
|
+
? TClass extends RpcErrorClass<SerializableErrorData, infer TError>
|
|
1255
|
+
? RuntimeRpcErrorDesc<
|
|
1256
|
+
TType,
|
|
1257
|
+
ResolveSchemaFromMap<TSchemas, TSchemaRef>,
|
|
1258
|
+
TError
|
|
1259
|
+
>
|
|
1260
|
+
: never
|
|
1261
|
+
: never
|
|
1262
|
+
: never;
|
|
1263
|
+
|
|
1264
|
+
type RuntimeErrorsForNames<TNames, TErrors, TSchemas> = TNames extends
|
|
1265
|
+
readonly string[] ? readonly RuntimeErrorFromSourceDecl<
|
|
1266
|
+
NonNullable<TErrors>[Extract<TNames[number], keyof NonNullable<TErrors>>],
|
|
1267
|
+
TSchemas
|
|
1268
|
+
>[]
|
|
1269
|
+
: undefined;
|
|
1270
|
+
|
|
1271
|
+
type ProjectedRpcMethod<
|
|
1272
|
+
TMethod extends ContractSourceRpcMethod,
|
|
1273
|
+
TSchemas,
|
|
1274
|
+
_TErrors,
|
|
1275
|
+
> =
|
|
1276
|
+
& {
|
|
1277
|
+
subject: string;
|
|
1278
|
+
input: ResolveSchemaFromMap<TSchemas, TMethod["input"]>;
|
|
1279
|
+
output: ResolveSchemaFromMap<TSchemas, TMethod["output"]>;
|
|
1280
|
+
callerCapabilities: readonly string[];
|
|
1281
|
+
authRequired?: boolean;
|
|
1282
|
+
errors?: TMethod["errors"];
|
|
1283
|
+
runtimeErrors?: readonly RuntimeRpcErrorDesc[];
|
|
1284
|
+
declaredErrorTypes?: readonly string[];
|
|
1285
|
+
}
|
|
1286
|
+
& (TMethod extends { transfer: infer TTransfer } ? { transfer: TTransfer }
|
|
1287
|
+
: {});
|
|
1288
|
+
|
|
1289
|
+
type BuiltRuntimeErrorDesc = {
|
|
1290
|
+
type: string;
|
|
1291
|
+
schema?: Schema<unknown>;
|
|
1292
|
+
fromSerializable(data: SerializableErrorData): BaseError;
|
|
1293
|
+
};
|
|
1294
|
+
|
|
1295
|
+
type BuiltRpcDesc = {
|
|
1296
|
+
subject: string;
|
|
1297
|
+
input: Schema<unknown>;
|
|
1298
|
+
output: Schema<unknown>;
|
|
1299
|
+
callerCapabilities: readonly string[];
|
|
1300
|
+
transfer?: { direction: "receive" };
|
|
1301
|
+
authRequired?: boolean;
|
|
1302
|
+
errors?: readonly string[];
|
|
1303
|
+
declaredErrorTypes?: readonly string[];
|
|
1304
|
+
runtimeErrors?: readonly BuiltRuntimeErrorDesc[];
|
|
1305
|
+
};
|
|
1306
|
+
|
|
1307
|
+
const TRELLIS_AUTH_CONTRACT_ID = "trellis.auth@v1";
|
|
1308
|
+
const TRELLIS_STATE_CONTRACT_ID = "trellis.state@v1";
|
|
1309
|
+
const TRELLIS_HEALTH_CONTRACT_ID = "trellis.health@v1";
|
|
1310
|
+
|
|
1311
|
+
const BASELINE_AUTH_RPC_CALL = [
|
|
1312
|
+
"Auth.Sessions.Me",
|
|
1313
|
+
"Auth.Sessions.Logout",
|
|
1314
|
+
] as const;
|
|
1315
|
+
const BASELINE_STATE_RPC_CALL = [
|
|
1316
|
+
"State.Get",
|
|
1317
|
+
"State.Put",
|
|
1318
|
+
"State.Delete",
|
|
1319
|
+
"State.List",
|
|
1320
|
+
] as const;
|
|
1321
|
+
const BASELINE_HEALTH_EVENTS_PUBLISH = ["Health.Heartbeat"] as const;
|
|
1322
|
+
|
|
1323
|
+
const UnknownRuntimeSchema = schema(Type.Unknown());
|
|
1324
|
+
|
|
1325
|
+
function typedUnknownRuntimeSchema<T>(): Schema<T> {
|
|
1326
|
+
return UnknownRuntimeSchema as Schema<T>;
|
|
1327
|
+
}
|
|
1328
|
+
|
|
1329
|
+
function trellisRpcDesc<TInput, TOutput>(
|
|
1330
|
+
name: string,
|
|
1331
|
+
): RPCDesc<Schema<TInput>, Schema<TOutput>> {
|
|
1332
|
+
return {
|
|
1333
|
+
subject: rpcSubject(name, "v1"),
|
|
1334
|
+
input: typedUnknownRuntimeSchema<TInput>(),
|
|
1335
|
+
output: typedUnknownRuntimeSchema<TOutput>(),
|
|
1336
|
+
callerCapabilities: [],
|
|
1337
|
+
};
|
|
1338
|
+
}
|
|
1339
|
+
|
|
1340
|
+
function trellisEventDesc<TEvent>(
|
|
1341
|
+
name: string,
|
|
1342
|
+
): EventDesc<Schema<TEvent>> {
|
|
1343
|
+
return {
|
|
1344
|
+
subject: eventSubject(name, "v1", undefined),
|
|
1345
|
+
event: typedUnknownRuntimeSchema<TEvent>(),
|
|
1346
|
+
publishCapabilities: [],
|
|
1347
|
+
subscribeCapabilities: [],
|
|
1348
|
+
};
|
|
1349
|
+
}
|
|
1350
|
+
|
|
1351
|
+
const BASELINE_AUTH_API: BaselineAuthApi = {
|
|
1352
|
+
rpc: {
|
|
1353
|
+
"Auth.Sessions.Me": trellisRpcDesc<
|
|
1354
|
+
Record<string, never>,
|
|
1355
|
+
AuthSessionsMeResponse
|
|
1356
|
+
>(
|
|
1357
|
+
"Auth.Sessions.Me",
|
|
1358
|
+
),
|
|
1359
|
+
"Auth.Sessions.Logout": trellisRpcDesc<
|
|
1360
|
+
AuthSessionsLogoutInput,
|
|
1361
|
+
AuthSessionsLogoutResponse
|
|
1362
|
+
>(
|
|
1363
|
+
"Auth.Sessions.Logout",
|
|
1364
|
+
),
|
|
1365
|
+
},
|
|
1366
|
+
operations: {},
|
|
1367
|
+
events: {},
|
|
1368
|
+
feeds: {},
|
|
1369
|
+
subjects: {},
|
|
1370
|
+
};
|
|
1371
|
+
|
|
1372
|
+
const BASELINE_STATE_API: BaselineStateApi = {
|
|
1373
|
+
rpc: {
|
|
1374
|
+
"State.Get": trellisRpcDesc<StateGetInput, StateGetResponse>("State.Get"),
|
|
1375
|
+
"State.Put": trellisRpcDesc<StatePutInput, StatePutResponse>("State.Put"),
|
|
1376
|
+
"State.Delete": trellisRpcDesc<StateDeleteInput, StateDeleteResponse>(
|
|
1377
|
+
"State.Delete",
|
|
1378
|
+
),
|
|
1379
|
+
"State.List": trellisRpcDesc<StateListInput, StateListResponse>(
|
|
1380
|
+
"State.List",
|
|
1381
|
+
),
|
|
1382
|
+
},
|
|
1383
|
+
operations: {},
|
|
1384
|
+
events: {},
|
|
1385
|
+
feeds: {},
|
|
1386
|
+
subjects: {},
|
|
1387
|
+
};
|
|
1388
|
+
|
|
1389
|
+
const BASELINE_HEALTH_API: BaselineHealthApi = {
|
|
1390
|
+
rpc: {},
|
|
1391
|
+
operations: {},
|
|
1392
|
+
events: {
|
|
1393
|
+
"Health.Heartbeat": trellisEventDesc<Record<string, unknown>>(
|
|
1394
|
+
"Health.Heartbeat",
|
|
1395
|
+
),
|
|
1396
|
+
},
|
|
1397
|
+
feeds: {},
|
|
1398
|
+
subjects: {},
|
|
1399
|
+
};
|
|
1400
|
+
|
|
1401
|
+
type ProjectedRpc<
|
|
1402
|
+
T,
|
|
1403
|
+
TSchemas,
|
|
1404
|
+
TErrors,
|
|
1405
|
+
> = T extends Readonly<Record<string, ContractSourceRpcMethod>> ? {
|
|
1406
|
+
[K in keyof T]: ProjectedRpcMethod<T[K], TSchemas, TErrors>;
|
|
1407
|
+
}
|
|
1408
|
+
: {};
|
|
1409
|
+
|
|
1410
|
+
type ProjectedOperations<
|
|
1411
|
+
T,
|
|
1412
|
+
TSchemas,
|
|
1413
|
+
> = T extends Readonly<Record<string, ContractSourceOperation>> ? {
|
|
1414
|
+
[K in keyof T]:
|
|
1415
|
+
& OperationDesc<
|
|
1416
|
+
ResolveSchemaFromMap<TSchemas, T[K]["input"]>,
|
|
1417
|
+
ResolveSchemaFromMap<TSchemas, T[K]["progress"]>,
|
|
1418
|
+
ResolveSchemaFromMap<TSchemas, T[K]["output"]>
|
|
1419
|
+
>
|
|
1420
|
+
& (T[K]["transfer"] extends undefined ? {}
|
|
1421
|
+
: { transfer: T[K]["transfer"] });
|
|
1422
|
+
}
|
|
1423
|
+
: {};
|
|
1424
|
+
|
|
1425
|
+
type ProjectedEvents<
|
|
1426
|
+
T,
|
|
1427
|
+
TSchemas,
|
|
1428
|
+
> = T extends Readonly<Record<string, ContractSourceEvent>> ? {
|
|
1429
|
+
[K in keyof T]: EventDesc<
|
|
1430
|
+
ResolveSchemaFromMap<TSchemas, T[K]["event"]>
|
|
1431
|
+
>;
|
|
1432
|
+
}
|
|
1433
|
+
: {};
|
|
1434
|
+
|
|
1435
|
+
type ProjectedFeeds<
|
|
1436
|
+
T,
|
|
1437
|
+
TSchemas,
|
|
1438
|
+
> = T extends Readonly<Record<string, ContractSourceFeed>> ? {
|
|
1439
|
+
[K in keyof T]: FeedDesc<
|
|
1440
|
+
ResolveSchemaFromMap<TSchemas, T[K]["input"]>,
|
|
1441
|
+
ResolveSchemaFromMap<TSchemas, T[K]["event"]>
|
|
1442
|
+
>;
|
|
1443
|
+
}
|
|
1444
|
+
: {};
|
|
1445
|
+
|
|
1446
|
+
export type OwnedApiFromSource<
|
|
1447
|
+
T extends {
|
|
1448
|
+
schemas?: Readonly<Record<string, TSchema>>;
|
|
1449
|
+
errors?: unknown;
|
|
1450
|
+
rpc?: unknown;
|
|
1451
|
+
operations?: unknown;
|
|
1452
|
+
events?: unknown;
|
|
1453
|
+
feeds?: unknown;
|
|
1454
|
+
},
|
|
1455
|
+
> = {
|
|
1456
|
+
rpc: ProjectedRpc<T["rpc"], T["schemas"], T["errors"]>;
|
|
1457
|
+
operations: ProjectedOperations<T["operations"], T["schemas"]>;
|
|
1458
|
+
events: ProjectedEvents<T["events"], T["schemas"]>;
|
|
1459
|
+
feeds: ProjectedFeeds<T["feeds"], T["schemas"]>;
|
|
1460
|
+
subjects: {};
|
|
1461
|
+
};
|
|
1462
|
+
|
|
1463
|
+
type RpcKeysFromSpec<TSpec> = TSpec extends { rpc?: { call?: infer TCall } }
|
|
1464
|
+
? KeysFromList<TCall>
|
|
1465
|
+
: never;
|
|
1466
|
+
type EventKeysFromSpec<TSpec> =
|
|
1467
|
+
| (TSpec extends { events?: { publish?: infer TPublish } }
|
|
1468
|
+
? KeysFromList<TPublish>
|
|
1469
|
+
: never)
|
|
1470
|
+
| (TSpec extends { events?: { subscribe?: infer TSubscribe } }
|
|
1471
|
+
? KeysFromList<TSubscribe>
|
|
1472
|
+
: never);
|
|
1473
|
+
type OperationKeysFromSpec<TSpec> = TSpec extends
|
|
1474
|
+
{ operations?: { call?: infer TCall } } ? KeysFromList<TCall>
|
|
1475
|
+
: never;
|
|
1476
|
+
type FeedKeysFromSpec<TSpec> = TSpec extends
|
|
1477
|
+
{ feeds?: { subscribe?: infer TSubscribe } } ? KeysFromList<TSubscribe>
|
|
1478
|
+
: never;
|
|
1479
|
+
type ApiFromDependencyUse<TUse> = TUse extends
|
|
1480
|
+
ContractDependencyUse<string, infer TApi, infer TSpec> ? {
|
|
1481
|
+
rpc: Pick<TApi["rpc"], RpcKeysFromSpec<TSpec>>;
|
|
1482
|
+
operations: Pick<TApi["operations"], OperationKeysFromSpec<TSpec>>;
|
|
1483
|
+
events: Pick<TApi["events"], EventKeysFromSpec<TSpec>>;
|
|
1484
|
+
feeds: Pick<NonNullable<TApi["feeds"]>, FeedKeysFromSpec<TSpec>>;
|
|
1485
|
+
subjects: {};
|
|
1486
|
+
}
|
|
1487
|
+
: EmptyApi;
|
|
1488
|
+
type DependencyUsesFromUses<TUses> = TUses extends {
|
|
1489
|
+
required?: AuthorContractUsesFlat;
|
|
1490
|
+
optional?: AuthorContractUsesFlat;
|
|
1491
|
+
} ?
|
|
1492
|
+
| NonNullable<TUses["required"]>[keyof NonNullable<TUses["required"]>]
|
|
1493
|
+
| NonNullable<TUses["optional"]>[keyof NonNullable<TUses["optional"]>]
|
|
1494
|
+
: never;
|
|
1495
|
+
|
|
1496
|
+
export type UsedApiFromUses<TUses> = [TUses] extends [undefined] ? EmptyApi
|
|
1497
|
+
: TUses extends Record<string, unknown> ? {
|
|
1498
|
+
rpc: MergeRecordUnion<
|
|
1499
|
+
ApiFromDependencyUse<DependencyUsesFromUses<TUses>>["rpc"]
|
|
1500
|
+
>;
|
|
1501
|
+
operations: MergeRecordUnion<
|
|
1502
|
+
ApiFromDependencyUse<DependencyUsesFromUses<TUses>>["operations"]
|
|
1503
|
+
>;
|
|
1504
|
+
events: MergeRecordUnion<
|
|
1505
|
+
ApiFromDependencyUse<DependencyUsesFromUses<TUses>>["events"]
|
|
1506
|
+
>;
|
|
1507
|
+
feeds: MergeRecordUnion<
|
|
1508
|
+
ApiFromDependencyUse<DependencyUsesFromUses<TUses>>["feeds"]
|
|
1509
|
+
>;
|
|
1510
|
+
subjects: MergeRecordUnion<
|
|
1511
|
+
ApiFromDependencyUse<DependencyUsesFromUses<TUses>>["subjects"]
|
|
1512
|
+
>;
|
|
1513
|
+
}
|
|
1514
|
+
: EmptyApi;
|
|
1515
|
+
|
|
1516
|
+
type ImplicitAuthApiForKind<TKind> = TKind extends "app" | "agent" | "device"
|
|
1517
|
+
? BaselineAuthApi
|
|
1518
|
+
: EmptyApi;
|
|
1519
|
+
|
|
1520
|
+
type ImplicitStateApiForSource<T> = [StateFromSource<T>] extends [undefined]
|
|
1521
|
+
? EmptyApi
|
|
1522
|
+
: BaselineStateApi;
|
|
1523
|
+
|
|
1524
|
+
type ImplicitHealthApiForSource<T> = T extends {
|
|
1525
|
+
kind: infer TKind;
|
|
1526
|
+
id: infer TId;
|
|
1527
|
+
} ? TId extends "trellis.health@v1" ? EmptyApi
|
|
1528
|
+
: TKind extends "service" | "device" ? BaselineHealthApi
|
|
1529
|
+
: EmptyApi
|
|
1530
|
+
: EmptyApi;
|
|
1531
|
+
|
|
1532
|
+
type ImplicitTrellisApiFromSource<T> = T extends { kind: infer TKind }
|
|
1533
|
+
? MergeApis<
|
|
1534
|
+
MergeApis<ImplicitAuthApiForKind<TKind>, ImplicitStateApiForSource<T>>,
|
|
1535
|
+
ImplicitHealthApiForSource<T>
|
|
1536
|
+
>
|
|
1537
|
+
: EmptyApi;
|
|
1538
|
+
|
|
1539
|
+
export type UsedApiFromSource<T extends { uses?: unknown }> = MergeApis<
|
|
1540
|
+
UsedApiFromUses<T["uses"]>,
|
|
1541
|
+
ImplicitTrellisApiFromSource<T>
|
|
1542
|
+
>;
|
|
1543
|
+
|
|
1544
|
+
export type MergeApis<TOwnedApi extends ApiShape, TUsedApi extends ApiShape> = {
|
|
1545
|
+
rpc: Simplify<TUsedApi["rpc"] & TOwnedApi["rpc"]>;
|
|
1546
|
+
operations: Simplify<TUsedApi["operations"] & TOwnedApi["operations"]>;
|
|
1547
|
+
events: Simplify<TUsedApi["events"] & TOwnedApi["events"]>;
|
|
1548
|
+
feeds: Simplify<TUsedApi["feeds"] & TOwnedApi["feeds"]>;
|
|
1549
|
+
subjects: Simplify<TUsedApi["subjects"] & TOwnedApi["subjects"]>;
|
|
1550
|
+
};
|
|
1551
|
+
|
|
1552
|
+
export type ContractModule<
|
|
1553
|
+
TContractId extends string,
|
|
1554
|
+
TOwnedApi extends ApiShape,
|
|
1555
|
+
TUsedApi extends ApiShape,
|
|
1556
|
+
TTrellisApi extends ApiShape,
|
|
1557
|
+
TJobs extends ContractJobsMetadata = {},
|
|
1558
|
+
TState extends ContractStateMetadata = {},
|
|
1559
|
+
TKv extends ContractKvMetadata = ContractKvMetadata,
|
|
1560
|
+
> = {
|
|
1561
|
+
CONTRACT_ID: TContractId;
|
|
1562
|
+
CONTRACT: TrellisContractV1;
|
|
1563
|
+
CONTRACT_DIGEST: string;
|
|
1564
|
+
API: ContractApiViews<TOwnedApi, TUsedApi, TTrellisApi>;
|
|
1565
|
+
use: ContractUseFn<TContractId, TOwnedApi>;
|
|
1566
|
+
readonly [CONTRACT_JOBS_METADATA]?: TJobs;
|
|
1567
|
+
readonly [CONTRACT_STATE_METADATA]?: TState;
|
|
1568
|
+
readonly [CONTRACT_KV_METADATA]?: TKv;
|
|
1569
|
+
};
|
|
1570
|
+
|
|
1571
|
+
export type SdkContractModule<
|
|
1572
|
+
TContractId extends string,
|
|
1573
|
+
TOwnedApi extends ApiShape,
|
|
1574
|
+
TJobs extends ContractJobsMetadata = {},
|
|
1575
|
+
TState extends ContractStateMetadata = {},
|
|
1576
|
+
TKv extends ContractKvMetadata = ContractKvMetadata,
|
|
1577
|
+
> =
|
|
1578
|
+
& Omit<
|
|
1579
|
+
ContractModule<
|
|
1580
|
+
TContractId,
|
|
1581
|
+
TOwnedApi,
|
|
1582
|
+
EmptyApi,
|
|
1583
|
+
TOwnedApi,
|
|
1584
|
+
TJobs,
|
|
1585
|
+
TState,
|
|
1586
|
+
TKv
|
|
1587
|
+
>,
|
|
1588
|
+
"use"
|
|
1589
|
+
>
|
|
1590
|
+
& {
|
|
1591
|
+
use: ContractUseFn<TContractId, TOwnedApi>;
|
|
1592
|
+
};
|
|
1593
|
+
|
|
1594
|
+
export type DefinedContract<
|
|
1595
|
+
TOwnedApi extends ApiShape,
|
|
1596
|
+
TUsedApi extends ApiShape,
|
|
1597
|
+
TTrellisApi extends ApiShape,
|
|
1598
|
+
TContractId extends string = string,
|
|
1599
|
+
TJobs extends ContractJobsMetadata = {},
|
|
1600
|
+
TState extends ContractStateMetadata = {},
|
|
1601
|
+
TKv extends ContractKvMetadata = ContractKvMetadata,
|
|
1602
|
+
> = ContractModule<
|
|
1603
|
+
TContractId,
|
|
1604
|
+
TOwnedApi,
|
|
1605
|
+
TUsedApi,
|
|
1606
|
+
TTrellisApi,
|
|
1607
|
+
TJobs,
|
|
1608
|
+
TState,
|
|
1609
|
+
TKv
|
|
1610
|
+
>;
|
|
1611
|
+
|
|
1612
|
+
export type DefineContractInput<
|
|
1613
|
+
TCapabilities extends ContractCapabilities | undefined =
|
|
1614
|
+
| ContractCapabilities
|
|
1615
|
+
| undefined,
|
|
1616
|
+
TSchemas extends Readonly<Record<string, TSchema>> | undefined = undefined,
|
|
1617
|
+
TUses extends
|
|
1618
|
+
| AuthorContractUses
|
|
1619
|
+
| undefined = undefined,
|
|
1620
|
+
TErrors extends
|
|
1621
|
+
| Readonly<Record<string, ErrorClass>>
|
|
1622
|
+
| undefined = undefined,
|
|
1623
|
+
TRpc extends
|
|
1624
|
+
| Readonly<
|
|
1625
|
+
Record<
|
|
1626
|
+
string,
|
|
1627
|
+
ContractSourceRpcMethod<
|
|
1628
|
+
SchemaNameOf<TSchemas>,
|
|
1629
|
+
ErrorNameOf<TErrors>,
|
|
1630
|
+
CapabilityRef<TCapabilities>
|
|
1631
|
+
>
|
|
1632
|
+
>
|
|
1633
|
+
>
|
|
1634
|
+
| undefined = undefined,
|
|
1635
|
+
TOperations extends
|
|
1636
|
+
| Readonly<
|
|
1637
|
+
Record<
|
|
1638
|
+
string,
|
|
1639
|
+
ContractSourceOperation<
|
|
1640
|
+
SchemaNameOf<TSchemas>,
|
|
1641
|
+
CapabilityRef<TCapabilities>
|
|
1642
|
+
>
|
|
1643
|
+
>
|
|
1644
|
+
>
|
|
1645
|
+
| undefined = undefined,
|
|
1646
|
+
TEvents extends
|
|
1647
|
+
| Readonly<
|
|
1648
|
+
Record<
|
|
1649
|
+
string,
|
|
1650
|
+
ContractSourceEvent<
|
|
1651
|
+
SchemaNameOf<TSchemas>,
|
|
1652
|
+
CapabilityRef<TCapabilities>
|
|
1653
|
+
>
|
|
1654
|
+
>
|
|
1655
|
+
>
|
|
1656
|
+
| undefined = undefined,
|
|
1657
|
+
> = {
|
|
1658
|
+
id: string;
|
|
1659
|
+
displayName: string;
|
|
1660
|
+
description: string;
|
|
1661
|
+
kind: ContractKind;
|
|
1662
|
+
capabilities?: ContractCapabilities;
|
|
1663
|
+
schemas?: TSchemas;
|
|
1664
|
+
exports?: ContractSourceExports<SchemaNameOf<TSchemas>>;
|
|
1665
|
+
state?: ContractSourceState<SchemaNameOf<TSchemas>>;
|
|
1666
|
+
uses?: TUses;
|
|
1667
|
+
errors?: TErrors;
|
|
1668
|
+
rpc?: TRpc;
|
|
1669
|
+
operations?: TOperations;
|
|
1670
|
+
events?: TEvents;
|
|
1671
|
+
feeds?: Readonly<
|
|
1672
|
+
Record<
|
|
1673
|
+
string,
|
|
1674
|
+
ContractSourceFeed<
|
|
1675
|
+
SchemaNameOf<TSchemas>,
|
|
1676
|
+
CapabilityRef<TCapabilities>
|
|
1677
|
+
>
|
|
1678
|
+
>
|
|
1679
|
+
>;
|
|
1680
|
+
jobs?: ContractSourceJobs<SchemaNameOf<TSchemas>>;
|
|
1681
|
+
resources?: ContractSourceResources<SchemaNameOf<TSchemas>>;
|
|
1682
|
+
};
|
|
1683
|
+
|
|
1684
|
+
type DefineContractSource = {
|
|
1685
|
+
id: string;
|
|
1686
|
+
displayName: string;
|
|
1687
|
+
description: string;
|
|
1688
|
+
kind: ContractKind;
|
|
1689
|
+
capabilities?: ContractCapabilities;
|
|
1690
|
+
schemas?: Readonly<Record<string, TSchema>>;
|
|
1691
|
+
exports?: ContractSourceExports;
|
|
1692
|
+
state?: ContractSourceState;
|
|
1693
|
+
uses?: AuthorContractUses;
|
|
1694
|
+
errors?: Readonly<Record<string, ContractSourceErrorDecl>>;
|
|
1695
|
+
rpc?: Readonly<Record<string, ContractSourceRpcMethod>>;
|
|
1696
|
+
operations?: Readonly<Record<string, ContractSourceOperation>>;
|
|
1697
|
+
events?: Readonly<Record<string, ContractSourceEvent>>;
|
|
1698
|
+
feeds?: Readonly<Record<string, ContractSourceFeed>>;
|
|
1699
|
+
jobs?: ContractSourceJobs;
|
|
1700
|
+
resources?: ContractSourceResources;
|
|
1701
|
+
};
|
|
1702
|
+
|
|
1703
|
+
type ConstrainSection<TSection, TExpected> = [TSection] extends [undefined]
|
|
1704
|
+
? undefined
|
|
1705
|
+
: TSection & TExpected;
|
|
1706
|
+
|
|
1707
|
+
type ValidateDefineContractInput<T extends DefineContractSource> =
|
|
1708
|
+
& T
|
|
1709
|
+
& DefineContractInput<
|
|
1710
|
+
T["capabilities"],
|
|
1711
|
+
T["schemas"],
|
|
1712
|
+
ConstrainSection<
|
|
1713
|
+
T["uses"],
|
|
1714
|
+
AuthorContractUses
|
|
1715
|
+
>,
|
|
1716
|
+
ConstrainSection<
|
|
1717
|
+
T["errors"],
|
|
1718
|
+
Readonly<Record<string, ErrorClass>>
|
|
1719
|
+
>,
|
|
1720
|
+
ConstrainSection<
|
|
1721
|
+
T["rpc"],
|
|
1722
|
+
Readonly<
|
|
1723
|
+
Record<
|
|
1724
|
+
string,
|
|
1725
|
+
ContractSourceRpcMethod<
|
|
1726
|
+
SchemaNameOf<T["schemas"]>,
|
|
1727
|
+
ErrorNameOf<T["errors"]>,
|
|
1728
|
+
CapabilityRef<T["capabilities"]>
|
|
1729
|
+
>
|
|
1730
|
+
>
|
|
1731
|
+
>
|
|
1732
|
+
>,
|
|
1733
|
+
ConstrainSection<
|
|
1734
|
+
T["operations"],
|
|
1735
|
+
Readonly<
|
|
1736
|
+
Record<
|
|
1737
|
+
string,
|
|
1738
|
+
ContractSourceOperation<
|
|
1739
|
+
SchemaNameOf<T["schemas"]>,
|
|
1740
|
+
CapabilityRef<T["capabilities"]>
|
|
1741
|
+
>
|
|
1742
|
+
>
|
|
1743
|
+
>
|
|
1744
|
+
>,
|
|
1745
|
+
ConstrainSection<
|
|
1746
|
+
T["events"],
|
|
1747
|
+
Readonly<
|
|
1748
|
+
Record<
|
|
1749
|
+
string,
|
|
1750
|
+
ContractSourceEvent<
|
|
1751
|
+
SchemaNameOf<T["schemas"]>,
|
|
1752
|
+
CapabilityRef<T["capabilities"]>
|
|
1753
|
+
>
|
|
1754
|
+
>
|
|
1755
|
+
>
|
|
1756
|
+
>
|
|
1757
|
+
>;
|
|
1758
|
+
|
|
1759
|
+
type DefineContractRegistry<
|
|
1760
|
+
TSchemas extends Readonly<Record<string, TSchema>> | undefined = undefined,
|
|
1761
|
+
TErrors extends
|
|
1762
|
+
| Readonly<Record<string, unknown>>
|
|
1763
|
+
| undefined = undefined,
|
|
1764
|
+
> = {
|
|
1765
|
+
schemas?: TSchemas;
|
|
1766
|
+
errors?: TErrors;
|
|
1767
|
+
};
|
|
1768
|
+
|
|
1769
|
+
type AnyDefineContractRegistry = DefineContractRegistry<
|
|
1770
|
+
Readonly<Record<string, TSchema>> | undefined,
|
|
1771
|
+
Readonly<Record<string, unknown>> | undefined
|
|
1772
|
+
>;
|
|
1773
|
+
|
|
1774
|
+
type ClientContractRegistry<
|
|
1775
|
+
TSchemas extends Readonly<Record<string, TSchema>> | undefined = undefined,
|
|
1776
|
+
> = {
|
|
1777
|
+
schemas?: TSchemas;
|
|
1778
|
+
};
|
|
1779
|
+
|
|
1780
|
+
type RegistrySchemas<TRegistry extends AnyDefineContractRegistry> =
|
|
1781
|
+
TRegistry extends { schemas?: infer TSchemas }
|
|
1782
|
+
? TSchemas extends Readonly<Record<string, TSchema>> | undefined ? TSchemas
|
|
1783
|
+
: undefined
|
|
1784
|
+
: undefined;
|
|
1785
|
+
|
|
1786
|
+
type RegistryErrors<TRegistry extends AnyDefineContractRegistry> =
|
|
1787
|
+
TRegistry extends { errors?: infer TErrors }
|
|
1788
|
+
? TErrors extends Readonly<Record<string, unknown>> | undefined
|
|
1789
|
+
? ExtractErrorClasses<
|
|
1790
|
+
TErrors
|
|
1791
|
+
>
|
|
1792
|
+
: undefined
|
|
1793
|
+
: undefined;
|
|
1794
|
+
|
|
1795
|
+
type RegistryUses = AuthorContractUses | undefined;
|
|
1796
|
+
|
|
1797
|
+
type RegistryRpcMethods<TRegistry extends AnyDefineContractRegistry> =
|
|
1798
|
+
| Readonly<
|
|
1799
|
+
Record<
|
|
1800
|
+
string,
|
|
1801
|
+
ContractSourceRpcMethod<
|
|
1802
|
+
SchemaNameOf<RegistrySchemas<TRegistry>>,
|
|
1803
|
+
ErrorNameOf<RegistryErrors<TRegistry>>
|
|
1804
|
+
>
|
|
1805
|
+
>
|
|
1806
|
+
>
|
|
1807
|
+
| undefined;
|
|
1808
|
+
|
|
1809
|
+
type RegistryOperations<TRegistry extends AnyDefineContractRegistry> =
|
|
1810
|
+
| Readonly<
|
|
1811
|
+
Record<
|
|
1812
|
+
string,
|
|
1813
|
+
ContractSourceOperation<SchemaNameOf<RegistrySchemas<TRegistry>>>
|
|
1814
|
+
>
|
|
1815
|
+
>
|
|
1816
|
+
| undefined;
|
|
1817
|
+
|
|
1818
|
+
type RegistryEvents<TRegistry extends AnyDefineContractRegistry> =
|
|
1819
|
+
| Readonly<
|
|
1820
|
+
Record<
|
|
1821
|
+
string,
|
|
1822
|
+
ContractSourceEvent<SchemaNameOf<RegistrySchemas<TRegistry>>>
|
|
1823
|
+
>
|
|
1824
|
+
>
|
|
1825
|
+
| undefined;
|
|
1826
|
+
|
|
1827
|
+
type BodyCapabilities<TBody> = Extract<
|
|
1828
|
+
TBody extends { capabilities: infer TCapabilities } ? TCapabilities
|
|
1829
|
+
: undefined,
|
|
1830
|
+
ContractCapabilities | undefined
|
|
1831
|
+
>;
|
|
1832
|
+
|
|
1833
|
+
type BodyRpcMethods<TBody, TRegistry extends AnyDefineContractRegistry> =
|
|
1834
|
+
TBody extends { rpc?: infer TRpc } ? ConstrainSection<
|
|
1835
|
+
TRpc,
|
|
1836
|
+
Readonly<
|
|
1837
|
+
Record<
|
|
1838
|
+
string,
|
|
1839
|
+
ContractSourceRpcMethod<
|
|
1840
|
+
SchemaNameOf<RegistrySchemas<TRegistry>>,
|
|
1841
|
+
ErrorNameOf<RegistryErrors<TRegistry>>,
|
|
1842
|
+
CapabilityRef<BodyCapabilities<TBody>>
|
|
1843
|
+
>
|
|
1844
|
+
>
|
|
1845
|
+
>
|
|
1846
|
+
>
|
|
1847
|
+
: undefined;
|
|
1848
|
+
|
|
1849
|
+
type BodyOperations<TBody, TRegistry extends AnyDefineContractRegistry> =
|
|
1850
|
+
TBody extends { operations?: infer TOperations } ? ConstrainSection<
|
|
1851
|
+
TOperations,
|
|
1852
|
+
Readonly<
|
|
1853
|
+
Record<
|
|
1854
|
+
string,
|
|
1855
|
+
ContractSourceOperation<
|
|
1856
|
+
SchemaNameOf<RegistrySchemas<TRegistry>>,
|
|
1857
|
+
CapabilityRef<BodyCapabilities<TBody>>
|
|
1858
|
+
>
|
|
1859
|
+
>
|
|
1860
|
+
>
|
|
1861
|
+
>
|
|
1862
|
+
: undefined;
|
|
1863
|
+
|
|
1864
|
+
type BodyEvents<TBody, TRegistry extends AnyDefineContractRegistry> =
|
|
1865
|
+
TBody extends { events?: infer TEvents } ? ConstrainSection<
|
|
1866
|
+
TEvents,
|
|
1867
|
+
Readonly<
|
|
1868
|
+
Record<
|
|
1869
|
+
string,
|
|
1870
|
+
ContractSourceEvent<
|
|
1871
|
+
SchemaNameOf<RegistrySchemas<TRegistry>>,
|
|
1872
|
+
CapabilityRef<BodyCapabilities<TBody>>
|
|
1873
|
+
>
|
|
1874
|
+
>
|
|
1875
|
+
>
|
|
1876
|
+
>
|
|
1877
|
+
: undefined;
|
|
1878
|
+
|
|
1879
|
+
type ValidateCapabilitySections<
|
|
1880
|
+
TBody,
|
|
1881
|
+
TRegistry extends AnyDefineContractRegistry,
|
|
1882
|
+
> = {
|
|
1883
|
+
rpc?: BodyRpcMethods<TBody, TRegistry>;
|
|
1884
|
+
operations?: BodyOperations<TBody, TRegistry>;
|
|
1885
|
+
events?: BodyEvents<TBody, TRegistry>;
|
|
1886
|
+
};
|
|
1887
|
+
|
|
1888
|
+
type UsedApiOf<TBody extends { uses?: unknown }> = UsedApiFromUses<
|
|
1889
|
+
TBody["uses"]
|
|
1890
|
+
>;
|
|
1891
|
+
|
|
1892
|
+
type DefineContractBodyInput<
|
|
1893
|
+
TCapabilities extends ContractCapabilities | undefined =
|
|
1894
|
+
| ContractCapabilities
|
|
1895
|
+
| undefined,
|
|
1896
|
+
TSchemas extends Readonly<Record<string, TSchema>> | undefined = undefined,
|
|
1897
|
+
TUses extends AuthorContractUses | undefined = undefined,
|
|
1898
|
+
TErrors extends
|
|
1899
|
+
| Readonly<Record<string, ErrorClass>>
|
|
1900
|
+
| undefined = undefined,
|
|
1901
|
+
TRpc extends
|
|
1902
|
+
| Readonly<
|
|
1903
|
+
Record<
|
|
1904
|
+
string,
|
|
1905
|
+
ContractSourceRpcMethod<
|
|
1906
|
+
SchemaNameOf<TSchemas>,
|
|
1907
|
+
ErrorNameOf<TErrors>,
|
|
1908
|
+
CapabilityRef<TCapabilities>
|
|
1909
|
+
>
|
|
1910
|
+
>
|
|
1911
|
+
>
|
|
1912
|
+
| undefined = undefined,
|
|
1913
|
+
TOperations extends
|
|
1914
|
+
| Readonly<
|
|
1915
|
+
Record<
|
|
1916
|
+
string,
|
|
1917
|
+
ContractSourceOperation<
|
|
1918
|
+
SchemaNameOf<TSchemas>,
|
|
1919
|
+
CapabilityRef<TCapabilities>
|
|
1920
|
+
>
|
|
1921
|
+
>
|
|
1922
|
+
>
|
|
1923
|
+
| undefined = undefined,
|
|
1924
|
+
TEvents extends
|
|
1925
|
+
| Readonly<
|
|
1926
|
+
Record<
|
|
1927
|
+
string,
|
|
1928
|
+
ContractSourceEvent<
|
|
1929
|
+
SchemaNameOf<TSchemas>,
|
|
1930
|
+
CapabilityRef<TCapabilities>
|
|
1931
|
+
>
|
|
1932
|
+
>
|
|
1933
|
+
>
|
|
1934
|
+
| undefined = undefined,
|
|
1935
|
+
> =
|
|
1936
|
+
& Omit<
|
|
1937
|
+
DefineContractInput<
|
|
1938
|
+
TCapabilities,
|
|
1939
|
+
TSchemas,
|
|
1940
|
+
TUses,
|
|
1941
|
+
TErrors,
|
|
1942
|
+
TRpc,
|
|
1943
|
+
TOperations,
|
|
1944
|
+
TEvents
|
|
1945
|
+
>,
|
|
1946
|
+
"schemas" | "errors"
|
|
1947
|
+
>
|
|
1948
|
+
& {
|
|
1949
|
+
schemas?: never;
|
|
1950
|
+
errors?: never;
|
|
1951
|
+
};
|
|
1952
|
+
|
|
1953
|
+
type ServiceContractBodyInput<
|
|
1954
|
+
TCapabilities extends ContractCapabilities | undefined =
|
|
1955
|
+
| ContractCapabilities
|
|
1956
|
+
| undefined,
|
|
1957
|
+
TSchemas extends Readonly<Record<string, TSchema>> | undefined = undefined,
|
|
1958
|
+
TUses extends AuthorContractUses | undefined = undefined,
|
|
1959
|
+
TErrors extends
|
|
1960
|
+
| Readonly<Record<string, ErrorClass>>
|
|
1961
|
+
| undefined = undefined,
|
|
1962
|
+
TRpc extends
|
|
1963
|
+
| Readonly<
|
|
1964
|
+
Record<
|
|
1965
|
+
string,
|
|
1966
|
+
ContractSourceRpcMethod<
|
|
1967
|
+
SchemaNameOf<TSchemas>,
|
|
1968
|
+
ErrorNameOf<TErrors>,
|
|
1969
|
+
CapabilityRef<TCapabilities>
|
|
1970
|
+
>
|
|
1971
|
+
>
|
|
1972
|
+
>
|
|
1973
|
+
| undefined = undefined,
|
|
1974
|
+
TOperations extends
|
|
1975
|
+
| Readonly<
|
|
1976
|
+
Record<
|
|
1977
|
+
string,
|
|
1978
|
+
ContractSourceOperation<
|
|
1979
|
+
SchemaNameOf<TSchemas>,
|
|
1980
|
+
CapabilityRef<TCapabilities>
|
|
1981
|
+
>
|
|
1982
|
+
>
|
|
1983
|
+
>
|
|
1984
|
+
| undefined = undefined,
|
|
1985
|
+
TEvents extends
|
|
1986
|
+
| Readonly<
|
|
1987
|
+
Record<
|
|
1988
|
+
string,
|
|
1989
|
+
ContractSourceEvent<
|
|
1990
|
+
SchemaNameOf<TSchemas>,
|
|
1991
|
+
CapabilityRef<TCapabilities>
|
|
1992
|
+
>
|
|
1993
|
+
>
|
|
1994
|
+
>
|
|
1995
|
+
| undefined = undefined,
|
|
1996
|
+
> =
|
|
1997
|
+
& Omit<
|
|
1998
|
+
DefineContractBodyInput<
|
|
1999
|
+
TCapabilities,
|
|
2000
|
+
TSchemas,
|
|
2001
|
+
TUses,
|
|
2002
|
+
TErrors,
|
|
2003
|
+
TRpc,
|
|
2004
|
+
TOperations,
|
|
2005
|
+
TEvents
|
|
2006
|
+
>,
|
|
2007
|
+
"kind"
|
|
2008
|
+
>
|
|
2009
|
+
& { kind?: never; subjects?: never };
|
|
2010
|
+
|
|
2011
|
+
type ClientContractBodyInput<
|
|
2012
|
+
TSchemas extends Readonly<Record<string, TSchema>> | undefined = undefined,
|
|
2013
|
+
TUses extends AuthorContractUses | undefined = undefined,
|
|
2014
|
+
> = ContractIdentityFields & {
|
|
2015
|
+
capabilities?: ContractCapabilities;
|
|
2016
|
+
exports?: ContractSourceExports<SchemaNameOf<TSchemas>>;
|
|
2017
|
+
state?: ContractSourceState<SchemaNameOf<TSchemas>>;
|
|
2018
|
+
uses?: TUses;
|
|
2019
|
+
kind?: never;
|
|
2020
|
+
schemas?: never;
|
|
2021
|
+
errors?: never;
|
|
2022
|
+
rpc?: never;
|
|
2023
|
+
operations?: never;
|
|
2024
|
+
events?: never;
|
|
2025
|
+
subjects?: never;
|
|
2026
|
+
resources?: never;
|
|
2027
|
+
};
|
|
2028
|
+
|
|
2029
|
+
type BuiltContractSource<
|
|
2030
|
+
TRegistry extends AnyDefineContractRegistry,
|
|
2031
|
+
TBody extends { id: string },
|
|
2032
|
+
> = Simplify<
|
|
2033
|
+
& Omit<TBody, "schemas" | "errors">
|
|
2034
|
+
& (TRegistry extends { schemas?: infer TSchemas } ? { schemas?: TSchemas }
|
|
2035
|
+
: {})
|
|
2036
|
+
& (TRegistry extends { errors?: infer TErrors } ? { errors?: TErrors } : {})
|
|
2037
|
+
>;
|
|
2038
|
+
|
|
2039
|
+
type WithKind<TBody extends { id: string }, TKind extends ContractKind> =
|
|
2040
|
+
Simplify<
|
|
2041
|
+
Omit<TBody, "kind"> & { kind: TKind }
|
|
2042
|
+
>;
|
|
2043
|
+
|
|
2044
|
+
function createContractRefBuilder<
|
|
2045
|
+
TSchemas extends Readonly<Record<string, TSchema>> | undefined,
|
|
2046
|
+
TErrors extends Readonly<Record<string, ErrorClass>> | undefined,
|
|
2047
|
+
>(
|
|
2048
|
+
registry: DefineContractRegistry<TSchemas, TErrors>,
|
|
2049
|
+
): ContractRefBuilder<TSchemas, TErrors> {
|
|
2050
|
+
const schemaRef = registry.schemas
|
|
2051
|
+
? createSchemaRef(registry.schemas)
|
|
2052
|
+
: undefined;
|
|
2053
|
+
return {
|
|
2054
|
+
schema<const TName extends SchemaNameOf<TSchemas>>(
|
|
2055
|
+
schemaName: TName,
|
|
2056
|
+
): ContractSchemaRef<TName> {
|
|
2057
|
+
if (!schemaRef) {
|
|
2058
|
+
throw new Error(
|
|
2059
|
+
`Contract builder ref.schema('${schemaName}') requires a schemas registry`,
|
|
2060
|
+
);
|
|
2061
|
+
}
|
|
2062
|
+
return schemaRef(schemaName);
|
|
2063
|
+
},
|
|
2064
|
+
error<const TName extends ErrorNameOf<TErrors>>(errorName: TName): TName {
|
|
2065
|
+
return errorName;
|
|
2066
|
+
},
|
|
2067
|
+
capability<const TName extends GlobalCapability | PlatformCapability>(
|
|
2068
|
+
capabilityName: TName,
|
|
2069
|
+
): TName {
|
|
2070
|
+
return capabilityName;
|
|
2071
|
+
},
|
|
2072
|
+
};
|
|
2073
|
+
}
|
|
2074
|
+
|
|
2075
|
+
function cloneSchema(schemaValue: TSchema): JsonSchema {
|
|
2076
|
+
const cloned = JSON.parse(JSON.stringify(schemaValue));
|
|
2077
|
+
if (!isJsonValue(cloned)) {
|
|
2078
|
+
throw new Error("Contract schema is not JSON-serializable");
|
|
2079
|
+
}
|
|
2080
|
+
return cloned;
|
|
2081
|
+
}
|
|
2082
|
+
|
|
2083
|
+
function cloneSchemas(
|
|
2084
|
+
schemas: ContractSourceSchemas | undefined,
|
|
2085
|
+
): ContractSchemas | undefined {
|
|
2086
|
+
if (!schemas) {
|
|
2087
|
+
return undefined;
|
|
2088
|
+
}
|
|
2089
|
+
|
|
2090
|
+
return Object.fromEntries(
|
|
2091
|
+
Object.entries(schemas).map((
|
|
2092
|
+
[name, schemaValue],
|
|
2093
|
+
) => [name, cloneSchema(schemaValue)]),
|
|
2094
|
+
);
|
|
2095
|
+
}
|
|
2096
|
+
|
|
2097
|
+
function cloneContractExports(
|
|
2098
|
+
contractExports: ContractSourceExports | undefined,
|
|
2099
|
+
): ContractExports | undefined {
|
|
2100
|
+
if (!contractExports) {
|
|
2101
|
+
return undefined;
|
|
2102
|
+
}
|
|
2103
|
+
|
|
2104
|
+
return {
|
|
2105
|
+
...(contractExports.schemas
|
|
2106
|
+
? { schemas: [...contractExports.schemas] }
|
|
2107
|
+
: {}),
|
|
2108
|
+
};
|
|
2109
|
+
}
|
|
2110
|
+
|
|
2111
|
+
function getErrorRuntimeSchema(
|
|
2112
|
+
errorDecl: ContractSourceErrorDecl,
|
|
2113
|
+
): TSchema | undefined {
|
|
2114
|
+
const errorClass = getContractErrorRuntimeClass(errorDecl);
|
|
2115
|
+
const runtimeSchema = errorClass
|
|
2116
|
+
? Reflect.get(errorClass, "schema")
|
|
2117
|
+
: undefined;
|
|
2118
|
+
if (!runtimeSchema || typeof runtimeSchema !== "object") {
|
|
2119
|
+
return undefined;
|
|
2120
|
+
}
|
|
2121
|
+
|
|
2122
|
+
return runtimeSchema as TSchema;
|
|
2123
|
+
}
|
|
2124
|
+
|
|
2125
|
+
function createContractErrorDecl<TClass extends ErrorClass>(
|
|
2126
|
+
errorClass: TClass,
|
|
2127
|
+
): ContractSourceErrorDecl<string> & ContractErrorRuntimeMarker<TClass> {
|
|
2128
|
+
const errorDecl: ContractSourceErrorDecl<string> = {
|
|
2129
|
+
type: getContractErrorType(errorClass),
|
|
2130
|
+
};
|
|
2131
|
+
return attachContractErrorRuntimeMetadata(errorDecl, errorClass);
|
|
2132
|
+
}
|
|
2133
|
+
|
|
2134
|
+
function normalizeErrorRegistry(
|
|
2135
|
+
errors: Readonly<Record<string, unknown>> | undefined,
|
|
2136
|
+
): Readonly<Record<string, ContractSourceErrorDecl>> | undefined {
|
|
2137
|
+
if (!errors) {
|
|
2138
|
+
return undefined;
|
|
2139
|
+
}
|
|
2140
|
+
|
|
2141
|
+
const normalizedEntries = Object.entries(errors).flatMap(([key, value]) =>
|
|
2142
|
+
isErrorClass(value) ? [[key, createContractErrorDecl(value)]] : []
|
|
2143
|
+
);
|
|
2144
|
+
if (normalizedEntries.length === 0) {
|
|
2145
|
+
return undefined;
|
|
2146
|
+
}
|
|
2147
|
+
|
|
2148
|
+
return Object.fromEntries(normalizedEntries);
|
|
2149
|
+
}
|
|
2150
|
+
|
|
2151
|
+
function getErrorClassRegistry(
|
|
2152
|
+
errors: Readonly<Record<string, unknown>> | undefined,
|
|
2153
|
+
): Readonly<Record<string, ErrorClass>> | undefined {
|
|
2154
|
+
if (!errors) {
|
|
2155
|
+
return undefined;
|
|
2156
|
+
}
|
|
2157
|
+
|
|
2158
|
+
const classEntries = Object.entries(errors).flatMap(([key, value]) =>
|
|
2159
|
+
isErrorClass(value) ? [[key, value]] : []
|
|
2160
|
+
);
|
|
2161
|
+
if (classEntries.length === 0) {
|
|
2162
|
+
return undefined;
|
|
2163
|
+
}
|
|
2164
|
+
|
|
2165
|
+
return Object.fromEntries(classEntries);
|
|
2166
|
+
}
|
|
2167
|
+
|
|
2168
|
+
function findMatchingSchemaName(
|
|
2169
|
+
schemas: ContractSourceSchemas | undefined,
|
|
2170
|
+
targetSchema: TSchema,
|
|
2171
|
+
): string | undefined {
|
|
2172
|
+
if (!schemas) {
|
|
2173
|
+
return undefined;
|
|
2174
|
+
}
|
|
2175
|
+
|
|
2176
|
+
const targetDigest = digestCanonicalJson(cloneSchema(targetSchema));
|
|
2177
|
+
for (const [schemaName, schemaValue] of Object.entries(schemas)) {
|
|
2178
|
+
if (schemaValue === targetSchema) {
|
|
2179
|
+
return schemaName;
|
|
2180
|
+
}
|
|
2181
|
+
|
|
2182
|
+
if (digestCanonicalJson(cloneSchema(schemaValue)) === targetDigest) {
|
|
2183
|
+
return schemaName;
|
|
2184
|
+
}
|
|
2185
|
+
}
|
|
2186
|
+
|
|
2187
|
+
return undefined;
|
|
2188
|
+
}
|
|
2189
|
+
|
|
2190
|
+
function chooseDerivedErrorSchemaName(
|
|
2191
|
+
schemas: ContractSourceSchemas,
|
|
2192
|
+
errorName: string,
|
|
2193
|
+
errorType: string,
|
|
2194
|
+
): string {
|
|
2195
|
+
const baseNames = [`${errorType}Data`, `${errorName}Data`];
|
|
2196
|
+
|
|
2197
|
+
for (const baseName of baseNames) {
|
|
2198
|
+
if (!Object.hasOwn(schemas, baseName)) {
|
|
2199
|
+
return baseName;
|
|
2200
|
+
}
|
|
2201
|
+
}
|
|
2202
|
+
|
|
2203
|
+
let suffix = 2;
|
|
2204
|
+
while (true) {
|
|
2205
|
+
const candidate = `${errorType}Data${suffix}`;
|
|
2206
|
+
if (!Object.hasOwn(schemas, candidate)) {
|
|
2207
|
+
return candidate;
|
|
2208
|
+
}
|
|
2209
|
+
suffix += 1;
|
|
2210
|
+
}
|
|
2211
|
+
}
|
|
2212
|
+
|
|
2213
|
+
function materializeErrorSchemas(
|
|
2214
|
+
schemas: ContractSourceSchemas | undefined,
|
|
2215
|
+
errors: Record<string, ContractSourceErrorDecl> | undefined,
|
|
2216
|
+
): ContractSourceSchemas | undefined {
|
|
2217
|
+
if (!errors) {
|
|
2218
|
+
return schemas;
|
|
2219
|
+
}
|
|
2220
|
+
|
|
2221
|
+
let mergedSchemas = schemas;
|
|
2222
|
+
for (const [errorName, errorDecl] of Object.entries(errors)) {
|
|
2223
|
+
if (errorDecl.schema) {
|
|
2224
|
+
continue;
|
|
2225
|
+
}
|
|
2226
|
+
|
|
2227
|
+
const runtimeSchema = getErrorRuntimeSchema(errorDecl);
|
|
2228
|
+
if (!runtimeSchema) {
|
|
2229
|
+
continue;
|
|
2230
|
+
}
|
|
2231
|
+
|
|
2232
|
+
if (findMatchingSchemaName(mergedSchemas, runtimeSchema)) {
|
|
2233
|
+
continue;
|
|
2234
|
+
}
|
|
2235
|
+
|
|
2236
|
+
mergedSchemas = { ...(mergedSchemas ?? {}) };
|
|
2237
|
+
const derivedSchemaName = chooseDerivedErrorSchemaName(
|
|
2238
|
+
mergedSchemas,
|
|
2239
|
+
errorName,
|
|
2240
|
+
errorDecl.type,
|
|
2241
|
+
);
|
|
2242
|
+
mergedSchemas[derivedSchemaName] = runtimeSchema;
|
|
2243
|
+
}
|
|
2244
|
+
|
|
2245
|
+
return mergedSchemas;
|
|
2246
|
+
}
|
|
2247
|
+
|
|
2248
|
+
function assertSchemaRefExists(
|
|
2249
|
+
schemas: ContractSourceSchemas | undefined,
|
|
2250
|
+
ref: ContractSchemaRef,
|
|
2251
|
+
context: string,
|
|
2252
|
+
): void {
|
|
2253
|
+
if (!schemas || !Object.hasOwn(schemas, ref.schema)) {
|
|
2254
|
+
throw new Error(`${context} references unknown schema '${ref.schema}'`);
|
|
2255
|
+
}
|
|
2256
|
+
}
|
|
2257
|
+
|
|
2258
|
+
function assertExportedSchemasExist(
|
|
2259
|
+
schemas: ContractSourceSchemas | undefined,
|
|
2260
|
+
contractExports: ContractSourceExports | undefined,
|
|
2261
|
+
): void {
|
|
2262
|
+
for (const schemaName of contractExports?.schemas ?? []) {
|
|
2263
|
+
if (!schemas || !Object.hasOwn(schemas, schemaName)) {
|
|
2264
|
+
throw new Error(
|
|
2265
|
+
`contract exports reference unknown schema '${schemaName}'`,
|
|
2266
|
+
);
|
|
2267
|
+
}
|
|
2268
|
+
}
|
|
2269
|
+
}
|
|
2270
|
+
|
|
2271
|
+
function assertRegistryDoesNotDeclareExports(
|
|
2272
|
+
registry: AnyDefineContractRegistry,
|
|
2273
|
+
): void {
|
|
2274
|
+
if (Object.hasOwn(registry, "exports")) {
|
|
2275
|
+
throw new Error(
|
|
2276
|
+
"contract exports must be declared in the callback body, not the registry argument",
|
|
2277
|
+
);
|
|
2278
|
+
}
|
|
2279
|
+
}
|
|
2280
|
+
|
|
2281
|
+
function assertRegistryDoesNotDeclareCapabilities(
|
|
2282
|
+
registry: AnyDefineContractRegistry,
|
|
2283
|
+
): void {
|
|
2284
|
+
if (Object.hasOwn(registry, "capabilities")) {
|
|
2285
|
+
throw new Error(
|
|
2286
|
+
"contract capabilities must be declared in the callback body, not the registry argument",
|
|
2287
|
+
);
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2290
|
+
|
|
2291
|
+
function resolveSchemaRef(
|
|
2292
|
+
schemas: ContractSourceSchemas | undefined,
|
|
2293
|
+
ref: ContractSchemaRef,
|
|
2294
|
+
context: string,
|
|
2295
|
+
): JsonSchema {
|
|
2296
|
+
assertSchemaRefExists(schemas, ref, context);
|
|
2297
|
+
const schema = schemas?.[ref.schema];
|
|
2298
|
+
if (!schema) {
|
|
2299
|
+
throw new Error(`${context} references missing schema '${ref.schema}'`);
|
|
2300
|
+
}
|
|
2301
|
+
return cloneSchema(schema);
|
|
2302
|
+
}
|
|
2303
|
+
|
|
2304
|
+
function digestCanonicalJson(value: JsonValue): string {
|
|
2305
|
+
return sha256Base64urlSync(canonicalizeJson(value));
|
|
2306
|
+
}
|
|
2307
|
+
|
|
2308
|
+
function sortedUnique(values: readonly string[]): string[] {
|
|
2309
|
+
return [...new Set(values)].sort();
|
|
2310
|
+
}
|
|
2311
|
+
|
|
2312
|
+
/** Return the global capability namespace for a contract id. */
|
|
2313
|
+
export function contractCapabilityNamespace(contractId: string): string {
|
|
2314
|
+
return contractId.replace(/@v\d+$/, "");
|
|
2315
|
+
}
|
|
2316
|
+
|
|
2317
|
+
/** Return the globally qualified name for a contract-local capability. */
|
|
2318
|
+
export function globalCapabilityName(
|
|
2319
|
+
contractId: string,
|
|
2320
|
+
localCapability: string,
|
|
2321
|
+
): string {
|
|
2322
|
+
return `${contractCapabilityNamespace(contractId)}::${localCapability}`;
|
|
2323
|
+
}
|
|
2324
|
+
|
|
2325
|
+
function projectCapabilities(
|
|
2326
|
+
capabilities: readonly Capability[] | undefined,
|
|
2327
|
+
contractId: string,
|
|
2328
|
+
declaredCapabilities: ContractCapabilities | undefined,
|
|
2329
|
+
context: string,
|
|
2330
|
+
): string[] | undefined {
|
|
2331
|
+
if (!capabilities) {
|
|
2332
|
+
return undefined;
|
|
2333
|
+
}
|
|
2334
|
+
return sortedUnique(
|
|
2335
|
+
capabilities.map((capability) => {
|
|
2336
|
+
if (
|
|
2337
|
+
declaredCapabilities && Object.hasOwn(declaredCapabilities, capability)
|
|
2338
|
+
) {
|
|
2339
|
+
return globalCapabilityName(contractId, capability);
|
|
2340
|
+
}
|
|
2341
|
+
if (
|
|
2342
|
+
capability === "admin" || capability === "service" ||
|
|
2343
|
+
capability.includes("::")
|
|
2344
|
+
) {
|
|
2345
|
+
return capability;
|
|
2346
|
+
}
|
|
2347
|
+
throw new Error(
|
|
2348
|
+
`${context} references undeclared local capability '${capability}'`,
|
|
2349
|
+
);
|
|
2350
|
+
}),
|
|
2351
|
+
);
|
|
2352
|
+
}
|
|
2353
|
+
|
|
2354
|
+
function emitCapabilities(
|
|
2355
|
+
contractId: string,
|
|
2356
|
+
capabilities: ContractCapabilities | undefined,
|
|
2357
|
+
): ContractCapabilities | undefined {
|
|
2358
|
+
if (!capabilities) {
|
|
2359
|
+
return undefined;
|
|
2360
|
+
}
|
|
2361
|
+
|
|
2362
|
+
const entries: [string, ContractCapabilityMetadata][] = Object.entries(
|
|
2363
|
+
capabilities,
|
|
2364
|
+
)
|
|
2365
|
+
.map(([localCapability, metadata]) => [
|
|
2366
|
+
globalCapabilityName(contractId, localCapability),
|
|
2367
|
+
{ ...metadata },
|
|
2368
|
+
]);
|
|
2369
|
+
entries.sort(([left], [right]) => left.localeCompare(right));
|
|
2370
|
+
return Object.fromEntries(entries);
|
|
2371
|
+
}
|
|
2372
|
+
|
|
2373
|
+
function collectSchemaRef(
|
|
2374
|
+
reachableSchemas: Set<string>,
|
|
2375
|
+
ref: ContractSchemaRef | undefined,
|
|
2376
|
+
): void {
|
|
2377
|
+
if (ref) {
|
|
2378
|
+
reachableSchemas.add(ref.schema);
|
|
2379
|
+
}
|
|
2380
|
+
}
|
|
2381
|
+
|
|
2382
|
+
function collectReachableSchemaNames(contract: TrellisContractV1): Set<string> {
|
|
2383
|
+
const reachableSchemas = new Set<string>();
|
|
2384
|
+
|
|
2385
|
+
for (const store of Object.values(contract.state ?? {})) {
|
|
2386
|
+
collectSchemaRef(reachableSchemas, store.schema);
|
|
2387
|
+
for (const accepted of Object.values(store.acceptedVersions ?? {})) {
|
|
2388
|
+
collectSchemaRef(reachableSchemas, accepted);
|
|
2389
|
+
}
|
|
2390
|
+
}
|
|
2391
|
+
|
|
2392
|
+
for (const method of Object.values(contract.rpc ?? {})) {
|
|
2393
|
+
collectSchemaRef(reachableSchemas, method.input);
|
|
2394
|
+
collectSchemaRef(reachableSchemas, method.output);
|
|
2395
|
+
for (const error of method.errors ?? []) {
|
|
2396
|
+
const declaration = Object.values(contract.errors ?? {}).find((decl) =>
|
|
2397
|
+
decl.type === error.type
|
|
2398
|
+
);
|
|
2399
|
+
collectSchemaRef(reachableSchemas, declaration?.schema);
|
|
2400
|
+
}
|
|
2401
|
+
}
|
|
2402
|
+
|
|
2403
|
+
for (const operation of Object.values(contract.operations ?? {})) {
|
|
2404
|
+
collectSchemaRef(reachableSchemas, operation.input);
|
|
2405
|
+
collectSchemaRef(reachableSchemas, operation.progress);
|
|
2406
|
+
collectSchemaRef(reachableSchemas, operation.output);
|
|
2407
|
+
for (const signal of Object.values(operation.signals ?? {})) {
|
|
2408
|
+
collectSchemaRef(reachableSchemas, signal.input);
|
|
2409
|
+
}
|
|
2410
|
+
}
|
|
2411
|
+
|
|
2412
|
+
for (const event of Object.values(contract.events ?? {})) {
|
|
2413
|
+
collectSchemaRef(reachableSchemas, event.event);
|
|
2414
|
+
}
|
|
2415
|
+
|
|
2416
|
+
for (const feed of Object.values(contract.feeds ?? {})) {
|
|
2417
|
+
collectSchemaRef(reachableSchemas, feed.input);
|
|
2418
|
+
collectSchemaRef(reachableSchemas, feed.event);
|
|
2419
|
+
}
|
|
2420
|
+
|
|
2421
|
+
for (const job of Object.values(contract.jobs ?? {})) {
|
|
2422
|
+
collectSchemaRef(reachableSchemas, job.payload);
|
|
2423
|
+
collectSchemaRef(reachableSchemas, job.result);
|
|
2424
|
+
}
|
|
2425
|
+
|
|
2426
|
+
for (const resource of Object.values(contract.resources?.kv ?? {})) {
|
|
2427
|
+
collectSchemaRef(reachableSchemas, resource.schema);
|
|
2428
|
+
}
|
|
2429
|
+
|
|
2430
|
+
return reachableSchemas;
|
|
2431
|
+
}
|
|
2432
|
+
|
|
2433
|
+
function projectReachableSchemas(
|
|
2434
|
+
contract: TrellisContractV1,
|
|
2435
|
+
): ContractSchemas | undefined {
|
|
2436
|
+
const reachableNames = collectReachableSchemaNames(contract);
|
|
2437
|
+
if (!contract.schemas || reachableNames.size === 0) {
|
|
2438
|
+
return undefined;
|
|
2439
|
+
}
|
|
2440
|
+
|
|
2441
|
+
const entries = Object.entries(contract.schemas).filter(([name]) =>
|
|
2442
|
+
reachableNames.has(name)
|
|
2443
|
+
);
|
|
2444
|
+
return entries.length > 0 ? Object.fromEntries(entries) : undefined;
|
|
2445
|
+
}
|
|
2446
|
+
|
|
2447
|
+
function projectRpcDeclaredErrors(
|
|
2448
|
+
contract: TrellisContractV1,
|
|
2449
|
+
): Record<string, ContractErrorDecl> | undefined {
|
|
2450
|
+
if (!contract.errors) {
|
|
2451
|
+
return undefined;
|
|
2452
|
+
}
|
|
2453
|
+
|
|
2454
|
+
const declaredErrorTypes = new Set<string>();
|
|
2455
|
+
for (const method of Object.values(contract.rpc ?? {})) {
|
|
2456
|
+
for (const error of method.errors ?? []) {
|
|
2457
|
+
declaredErrorTypes.add(error.type);
|
|
2458
|
+
}
|
|
2459
|
+
}
|
|
2460
|
+
|
|
2461
|
+
const entries = Object.entries(contract.errors).filter(([, error]) =>
|
|
2462
|
+
declaredErrorTypes.has(error.type)
|
|
2463
|
+
);
|
|
2464
|
+
return entries.length > 0 ? Object.fromEntries(entries) : undefined;
|
|
2465
|
+
}
|
|
2466
|
+
|
|
2467
|
+
function projectDigestResources(
|
|
2468
|
+
resources: ContractResources | undefined,
|
|
2469
|
+
): ContractResources | undefined {
|
|
2470
|
+
if (!resources?.kv && !resources?.store) {
|
|
2471
|
+
return undefined;
|
|
2472
|
+
}
|
|
2473
|
+
return {
|
|
2474
|
+
...(resources.kv ? { kv: resources.kv } : {}),
|
|
2475
|
+
...(resources.store ? { store: resources.store } : {}),
|
|
2476
|
+
};
|
|
2477
|
+
}
|
|
2478
|
+
|
|
2479
|
+
function projectDigestUsesFlat(
|
|
2480
|
+
uses: ContractUsesFlat | undefined,
|
|
2481
|
+
): ContractUsesFlat | undefined {
|
|
2482
|
+
if (!uses) {
|
|
2483
|
+
return undefined;
|
|
2484
|
+
}
|
|
2485
|
+
|
|
2486
|
+
return Object.fromEntries(
|
|
2487
|
+
Object.entries(uses).map(([alias, use]) => [
|
|
2488
|
+
alias,
|
|
2489
|
+
{
|
|
2490
|
+
contract: use.contract,
|
|
2491
|
+
...(use.rpc?.call ? { rpc: { call: sortedUnique(use.rpc.call) } } : {}),
|
|
2492
|
+
...(use.operations?.call
|
|
2493
|
+
? { operations: { call: sortedUnique(use.operations.call) } }
|
|
2494
|
+
: {}),
|
|
2495
|
+
...((use.events?.publish || use.events?.subscribe)
|
|
2496
|
+
? {
|
|
2497
|
+
events: {
|
|
2498
|
+
...(use.events.publish
|
|
2499
|
+
? { publish: sortedUnique(use.events.publish) }
|
|
2500
|
+
: {}),
|
|
2501
|
+
...(use.events.subscribe
|
|
2502
|
+
? { subscribe: sortedUnique(use.events.subscribe) }
|
|
2503
|
+
: {}),
|
|
2504
|
+
},
|
|
2505
|
+
}
|
|
2506
|
+
: {}),
|
|
2507
|
+
...(use.feeds?.subscribe
|
|
2508
|
+
? { feeds: { subscribe: sortedUnique(use.feeds.subscribe) } }
|
|
2509
|
+
: {}),
|
|
2510
|
+
} satisfies ContractUse,
|
|
2511
|
+
]),
|
|
2512
|
+
);
|
|
2513
|
+
}
|
|
2514
|
+
|
|
2515
|
+
function omitRequiredUseAliases<TUse>(
|
|
2516
|
+
optional: Record<string, TUse> | undefined,
|
|
2517
|
+
required: Record<string, TUse> | undefined,
|
|
2518
|
+
): Record<string, TUse> | undefined {
|
|
2519
|
+
if (!optional) {
|
|
2520
|
+
return undefined;
|
|
2521
|
+
}
|
|
2522
|
+
if (!required) {
|
|
2523
|
+
return optional;
|
|
2524
|
+
}
|
|
2525
|
+
const requiredAliases = new Set(Object.keys(required));
|
|
2526
|
+
const entries = Object.entries(optional).filter(([alias]) =>
|
|
2527
|
+
!requiredAliases.has(alias)
|
|
2528
|
+
);
|
|
2529
|
+
return entries.length > 0 ? Object.fromEntries(entries) : undefined;
|
|
2530
|
+
}
|
|
2531
|
+
|
|
2532
|
+
function projectDigestUses(
|
|
2533
|
+
uses: ContractUses | undefined,
|
|
2534
|
+
): ContractUses | undefined {
|
|
2535
|
+
if (!uses) {
|
|
2536
|
+
return undefined;
|
|
2537
|
+
}
|
|
2538
|
+
|
|
2539
|
+
const required = projectDigestUsesFlat(uses.required);
|
|
2540
|
+
const optional = omitRequiredUseAliases(
|
|
2541
|
+
projectDigestUsesFlat(uses.optional),
|
|
2542
|
+
required,
|
|
2543
|
+
);
|
|
2544
|
+
if (!required && !optional) {
|
|
2545
|
+
return undefined;
|
|
2546
|
+
}
|
|
2547
|
+
return {
|
|
2548
|
+
...(required ? { required } : {}),
|
|
2549
|
+
...(optional ? { optional } : {}),
|
|
2550
|
+
};
|
|
2551
|
+
}
|
|
2552
|
+
|
|
2553
|
+
function projectDigestRpc(
|
|
2554
|
+
rpc: Record<string, ContractRpcMethod> | undefined,
|
|
2555
|
+
): Record<string, ContractRpcMethod> | undefined {
|
|
2556
|
+
if (!rpc) {
|
|
2557
|
+
return undefined;
|
|
2558
|
+
}
|
|
2559
|
+
|
|
2560
|
+
return Object.fromEntries(
|
|
2561
|
+
Object.entries(rpc).map(([name, method]) => [
|
|
2562
|
+
name,
|
|
2563
|
+
{
|
|
2564
|
+
...method,
|
|
2565
|
+
...(method.capabilities?.call
|
|
2566
|
+
? { capabilities: { call: sortedUnique(method.capabilities.call) } }
|
|
2567
|
+
: {}),
|
|
2568
|
+
...(method.errors
|
|
2569
|
+
? {
|
|
2570
|
+
errors: sortedUnique(method.errors.map((error) => error.type)).map((
|
|
2571
|
+
type,
|
|
2572
|
+
) => ({ type })),
|
|
2573
|
+
}
|
|
2574
|
+
: {}),
|
|
2575
|
+
} satisfies ContractRpcMethod,
|
|
2576
|
+
]),
|
|
2577
|
+
);
|
|
2578
|
+
}
|
|
2579
|
+
|
|
2580
|
+
function projectDigestOperations(
|
|
2581
|
+
operations: Record<string, ContractOperation> | undefined,
|
|
2582
|
+
): Record<string, ContractOperation> | undefined {
|
|
2583
|
+
if (!operations) {
|
|
2584
|
+
return undefined;
|
|
2585
|
+
}
|
|
2586
|
+
|
|
2587
|
+
return Object.fromEntries(
|
|
2588
|
+
Object.entries(operations).map(([name, operation]) => [
|
|
2589
|
+
name,
|
|
2590
|
+
{
|
|
2591
|
+
...operation,
|
|
2592
|
+
...((operation.capabilities?.call || operation.capabilities?.read ||
|
|
2593
|
+
operation.capabilities?.cancel || operation.capabilities?.control)
|
|
2594
|
+
? {
|
|
2595
|
+
capabilities: {
|
|
2596
|
+
...(operation.capabilities.call
|
|
2597
|
+
? { call: sortedUnique(operation.capabilities.call) }
|
|
2598
|
+
: {}),
|
|
2599
|
+
...(operation.capabilities.read
|
|
2600
|
+
? { read: sortedUnique(operation.capabilities.read) }
|
|
2601
|
+
: {}),
|
|
2602
|
+
...(operation.capabilities.cancel
|
|
2603
|
+
? { cancel: sortedUnique(operation.capabilities.cancel) }
|
|
2604
|
+
: {}),
|
|
2605
|
+
...(operation.capabilities.control
|
|
2606
|
+
? { control: sortedUnique(operation.capabilities.control) }
|
|
2607
|
+
: {}),
|
|
2608
|
+
},
|
|
2609
|
+
}
|
|
2610
|
+
: {}),
|
|
2611
|
+
} satisfies ContractOperation,
|
|
2612
|
+
]),
|
|
2613
|
+
);
|
|
2614
|
+
}
|
|
2615
|
+
|
|
2616
|
+
function projectDigestEvents(
|
|
2617
|
+
events: Record<string, ContractEvent> | undefined,
|
|
2618
|
+
): Record<string, ContractEvent> | undefined {
|
|
2619
|
+
if (!events) {
|
|
2620
|
+
return undefined;
|
|
2621
|
+
}
|
|
2622
|
+
|
|
2623
|
+
return Object.fromEntries(
|
|
2624
|
+
Object.entries(events).map(([name, event]) => [
|
|
2625
|
+
name,
|
|
2626
|
+
{
|
|
2627
|
+
...event,
|
|
2628
|
+
...((event.capabilities?.publish || event.capabilities?.subscribe)
|
|
2629
|
+
? {
|
|
2630
|
+
capabilities: {
|
|
2631
|
+
...(event.capabilities.publish
|
|
2632
|
+
? { publish: sortedUnique(event.capabilities.publish) }
|
|
2633
|
+
: {}),
|
|
2634
|
+
...(event.capabilities.subscribe
|
|
2635
|
+
? { subscribe: sortedUnique(event.capabilities.subscribe) }
|
|
2636
|
+
: {}),
|
|
2637
|
+
},
|
|
2638
|
+
}
|
|
2639
|
+
: {}),
|
|
2640
|
+
} satisfies ContractEvent,
|
|
2641
|
+
]),
|
|
2642
|
+
);
|
|
2643
|
+
}
|
|
2644
|
+
|
|
2645
|
+
function projectDigestFeeds(
|
|
2646
|
+
feeds: Record<string, ContractFeed> | undefined,
|
|
2647
|
+
): Record<string, ContractFeed> | undefined {
|
|
2648
|
+
if (!feeds) {
|
|
2649
|
+
return undefined;
|
|
2650
|
+
}
|
|
2651
|
+
|
|
2652
|
+
return Object.fromEntries(
|
|
2653
|
+
Object.entries(feeds).map(([name, feed]) => [
|
|
2654
|
+
name,
|
|
2655
|
+
{
|
|
2656
|
+
...feed,
|
|
2657
|
+
...(feed.capabilities?.subscribe
|
|
2658
|
+
? {
|
|
2659
|
+
capabilities: {
|
|
2660
|
+
subscribe: sortedUnique(feed.capabilities.subscribe),
|
|
2661
|
+
},
|
|
2662
|
+
}
|
|
2663
|
+
: {}),
|
|
2664
|
+
} satisfies ContractFeed,
|
|
2665
|
+
]),
|
|
2666
|
+
);
|
|
2667
|
+
}
|
|
2668
|
+
|
|
2669
|
+
function mapValues<TInput, TOutput>(
|
|
2670
|
+
values: Record<string, TInput> | undefined,
|
|
2671
|
+
map: (value: TInput) => TOutput,
|
|
2672
|
+
): Record<string, TOutput> | undefined {
|
|
2673
|
+
if (!values) return undefined;
|
|
2674
|
+
return Object.fromEntries(
|
|
2675
|
+
Object.entries(values).map(([key, value]) => [key, map(value)]),
|
|
2676
|
+
);
|
|
2677
|
+
}
|
|
2678
|
+
|
|
2679
|
+
function schemaRef(ref: ContractSchemaRef): ContractSchemaRef {
|
|
2680
|
+
return { schema: ref.schema };
|
|
2681
|
+
}
|
|
2682
|
+
|
|
2683
|
+
function capabilityMetadata(
|
|
2684
|
+
metadata: ContractCapabilityMetadata,
|
|
2685
|
+
): ContractCapabilityMetadata {
|
|
2686
|
+
return {
|
|
2687
|
+
displayName: metadata.displayName,
|
|
2688
|
+
description: metadata.description,
|
|
2689
|
+
...(metadata.consequence ? { consequence: metadata.consequence } : {}),
|
|
2690
|
+
};
|
|
2691
|
+
}
|
|
2692
|
+
|
|
2693
|
+
function useRpc(use: ContractUsesRpc | undefined): ContractUsesRpc | undefined {
|
|
2694
|
+
if (!use) return undefined;
|
|
2695
|
+
return {
|
|
2696
|
+
...(use.call ? { call: [...use.call] } : {}),
|
|
2697
|
+
};
|
|
2698
|
+
}
|
|
2699
|
+
|
|
2700
|
+
function usePubSub(
|
|
2701
|
+
use: ContractUsesPubSub | undefined,
|
|
2702
|
+
): ContractUsesPubSub | undefined {
|
|
2703
|
+
if (!use) return undefined;
|
|
2704
|
+
return {
|
|
2705
|
+
...(use.publish ? { publish: [...use.publish] } : {}),
|
|
2706
|
+
...(use.subscribe ? { subscribe: [...use.subscribe] } : {}),
|
|
2707
|
+
};
|
|
2708
|
+
}
|
|
2709
|
+
|
|
2710
|
+
function contractUse(use: ContractUse): ContractUse {
|
|
2711
|
+
return {
|
|
2712
|
+
contract: use.contract,
|
|
2713
|
+
...(use.rpc ? { rpc: useRpc(use.rpc) } : {}),
|
|
2714
|
+
...(use.operations ? { operations: useRpc(use.operations) } : {}),
|
|
2715
|
+
...(use.events ? { events: usePubSub(use.events) } : {}),
|
|
2716
|
+
...(use.feeds
|
|
2717
|
+
? {
|
|
2718
|
+
feeds: {
|
|
2719
|
+
...(use.feeds.subscribe
|
|
2720
|
+
? { subscribe: [...use.feeds.subscribe] }
|
|
2721
|
+
: {}),
|
|
2722
|
+
},
|
|
2723
|
+
}
|
|
2724
|
+
: {}),
|
|
2725
|
+
};
|
|
2726
|
+
}
|
|
2727
|
+
|
|
2728
|
+
function contractUses(
|
|
2729
|
+
uses: ContractUses | undefined,
|
|
2730
|
+
): ContractUses | undefined {
|
|
2731
|
+
if (!uses) return undefined;
|
|
2732
|
+
return {
|
|
2733
|
+
...(uses.required
|
|
2734
|
+
? { required: mapValues(uses.required, contractUse) }
|
|
2735
|
+
: {}),
|
|
2736
|
+
...(uses.optional
|
|
2737
|
+
? { optional: mapValues(uses.optional, contractUse) }
|
|
2738
|
+
: {}),
|
|
2739
|
+
};
|
|
2740
|
+
}
|
|
2741
|
+
|
|
2742
|
+
function stateStore(store: ContractStateStore): ContractStateStore {
|
|
2743
|
+
return {
|
|
2744
|
+
kind: store.kind,
|
|
2745
|
+
schema: schemaRef(store.schema),
|
|
2746
|
+
...(store.stateVersion ? { stateVersion: store.stateVersion } : {}),
|
|
2747
|
+
...(store.acceptedVersions
|
|
2748
|
+
? { acceptedVersions: mapValues(store.acceptedVersions, schemaRef) }
|
|
2749
|
+
: {}),
|
|
2750
|
+
};
|
|
2751
|
+
}
|
|
2752
|
+
|
|
2753
|
+
function rpcMethod(method: ContractRpcMethod): ContractRpcMethod {
|
|
2754
|
+
return {
|
|
2755
|
+
version: method.version,
|
|
2756
|
+
subject: method.subject,
|
|
2757
|
+
input: schemaRef(method.input),
|
|
2758
|
+
output: schemaRef(method.output),
|
|
2759
|
+
...(method.transfer
|
|
2760
|
+
? { transfer: { direction: method.transfer.direction } }
|
|
2761
|
+
: {}),
|
|
2762
|
+
...(method.capabilities?.call
|
|
2763
|
+
? { capabilities: { call: [...method.capabilities.call] } }
|
|
2764
|
+
: {}),
|
|
2765
|
+
...(method.errors
|
|
2766
|
+
? { errors: method.errors.map((error) => ({ type: error.type })) }
|
|
2767
|
+
: {}),
|
|
2768
|
+
};
|
|
2769
|
+
}
|
|
2770
|
+
|
|
2771
|
+
function operation(operation: ContractOperation): ContractOperation {
|
|
2772
|
+
return {
|
|
2773
|
+
version: operation.version,
|
|
2774
|
+
subject: operation.subject,
|
|
2775
|
+
input: schemaRef(operation.input),
|
|
2776
|
+
...(operation.progress ? { progress: schemaRef(operation.progress) } : {}),
|
|
2777
|
+
output: schemaRef(operation.output),
|
|
2778
|
+
...(operation.transfer
|
|
2779
|
+
? {
|
|
2780
|
+
transfer: {
|
|
2781
|
+
direction: operation.transfer.direction,
|
|
2782
|
+
store: operation.transfer.store,
|
|
2783
|
+
key: operation.transfer.key,
|
|
2784
|
+
...(operation.transfer.contentType
|
|
2785
|
+
? { contentType: operation.transfer.contentType }
|
|
2786
|
+
: {}),
|
|
2787
|
+
...(operation.transfer.metadata
|
|
2788
|
+
? { metadata: operation.transfer.metadata }
|
|
2789
|
+
: {}),
|
|
2790
|
+
...(operation.transfer.expiresInMs !== undefined
|
|
2791
|
+
? { expiresInMs: operation.transfer.expiresInMs }
|
|
2792
|
+
: {}),
|
|
2793
|
+
...(operation.transfer.maxBytes !== undefined
|
|
2794
|
+
? { maxBytes: operation.transfer.maxBytes }
|
|
2795
|
+
: {}),
|
|
2796
|
+
},
|
|
2797
|
+
}
|
|
2798
|
+
: {}),
|
|
2799
|
+
...(operation.capabilities
|
|
2800
|
+
? {
|
|
2801
|
+
capabilities: {
|
|
2802
|
+
...(operation.capabilities.call
|
|
2803
|
+
? { call: [...operation.capabilities.call] }
|
|
2804
|
+
: {}),
|
|
2805
|
+
...(operation.capabilities.read
|
|
2806
|
+
? { read: [...operation.capabilities.read] }
|
|
2807
|
+
: {}),
|
|
2808
|
+
...(operation.capabilities.cancel
|
|
2809
|
+
? { cancel: [...operation.capabilities.cancel] }
|
|
2810
|
+
: {}),
|
|
2811
|
+
...(operation.capabilities.control
|
|
2812
|
+
? { control: [...operation.capabilities.control] }
|
|
2813
|
+
: {}),
|
|
2814
|
+
},
|
|
2815
|
+
}
|
|
2816
|
+
: {}),
|
|
2817
|
+
...(operation.signals
|
|
2818
|
+
? {
|
|
2819
|
+
signals: mapValues(
|
|
2820
|
+
operation.signals,
|
|
2821
|
+
(signal) => ({ input: schemaRef(signal.input) }),
|
|
2822
|
+
),
|
|
2823
|
+
}
|
|
2824
|
+
: {}),
|
|
2825
|
+
...(operation.cancel !== undefined ? { cancel: operation.cancel } : {}),
|
|
2826
|
+
};
|
|
2827
|
+
}
|
|
2828
|
+
|
|
2829
|
+
function event(event: ContractEvent): ContractEvent {
|
|
2830
|
+
return {
|
|
2831
|
+
version: event.version,
|
|
2832
|
+
subject: event.subject,
|
|
2833
|
+
...(event.params ? { params: [...event.params] } : {}),
|
|
2834
|
+
event: schemaRef(event.event),
|
|
2835
|
+
...(event.capabilities
|
|
2836
|
+
? {
|
|
2837
|
+
capabilities: {
|
|
2838
|
+
...(event.capabilities.publish
|
|
2839
|
+
? { publish: [...event.capabilities.publish] }
|
|
2840
|
+
: {}),
|
|
2841
|
+
...(event.capabilities.subscribe
|
|
2842
|
+
? { subscribe: [...event.capabilities.subscribe] }
|
|
2843
|
+
: {}),
|
|
2844
|
+
},
|
|
2845
|
+
}
|
|
2846
|
+
: {}),
|
|
2847
|
+
};
|
|
2848
|
+
}
|
|
2849
|
+
|
|
2850
|
+
function feed(feed: ContractFeed): ContractFeed {
|
|
2851
|
+
return {
|
|
2852
|
+
version: feed.version,
|
|
2853
|
+
subject: feed.subject,
|
|
2854
|
+
input: schemaRef(feed.input),
|
|
2855
|
+
event: schemaRef(feed.event),
|
|
2856
|
+
...(feed.capabilities?.subscribe
|
|
2857
|
+
? { capabilities: { subscribe: [...feed.capabilities.subscribe] } }
|
|
2858
|
+
: {}),
|
|
2859
|
+
};
|
|
2860
|
+
}
|
|
2861
|
+
|
|
2862
|
+
function errorDecl(error: ContractErrorDecl): ContractErrorDecl {
|
|
2863
|
+
return {
|
|
2864
|
+
type: error.type,
|
|
2865
|
+
...(error.schema ? { schema: schemaRef(error.schema) } : {}),
|
|
2866
|
+
};
|
|
2867
|
+
}
|
|
2868
|
+
|
|
2869
|
+
function jobQueue(queue: ContractJobQueue): ContractJobQueue {
|
|
2870
|
+
return {
|
|
2871
|
+
payload: schemaRef(queue.payload),
|
|
2872
|
+
...(queue.result ? { result: schemaRef(queue.result) } : {}),
|
|
2873
|
+
...(queue.maxDeliver !== undefined ? { maxDeliver: queue.maxDeliver } : {}),
|
|
2874
|
+
...(queue.backoffMs ? { backoffMs: [...queue.backoffMs] } : {}),
|
|
2875
|
+
...(queue.ackWaitMs !== undefined ? { ackWaitMs: queue.ackWaitMs } : {}),
|
|
2876
|
+
...(queue.defaultDeadlineMs !== undefined
|
|
2877
|
+
? { defaultDeadlineMs: queue.defaultDeadlineMs }
|
|
2878
|
+
: {}),
|
|
2879
|
+
...(queue.progress !== undefined ? { progress: queue.progress } : {}),
|
|
2880
|
+
...(queue.logs !== undefined ? { logs: queue.logs } : {}),
|
|
2881
|
+
...(queue.dlq !== undefined ? { dlq: queue.dlq } : {}),
|
|
2882
|
+
...(queue.concurrency !== undefined
|
|
2883
|
+
? { concurrency: queue.concurrency }
|
|
2884
|
+
: {}),
|
|
2885
|
+
};
|
|
2886
|
+
}
|
|
2887
|
+
|
|
2888
|
+
function kvResource(resource: ContractKvResource): ContractKvResource {
|
|
2889
|
+
return {
|
|
2890
|
+
purpose: resource.purpose,
|
|
2891
|
+
schema: schemaRef(resource.schema),
|
|
2892
|
+
...(resource.required !== undefined ? { required: resource.required } : {}),
|
|
2893
|
+
...(resource.history !== undefined ? { history: resource.history } : {}),
|
|
2894
|
+
...(resource.ttlMs !== undefined ? { ttlMs: resource.ttlMs } : {}),
|
|
2895
|
+
...(resource.maxValueBytes !== undefined
|
|
2896
|
+
? { maxValueBytes: resource.maxValueBytes }
|
|
2897
|
+
: {}),
|
|
2898
|
+
};
|
|
2899
|
+
}
|
|
2900
|
+
|
|
2901
|
+
function storeResource(resource: ContractStoreResource): ContractStoreResource {
|
|
2902
|
+
return {
|
|
2903
|
+
purpose: resource.purpose,
|
|
2904
|
+
...(resource.required !== undefined ? { required: resource.required } : {}),
|
|
2905
|
+
...(resource.ttlMs !== undefined ? { ttlMs: resource.ttlMs } : {}),
|
|
2906
|
+
...(resource.maxObjectBytes !== undefined
|
|
2907
|
+
? { maxObjectBytes: resource.maxObjectBytes }
|
|
2908
|
+
: {}),
|
|
2909
|
+
...(resource.maxTotalBytes !== undefined
|
|
2910
|
+
? { maxTotalBytes: resource.maxTotalBytes }
|
|
2911
|
+
: {}),
|
|
2912
|
+
};
|
|
2913
|
+
}
|
|
2914
|
+
|
|
2915
|
+
/**
|
|
2916
|
+
* Return the canonical manifest shape used by Trellis runtimes before
|
|
2917
|
+
* validation, persistence, and digesting.
|
|
2918
|
+
*
|
|
2919
|
+
* This is not the digest projection: human-facing fields such as
|
|
2920
|
+
* `displayName` and `description` are preserved here even though they are not
|
|
2921
|
+
* part of contract identity. Unknown extension fields are intentionally omitted
|
|
2922
|
+
* until the runtime explicitly supports them.
|
|
2923
|
+
*/
|
|
2924
|
+
export function normalizeContractManifest(
|
|
2925
|
+
contract: TrellisContractV1,
|
|
2926
|
+
): TrellisContractV1 {
|
|
2927
|
+
return {
|
|
2928
|
+
format: contract.format,
|
|
2929
|
+
id: contract.id,
|
|
2930
|
+
displayName: contract.displayName,
|
|
2931
|
+
description: contract.description,
|
|
2932
|
+
kind: contract.kind,
|
|
2933
|
+
...(contract.capabilities
|
|
2934
|
+
? { capabilities: mapValues(contract.capabilities, capabilityMetadata) }
|
|
2935
|
+
: {}),
|
|
2936
|
+
...(contract.schemas ? { schemas: contract.schemas } : {}),
|
|
2937
|
+
...(contract.exports
|
|
2938
|
+
? {
|
|
2939
|
+
exports: {
|
|
2940
|
+
...(contract.exports.schemas
|
|
2941
|
+
? { schemas: [...contract.exports.schemas] }
|
|
2942
|
+
: {}),
|
|
2943
|
+
},
|
|
2944
|
+
}
|
|
2945
|
+
: {}),
|
|
2946
|
+
...(contract.uses ? { uses: contractUses(contract.uses) } : {}),
|
|
2947
|
+
...(contract.state ? { state: mapValues(contract.state, stateStore) } : {}),
|
|
2948
|
+
...(contract.rpc ? { rpc: mapValues(contract.rpc, rpcMethod) } : {}),
|
|
2949
|
+
...(contract.operations
|
|
2950
|
+
? { operations: mapValues(contract.operations, operation) }
|
|
2951
|
+
: {}),
|
|
2952
|
+
...(contract.events ? { events: mapValues(contract.events, event) } : {}),
|
|
2953
|
+
...(contract.feeds ? { feeds: mapValues(contract.feeds, feed) } : {}),
|
|
2954
|
+
...(contract.jobs ? { jobs: mapValues(contract.jobs, jobQueue) } : {}),
|
|
2955
|
+
...(contract.resources
|
|
2956
|
+
? {
|
|
2957
|
+
resources: {
|
|
2958
|
+
...(contract.resources.kv
|
|
2959
|
+
? { kv: mapValues(contract.resources.kv, kvResource) }
|
|
2960
|
+
: {}),
|
|
2961
|
+
...(contract.resources.store
|
|
2962
|
+
? { store: mapValues(contract.resources.store, storeResource) }
|
|
2963
|
+
: {}),
|
|
2964
|
+
},
|
|
2965
|
+
}
|
|
2966
|
+
: {}),
|
|
2967
|
+
...(contract.errors
|
|
2968
|
+
? { errors: mapValues(contract.errors, errorDecl) }
|
|
2969
|
+
: {}),
|
|
2970
|
+
};
|
|
2971
|
+
}
|
|
2972
|
+
|
|
2973
|
+
/**
|
|
2974
|
+
* Parse untrusted contract JSON into the current Trellis v1 manifest shape.
|
|
2975
|
+
*
|
|
2976
|
+
* Unknown extension fields are accepted for forward compatibility but are not
|
|
2977
|
+
* returned. Callers must use the returned value for persistence and digesting.
|
|
2978
|
+
*/
|
|
2979
|
+
export function parseContractManifest(value: unknown): TrellisContractV1 {
|
|
2980
|
+
try {
|
|
2981
|
+
return normalizeContractManifest(
|
|
2982
|
+
Value.Parse(TrellisContractV1Schema, value) as TrellisContractV1,
|
|
2983
|
+
);
|
|
2984
|
+
} catch (error) {
|
|
2985
|
+
const details = [...Value.Errors(TrellisContractV1Schema, value)].map((
|
|
2986
|
+
entry,
|
|
2987
|
+
) => `${entry.instancePath || "#"}: ${entry.message}`);
|
|
2988
|
+
throw new TypeError(
|
|
2989
|
+
`Invalid contract${details.length > 0 ? `:\n${details.join("\n")}` : ""}`,
|
|
2990
|
+
{ cause: error },
|
|
2991
|
+
);
|
|
2992
|
+
}
|
|
2993
|
+
}
|
|
2994
|
+
|
|
2995
|
+
/**
|
|
2996
|
+
* Build the normalized runtime/interface projection used for contract identity.
|
|
2997
|
+
*/
|
|
2998
|
+
export function projectContractDigestManifest(
|
|
2999
|
+
contract: TrellisContractV1,
|
|
3000
|
+
): JsonValue {
|
|
3001
|
+
const schemas = projectReachableSchemas(contract);
|
|
3002
|
+
const errors = projectRpcDeclaredErrors(contract);
|
|
3003
|
+
const resources = projectDigestResources(contract.resources);
|
|
3004
|
+
const uses = projectDigestUses(contract.uses);
|
|
3005
|
+
const rpc = projectDigestRpc(contract.rpc);
|
|
3006
|
+
const operations = projectDigestOperations(contract.operations);
|
|
3007
|
+
const events = projectDigestEvents(contract.events);
|
|
3008
|
+
const feeds = projectDigestFeeds(contract.feeds);
|
|
3009
|
+
|
|
3010
|
+
return {
|
|
3011
|
+
format: contract.format,
|
|
3012
|
+
id: contract.id,
|
|
3013
|
+
kind: contract.kind,
|
|
3014
|
+
...(contract.capabilities ? { capabilities: contract.capabilities } : {}),
|
|
3015
|
+
...(schemas ? { schemas } : {}),
|
|
3016
|
+
...(contract.state ? { state: contract.state } : {}),
|
|
3017
|
+
...(uses ? { uses } : {}),
|
|
3018
|
+
...(rpc ? { rpc } : {}),
|
|
3019
|
+
...(operations ? { operations } : {}),
|
|
3020
|
+
...(events ? { events } : {}),
|
|
3021
|
+
...(feeds ? { feeds } : {}),
|
|
3022
|
+
...(errors ? { errors } : {}),
|
|
3023
|
+
...(contract.jobs ? { jobs: contract.jobs } : {}),
|
|
3024
|
+
...(resources ? { resources } : {}),
|
|
3025
|
+
};
|
|
3026
|
+
}
|
|
3027
|
+
|
|
3028
|
+
/** Compute the v1 contract digest from the normalized digest projection. */
|
|
3029
|
+
export function digestContractManifest(contract: TrellisContractV1): string {
|
|
3030
|
+
return digestCanonicalJson(
|
|
3031
|
+
projectContractDigestManifest(normalizeContractManifest(contract)),
|
|
3032
|
+
);
|
|
3033
|
+
}
|
|
3034
|
+
|
|
3035
|
+
function rpcSubject(name: string, version: `v${number}`): string {
|
|
3036
|
+
return `rpc.${version}.${name}`;
|
|
3037
|
+
}
|
|
3038
|
+
|
|
3039
|
+
function operationSubject(name: string, version: `v${number}`): string {
|
|
3040
|
+
return `operations.${version}.${name}`;
|
|
3041
|
+
}
|
|
3042
|
+
|
|
3043
|
+
function feedSubject(name: string, version: `v${number}`): string {
|
|
3044
|
+
return `feeds.${version}.${name}`;
|
|
3045
|
+
}
|
|
3046
|
+
|
|
3047
|
+
function eventSubject(
|
|
3048
|
+
name: string,
|
|
3049
|
+
version: `v${number}`,
|
|
3050
|
+
params: readonly SubjectParam[] | undefined,
|
|
3051
|
+
): string {
|
|
3052
|
+
const suffix = params && params.length > 0
|
|
3053
|
+
? `.${params.map((pointer) => `{${pointer}}`).join(".")}`
|
|
3054
|
+
: "";
|
|
3055
|
+
return `events.${version}.${name}${suffix}`;
|
|
3056
|
+
}
|
|
3057
|
+
|
|
3058
|
+
function emitResources(
|
|
3059
|
+
resources: ContractSourceResources | undefined,
|
|
3060
|
+
): ContractResources | undefined {
|
|
3061
|
+
if (!resources?.kv && !resources?.store) {
|
|
3062
|
+
return undefined;
|
|
3063
|
+
}
|
|
3064
|
+
|
|
3065
|
+
return {
|
|
3066
|
+
...(resources.kv
|
|
3067
|
+
? {
|
|
3068
|
+
kv: Object.fromEntries(
|
|
3069
|
+
Object.entries(resources.kv).map(([alias, resource]) => [
|
|
3070
|
+
alias,
|
|
3071
|
+
{
|
|
3072
|
+
purpose: resource.purpose,
|
|
3073
|
+
schema: { ...resource.schema },
|
|
3074
|
+
required: resource.required ?? true,
|
|
3075
|
+
history: resource.history ?? 1,
|
|
3076
|
+
ttlMs: resource.ttlMs ?? 0,
|
|
3077
|
+
...(resource.maxValueBytes
|
|
3078
|
+
? { maxValueBytes: resource.maxValueBytes }
|
|
3079
|
+
: {}),
|
|
3080
|
+
} satisfies ContractKvResource,
|
|
3081
|
+
]),
|
|
3082
|
+
),
|
|
3083
|
+
}
|
|
3084
|
+
: {}),
|
|
3085
|
+
...(resources.store
|
|
3086
|
+
? {
|
|
3087
|
+
store: Object.fromEntries(
|
|
3088
|
+
Object.entries(resources.store).map(([alias, resource]) => [
|
|
3089
|
+
alias,
|
|
3090
|
+
{
|
|
3091
|
+
purpose: resource.purpose,
|
|
3092
|
+
required: resource.required ?? true,
|
|
3093
|
+
ttlMs: resource.ttlMs ?? 0,
|
|
3094
|
+
...(resource.maxObjectBytes !== undefined
|
|
3095
|
+
? { maxObjectBytes: resource.maxObjectBytes }
|
|
3096
|
+
: {}),
|
|
3097
|
+
...(resource.maxTotalBytes !== undefined
|
|
3098
|
+
? { maxTotalBytes: resource.maxTotalBytes }
|
|
3099
|
+
: {}),
|
|
3100
|
+
} satisfies ContractStoreResource,
|
|
3101
|
+
]),
|
|
3102
|
+
),
|
|
3103
|
+
}
|
|
3104
|
+
: {}),
|
|
3105
|
+
};
|
|
3106
|
+
}
|
|
3107
|
+
|
|
3108
|
+
function emitJobs(
|
|
3109
|
+
jobs: ContractSourceJobs | undefined,
|
|
3110
|
+
): ContractJobs | undefined {
|
|
3111
|
+
if (!jobs) {
|
|
3112
|
+
return undefined;
|
|
3113
|
+
}
|
|
3114
|
+
|
|
3115
|
+
return Object.fromEntries(
|
|
3116
|
+
Object.entries(jobs).map(([queueType, queue]) => [
|
|
3117
|
+
queueType,
|
|
3118
|
+
{
|
|
3119
|
+
payload: { ...queue.payload },
|
|
3120
|
+
...(queue.result ? { result: { ...queue.result } } : {}),
|
|
3121
|
+
...(queue.maxDeliver !== undefined
|
|
3122
|
+
? { maxDeliver: queue.maxDeliver }
|
|
3123
|
+
: {}),
|
|
3124
|
+
...(queue.backoffMs ? { backoffMs: [...queue.backoffMs] } : {}),
|
|
3125
|
+
...(queue.ackWaitMs !== undefined
|
|
3126
|
+
? { ackWaitMs: queue.ackWaitMs }
|
|
3127
|
+
: {}),
|
|
3128
|
+
...(queue.defaultDeadlineMs !== undefined
|
|
3129
|
+
? { defaultDeadlineMs: queue.defaultDeadlineMs }
|
|
3130
|
+
: {}),
|
|
3131
|
+
...(queue.progress !== undefined ? { progress: queue.progress } : {}),
|
|
3132
|
+
...(queue.logs !== undefined ? { logs: queue.logs } : {}),
|
|
3133
|
+
...(queue.dlq !== undefined ? { dlq: queue.dlq } : {}),
|
|
3134
|
+
...(queue.concurrency !== undefined
|
|
3135
|
+
? { concurrency: queue.concurrency }
|
|
3136
|
+
: {}),
|
|
3137
|
+
} satisfies ContractJobQueue,
|
|
3138
|
+
]),
|
|
3139
|
+
);
|
|
3140
|
+
}
|
|
3141
|
+
|
|
3142
|
+
function buildContractJobsMetadata(
|
|
3143
|
+
jobs: ContractSourceJobs | undefined,
|
|
3144
|
+
): ContractJobsMetadata {
|
|
3145
|
+
if (!jobs) {
|
|
3146
|
+
return {};
|
|
3147
|
+
}
|
|
3148
|
+
|
|
3149
|
+
return Object.fromEntries(
|
|
3150
|
+
Object.keys(jobs).map((queueType) => [queueType, {
|
|
3151
|
+
payload: undefined,
|
|
3152
|
+
result: undefined,
|
|
3153
|
+
}]),
|
|
3154
|
+
) as ContractJobsMetadata;
|
|
3155
|
+
}
|
|
3156
|
+
|
|
3157
|
+
function buildContractKvMetadata(
|
|
3158
|
+
resources: ContractSourceResources | undefined,
|
|
3159
|
+
schemas: ContractSourceSchemas | undefined,
|
|
3160
|
+
): ContractKvMetadata {
|
|
3161
|
+
const kv = resources?.kv;
|
|
3162
|
+
if (!kv) {
|
|
3163
|
+
return {};
|
|
3164
|
+
}
|
|
3165
|
+
|
|
3166
|
+
const metadata: ContractKvMetadata = {};
|
|
3167
|
+
for (const [alias, resource] of Object.entries(kv)) {
|
|
3168
|
+
assertSchemaRefExists(schemas, resource.schema, `kv resource '${alias}'`);
|
|
3169
|
+
const schema = schemas?.[resource.schema.schema];
|
|
3170
|
+
if (!schema) {
|
|
3171
|
+
throw new Error(
|
|
3172
|
+
`kv resource '${alias}' references missing schema '${resource.schema.schema}'`,
|
|
3173
|
+
);
|
|
3174
|
+
}
|
|
3175
|
+
metadata[alias] = {
|
|
3176
|
+
required: resource.required ?? true,
|
|
3177
|
+
value: undefined,
|
|
3178
|
+
schema,
|
|
3179
|
+
};
|
|
3180
|
+
}
|
|
3181
|
+
return metadata;
|
|
3182
|
+
}
|
|
3183
|
+
|
|
3184
|
+
function buildContractStateMetadata(
|
|
3185
|
+
state: ContractSourceState | undefined,
|
|
3186
|
+
schemas: ContractSourceSchemas | undefined,
|
|
3187
|
+
): ContractStateMetadata {
|
|
3188
|
+
if (!state) {
|
|
3189
|
+
return {};
|
|
3190
|
+
}
|
|
3191
|
+
|
|
3192
|
+
return Object.fromEntries(
|
|
3193
|
+
Object.entries(state).map(([storeName, store]) => [storeName, {
|
|
3194
|
+
kind: store.kind,
|
|
3195
|
+
value: undefined,
|
|
3196
|
+
schema: resolveSchemaRef(
|
|
3197
|
+
schemas,
|
|
3198
|
+
store.schema,
|
|
3199
|
+
`state store '${storeName}'`,
|
|
3200
|
+
),
|
|
3201
|
+
stateVersion: store.stateVersion ?? "v1",
|
|
3202
|
+
acceptedVersions: Object.fromEntries(
|
|
3203
|
+
Object.entries(store.acceptedVersions ?? {}).map((
|
|
3204
|
+
[version, schema],
|
|
3205
|
+
) => [
|
|
3206
|
+
version,
|
|
3207
|
+
resolveSchemaRef(
|
|
3208
|
+
schemas,
|
|
3209
|
+
schema,
|
|
3210
|
+
`state store '${storeName}' accepted version '${version}'`,
|
|
3211
|
+
),
|
|
3212
|
+
]),
|
|
3213
|
+
),
|
|
3214
|
+
}]),
|
|
3215
|
+
) as ContractStateMetadata;
|
|
3216
|
+
}
|
|
3217
|
+
|
|
3218
|
+
function emitState(
|
|
3219
|
+
state: ContractSourceState | undefined,
|
|
3220
|
+
): ContractState | undefined {
|
|
3221
|
+
if (!state) {
|
|
3222
|
+
return undefined;
|
|
3223
|
+
}
|
|
3224
|
+
|
|
3225
|
+
return Object.fromEntries(
|
|
3226
|
+
Object.entries(state).map(([storeName, store]) => [
|
|
3227
|
+
storeName,
|
|
3228
|
+
{
|
|
3229
|
+
kind: store.kind,
|
|
3230
|
+
schema: { ...store.schema },
|
|
3231
|
+
...(store.stateVersion === undefined
|
|
3232
|
+
? {}
|
|
3233
|
+
: { stateVersion: store.stateVersion }),
|
|
3234
|
+
...(store.acceptedVersions === undefined
|
|
3235
|
+
? {}
|
|
3236
|
+
: { acceptedVersions: store.acceptedVersions }),
|
|
3237
|
+
} satisfies ContractStateStore,
|
|
3238
|
+
]),
|
|
3239
|
+
);
|
|
3240
|
+
}
|
|
3241
|
+
|
|
3242
|
+
function emitUsesFlat(
|
|
3243
|
+
uses: ContractSourceUsesFlat | undefined,
|
|
3244
|
+
): ContractUsesFlat | undefined {
|
|
3245
|
+
if (!uses) {
|
|
3246
|
+
return undefined;
|
|
3247
|
+
}
|
|
3248
|
+
|
|
3249
|
+
return Object.fromEntries(
|
|
3250
|
+
Object.entries(uses).map(([alias, use]) => [
|
|
3251
|
+
alias,
|
|
3252
|
+
{
|
|
3253
|
+
contract: use.contract,
|
|
3254
|
+
...(use.rpc?.call ? { rpc: { call: sortedUnique(use.rpc.call) } } : {}),
|
|
3255
|
+
...(use.operations?.call
|
|
3256
|
+
? { operations: { call: sortedUnique(use.operations.call) } }
|
|
3257
|
+
: {}),
|
|
3258
|
+
...((use.events?.publish || use.events?.subscribe)
|
|
3259
|
+
? {
|
|
3260
|
+
events: {
|
|
3261
|
+
...(use.events.publish
|
|
3262
|
+
? { publish: sortedUnique(use.events.publish) }
|
|
3263
|
+
: {}),
|
|
3264
|
+
...(use.events.subscribe
|
|
3265
|
+
? { subscribe: sortedUnique(use.events.subscribe) }
|
|
3266
|
+
: {}),
|
|
3267
|
+
},
|
|
3268
|
+
}
|
|
3269
|
+
: {}),
|
|
3270
|
+
...(use.feeds?.subscribe
|
|
3271
|
+
? { feeds: { subscribe: sortedUnique(use.feeds.subscribe) } }
|
|
3272
|
+
: {}),
|
|
3273
|
+
} satisfies ContractUse,
|
|
3274
|
+
]),
|
|
3275
|
+
);
|
|
3276
|
+
}
|
|
3277
|
+
|
|
3278
|
+
function emitUses(
|
|
3279
|
+
uses: ContractSourceUses | undefined,
|
|
3280
|
+
): ContractUses | undefined {
|
|
3281
|
+
if (!uses) {
|
|
3282
|
+
return undefined;
|
|
3283
|
+
}
|
|
3284
|
+
|
|
3285
|
+
const required = emitUsesFlat(uses.required);
|
|
3286
|
+
const optional = omitRequiredUseAliases(
|
|
3287
|
+
emitUsesFlat(uses.optional),
|
|
3288
|
+
required,
|
|
3289
|
+
);
|
|
3290
|
+
if (!required && !optional) {
|
|
3291
|
+
return undefined;
|
|
3292
|
+
}
|
|
3293
|
+
return {
|
|
3294
|
+
...(required ? { required } : {}),
|
|
3295
|
+
...(optional ? { optional } : {}),
|
|
3296
|
+
};
|
|
3297
|
+
}
|
|
3298
|
+
|
|
3299
|
+
function emitContract(source: TrellisContractSource): TrellisContractV1 {
|
|
3300
|
+
const capabilities = emitCapabilities(source.id, source.capabilities);
|
|
3301
|
+
const rpc = source.rpc
|
|
3302
|
+
? Object.fromEntries(
|
|
3303
|
+
Object.entries(source.rpc).map(([name, method]) => {
|
|
3304
|
+
const emitted: ContractRpcMethod = {
|
|
3305
|
+
version: method.version,
|
|
3306
|
+
subject: method.subject ?? rpcSubject(name, method.version),
|
|
3307
|
+
input: { ...method.input },
|
|
3308
|
+
output: { ...method.output },
|
|
3309
|
+
};
|
|
3310
|
+
if (method.capabilities?.call) {
|
|
3311
|
+
emitted.capabilities = {
|
|
3312
|
+
call: projectCapabilities(
|
|
3313
|
+
method.capabilities.call,
|
|
3314
|
+
source.id,
|
|
3315
|
+
source.capabilities,
|
|
3316
|
+
`rpc '${name}' call capabilities`,
|
|
3317
|
+
) ?? [],
|
|
3318
|
+
};
|
|
3319
|
+
}
|
|
3320
|
+
if (method.transfer) {
|
|
3321
|
+
emitted.transfer = { ...method.transfer };
|
|
3322
|
+
}
|
|
3323
|
+
if (method.errors && method.errors.length > 0) {
|
|
3324
|
+
emitted.errors = sortedUnique(
|
|
3325
|
+
method.errors.map((errorName) =>
|
|
3326
|
+
source.errors?.[errorName]?.type ?? errorName
|
|
3327
|
+
),
|
|
3328
|
+
).map((type) => ({ type }));
|
|
3329
|
+
}
|
|
3330
|
+
return [name, emitted];
|
|
3331
|
+
}),
|
|
3332
|
+
)
|
|
3333
|
+
: undefined;
|
|
3334
|
+
|
|
3335
|
+
const operations = source.operations
|
|
3336
|
+
? Object.fromEntries(
|
|
3337
|
+
Object.entries(source.operations).map(([name, operation]) => {
|
|
3338
|
+
if (operation.transfer) {
|
|
3339
|
+
const store = source.resources?.store?.[operation.transfer.store];
|
|
3340
|
+
if (!store) {
|
|
3341
|
+
throw new Error(
|
|
3342
|
+
`Operation '${name}' references unknown store resource '${operation.transfer.store}'`,
|
|
3343
|
+
);
|
|
3344
|
+
}
|
|
3345
|
+
|
|
3346
|
+
const inputSchema = resolveSchemaRef(
|
|
3347
|
+
source.schemas,
|
|
3348
|
+
operation.input,
|
|
3349
|
+
`operation '${name}' input`,
|
|
3350
|
+
);
|
|
3351
|
+
for (
|
|
3352
|
+
const pointer of [
|
|
3353
|
+
operation.transfer.key,
|
|
3354
|
+
operation.transfer.contentType,
|
|
3355
|
+
operation.transfer.metadata,
|
|
3356
|
+
]
|
|
3357
|
+
) {
|
|
3358
|
+
if (!pointer) {
|
|
3359
|
+
continue;
|
|
3360
|
+
}
|
|
3361
|
+
if (getSubschemaAtDataPointer(inputSchema, pointer) === undefined) {
|
|
3362
|
+
throw new Error(
|
|
3363
|
+
`Invalid transfer pointer '${pointer}' for operation '${name}' (path not found in input schema)`,
|
|
3364
|
+
);
|
|
3365
|
+
}
|
|
3366
|
+
}
|
|
3367
|
+
}
|
|
3368
|
+
|
|
3369
|
+
const emitted: ContractOperation = {
|
|
3370
|
+
version: operation.version,
|
|
3371
|
+
subject: operation.subject ??
|
|
3372
|
+
operationSubject(name, operation.version),
|
|
3373
|
+
input: { ...operation.input },
|
|
3374
|
+
output: { ...operation.output },
|
|
3375
|
+
};
|
|
3376
|
+
if (operation.progress) {
|
|
3377
|
+
emitted.progress = { ...operation.progress };
|
|
3378
|
+
}
|
|
3379
|
+
if (operation.transfer) {
|
|
3380
|
+
emitted.transfer = { ...operation.transfer, direction: "send" };
|
|
3381
|
+
}
|
|
3382
|
+
if (
|
|
3383
|
+
operation.capabilities?.call || operation.capabilities?.read ||
|
|
3384
|
+
operation.capabilities?.cancel || operation.capabilities?.control
|
|
3385
|
+
) {
|
|
3386
|
+
emitted.capabilities = {
|
|
3387
|
+
...(operation.capabilities.call
|
|
3388
|
+
? {
|
|
3389
|
+
call: projectCapabilities(
|
|
3390
|
+
operation.capabilities.call,
|
|
3391
|
+
source.id,
|
|
3392
|
+
source.capabilities,
|
|
3393
|
+
`operation '${name}' call capabilities`,
|
|
3394
|
+
) ?? [],
|
|
3395
|
+
}
|
|
3396
|
+
: {}),
|
|
3397
|
+
...(operation.capabilities.read
|
|
3398
|
+
? {
|
|
3399
|
+
read: projectCapabilities(
|
|
3400
|
+
operation.capabilities.read,
|
|
3401
|
+
source.id,
|
|
3402
|
+
source.capabilities,
|
|
3403
|
+
`operation '${name}' read capabilities`,
|
|
3404
|
+
) ?? [],
|
|
3405
|
+
}
|
|
3406
|
+
: {}),
|
|
3407
|
+
...(operation.capabilities.cancel
|
|
3408
|
+
? {
|
|
3409
|
+
cancel: projectCapabilities(
|
|
3410
|
+
operation.capabilities.cancel,
|
|
3411
|
+
source.id,
|
|
3412
|
+
source.capabilities,
|
|
3413
|
+
`operation '${name}' cancel capabilities`,
|
|
3414
|
+
) ?? [],
|
|
3415
|
+
}
|
|
3416
|
+
: {}),
|
|
3417
|
+
...(operation.capabilities.control
|
|
3418
|
+
? {
|
|
3419
|
+
control: projectCapabilities(
|
|
3420
|
+
operation.capabilities.control,
|
|
3421
|
+
source.id,
|
|
3422
|
+
source.capabilities,
|
|
3423
|
+
`operation '${name}' control capabilities`,
|
|
3424
|
+
) ?? [],
|
|
3425
|
+
}
|
|
3426
|
+
: {}),
|
|
3427
|
+
};
|
|
3428
|
+
}
|
|
3429
|
+
if (operation.signals) {
|
|
3430
|
+
emitted.signals = Object.fromEntries(
|
|
3431
|
+
Object.entries(operation.signals).map(([signalName, signal]) => [
|
|
3432
|
+
signalName,
|
|
3433
|
+
{ input: { ...signal.input } },
|
|
3434
|
+
]),
|
|
3435
|
+
);
|
|
3436
|
+
}
|
|
3437
|
+
if (operation.cancel !== undefined) {
|
|
3438
|
+
emitted.cancel = operation.cancel;
|
|
3439
|
+
}
|
|
3440
|
+
return [name, emitted];
|
|
3441
|
+
}),
|
|
3442
|
+
)
|
|
3443
|
+
: undefined;
|
|
3444
|
+
|
|
3445
|
+
const events = source.events
|
|
3446
|
+
? Object.fromEntries(
|
|
3447
|
+
Object.entries(source.events).map(([name, event]) => {
|
|
3448
|
+
if (event.params && event.params.length > 0) {
|
|
3449
|
+
assertDataPointersExistAndAreTokenable(
|
|
3450
|
+
name,
|
|
3451
|
+
resolveSchemaRef(source.schemas, event.event, `event '${name}'`),
|
|
3452
|
+
event.params,
|
|
3453
|
+
);
|
|
3454
|
+
}
|
|
3455
|
+
|
|
3456
|
+
const emitted: ContractEvent = {
|
|
3457
|
+
version: event.version,
|
|
3458
|
+
subject: event.subject ??
|
|
3459
|
+
eventSubject(name, event.version, event.params),
|
|
3460
|
+
event: { ...event.event },
|
|
3461
|
+
};
|
|
3462
|
+
if (event.params && event.params.length > 0) {
|
|
3463
|
+
emitted.params = [...event.params];
|
|
3464
|
+
}
|
|
3465
|
+
if (event.capabilities?.publish || event.capabilities?.subscribe) {
|
|
3466
|
+
emitted.capabilities = {
|
|
3467
|
+
...(event.capabilities.publish
|
|
3468
|
+
? {
|
|
3469
|
+
publish: projectCapabilities(
|
|
3470
|
+
event.capabilities.publish,
|
|
3471
|
+
source.id,
|
|
3472
|
+
source.capabilities,
|
|
3473
|
+
`event '${name}' publish capabilities`,
|
|
3474
|
+
) ?? [],
|
|
3475
|
+
}
|
|
3476
|
+
: {}),
|
|
3477
|
+
...(event.capabilities.subscribe
|
|
3478
|
+
? {
|
|
3479
|
+
subscribe: projectCapabilities(
|
|
3480
|
+
event.capabilities.subscribe,
|
|
3481
|
+
source.id,
|
|
3482
|
+
source.capabilities,
|
|
3483
|
+
`event '${name}' subscribe capabilities`,
|
|
3484
|
+
) ?? [],
|
|
3485
|
+
}
|
|
3486
|
+
: {}),
|
|
3487
|
+
};
|
|
3488
|
+
}
|
|
3489
|
+
|
|
3490
|
+
return [name, emitted];
|
|
3491
|
+
}),
|
|
3492
|
+
)
|
|
3493
|
+
: undefined;
|
|
3494
|
+
|
|
3495
|
+
const feeds = source.feeds
|
|
3496
|
+
? Object.fromEntries(
|
|
3497
|
+
Object.entries(source.feeds).map(([name, feed]) => {
|
|
3498
|
+
const emitted: ContractFeed = {
|
|
3499
|
+
version: feed.version,
|
|
3500
|
+
subject: feed.subject ?? feedSubject(name, feed.version),
|
|
3501
|
+
input: { ...feed.input },
|
|
3502
|
+
event: { ...feed.event },
|
|
3503
|
+
};
|
|
3504
|
+
if (feed.capabilities?.subscribe) {
|
|
3505
|
+
emitted.capabilities = {
|
|
3506
|
+
subscribe: projectCapabilities(
|
|
3507
|
+
feed.capabilities.subscribe,
|
|
3508
|
+
source.id,
|
|
3509
|
+
source.capabilities,
|
|
3510
|
+
`feed '${name}' subscribe capabilities`,
|
|
3511
|
+
) ?? [],
|
|
3512
|
+
};
|
|
3513
|
+
}
|
|
3514
|
+
return [name, emitted];
|
|
3515
|
+
}),
|
|
3516
|
+
)
|
|
3517
|
+
: undefined;
|
|
3518
|
+
|
|
3519
|
+
const errors = source.errors
|
|
3520
|
+
? Object.fromEntries(
|
|
3521
|
+
Object.entries(source.errors).map(([name, error]) => {
|
|
3522
|
+
const emitted: ContractErrorDecl = { type: error.type };
|
|
3523
|
+
const schemaRef = resolveErrorSchemaRef(source.schemas, name, error);
|
|
3524
|
+
if (schemaRef) {
|
|
3525
|
+
emitted.schema = { ...schemaRef };
|
|
3526
|
+
}
|
|
3527
|
+
return [name, emitted];
|
|
3528
|
+
}),
|
|
3529
|
+
)
|
|
3530
|
+
: undefined;
|
|
3531
|
+
|
|
3532
|
+
const jobs = emitJobs(source.jobs);
|
|
3533
|
+
const state = emitState(source.state);
|
|
3534
|
+
const resources = emitResources(source.resources);
|
|
3535
|
+
const uses = emitUses(source.uses);
|
|
3536
|
+
|
|
3537
|
+
return {
|
|
3538
|
+
format: CONTRACT_FORMAT_V1,
|
|
3539
|
+
id: source.id,
|
|
3540
|
+
displayName: source.displayName,
|
|
3541
|
+
description: source.description,
|
|
3542
|
+
kind: source.kind,
|
|
3543
|
+
...(capabilities ? { capabilities } : {}),
|
|
3544
|
+
...(source.schemas ? { schemas: cloneSchemas(source.schemas) } : {}),
|
|
3545
|
+
...(source.exports
|
|
3546
|
+
? { exports: cloneContractExports(source.exports) }
|
|
3547
|
+
: {}),
|
|
3548
|
+
...(state ? { state } : {}),
|
|
3549
|
+
...(uses ? { uses } : {}),
|
|
3550
|
+
...(rpc ? { rpc } : {}),
|
|
3551
|
+
...(operations ? { operations } : {}),
|
|
3552
|
+
...(events ? { events } : {}),
|
|
3553
|
+
...(feeds ? { feeds } : {}),
|
|
3554
|
+
...(errors ? { errors } : {}),
|
|
3555
|
+
...(jobs ? { jobs } : {}),
|
|
3556
|
+
...(resources ? { resources } : {}),
|
|
3557
|
+
};
|
|
3558
|
+
}
|
|
3559
|
+
|
|
3560
|
+
function buildOwnedApi(source: TrellisContractSource): ApiShape {
|
|
3561
|
+
const localRuntimeErrors: Record<string, BuiltRuntimeErrorDesc> = {};
|
|
3562
|
+
for (const [name, errorDecl] of Object.entries(source.errors ?? {})) {
|
|
3563
|
+
const errorClass = getContractErrorRuntimeClass(errorDecl);
|
|
3564
|
+
if (!errorClass) {
|
|
3565
|
+
continue;
|
|
3566
|
+
}
|
|
3567
|
+
|
|
3568
|
+
const errorSchemaRef = resolveErrorSchemaRef(
|
|
3569
|
+
source.schemas,
|
|
3570
|
+
name,
|
|
3571
|
+
errorDecl,
|
|
3572
|
+
);
|
|
3573
|
+
localRuntimeErrors[name] = {
|
|
3574
|
+
type: errorDecl.type,
|
|
3575
|
+
...(errorSchemaRef
|
|
3576
|
+
? {
|
|
3577
|
+
schema: schema(
|
|
3578
|
+
resolveSchemaRef(
|
|
3579
|
+
source.schemas,
|
|
3580
|
+
errorSchemaRef,
|
|
3581
|
+
`error '${name}' schema`,
|
|
3582
|
+
),
|
|
3583
|
+
),
|
|
3584
|
+
}
|
|
3585
|
+
: {}),
|
|
3586
|
+
fromSerializable(data: SerializableErrorData) {
|
|
3587
|
+
if (!isSerializableErrorData(data)) {
|
|
3588
|
+
throw new Error(
|
|
3589
|
+
`Transport error '${errorDecl.type}' is missing base error fields`,
|
|
3590
|
+
);
|
|
3591
|
+
}
|
|
3592
|
+
return errorClass.fromSerializable(data);
|
|
3593
|
+
},
|
|
3594
|
+
};
|
|
3595
|
+
}
|
|
3596
|
+
|
|
3597
|
+
const rpc: Record<string, BuiltRpcDesc> = {};
|
|
3598
|
+
for (const [name, method] of Object.entries(source.rpc ?? {})) {
|
|
3599
|
+
rpc[name] = {
|
|
3600
|
+
subject: method.subject ?? rpcSubject(name, method.version),
|
|
3601
|
+
input: schema(
|
|
3602
|
+
resolveSchemaRef(source.schemas, method.input, `rpc '${name}' input`),
|
|
3603
|
+
),
|
|
3604
|
+
output: schema(
|
|
3605
|
+
resolveSchemaRef(
|
|
3606
|
+
source.schemas,
|
|
3607
|
+
method.output,
|
|
3608
|
+
`rpc '${name}' output`,
|
|
3609
|
+
),
|
|
3610
|
+
),
|
|
3611
|
+
callerCapabilities: projectCapabilities(
|
|
3612
|
+
method.capabilities?.call,
|
|
3613
|
+
source.id,
|
|
3614
|
+
source.capabilities,
|
|
3615
|
+
`rpc '${name}' call capabilities`,
|
|
3616
|
+
) ?? [],
|
|
3617
|
+
transfer: method.transfer ? { ...method.transfer } : undefined,
|
|
3618
|
+
authRequired: method.authRequired ?? true,
|
|
3619
|
+
errors: method.errors,
|
|
3620
|
+
declaredErrorTypes: method.errors?.map((errorName) =>
|
|
3621
|
+
source.errors?.[errorName]?.type ?? errorName
|
|
3622
|
+
),
|
|
3623
|
+
runtimeErrors: method.errors?.flatMap((errorName) => {
|
|
3624
|
+
const runtimeError = localRuntimeErrors[errorName];
|
|
3625
|
+
return runtimeError ? [runtimeError] : [];
|
|
3626
|
+
}),
|
|
3627
|
+
};
|
|
3628
|
+
}
|
|
3629
|
+
|
|
3630
|
+
const operations = Object.fromEntries(
|
|
3631
|
+
Object.entries(source.operations ?? {}).map(([name, operation]) => [
|
|
3632
|
+
name,
|
|
3633
|
+
{
|
|
3634
|
+
subject: operation.subject ?? operationSubject(name, operation.version),
|
|
3635
|
+
input: schema(
|
|
3636
|
+
resolveSchemaRef(
|
|
3637
|
+
source.schemas,
|
|
3638
|
+
operation.input,
|
|
3639
|
+
`operation '${name}' input`,
|
|
3640
|
+
),
|
|
3641
|
+
),
|
|
3642
|
+
progress: operation.progress
|
|
3643
|
+
? schema(
|
|
3644
|
+
resolveSchemaRef(
|
|
3645
|
+
source.schemas,
|
|
3646
|
+
operation.progress,
|
|
3647
|
+
`operation '${name}' progress`,
|
|
3648
|
+
),
|
|
3649
|
+
)
|
|
3650
|
+
: undefined,
|
|
3651
|
+
output: operation.output
|
|
3652
|
+
? schema(
|
|
3653
|
+
resolveSchemaRef(
|
|
3654
|
+
source.schemas,
|
|
3655
|
+
operation.output,
|
|
3656
|
+
`operation '${name}' output`,
|
|
3657
|
+
),
|
|
3658
|
+
)
|
|
3659
|
+
: undefined,
|
|
3660
|
+
transfer: operation.transfer
|
|
3661
|
+
? { ...operation.transfer, direction: "send" }
|
|
3662
|
+
: undefined,
|
|
3663
|
+
signals: operation.signals
|
|
3664
|
+
? Object.fromEntries(
|
|
3665
|
+
Object.entries(operation.signals).map(([signalName, signal]) => [
|
|
3666
|
+
signalName,
|
|
3667
|
+
{
|
|
3668
|
+
input: schema(
|
|
3669
|
+
resolveSchemaRef(
|
|
3670
|
+
source.schemas,
|
|
3671
|
+
signal.input,
|
|
3672
|
+
`operation '${name}' signal '${signalName}' input`,
|
|
3673
|
+
),
|
|
3674
|
+
),
|
|
3675
|
+
},
|
|
3676
|
+
]),
|
|
3677
|
+
)
|
|
3678
|
+
: undefined,
|
|
3679
|
+
callerCapabilities: projectCapabilities(
|
|
3680
|
+
operation.capabilities?.call,
|
|
3681
|
+
source.id,
|
|
3682
|
+
source.capabilities,
|
|
3683
|
+
`operation '${name}' call capabilities`,
|
|
3684
|
+
) ?? [],
|
|
3685
|
+
readCapabilities: projectCapabilities(
|
|
3686
|
+
operation.capabilities?.read,
|
|
3687
|
+
source.id,
|
|
3688
|
+
source.capabilities,
|
|
3689
|
+
`operation '${name}' read capabilities`,
|
|
3690
|
+
) ?? [],
|
|
3691
|
+
cancelCapabilities: projectCapabilities(
|
|
3692
|
+
operation.capabilities?.cancel,
|
|
3693
|
+
source.id,
|
|
3694
|
+
source.capabilities,
|
|
3695
|
+
`operation '${name}' cancel capabilities`,
|
|
3696
|
+
) ?? [],
|
|
3697
|
+
controlCapabilities: projectCapabilities(
|
|
3698
|
+
operation.capabilities?.control,
|
|
3699
|
+
source.id,
|
|
3700
|
+
source.capabilities,
|
|
3701
|
+
`operation '${name}' control capabilities`,
|
|
3702
|
+
) ?? [],
|
|
3703
|
+
cancel: operation.cancel,
|
|
3704
|
+
},
|
|
3705
|
+
]),
|
|
3706
|
+
) as Record<string, OperationDesc>;
|
|
3707
|
+
|
|
3708
|
+
const events = Object.fromEntries(
|
|
3709
|
+
Object.entries(source.events ?? {}).map(([name, event]) => {
|
|
3710
|
+
if (event.params && event.params.length > 0) {
|
|
3711
|
+
assertDataPointersExistAndAreTokenable(
|
|
3712
|
+
name,
|
|
3713
|
+
resolveSchemaRef(source.schemas, event.event, `event '${name}'`),
|
|
3714
|
+
event.params,
|
|
3715
|
+
);
|
|
3716
|
+
}
|
|
3717
|
+
|
|
3718
|
+
return [
|
|
3719
|
+
name,
|
|
3720
|
+
{
|
|
3721
|
+
subject: event.subject ??
|
|
3722
|
+
eventSubject(name, event.version, event.params),
|
|
3723
|
+
params: event.params,
|
|
3724
|
+
event: schema(
|
|
3725
|
+
resolveSchemaRef(source.schemas, event.event, `event '${name}'`),
|
|
3726
|
+
),
|
|
3727
|
+
publishCapabilities: projectCapabilities(
|
|
3728
|
+
event.capabilities?.publish,
|
|
3729
|
+
source.id,
|
|
3730
|
+
source.capabilities,
|
|
3731
|
+
`event '${name}' publish capabilities`,
|
|
3732
|
+
) ?? [],
|
|
3733
|
+
subscribeCapabilities: projectCapabilities(
|
|
3734
|
+
event.capabilities?.subscribe,
|
|
3735
|
+
source.id,
|
|
3736
|
+
source.capabilities,
|
|
3737
|
+
`event '${name}' subscribe capabilities`,
|
|
3738
|
+
) ?? [],
|
|
3739
|
+
},
|
|
3740
|
+
];
|
|
3741
|
+
}),
|
|
3742
|
+
) as Record<string, EventDesc>;
|
|
3743
|
+
|
|
3744
|
+
const feeds = Object.fromEntries(
|
|
3745
|
+
Object.entries(source.feeds ?? {}).map(([name, feed]) => [
|
|
3746
|
+
name,
|
|
3747
|
+
{
|
|
3748
|
+
subject: feed.subject ?? feedSubject(name, feed.version),
|
|
3749
|
+
input: schema(
|
|
3750
|
+
resolveSchemaRef(source.schemas, feed.input, `feed '${name}' input`),
|
|
3751
|
+
),
|
|
3752
|
+
event: schema(
|
|
3753
|
+
resolveSchemaRef(source.schemas, feed.event, `feed '${name}' event`),
|
|
3754
|
+
),
|
|
3755
|
+
subscribeCapabilities: projectCapabilities(
|
|
3756
|
+
feed.capabilities?.subscribe,
|
|
3757
|
+
source.id,
|
|
3758
|
+
source.capabilities,
|
|
3759
|
+
`feed '${name}' subscribe capabilities`,
|
|
3760
|
+
) ?? [],
|
|
3761
|
+
},
|
|
3762
|
+
]),
|
|
3763
|
+
) as Record<string, FeedDesc>;
|
|
3764
|
+
|
|
3765
|
+
return { rpc, operations, events, feeds, subjects: {} } as ApiShape;
|
|
3766
|
+
}
|
|
3767
|
+
|
|
3768
|
+
function mergeRecord(
|
|
3769
|
+
kind: "rpc" | "operations" | "events" | "feeds" | "subjects",
|
|
3770
|
+
out: Record<string, unknown>,
|
|
3771
|
+
next: Record<string, unknown>,
|
|
3772
|
+
) {
|
|
3773
|
+
for (const [key, value] of Object.entries(next)) {
|
|
3774
|
+
if (Object.hasOwn(out, key)) {
|
|
3775
|
+
throw new Error(
|
|
3776
|
+
`Duplicate ${kind} key '${key}' while deriving contract API`,
|
|
3777
|
+
);
|
|
3778
|
+
}
|
|
3779
|
+
out[key] = value;
|
|
3780
|
+
}
|
|
3781
|
+
}
|
|
3782
|
+
|
|
3783
|
+
function assertSelectedKeysExist(
|
|
3784
|
+
contractId: string,
|
|
3785
|
+
kind: "rpc" | "operations" | "events" | "feeds" | "subjects",
|
|
3786
|
+
keys: readonly string[] | undefined,
|
|
3787
|
+
api: Record<string, unknown>,
|
|
3788
|
+
) {
|
|
3789
|
+
if (!keys) {
|
|
3790
|
+
return;
|
|
3791
|
+
}
|
|
3792
|
+
|
|
3793
|
+
for (const key of keys) {
|
|
3794
|
+
if (!Object.hasOwn(api, key)) {
|
|
3795
|
+
throw new Error(
|
|
3796
|
+
`Contract '${contractId}' does not expose ${kind} key '${key}'`,
|
|
3797
|
+
);
|
|
3798
|
+
}
|
|
3799
|
+
}
|
|
3800
|
+
}
|
|
3801
|
+
|
|
3802
|
+
function assertValidUseSpec<TApi extends TrellisApiLike>(
|
|
3803
|
+
contractId: string,
|
|
3804
|
+
spec: UseSpec<TApi>,
|
|
3805
|
+
api: TApi,
|
|
3806
|
+
) {
|
|
3807
|
+
assertSelectedKeysExist(contractId, "rpc", spec.rpc?.call, api.rpc);
|
|
3808
|
+
assertSelectedKeysExist(
|
|
3809
|
+
contractId,
|
|
3810
|
+
"operations",
|
|
3811
|
+
spec.operations?.call,
|
|
3812
|
+
api.operations,
|
|
3813
|
+
);
|
|
3814
|
+
assertSelectedKeysExist(
|
|
3815
|
+
contractId,
|
|
3816
|
+
"events",
|
|
3817
|
+
spec.events?.publish,
|
|
3818
|
+
api.events,
|
|
3819
|
+
);
|
|
3820
|
+
assertSelectedKeysExist(
|
|
3821
|
+
contractId,
|
|
3822
|
+
"events",
|
|
3823
|
+
spec.events?.subscribe,
|
|
3824
|
+
api.events,
|
|
3825
|
+
);
|
|
3826
|
+
assertSelectedKeysExist(
|
|
3827
|
+
contractId,
|
|
3828
|
+
"feeds",
|
|
3829
|
+
spec.feeds?.subscribe,
|
|
3830
|
+
api.feeds ?? {},
|
|
3831
|
+
);
|
|
3832
|
+
}
|
|
3833
|
+
|
|
3834
|
+
function attachContractModuleMetadata<
|
|
3835
|
+
TValue extends object,
|
|
3836
|
+
TContractModule,
|
|
3837
|
+
>(
|
|
3838
|
+
value: TValue,
|
|
3839
|
+
contractModule: TContractModule,
|
|
3840
|
+
): TValue & ContractModuleMarker<TContractModule> {
|
|
3841
|
+
Object.defineProperty(value, CONTRACT_MODULE_METADATA, {
|
|
3842
|
+
value: contractModule,
|
|
3843
|
+
enumerable: false,
|
|
3844
|
+
});
|
|
3845
|
+
return value as TValue & ContractModuleMarker<TContractModule>;
|
|
3846
|
+
}
|
|
3847
|
+
|
|
3848
|
+
function attachContractErrorRuntimeMetadata<
|
|
3849
|
+
TValue extends object,
|
|
3850
|
+
TClass extends RpcErrorClass,
|
|
3851
|
+
>(
|
|
3852
|
+
value: TValue,
|
|
3853
|
+
errorClass: TClass,
|
|
3854
|
+
): TValue & ContractErrorRuntimeMarker<TClass> {
|
|
3855
|
+
Object.defineProperty(value, CONTRACT_ERROR_RUNTIME_METADATA, {
|
|
3856
|
+
value: errorClass,
|
|
3857
|
+
enumerable: false,
|
|
3858
|
+
});
|
|
3859
|
+
return value as TValue & ContractErrorRuntimeMarker<TClass>;
|
|
3860
|
+
}
|
|
3861
|
+
|
|
3862
|
+
function getContractErrorRuntimeClass(
|
|
3863
|
+
errorDecl: ContractSourceErrorDecl,
|
|
3864
|
+
): ErrorClass | undefined {
|
|
3865
|
+
const value = Object.getOwnPropertyDescriptor(
|
|
3866
|
+
errorDecl,
|
|
3867
|
+
CONTRACT_ERROR_RUNTIME_METADATA,
|
|
3868
|
+
)?.value;
|
|
3869
|
+
if (isErrorClass(value)) {
|
|
3870
|
+
return value;
|
|
3871
|
+
}
|
|
3872
|
+
return undefined;
|
|
3873
|
+
}
|
|
3874
|
+
|
|
3875
|
+
function resolveErrorSchemaRef(
|
|
3876
|
+
schemas: ContractSourceSchemas | undefined,
|
|
3877
|
+
errorName: string,
|
|
3878
|
+
errorDecl: ContractSourceErrorDecl,
|
|
3879
|
+
): ContractSchemaRef | undefined {
|
|
3880
|
+
if (errorDecl.schema) {
|
|
3881
|
+
return errorDecl.schema;
|
|
3882
|
+
}
|
|
3883
|
+
|
|
3884
|
+
const runtimeSchema = getErrorRuntimeSchema(errorDecl);
|
|
3885
|
+
if (!runtimeSchema) {
|
|
3886
|
+
return undefined;
|
|
3887
|
+
}
|
|
3888
|
+
|
|
3889
|
+
const schemaName = findMatchingSchemaName(schemas, runtimeSchema);
|
|
3890
|
+
if (schemaName) {
|
|
3891
|
+
return { schema: schemaName };
|
|
3892
|
+
}
|
|
3893
|
+
|
|
3894
|
+
throw new Error(
|
|
3895
|
+
`error '${errorName}' schema must be declared in contract.schemas`,
|
|
3896
|
+
);
|
|
3897
|
+
}
|
|
3898
|
+
|
|
3899
|
+
/**
|
|
3900
|
+
* Define a transportable Trellis error class from a payload-object schema.
|
|
3901
|
+
*
|
|
3902
|
+
* The returned value is a real runtime error class that carries the wire schema
|
|
3903
|
+
* and reconstruction logic needed by `defineServiceContract(...)`.
|
|
3904
|
+
*/
|
|
3905
|
+
export function defineError<
|
|
3906
|
+
const TType extends string,
|
|
3907
|
+
const TFields extends TProperties,
|
|
3908
|
+
>(
|
|
3909
|
+
options: DefineErrorOptions<TType, TFields>,
|
|
3910
|
+
): DefinedErrorClass<TType, TFields> {
|
|
3911
|
+
assertNoReservedDefinedErrorFieldNames(options.fields);
|
|
3912
|
+
|
|
3913
|
+
const errorSchema = createDefinedErrorSchema(options.type, options.fields);
|
|
3914
|
+
const fieldNames = definedErrorPayloadFieldNames(options.fields);
|
|
3915
|
+
|
|
3916
|
+
type TPayload = DefinedErrorPayload<TFields>;
|
|
3917
|
+
type TData = DefinedErrorData<TType, TFields>;
|
|
3918
|
+
type TInit = DefinedErrorInit<TFields>;
|
|
3919
|
+
|
|
3920
|
+
class DefinedErrorImpl extends TrellisError<SerializableErrorData>
|
|
3921
|
+
implements DefinedErrorPayloadCarrier<TPayload> {
|
|
3922
|
+
static readonly type = options.type;
|
|
3923
|
+
static readonly schema = errorSchema;
|
|
3924
|
+
override readonly name = options.type;
|
|
3925
|
+
[DEFINED_ERROR_PAYLOAD]: Readonly<TPayload>;
|
|
3926
|
+
|
|
3927
|
+
constructor(payload: TInit) {
|
|
3928
|
+
const customPayload = pickDefinedErrorPayload(fieldNames, payload);
|
|
3929
|
+
const message = typeof options.message === "function"
|
|
3930
|
+
? options.message(customPayload)
|
|
3931
|
+
: options.message;
|
|
3932
|
+
super(message, definedErrorBaseOptions(payload));
|
|
3933
|
+
this[DEFINED_ERROR_PAYLOAD] = customPayload;
|
|
3934
|
+
Object.assign(this, customPayload);
|
|
3935
|
+
}
|
|
3936
|
+
|
|
3937
|
+
static fromSerializable(data: TData): DefinedErrorInstance<TType, TFields> {
|
|
3938
|
+
const customPayload = pickDefinedErrorPayload(fieldNames, data);
|
|
3939
|
+
const ErrorCtor = DefinedErrorImpl as new (
|
|
3940
|
+
payload: object,
|
|
3941
|
+
) =>
|
|
3942
|
+
& TrellisError<SerializableErrorData>
|
|
3943
|
+
& DefinedErrorPayloadCarrier<Record<string, unknown>>;
|
|
3944
|
+
const error = new ErrorCtor({
|
|
3945
|
+
...customPayload,
|
|
3946
|
+
id: data.id,
|
|
3947
|
+
context: data.context,
|
|
3948
|
+
traceId: data.traceId,
|
|
3949
|
+
});
|
|
3950
|
+
error[DEFINED_ERROR_PAYLOAD] = customPayload;
|
|
3951
|
+
return Object.assign(error, customPayload) as DefinedErrorInstance<
|
|
3952
|
+
TType,
|
|
3953
|
+
TFields
|
|
3954
|
+
>;
|
|
3955
|
+
}
|
|
3956
|
+
|
|
3957
|
+
override toSerializable(): SerializableErrorData {
|
|
3958
|
+
return {
|
|
3959
|
+
...this.baseSerializable(),
|
|
3960
|
+
type: this.name,
|
|
3961
|
+
...this[DEFINED_ERROR_PAYLOAD],
|
|
3962
|
+
};
|
|
3963
|
+
}
|
|
3964
|
+
}
|
|
3965
|
+
|
|
3966
|
+
// @ts-expect-error TypeScript cannot model the dynamically assigned payload
|
|
3967
|
+
// fields on the generated class instance constructor return type.
|
|
3968
|
+
return DefinedErrorImpl;
|
|
3969
|
+
}
|
|
3970
|
+
|
|
3971
|
+
function createUseHelper<
|
|
3972
|
+
TContractId extends string,
|
|
3973
|
+
TOwnedApi extends TrellisApiLike,
|
|
3974
|
+
TUsedApi extends ApiShape,
|
|
3975
|
+
TTrellisApi extends ApiShape,
|
|
3976
|
+
>(
|
|
3977
|
+
getContractModule: () => ContractModule<
|
|
3978
|
+
TContractId,
|
|
3979
|
+
TOwnedApi,
|
|
3980
|
+
TUsedApi,
|
|
3981
|
+
TTrellisApi
|
|
3982
|
+
>,
|
|
3983
|
+
) {
|
|
3984
|
+
return ((spec) => {
|
|
3985
|
+
const contractModule = getContractModule();
|
|
3986
|
+
assertValidUseSpec(
|
|
3987
|
+
contractModule.CONTRACT_ID,
|
|
3988
|
+
spec,
|
|
3989
|
+
contractModule.API.owned,
|
|
3990
|
+
);
|
|
3991
|
+
|
|
3992
|
+
const dependencyUse = {
|
|
3993
|
+
contract: contractModule.CONTRACT_ID,
|
|
3994
|
+
...(spec.rpc?.call ? { rpc: { call: [...spec.rpc.call] } } : {}),
|
|
3995
|
+
...(spec.operations?.call
|
|
3996
|
+
? { operations: { call: [...spec.operations.call] } }
|
|
3997
|
+
: {}),
|
|
3998
|
+
...((spec.events?.publish || spec.events?.subscribe)
|
|
3999
|
+
? {
|
|
4000
|
+
events: {
|
|
4001
|
+
...(spec.events.publish
|
|
4002
|
+
? { publish: [...spec.events.publish] }
|
|
4003
|
+
: {}),
|
|
4004
|
+
...(spec.events.subscribe
|
|
4005
|
+
? { subscribe: [...spec.events.subscribe] }
|
|
4006
|
+
: {}),
|
|
4007
|
+
},
|
|
4008
|
+
}
|
|
4009
|
+
: {}),
|
|
4010
|
+
...(spec.feeds?.subscribe
|
|
4011
|
+
? { feeds: { subscribe: [...spec.feeds.subscribe] } }
|
|
4012
|
+
: {}),
|
|
4013
|
+
};
|
|
4014
|
+
|
|
4015
|
+
return attachContractModuleMetadata(
|
|
4016
|
+
dependencyUse,
|
|
4017
|
+
contractModule,
|
|
4018
|
+
);
|
|
4019
|
+
}) as ContractUseFn<TContractId, TOwnedApi>;
|
|
4020
|
+
}
|
|
4021
|
+
|
|
4022
|
+
function getContractModuleFromUse(
|
|
4023
|
+
alias: string,
|
|
4024
|
+
useValue: ContractSourceUse | AuthorContractDependencyUse,
|
|
4025
|
+
): ContractModule<string, TrellisApiLike, TrellisApiLike, TrellisApiLike> {
|
|
4026
|
+
const contractModule = Object.getOwnPropertyDescriptor(
|
|
4027
|
+
useValue,
|
|
4028
|
+
CONTRACT_MODULE_METADATA,
|
|
4029
|
+
)?.value as
|
|
4030
|
+
| ContractModule<
|
|
4031
|
+
string,
|
|
4032
|
+
TrellisApiLike,
|
|
4033
|
+
TrellisApiLike,
|
|
4034
|
+
TrellisApiLike
|
|
4035
|
+
>
|
|
4036
|
+
| undefined;
|
|
4037
|
+
if (!contractModule) {
|
|
4038
|
+
throw new Error(
|
|
4039
|
+
`Contract use '${alias}' must be created with contractModule.use(...) from @qlever-llc/trellis/contracts`,
|
|
4040
|
+
);
|
|
4041
|
+
}
|
|
4042
|
+
return contractModule;
|
|
4043
|
+
}
|
|
4044
|
+
|
|
4045
|
+
function normalizeUseEntries(
|
|
4046
|
+
uses: AuthorContractUsesFlat | undefined,
|
|
4047
|
+
): {
|
|
4048
|
+
manifestUses: Record<string, ContractSourceUse> | undefined;
|
|
4049
|
+
usedApi: TrellisApiLike;
|
|
4050
|
+
} {
|
|
4051
|
+
if (!uses) {
|
|
4052
|
+
return {
|
|
4053
|
+
manifestUses: undefined,
|
|
4054
|
+
usedApi: { rpc: {}, operations: {}, events: {}, feeds: {}, subjects: {} },
|
|
4055
|
+
};
|
|
4056
|
+
}
|
|
4057
|
+
|
|
4058
|
+
const manifestUses: Record<string, ContractSourceUse> = {};
|
|
4059
|
+
const usedApi: TrellisApiLike = {
|
|
4060
|
+
rpc: {},
|
|
4061
|
+
operations: {},
|
|
4062
|
+
events: {},
|
|
4063
|
+
feeds: {},
|
|
4064
|
+
subjects: {},
|
|
4065
|
+
};
|
|
4066
|
+
|
|
4067
|
+
for (const [alias, useValue] of Object.entries(uses)) {
|
|
4068
|
+
const contractModule = getContractModuleFromUse(alias, useValue);
|
|
4069
|
+
const rpcCall = useValue.rpc?.call as readonly string[] | undefined;
|
|
4070
|
+
const operationsCall = useValue.operations?.call as
|
|
4071
|
+
| readonly string[]
|
|
4072
|
+
| undefined;
|
|
4073
|
+
const eventsPublish = useValue.events?.publish as
|
|
4074
|
+
| readonly string[]
|
|
4075
|
+
| undefined;
|
|
4076
|
+
const eventsSubscribe = useValue.events?.subscribe as
|
|
4077
|
+
| readonly string[]
|
|
4078
|
+
| undefined;
|
|
4079
|
+
const feedsSubscribe = useValue.feeds?.subscribe as
|
|
4080
|
+
| readonly string[]
|
|
4081
|
+
| undefined;
|
|
4082
|
+
if (useValue.contract !== contractModule.CONTRACT_ID) {
|
|
4083
|
+
throw new Error(
|
|
4084
|
+
`Contract use '${alias}' references '${useValue.contract}' but module id is '${contractModule.CONTRACT_ID}'`,
|
|
4085
|
+
);
|
|
4086
|
+
}
|
|
4087
|
+
|
|
4088
|
+
assertValidUseSpec(
|
|
4089
|
+
contractModule.CONTRACT_ID,
|
|
4090
|
+
{
|
|
4091
|
+
...(rpcCall ? { rpc: { call: rpcCall } } : {}),
|
|
4092
|
+
...(operationsCall ? { operations: { call: operationsCall } } : {}),
|
|
4093
|
+
...((eventsPublish || eventsSubscribe)
|
|
4094
|
+
? {
|
|
4095
|
+
events: {
|
|
4096
|
+
...(eventsPublish ? { publish: eventsPublish } : {}),
|
|
4097
|
+
...(eventsSubscribe ? { subscribe: eventsSubscribe } : {}),
|
|
4098
|
+
},
|
|
4099
|
+
}
|
|
4100
|
+
: {}),
|
|
4101
|
+
...(feedsSubscribe ? { feeds: { subscribe: feedsSubscribe } } : {}),
|
|
4102
|
+
},
|
|
4103
|
+
contractModule.API.owned,
|
|
4104
|
+
);
|
|
4105
|
+
|
|
4106
|
+
manifestUses[alias] = {
|
|
4107
|
+
contract: contractModule.CONTRACT_ID,
|
|
4108
|
+
...(rpcCall ? { rpc: { call: [...rpcCall] } } : {}),
|
|
4109
|
+
...(operationsCall ? { operations: { call: [...operationsCall] } } : {}),
|
|
4110
|
+
...((eventsPublish || eventsSubscribe)
|
|
4111
|
+
? {
|
|
4112
|
+
events: {
|
|
4113
|
+
...(eventsPublish ? { publish: [...eventsPublish] } : {}),
|
|
4114
|
+
...(eventsSubscribe ? { subscribe: [...eventsSubscribe] } : {}),
|
|
4115
|
+
},
|
|
4116
|
+
}
|
|
4117
|
+
: {}),
|
|
4118
|
+
...(feedsSubscribe ? { feeds: { subscribe: [...feedsSubscribe] } } : {}),
|
|
4119
|
+
};
|
|
4120
|
+
|
|
4121
|
+
const rpcKeys = selectedKeys(
|
|
4122
|
+
rpcCall,
|
|
4123
|
+
);
|
|
4124
|
+
if (rpcKeys.length > 0) {
|
|
4125
|
+
mergeRecord(
|
|
4126
|
+
"rpc",
|
|
4127
|
+
usedApi.rpc,
|
|
4128
|
+
Object.fromEntries(
|
|
4129
|
+
rpcKeys.map((key) => [key, contractModule.API.owned.rpc[key]]),
|
|
4130
|
+
),
|
|
4131
|
+
);
|
|
4132
|
+
}
|
|
4133
|
+
|
|
4134
|
+
const operationKeys = selectedKeys(
|
|
4135
|
+
operationsCall,
|
|
4136
|
+
);
|
|
4137
|
+
if (operationKeys.length > 0) {
|
|
4138
|
+
mergeRecord(
|
|
4139
|
+
"operations",
|
|
4140
|
+
usedApi.operations,
|
|
4141
|
+
Object.fromEntries(
|
|
4142
|
+
operationKeys.map((
|
|
4143
|
+
key,
|
|
4144
|
+
) => [key, contractModule.API.owned.operations[key]]),
|
|
4145
|
+
),
|
|
4146
|
+
);
|
|
4147
|
+
}
|
|
4148
|
+
|
|
4149
|
+
const eventKeys = new Set([
|
|
4150
|
+
...selectedKeys(eventsPublish),
|
|
4151
|
+
...selectedKeys(eventsSubscribe),
|
|
4152
|
+
]);
|
|
4153
|
+
if (eventKeys.size > 0) {
|
|
4154
|
+
mergeRecord(
|
|
4155
|
+
"events",
|
|
4156
|
+
usedApi.events,
|
|
4157
|
+
Object.fromEntries(
|
|
4158
|
+
[...eventKeys].map((
|
|
4159
|
+
key,
|
|
4160
|
+
) => [key, contractModule.API.owned.events[key]]),
|
|
4161
|
+
),
|
|
4162
|
+
);
|
|
4163
|
+
}
|
|
4164
|
+
|
|
4165
|
+
const feedKeys = selectedKeys(feedsSubscribe);
|
|
4166
|
+
if (feedKeys.length > 0) {
|
|
4167
|
+
mergeRecord(
|
|
4168
|
+
"feeds",
|
|
4169
|
+
usedApi.feeds ?? {},
|
|
4170
|
+
Object.fromEntries(
|
|
4171
|
+
feedKeys.map((key) => [key, contractModule.API.owned.feeds?.[key]]),
|
|
4172
|
+
),
|
|
4173
|
+
);
|
|
4174
|
+
}
|
|
4175
|
+
}
|
|
4176
|
+
|
|
4177
|
+
return { manifestUses, usedApi };
|
|
4178
|
+
}
|
|
4179
|
+
|
|
4180
|
+
function normalizeUses(
|
|
4181
|
+
uses: AuthorContractUses | undefined,
|
|
4182
|
+
): {
|
|
4183
|
+
manifestUses: ContractSourceUses | undefined;
|
|
4184
|
+
usedApi: TrellisApiLike;
|
|
4185
|
+
} {
|
|
4186
|
+
if (!uses) {
|
|
4187
|
+
return {
|
|
4188
|
+
manifestUses: undefined,
|
|
4189
|
+
usedApi: emptyApi(),
|
|
4190
|
+
};
|
|
4191
|
+
}
|
|
4192
|
+
|
|
4193
|
+
const required = normalizeUseEntries(uses.required);
|
|
4194
|
+
const optional = normalizeUseEntries(
|
|
4195
|
+
omitRequiredUseAliases(uses.optional, uses.required),
|
|
4196
|
+
);
|
|
4197
|
+
const usedApi = emptyApi();
|
|
4198
|
+
mergeUseIntoApi(usedApi, required.usedApi);
|
|
4199
|
+
mergeUseIntoApi(usedApi, optional.usedApi);
|
|
4200
|
+
|
|
4201
|
+
return {
|
|
4202
|
+
manifestUses: {
|
|
4203
|
+
...(required.manifestUses ? { required: required.manifestUses } : {}),
|
|
4204
|
+
...(optional.manifestUses ? { optional: optional.manifestUses } : {}),
|
|
4205
|
+
},
|
|
4206
|
+
usedApi,
|
|
4207
|
+
};
|
|
4208
|
+
}
|
|
4209
|
+
|
|
4210
|
+
type NormalizedUse = {
|
|
4211
|
+
manifestUse: ContractSourceUse;
|
|
4212
|
+
api: TrellisApiLike;
|
|
4213
|
+
};
|
|
4214
|
+
|
|
4215
|
+
function emptyApi(): TrellisApiLike {
|
|
4216
|
+
return { rpc: {}, operations: {}, events: {}, feeds: {}, subjects: {} };
|
|
4217
|
+
}
|
|
4218
|
+
|
|
4219
|
+
function addUniqueStrings(target: string[], values: readonly string[]): void {
|
|
4220
|
+
for (const value of values) {
|
|
4221
|
+
if (!target.includes(value)) {
|
|
4222
|
+
target.push(value);
|
|
4223
|
+
}
|
|
4224
|
+
}
|
|
4225
|
+
}
|
|
4226
|
+
|
|
4227
|
+
function mergeUseIntoManifest(
|
|
4228
|
+
manifestUses: Record<string, ContractSourceUse>,
|
|
4229
|
+
alias: string,
|
|
4230
|
+
use: ContractSourceUse,
|
|
4231
|
+
): void {
|
|
4232
|
+
const existing = manifestUses[alias];
|
|
4233
|
+
if (!existing) {
|
|
4234
|
+
manifestUses[alias] = use;
|
|
4235
|
+
return;
|
|
4236
|
+
}
|
|
4237
|
+
|
|
4238
|
+
if (existing.contract !== use.contract) {
|
|
4239
|
+
throw new Error(
|
|
4240
|
+
`Contract use '${alias}' references both '${existing.contract}' and '${use.contract}'`,
|
|
4241
|
+
);
|
|
4242
|
+
}
|
|
4243
|
+
|
|
4244
|
+
const rpcCall = [...(existing.rpc?.call ?? [])];
|
|
4245
|
+
addUniqueStrings(rpcCall, use.rpc?.call ?? []);
|
|
4246
|
+
const operationsCall = [...(existing.operations?.call ?? [])];
|
|
4247
|
+
addUniqueStrings(operationsCall, use.operations?.call ?? []);
|
|
4248
|
+
const eventsPublish = [...(existing.events?.publish ?? [])];
|
|
4249
|
+
addUniqueStrings(eventsPublish, use.events?.publish ?? []);
|
|
4250
|
+
const eventsSubscribe = [...(existing.events?.subscribe ?? [])];
|
|
4251
|
+
addUniqueStrings(eventsSubscribe, use.events?.subscribe ?? []);
|
|
4252
|
+
const feedsSubscribe = [...(existing.feeds?.subscribe ?? [])];
|
|
4253
|
+
addUniqueStrings(feedsSubscribe, use.feeds?.subscribe ?? []);
|
|
4254
|
+
manifestUses[alias] = {
|
|
4255
|
+
contract: existing.contract,
|
|
4256
|
+
...(rpcCall.length > 0 ? { rpc: { call: rpcCall } } : {}),
|
|
4257
|
+
...(operationsCall.length > 0
|
|
4258
|
+
? { operations: { call: operationsCall } }
|
|
4259
|
+
: {}),
|
|
4260
|
+
...((eventsPublish.length > 0 || eventsSubscribe.length > 0)
|
|
4261
|
+
? {
|
|
4262
|
+
events: {
|
|
4263
|
+
...(eventsPublish.length > 0 ? { publish: eventsPublish } : {}),
|
|
4264
|
+
...(eventsSubscribe.length > 0 ? { subscribe: eventsSubscribe } : {}),
|
|
4265
|
+
},
|
|
4266
|
+
}
|
|
4267
|
+
: {}),
|
|
4268
|
+
...(feedsSubscribe.length > 0
|
|
4269
|
+
? { feeds: { subscribe: feedsSubscribe } }
|
|
4270
|
+
: {}),
|
|
4271
|
+
};
|
|
4272
|
+
}
|
|
4273
|
+
|
|
4274
|
+
function mergeApiAllowDuplicateSubject(
|
|
4275
|
+
kind: "rpc" | "operations" | "events" | "feeds" | "subjects",
|
|
4276
|
+
out: Record<string, unknown>,
|
|
4277
|
+
next: Record<string, unknown>,
|
|
4278
|
+
): void {
|
|
4279
|
+
for (const [key, value] of Object.entries(next)) {
|
|
4280
|
+
const existing = out[key];
|
|
4281
|
+
if (existing !== undefined) {
|
|
4282
|
+
const existingSubject = typeof existing === "object" && existing !== null
|
|
4283
|
+
? (existing as { subject?: unknown }).subject
|
|
4284
|
+
: undefined;
|
|
4285
|
+
const nextSubject = typeof value === "object" && value !== null
|
|
4286
|
+
? (value as { subject?: unknown }).subject
|
|
4287
|
+
: undefined;
|
|
4288
|
+
if (
|
|
4289
|
+
typeof existingSubject === "string" && existingSubject === nextSubject
|
|
4290
|
+
) {
|
|
4291
|
+
continue;
|
|
4292
|
+
}
|
|
4293
|
+
throw new Error(
|
|
4294
|
+
`Duplicate ${kind} key '${key}' while deriving contract API`,
|
|
4295
|
+
);
|
|
4296
|
+
}
|
|
4297
|
+
out[key] = value;
|
|
4298
|
+
}
|
|
4299
|
+
}
|
|
4300
|
+
|
|
4301
|
+
function mergeUseIntoApi(target: TrellisApiLike, api: TrellisApiLike): void {
|
|
4302
|
+
mergeApiAllowDuplicateSubject("rpc", target.rpc, api.rpc);
|
|
4303
|
+
mergeApiAllowDuplicateSubject(
|
|
4304
|
+
"operations",
|
|
4305
|
+
target.operations,
|
|
4306
|
+
api.operations,
|
|
4307
|
+
);
|
|
4308
|
+
mergeApiAllowDuplicateSubject("events", target.events, api.events);
|
|
4309
|
+
mergeApiAllowDuplicateSubject("feeds", target.feeds ?? {}, api.feeds ?? {});
|
|
4310
|
+
mergeApiAllowDuplicateSubject("subjects", target.subjects, api.subjects);
|
|
4311
|
+
}
|
|
4312
|
+
|
|
4313
|
+
function baselineUse(
|
|
4314
|
+
contract: string,
|
|
4315
|
+
use: Omit<ContractSourceUse, "contract">,
|
|
4316
|
+
api: TrellisApiLike,
|
|
4317
|
+
): NormalizedUse {
|
|
4318
|
+
return { manifestUse: { contract, ...use }, api };
|
|
4319
|
+
}
|
|
4320
|
+
|
|
4321
|
+
function deriveImplicitTrellisUses(source: DefineContractSource): Record<
|
|
4322
|
+
string,
|
|
4323
|
+
NormalizedUse
|
|
4324
|
+
> {
|
|
4325
|
+
const uses: Record<string, NormalizedUse> = {};
|
|
4326
|
+
|
|
4327
|
+
if (
|
|
4328
|
+
source.kind === "app" || source.kind === "agent" || source.kind === "device"
|
|
4329
|
+
) {
|
|
4330
|
+
uses.auth = baselineUse(
|
|
4331
|
+
TRELLIS_AUTH_CONTRACT_ID,
|
|
4332
|
+
{ rpc: { call: [...BASELINE_AUTH_RPC_CALL] } },
|
|
4333
|
+
BASELINE_AUTH_API,
|
|
4334
|
+
);
|
|
4335
|
+
}
|
|
4336
|
+
|
|
4337
|
+
if (source.state) {
|
|
4338
|
+
uses.state = baselineUse(
|
|
4339
|
+
TRELLIS_STATE_CONTRACT_ID,
|
|
4340
|
+
{ rpc: { call: [...BASELINE_STATE_RPC_CALL] } },
|
|
4341
|
+
BASELINE_STATE_API,
|
|
4342
|
+
);
|
|
4343
|
+
}
|
|
4344
|
+
|
|
4345
|
+
if (
|
|
4346
|
+
(source.kind === "service" || source.kind === "device") &&
|
|
4347
|
+
source.id !== TRELLIS_HEALTH_CONTRACT_ID
|
|
4348
|
+
) {
|
|
4349
|
+
uses.health = baselineUse(
|
|
4350
|
+
TRELLIS_HEALTH_CONTRACT_ID,
|
|
4351
|
+
{ events: { publish: [...BASELINE_HEALTH_EVENTS_PUBLISH] } },
|
|
4352
|
+
BASELINE_HEALTH_API,
|
|
4353
|
+
);
|
|
4354
|
+
}
|
|
4355
|
+
|
|
4356
|
+
return uses;
|
|
4357
|
+
}
|
|
4358
|
+
|
|
4359
|
+
function normalizeContractUses(source: DefineContractSource): {
|
|
4360
|
+
manifestUses: ContractSourceUses | undefined;
|
|
4361
|
+
usedApi: TrellisApiLike;
|
|
4362
|
+
} {
|
|
4363
|
+
const explicit = normalizeUses(source.uses);
|
|
4364
|
+
const usedApi = emptyApi();
|
|
4365
|
+
mergeUseIntoApi(usedApi, explicit.usedApi);
|
|
4366
|
+
|
|
4367
|
+
const required: Record<string, ContractSourceUse> = {
|
|
4368
|
+
...(explicit.manifestUses?.required ?? {}),
|
|
4369
|
+
};
|
|
4370
|
+
const optional = explicit.manifestUses?.optional
|
|
4371
|
+
? { ...explicit.manifestUses.optional }
|
|
4372
|
+
: undefined;
|
|
4373
|
+
|
|
4374
|
+
for (
|
|
4375
|
+
const [alias, use] of Object.entries(deriveImplicitTrellisUses(source))
|
|
4376
|
+
) {
|
|
4377
|
+
mergeUseIntoManifest(required, alias, use.manifestUse);
|
|
4378
|
+
mergeUseIntoApi(usedApi, use.api);
|
|
4379
|
+
}
|
|
4380
|
+
|
|
4381
|
+
return {
|
|
4382
|
+
manifestUses: Object.keys(required).length > 0 ||
|
|
4383
|
+
(optional && Object.keys(optional).length > 0)
|
|
4384
|
+
? {
|
|
4385
|
+
...(Object.keys(required).length > 0 ? { required } : {}),
|
|
4386
|
+
...(optional && Object.keys(optional).length > 0 ? { optional } : {}),
|
|
4387
|
+
}
|
|
4388
|
+
: undefined,
|
|
4389
|
+
usedApi,
|
|
4390
|
+
};
|
|
4391
|
+
}
|
|
4392
|
+
|
|
4393
|
+
function selectedKeys(keys: readonly string[] | undefined): readonly string[] {
|
|
4394
|
+
return keys ?? [];
|
|
4395
|
+
}
|
|
4396
|
+
|
|
4397
|
+
function mergeApiSection(
|
|
4398
|
+
kind: keyof TrellisApiLike,
|
|
4399
|
+
usedEntries: Record<string, unknown>,
|
|
4400
|
+
ownedEntries: Record<string, unknown>,
|
|
4401
|
+
): Record<string, unknown> {
|
|
4402
|
+
const merged: Record<string, unknown> = {};
|
|
4403
|
+
mergeRecord(kind, merged, usedEntries);
|
|
4404
|
+
mergeRecord(kind, merged, ownedEntries);
|
|
4405
|
+
return merged;
|
|
4406
|
+
}
|
|
4407
|
+
|
|
4408
|
+
function mergeDerivedApis<
|
|
4409
|
+
TOwnedApi extends TrellisApiLike,
|
|
4410
|
+
TUsedApi extends TrellisApiLike,
|
|
4411
|
+
>(
|
|
4412
|
+
ownedApi: TOwnedApi,
|
|
4413
|
+
usedApi: TUsedApi,
|
|
4414
|
+
): MergeApis<TOwnedApi, TUsedApi> {
|
|
4415
|
+
return {
|
|
4416
|
+
rpc: mergeApiSection("rpc", usedApi.rpc, ownedApi.rpc) as MergeApis<
|
|
4417
|
+
TOwnedApi,
|
|
4418
|
+
TUsedApi
|
|
4419
|
+
>["rpc"],
|
|
4420
|
+
operations: mergeApiSection(
|
|
4421
|
+
"operations",
|
|
4422
|
+
usedApi.operations,
|
|
4423
|
+
ownedApi.operations,
|
|
4424
|
+
) as MergeApis<TOwnedApi, TUsedApi>["operations"],
|
|
4425
|
+
events: mergeApiSection(
|
|
4426
|
+
"events",
|
|
4427
|
+
usedApi.events,
|
|
4428
|
+
ownedApi.events,
|
|
4429
|
+
) as MergeApis<TOwnedApi, TUsedApi>["events"],
|
|
4430
|
+
feeds: mergeApiSection(
|
|
4431
|
+
"feeds",
|
|
4432
|
+
usedApi.feeds ?? {},
|
|
4433
|
+
ownedApi.feeds ?? {},
|
|
4434
|
+
) as MergeApis<TOwnedApi, TUsedApi>["feeds"],
|
|
4435
|
+
subjects: mergeApiSection(
|
|
4436
|
+
"subjects",
|
|
4437
|
+
usedApi.subjects,
|
|
4438
|
+
ownedApi.subjects,
|
|
4439
|
+
) as MergeApis<TOwnedApi, TUsedApi>["subjects"],
|
|
4440
|
+
};
|
|
4441
|
+
}
|
|
4442
|
+
|
|
4443
|
+
function defineContract(
|
|
4444
|
+
registry: AnyDefineContractRegistry,
|
|
4445
|
+
build: (
|
|
4446
|
+
ref: ContractRefBuilder,
|
|
4447
|
+
) => Omit<DefineContractSource, "schemas" | "errors">,
|
|
4448
|
+
): DefinedContract<TrellisApiLike, ApiShape, ApiShape, string>;
|
|
4449
|
+
function defineContract(
|
|
4450
|
+
registry: AnyDefineContractRegistry,
|
|
4451
|
+
build: (
|
|
4452
|
+
ref: ContractRefBuilder,
|
|
4453
|
+
) => Omit<DefineContractSource, "schemas" | "errors">,
|
|
4454
|
+
): DefinedContract<
|
|
4455
|
+
TrellisApiLike,
|
|
4456
|
+
ApiShape,
|
|
4457
|
+
ApiShape,
|
|
4458
|
+
string
|
|
4459
|
+
> {
|
|
4460
|
+
assertRegistryDoesNotDeclareExports(registry);
|
|
4461
|
+
assertRegistryDoesNotDeclareCapabilities(registry);
|
|
4462
|
+
const errorClasses = getErrorClassRegistry(registry.errors);
|
|
4463
|
+
const normalizedErrors = normalizeErrorRegistry(registry.errors);
|
|
4464
|
+
const body = build(createContractRefBuilder({
|
|
4465
|
+
...(registry.schemas ? { schemas: registry.schemas } : {}),
|
|
4466
|
+
...(errorClasses ? { errors: errorClasses } : {}),
|
|
4467
|
+
}));
|
|
4468
|
+
const materializedSchemas = materializeErrorSchemas(
|
|
4469
|
+
registry.schemas,
|
|
4470
|
+
normalizedErrors,
|
|
4471
|
+
);
|
|
4472
|
+
const source: DefineContractSource = {
|
|
4473
|
+
...body,
|
|
4474
|
+
...(materializedSchemas ? { schemas: materializedSchemas } : {}),
|
|
4475
|
+
...(normalizedErrors ? { errors: normalizedErrors } : {}),
|
|
4476
|
+
};
|
|
4477
|
+
assertExportedSchemasExist(source.schemas, source.exports);
|
|
4478
|
+
|
|
4479
|
+
const { manifestUses, usedApi } = normalizeContractUses(source);
|
|
4480
|
+
const emittedSource: TrellisContractSource = {
|
|
4481
|
+
id: source.id,
|
|
4482
|
+
displayName: source.displayName,
|
|
4483
|
+
description: source.description,
|
|
4484
|
+
kind: source.kind,
|
|
4485
|
+
...(source.capabilities ? { capabilities: source.capabilities } : {}),
|
|
4486
|
+
...(source.schemas ? { schemas: source.schemas } : {}),
|
|
4487
|
+
...(source.exports ? { exports: source.exports } : {}),
|
|
4488
|
+
...(source.state ? { state: source.state } : {}),
|
|
4489
|
+
...(manifestUses ? { uses: manifestUses } : {}),
|
|
4490
|
+
...(source.rpc ? { rpc: source.rpc } : {}),
|
|
4491
|
+
...(source.operations ? { operations: source.operations } : {}),
|
|
4492
|
+
...(source.events ? { events: source.events } : {}),
|
|
4493
|
+
...(source.feeds ? { feeds: source.feeds } : {}),
|
|
4494
|
+
...(source.errors ? { errors: source.errors } : {}),
|
|
4495
|
+
...(source.jobs ? { jobs: source.jobs } : {}),
|
|
4496
|
+
...(source.resources ? { resources: source.resources } : {}),
|
|
4497
|
+
};
|
|
4498
|
+
|
|
4499
|
+
const ownedApi = buildOwnedApi(emittedSource);
|
|
4500
|
+
const trellisApi = mergeDerivedApis(
|
|
4501
|
+
ownedApi as ApiShape & TrellisApiLike,
|
|
4502
|
+
usedApi as ApiShape & TrellisApiLike,
|
|
4503
|
+
) as ApiShape;
|
|
4504
|
+
const CONTRACT = emitContract(emittedSource);
|
|
4505
|
+
const CONTRACT_DIGEST = digestContractManifest(CONTRACT);
|
|
4506
|
+
|
|
4507
|
+
type ConcreteDefinedContract = DefinedContract<
|
|
4508
|
+
TrellisApiLike,
|
|
4509
|
+
ApiShape,
|
|
4510
|
+
ApiShape,
|
|
4511
|
+
string
|
|
4512
|
+
>;
|
|
4513
|
+
|
|
4514
|
+
let contract!: ConcreteDefinedContract;
|
|
4515
|
+
contract = {
|
|
4516
|
+
CONTRACT_ID: source.id,
|
|
4517
|
+
CONTRACT,
|
|
4518
|
+
CONTRACT_DIGEST,
|
|
4519
|
+
API: {
|
|
4520
|
+
owned: ownedApi as TrellisApiLike,
|
|
4521
|
+
used: usedApi as ApiShape,
|
|
4522
|
+
trellis: trellisApi,
|
|
4523
|
+
},
|
|
4524
|
+
use: createUseHelper(
|
|
4525
|
+
() => contract,
|
|
4526
|
+
),
|
|
4527
|
+
[CONTRACT_JOBS_METADATA]: buildContractJobsMetadata(source.jobs),
|
|
4528
|
+
[CONTRACT_KV_METADATA]: buildContractKvMetadata(
|
|
4529
|
+
source.resources,
|
|
4530
|
+
source.schemas,
|
|
4531
|
+
),
|
|
4532
|
+
[CONTRACT_STATE_METADATA]: buildContractStateMetadata(
|
|
4533
|
+
source.state,
|
|
4534
|
+
source.schemas,
|
|
4535
|
+
),
|
|
4536
|
+
};
|
|
4537
|
+
|
|
4538
|
+
return contract;
|
|
4539
|
+
}
|
|
4540
|
+
|
|
4541
|
+
export function defineServiceContract<
|
|
4542
|
+
const TErrors extends Readonly<Record<string, unknown>> | undefined,
|
|
4543
|
+
const TRegistry extends DefineContractRegistry<
|
|
4544
|
+
Readonly<Record<string, TSchema>> | undefined,
|
|
4545
|
+
TErrors
|
|
4546
|
+
>,
|
|
4547
|
+
const TCapabilities extends ContractCapabilities | undefined,
|
|
4548
|
+
const TUses extends AuthorContractUses | undefined,
|
|
4549
|
+
const TRpc extends
|
|
4550
|
+
| Readonly<
|
|
4551
|
+
Record<
|
|
4552
|
+
string,
|
|
4553
|
+
ContractSourceRpcMethod<
|
|
4554
|
+
SchemaNameOf<RegistrySchemas<TRegistry>>,
|
|
4555
|
+
ErrorNameOf<RegistryErrors<TRegistry>>,
|
|
4556
|
+
CapabilityRef<TCapabilities>
|
|
4557
|
+
>
|
|
4558
|
+
>
|
|
4559
|
+
>
|
|
4560
|
+
| undefined,
|
|
4561
|
+
const TOperations extends
|
|
4562
|
+
| Readonly<
|
|
4563
|
+
Record<
|
|
4564
|
+
string,
|
|
4565
|
+
ContractSourceOperation<
|
|
4566
|
+
SchemaNameOf<RegistrySchemas<TRegistry>>,
|
|
4567
|
+
CapabilityRef<TCapabilities>
|
|
4568
|
+
>
|
|
4569
|
+
>
|
|
4570
|
+
>
|
|
4571
|
+
| undefined,
|
|
4572
|
+
const TEvents extends
|
|
4573
|
+
| Readonly<
|
|
4574
|
+
Record<
|
|
4575
|
+
string,
|
|
4576
|
+
ContractSourceEvent<
|
|
4577
|
+
SchemaNameOf<RegistrySchemas<TRegistry>>,
|
|
4578
|
+
CapabilityRef<TCapabilities>
|
|
4579
|
+
>
|
|
4580
|
+
>
|
|
4581
|
+
>
|
|
4582
|
+
| undefined,
|
|
4583
|
+
const TBody extends ServiceContractBodyInput<
|
|
4584
|
+
TCapabilities,
|
|
4585
|
+
RegistrySchemas<TRegistry>,
|
|
4586
|
+
TUses,
|
|
4587
|
+
RegistryErrors<TRegistry>,
|
|
4588
|
+
TRpc,
|
|
4589
|
+
TOperations,
|
|
4590
|
+
TEvents
|
|
4591
|
+
>,
|
|
4592
|
+
>(
|
|
4593
|
+
registry: TRegistry & { capabilities?: never; exports?: never },
|
|
4594
|
+
build: (
|
|
4595
|
+
ref: ContractRefBuilder<
|
|
4596
|
+
RegistrySchemas<TRegistry>,
|
|
4597
|
+
RegistryErrors<TRegistry>
|
|
4598
|
+
>,
|
|
4599
|
+
) => TBody,
|
|
4600
|
+
): DefinedContract<
|
|
4601
|
+
OwnedApiFromSource<
|
|
4602
|
+
BuiltContractSource<TRegistry, WithKind<TBody, "service">>
|
|
4603
|
+
>,
|
|
4604
|
+
UsedApiFromSource<BuiltContractSource<TRegistry, WithKind<TBody, "service">>>,
|
|
4605
|
+
MergeApis<
|
|
4606
|
+
OwnedApiFromSource<
|
|
4607
|
+
BuiltContractSource<TRegistry, WithKind<TBody, "service">>
|
|
4608
|
+
>,
|
|
4609
|
+
UsedApiFromSource<
|
|
4610
|
+
BuiltContractSource<TRegistry, WithKind<TBody, "service">>
|
|
4611
|
+
>
|
|
4612
|
+
>,
|
|
4613
|
+
TBody["id"],
|
|
4614
|
+
ProjectedJobs<
|
|
4615
|
+
JobsFromSource<BuiltContractSource<TRegistry, WithKind<TBody, "service">>>,
|
|
4616
|
+
SchemasFromSource<
|
|
4617
|
+
BuiltContractSource<TRegistry, WithKind<TBody, "service">>
|
|
4618
|
+
>
|
|
4619
|
+
>,
|
|
4620
|
+
ProjectedState<
|
|
4621
|
+
StateFromSource<BuiltContractSource<TRegistry, WithKind<TBody, "service">>>,
|
|
4622
|
+
SchemasFromSource<
|
|
4623
|
+
BuiltContractSource<TRegistry, WithKind<TBody, "service">>
|
|
4624
|
+
>
|
|
4625
|
+
>,
|
|
4626
|
+
ProjectedKvResources<
|
|
4627
|
+
ResourcesFromSource<
|
|
4628
|
+
BuiltContractSource<TRegistry, WithKind<TBody, "service">>
|
|
4629
|
+
>,
|
|
4630
|
+
SchemasFromSource<
|
|
4631
|
+
BuiltContractSource<TRegistry, WithKind<TBody, "service">>
|
|
4632
|
+
>
|
|
4633
|
+
>
|
|
4634
|
+
> {
|
|
4635
|
+
return defineContract(
|
|
4636
|
+
registry,
|
|
4637
|
+
(ref) => ({
|
|
4638
|
+
...build(ref),
|
|
4639
|
+
kind: "service",
|
|
4640
|
+
}),
|
|
4641
|
+
) as unknown as DefinedContract<
|
|
4642
|
+
OwnedApiFromSource<
|
|
4643
|
+
BuiltContractSource<TRegistry, WithKind<TBody, "service">>
|
|
4644
|
+
>,
|
|
4645
|
+
UsedApiFromSource<
|
|
4646
|
+
BuiltContractSource<TRegistry, WithKind<TBody, "service">>
|
|
4647
|
+
>,
|
|
4648
|
+
MergeApis<
|
|
4649
|
+
OwnedApiFromSource<
|
|
4650
|
+
BuiltContractSource<TRegistry, WithKind<TBody, "service">>
|
|
4651
|
+
>,
|
|
4652
|
+
UsedApiFromSource<
|
|
4653
|
+
BuiltContractSource<TRegistry, WithKind<TBody, "service">>
|
|
4654
|
+
>
|
|
4655
|
+
>,
|
|
4656
|
+
TBody["id"],
|
|
4657
|
+
ProjectedJobs<
|
|
4658
|
+
JobsFromSource<
|
|
4659
|
+
BuiltContractSource<TRegistry, WithKind<TBody, "service">>
|
|
4660
|
+
>,
|
|
4661
|
+
SchemasFromSource<
|
|
4662
|
+
BuiltContractSource<TRegistry, WithKind<TBody, "service">>
|
|
4663
|
+
>
|
|
4664
|
+
>,
|
|
4665
|
+
ProjectedState<
|
|
4666
|
+
StateFromSource<
|
|
4667
|
+
BuiltContractSource<TRegistry, WithKind<TBody, "service">>
|
|
4668
|
+
>,
|
|
4669
|
+
SchemasFromSource<
|
|
4670
|
+
BuiltContractSource<TRegistry, WithKind<TBody, "service">>
|
|
4671
|
+
>
|
|
4672
|
+
>,
|
|
4673
|
+
ProjectedKvResources<
|
|
4674
|
+
ResourcesFromSource<
|
|
4675
|
+
BuiltContractSource<TRegistry, WithKind<TBody, "service">>
|
|
4676
|
+
>,
|
|
4677
|
+
SchemasFromSource<
|
|
4678
|
+
BuiltContractSource<TRegistry, WithKind<TBody, "service">>
|
|
4679
|
+
>
|
|
4680
|
+
>
|
|
4681
|
+
>;
|
|
4682
|
+
}
|
|
4683
|
+
|
|
4684
|
+
function defineClientContract<
|
|
4685
|
+
const TKind extends Exclude<ContractKind, "service">,
|
|
4686
|
+
const TSchemas extends Readonly<Record<string, TSchema>> | undefined,
|
|
4687
|
+
const TUses extends AuthorContractUses | undefined,
|
|
4688
|
+
const TBody extends ClientContractBodyInput<TSchemas, TUses>,
|
|
4689
|
+
>(
|
|
4690
|
+
kind: TKind,
|
|
4691
|
+
registry: ClientContractRegistry<TSchemas> & {
|
|
4692
|
+
capabilities?: never;
|
|
4693
|
+
exports?: never;
|
|
4694
|
+
},
|
|
4695
|
+
build: (ref: ContractRefBuilder<TSchemas>) => TBody,
|
|
4696
|
+
): DefinedContract<
|
|
4697
|
+
OwnedApiFromSource<
|
|
4698
|
+
BuiltContractSource<
|
|
4699
|
+
ClientContractRegistry<TSchemas>,
|
|
4700
|
+
WithKind<TBody, TKind>
|
|
4701
|
+
>
|
|
4702
|
+
>,
|
|
4703
|
+
UsedApiFromSource<
|
|
4704
|
+
BuiltContractSource<
|
|
4705
|
+
ClientContractRegistry<TSchemas>,
|
|
4706
|
+
WithKind<TBody, TKind>
|
|
4707
|
+
>
|
|
4708
|
+
>,
|
|
4709
|
+
MergeApis<
|
|
4710
|
+
OwnedApiFromSource<
|
|
4711
|
+
BuiltContractSource<
|
|
4712
|
+
ClientContractRegistry<TSchemas>,
|
|
4713
|
+
WithKind<TBody, TKind>
|
|
4714
|
+
>
|
|
4715
|
+
>,
|
|
4716
|
+
UsedApiFromSource<
|
|
4717
|
+
BuiltContractSource<
|
|
4718
|
+
ClientContractRegistry<TSchemas>,
|
|
4719
|
+
WithKind<TBody, TKind>
|
|
4720
|
+
>
|
|
4721
|
+
>
|
|
4722
|
+
>,
|
|
4723
|
+
TBody["id"],
|
|
4724
|
+
{},
|
|
4725
|
+
ProjectedState<
|
|
4726
|
+
StateFromSource<
|
|
4727
|
+
BuiltContractSource<
|
|
4728
|
+
ClientContractRegistry<TSchemas>,
|
|
4729
|
+
WithKind<TBody, TKind>
|
|
4730
|
+
>
|
|
4731
|
+
>,
|
|
4732
|
+
SchemasFromSource<
|
|
4733
|
+
BuiltContractSource<
|
|
4734
|
+
ClientContractRegistry<TSchemas>,
|
|
4735
|
+
WithKind<TBody, TKind>
|
|
4736
|
+
>
|
|
4737
|
+
>
|
|
4738
|
+
>
|
|
4739
|
+
> {
|
|
4740
|
+
return defineContract(
|
|
4741
|
+
registry,
|
|
4742
|
+
(ref) => ({ ...build(ref), kind }),
|
|
4743
|
+
) as unknown as DefinedContract<
|
|
4744
|
+
OwnedApiFromSource<
|
|
4745
|
+
BuiltContractSource<
|
|
4746
|
+
ClientContractRegistry<TSchemas>,
|
|
4747
|
+
WithKind<TBody, TKind>
|
|
4748
|
+
>
|
|
4749
|
+
>,
|
|
4750
|
+
UsedApiFromSource<
|
|
4751
|
+
BuiltContractSource<
|
|
4752
|
+
ClientContractRegistry<TSchemas>,
|
|
4753
|
+
WithKind<TBody, TKind>
|
|
4754
|
+
>
|
|
4755
|
+
>,
|
|
4756
|
+
MergeApis<
|
|
4757
|
+
OwnedApiFromSource<
|
|
4758
|
+
BuiltContractSource<
|
|
4759
|
+
ClientContractRegistry<TSchemas>,
|
|
4760
|
+
WithKind<TBody, TKind>
|
|
4761
|
+
>
|
|
4762
|
+
>,
|
|
4763
|
+
UsedApiFromSource<
|
|
4764
|
+
BuiltContractSource<
|
|
4765
|
+
ClientContractRegistry<TSchemas>,
|
|
4766
|
+
WithKind<TBody, TKind>
|
|
4767
|
+
>
|
|
4768
|
+
>
|
|
4769
|
+
>,
|
|
4770
|
+
TBody["id"],
|
|
4771
|
+
{},
|
|
4772
|
+
ProjectedState<
|
|
4773
|
+
StateFromSource<
|
|
4774
|
+
BuiltContractSource<
|
|
4775
|
+
ClientContractRegistry<TSchemas>,
|
|
4776
|
+
WithKind<TBody, TKind>
|
|
4777
|
+
>
|
|
4778
|
+
>,
|
|
4779
|
+
SchemasFromSource<
|
|
4780
|
+
BuiltContractSource<
|
|
4781
|
+
ClientContractRegistry<TSchemas>,
|
|
4782
|
+
WithKind<TBody, TKind>
|
|
4783
|
+
>
|
|
4784
|
+
>
|
|
4785
|
+
>
|
|
4786
|
+
>;
|
|
4787
|
+
}
|
|
4788
|
+
|
|
4789
|
+
export function defineAppContract<
|
|
4790
|
+
const TSchemas extends Readonly<Record<string, TSchema>> | undefined,
|
|
4791
|
+
const TUses extends AuthorContractUses | undefined,
|
|
4792
|
+
const TBody extends ClientContractBodyInput<TSchemas, TUses>,
|
|
4793
|
+
>(
|
|
4794
|
+
registry: ClientContractRegistry<TSchemas> & {
|
|
4795
|
+
capabilities?: never;
|
|
4796
|
+
exports?: never;
|
|
4797
|
+
},
|
|
4798
|
+
build: (ref: ContractRefBuilder<TSchemas>) => TBody,
|
|
4799
|
+
): DefinedContract<
|
|
4800
|
+
OwnedApiFromSource<
|
|
4801
|
+
BuiltContractSource<
|
|
4802
|
+
ClientContractRegistry<TSchemas>,
|
|
4803
|
+
WithKind<TBody, "app">
|
|
4804
|
+
>
|
|
4805
|
+
>,
|
|
4806
|
+
UsedApiFromSource<
|
|
4807
|
+
BuiltContractSource<
|
|
4808
|
+
ClientContractRegistry<TSchemas>,
|
|
4809
|
+
WithKind<TBody, "app">
|
|
4810
|
+
>
|
|
4811
|
+
>,
|
|
4812
|
+
MergeApis<
|
|
4813
|
+
OwnedApiFromSource<
|
|
4814
|
+
BuiltContractSource<
|
|
4815
|
+
ClientContractRegistry<TSchemas>,
|
|
4816
|
+
WithKind<TBody, "app">
|
|
4817
|
+
>
|
|
4818
|
+
>,
|
|
4819
|
+
UsedApiFromSource<
|
|
4820
|
+
BuiltContractSource<
|
|
4821
|
+
ClientContractRegistry<TSchemas>,
|
|
4822
|
+
WithKind<TBody, "app">
|
|
4823
|
+
>
|
|
4824
|
+
>
|
|
4825
|
+
>,
|
|
4826
|
+
TBody["id"],
|
|
4827
|
+
{},
|
|
4828
|
+
ProjectedState<
|
|
4829
|
+
StateFromSource<
|
|
4830
|
+
BuiltContractSource<
|
|
4831
|
+
ClientContractRegistry<TSchemas>,
|
|
4832
|
+
WithKind<TBody, "app">
|
|
4833
|
+
>
|
|
4834
|
+
>,
|
|
4835
|
+
SchemasFromSource<
|
|
4836
|
+
BuiltContractSource<
|
|
4837
|
+
ClientContractRegistry<TSchemas>,
|
|
4838
|
+
WithKind<TBody, "app">
|
|
4839
|
+
>
|
|
4840
|
+
>
|
|
4841
|
+
>
|
|
4842
|
+
>;
|
|
4843
|
+
export function defineAppContract<
|
|
4844
|
+
const TUses extends AuthorContractUses | undefined,
|
|
4845
|
+
const TBody extends ClientContractBodyInput<undefined, TUses>,
|
|
4846
|
+
>(build: () => TBody): DefinedContract<
|
|
4847
|
+
OwnedApiFromSource<WithKind<TBody, "app">>,
|
|
4848
|
+
UsedApiFromSource<WithKind<TBody, "app">>,
|
|
4849
|
+
MergeApis<
|
|
4850
|
+
OwnedApiFromSource<WithKind<TBody, "app">>,
|
|
4851
|
+
UsedApiFromSource<WithKind<TBody, "app">>
|
|
4852
|
+
>,
|
|
4853
|
+
TBody["id"],
|
|
4854
|
+
{},
|
|
4855
|
+
ProjectedState<
|
|
4856
|
+
StateFromSource<WithKind<TBody, "app">>,
|
|
4857
|
+
SchemasFromSource<WithKind<TBody, "app">>
|
|
4858
|
+
>
|
|
4859
|
+
>;
|
|
4860
|
+
export function defineAppContract(
|
|
4861
|
+
...args:
|
|
4862
|
+
| [() => ContractIdentityFields & Record<string, unknown>]
|
|
4863
|
+
| [
|
|
4864
|
+
ClientContractRegistry<Readonly<Record<string, TSchema>>> & {
|
|
4865
|
+
capabilities?: never;
|
|
4866
|
+
exports?: never;
|
|
4867
|
+
},
|
|
4868
|
+
(
|
|
4869
|
+
ref: ContractRefBuilder<Readonly<Record<string, TSchema>>>,
|
|
4870
|
+
) => ContractIdentityFields & Record<string, unknown>,
|
|
4871
|
+
]
|
|
4872
|
+
) {
|
|
4873
|
+
const [registryOrBuild, maybeBuild] = args;
|
|
4874
|
+
if (typeof registryOrBuild === "function") {
|
|
4875
|
+
return defineClientContract("app", {}, () => registryOrBuild());
|
|
4876
|
+
}
|
|
4877
|
+
|
|
4878
|
+
return defineClientContract("app", registryOrBuild, maybeBuild!);
|
|
4879
|
+
}
|
|
4880
|
+
|
|
4881
|
+
export function defineAgentContract<
|
|
4882
|
+
const TSchemas extends Readonly<Record<string, TSchema>> | undefined,
|
|
4883
|
+
const TUses extends AuthorContractUses | undefined,
|
|
4884
|
+
const TBody extends ClientContractBodyInput<TSchemas, TUses>,
|
|
4885
|
+
>(
|
|
4886
|
+
registry: ClientContractRegistry<TSchemas> & {
|
|
4887
|
+
capabilities?: never;
|
|
4888
|
+
exports?: never;
|
|
4889
|
+
},
|
|
4890
|
+
build: (ref: ContractRefBuilder<TSchemas>) => TBody,
|
|
4891
|
+
): DefinedContract<
|
|
4892
|
+
OwnedApiFromSource<
|
|
4893
|
+
BuiltContractSource<
|
|
4894
|
+
ClientContractRegistry<TSchemas>,
|
|
4895
|
+
WithKind<TBody, "agent">
|
|
4896
|
+
>
|
|
4897
|
+
>,
|
|
4898
|
+
UsedApiFromSource<
|
|
4899
|
+
BuiltContractSource<
|
|
4900
|
+
ClientContractRegistry<TSchemas>,
|
|
4901
|
+
WithKind<TBody, "agent">
|
|
4902
|
+
>
|
|
4903
|
+
>,
|
|
4904
|
+
MergeApis<
|
|
4905
|
+
OwnedApiFromSource<
|
|
4906
|
+
BuiltContractSource<
|
|
4907
|
+
ClientContractRegistry<TSchemas>,
|
|
4908
|
+
WithKind<TBody, "agent">
|
|
4909
|
+
>
|
|
4910
|
+
>,
|
|
4911
|
+
UsedApiFromSource<
|
|
4912
|
+
BuiltContractSource<
|
|
4913
|
+
ClientContractRegistry<TSchemas>,
|
|
4914
|
+
WithKind<TBody, "agent">
|
|
4915
|
+
>
|
|
4916
|
+
>
|
|
4917
|
+
>,
|
|
4918
|
+
TBody["id"],
|
|
4919
|
+
{},
|
|
4920
|
+
ProjectedState<
|
|
4921
|
+
StateFromSource<
|
|
4922
|
+
BuiltContractSource<
|
|
4923
|
+
ClientContractRegistry<TSchemas>,
|
|
4924
|
+
WithKind<TBody, "agent">
|
|
4925
|
+
>
|
|
4926
|
+
>,
|
|
4927
|
+
SchemasFromSource<
|
|
4928
|
+
BuiltContractSource<
|
|
4929
|
+
ClientContractRegistry<TSchemas>,
|
|
4930
|
+
WithKind<TBody, "agent">
|
|
4931
|
+
>
|
|
4932
|
+
>
|
|
4933
|
+
>
|
|
4934
|
+
>;
|
|
4935
|
+
export function defineAgentContract<
|
|
4936
|
+
const TUses extends AuthorContractUses | undefined,
|
|
4937
|
+
const TBody extends ClientContractBodyInput<undefined, TUses>,
|
|
4938
|
+
>(build: () => TBody): DefinedContract<
|
|
4939
|
+
OwnedApiFromSource<WithKind<TBody, "agent">>,
|
|
4940
|
+
UsedApiFromSource<WithKind<TBody, "agent">>,
|
|
4941
|
+
MergeApis<
|
|
4942
|
+
OwnedApiFromSource<WithKind<TBody, "agent">>,
|
|
4943
|
+
UsedApiFromSource<WithKind<TBody, "agent">>
|
|
4944
|
+
>,
|
|
4945
|
+
TBody["id"],
|
|
4946
|
+
{},
|
|
4947
|
+
ProjectedState<
|
|
4948
|
+
StateFromSource<WithKind<TBody, "agent">>,
|
|
4949
|
+
SchemasFromSource<WithKind<TBody, "agent">>
|
|
4950
|
+
>
|
|
4951
|
+
>;
|
|
4952
|
+
export function defineAgentContract(
|
|
4953
|
+
...args:
|
|
4954
|
+
| [() => ContractIdentityFields & Record<string, unknown>]
|
|
4955
|
+
| [
|
|
4956
|
+
ClientContractRegistry<Readonly<Record<string, TSchema>>> & {
|
|
4957
|
+
capabilities?: never;
|
|
4958
|
+
exports?: never;
|
|
4959
|
+
},
|
|
4960
|
+
(
|
|
4961
|
+
ref: ContractRefBuilder<Readonly<Record<string, TSchema>>>,
|
|
4962
|
+
) => ContractIdentityFields & Record<string, unknown>,
|
|
4963
|
+
]
|
|
4964
|
+
) {
|
|
4965
|
+
const [registryOrBuild, maybeBuild] = args;
|
|
4966
|
+
if (typeof registryOrBuild === "function") {
|
|
4967
|
+
return defineClientContract("agent", {}, () => registryOrBuild());
|
|
4968
|
+
}
|
|
4969
|
+
|
|
4970
|
+
return defineClientContract("agent", registryOrBuild, maybeBuild!);
|
|
4971
|
+
}
|
|
4972
|
+
|
|
4973
|
+
export function defineDeviceContract<
|
|
4974
|
+
const TSchemas extends Readonly<Record<string, TSchema>> | undefined,
|
|
4975
|
+
const TUses extends AuthorContractUses | undefined,
|
|
4976
|
+
const TBody extends ClientContractBodyInput<TSchemas, TUses>,
|
|
4977
|
+
>(
|
|
4978
|
+
registry: ClientContractRegistry<TSchemas> & {
|
|
4979
|
+
capabilities?: never;
|
|
4980
|
+
exports?: never;
|
|
4981
|
+
},
|
|
4982
|
+
build: (ref: ContractRefBuilder<TSchemas>) => TBody,
|
|
4983
|
+
): DefinedContract<
|
|
4984
|
+
OwnedApiFromSource<
|
|
4985
|
+
BuiltContractSource<
|
|
4986
|
+
ClientContractRegistry<TSchemas>,
|
|
4987
|
+
WithKind<TBody, "device">
|
|
4988
|
+
>
|
|
4989
|
+
>,
|
|
4990
|
+
UsedApiFromSource<
|
|
4991
|
+
BuiltContractSource<
|
|
4992
|
+
ClientContractRegistry<TSchemas>,
|
|
4993
|
+
WithKind<TBody, "device">
|
|
4994
|
+
>
|
|
4995
|
+
>,
|
|
4996
|
+
MergeApis<
|
|
4997
|
+
OwnedApiFromSource<
|
|
4998
|
+
BuiltContractSource<
|
|
4999
|
+
ClientContractRegistry<TSchemas>,
|
|
5000
|
+
WithKind<TBody, "device">
|
|
5001
|
+
>
|
|
5002
|
+
>,
|
|
5003
|
+
UsedApiFromSource<
|
|
5004
|
+
BuiltContractSource<
|
|
5005
|
+
ClientContractRegistry<TSchemas>,
|
|
5006
|
+
WithKind<TBody, "device">
|
|
5007
|
+
>
|
|
5008
|
+
>
|
|
5009
|
+
>,
|
|
5010
|
+
TBody["id"],
|
|
5011
|
+
{},
|
|
5012
|
+
ProjectedState<
|
|
5013
|
+
StateFromSource<
|
|
5014
|
+
BuiltContractSource<
|
|
5015
|
+
ClientContractRegistry<TSchemas>,
|
|
5016
|
+
WithKind<TBody, "device">
|
|
5017
|
+
>
|
|
5018
|
+
>,
|
|
5019
|
+
SchemasFromSource<
|
|
5020
|
+
BuiltContractSource<
|
|
5021
|
+
ClientContractRegistry<TSchemas>,
|
|
5022
|
+
WithKind<TBody, "device">
|
|
5023
|
+
>
|
|
5024
|
+
>
|
|
5025
|
+
>
|
|
5026
|
+
>;
|
|
5027
|
+
export function defineDeviceContract<
|
|
5028
|
+
const TUses extends AuthorContractUses | undefined,
|
|
5029
|
+
const TBody extends ClientContractBodyInput<undefined, TUses>,
|
|
5030
|
+
>(build: () => TBody): DefinedContract<
|
|
5031
|
+
OwnedApiFromSource<WithKind<TBody, "device">>,
|
|
5032
|
+
UsedApiFromSource<WithKind<TBody, "device">>,
|
|
5033
|
+
MergeApis<
|
|
5034
|
+
OwnedApiFromSource<WithKind<TBody, "device">>,
|
|
5035
|
+
UsedApiFromSource<WithKind<TBody, "device">>
|
|
5036
|
+
>,
|
|
5037
|
+
TBody["id"],
|
|
5038
|
+
{},
|
|
5039
|
+
ProjectedState<
|
|
5040
|
+
StateFromSource<WithKind<TBody, "device">>,
|
|
5041
|
+
SchemasFromSource<WithKind<TBody, "device">>
|
|
5042
|
+
>
|
|
5043
|
+
>;
|
|
5044
|
+
export function defineDeviceContract(
|
|
5045
|
+
...args:
|
|
5046
|
+
| [() => ContractIdentityFields & Record<string, unknown>]
|
|
5047
|
+
| [
|
|
5048
|
+
ClientContractRegistry<Readonly<Record<string, TSchema>>> & {
|
|
5049
|
+
capabilities?: never;
|
|
5050
|
+
exports?: never;
|
|
5051
|
+
},
|
|
5052
|
+
(
|
|
5053
|
+
ref: ContractRefBuilder<Readonly<Record<string, TSchema>>>,
|
|
5054
|
+
) => ContractIdentityFields & Record<string, unknown>,
|
|
5055
|
+
]
|
|
5056
|
+
) {
|
|
5057
|
+
const [registryOrBuild, maybeBuild] = args;
|
|
5058
|
+
if (typeof registryOrBuild === "function") {
|
|
5059
|
+
return defineClientContract("device", {}, () => registryOrBuild());
|
|
5060
|
+
}
|
|
5061
|
+
|
|
5062
|
+
return defineClientContract("device", registryOrBuild, maybeBuild!);
|
|
5063
|
+
}
|
|
5064
|
+
|
|
5065
|
+
export type {
|
|
5066
|
+
EventDesc,
|
|
5067
|
+
FeedDesc,
|
|
5068
|
+
InferRuntimeRpcError,
|
|
5069
|
+
InferSchemaType,
|
|
5070
|
+
JsonValue,
|
|
5071
|
+
RPCDesc,
|
|
5072
|
+
RpcErrorClass,
|
|
5073
|
+
RuntimeRpcErrorDesc,
|
|
5074
|
+
Schema,
|
|
5075
|
+
SchemaLike,
|
|
5076
|
+
SerializableErrorData,
|
|
5077
|
+
TrellisAPI,
|
|
5078
|
+
};
|
|
5079
|
+
export { canonicalizeJson, digestJson, isJsonValue, schema, unwrapSchema };
|