@segmentstream/ontology 0.0.0-stage → 0.92.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -0
- package/NOTICE +2 -0
- package/README.md +1655 -2
- package/dist/action.d.ts +193 -0
- package/dist/action.js +41 -0
- package/dist/agent-chat.d.ts +44 -0
- package/dist/agent-chat.js +91 -0
- package/dist/agent-task-contract.d.ts +64 -0
- package/dist/agent-task-contract.js +15 -0
- package/dist/agent-task.d.ts +39 -0
- package/dist/agent-task.js +112 -0
- package/dist/analyze.d.ts +215 -0
- package/dist/analyze.js +2438 -0
- package/dist/app-feedback.d.ts +167 -0
- package/dist/app-feedback.js +176 -0
- package/dist/authoring-input.d.ts +3 -0
- package/dist/authoring-input.js +107 -0
- package/dist/authoring-names.d.ts +4 -0
- package/dist/authoring-names.js +13 -0
- package/dist/authoring-records.d.ts +35 -0
- package/dist/authoring-records.js +264 -0
- package/dist/authoring.d.ts +15 -0
- package/dist/authoring.js +331 -0
- package/dist/bin/check.d.ts +30 -0
- package/dist/bin/check.js +99 -0
- package/dist/bin/load.d.ts +48 -0
- package/dist/bin/load.js +139 -0
- package/dist/bin/main.d.ts +31 -0
- package/dist/bin/main.js +121 -0
- package/dist/bin/migrate.d.ts +57 -0
- package/dist/bin/migrate.js +170 -0
- package/dist/bin/output.d.ts +31 -0
- package/dist/bin/output.js +84 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +31 -0
- package/dist/blob.d.ts +52 -0
- package/dist/blob.js +87 -0
- package/dist/channel-session.d.ts +16 -0
- package/dist/channel-session.js +16 -0
- package/dist/chat.d.ts +43 -0
- package/dist/chat.js +34 -0
- package/dist/confirmation.d.ts +46 -0
- package/dist/confirmation.js +41 -0
- package/dist/connection.d.ts +213 -0
- package/dist/connection.js +289 -0
- package/dist/deployment.d.ts +35 -0
- package/dist/deployment.js +76 -0
- package/dist/diagnostics.d.ts +27 -0
- package/dist/diagnostics.js +106 -0
- package/dist/emails.d.ts +70 -0
- package/dist/emails.js +221 -0
- package/dist/entity.d.ts +331 -0
- package/dist/entity.js +153 -0
- package/dist/errors.d.ts +154 -0
- package/dist/errors.js +109 -0
- package/dist/feedback-config.d.ts +24 -0
- package/dist/feedback-config.js +126 -0
- package/dist/files.d.ts +39 -0
- package/dist/files.js +4 -0
- package/dist/groups.d.ts +95 -0
- package/dist/groups.js +280 -0
- package/dist/index.d.ts +109 -0
- package/dist/index.js +70 -0
- package/dist/internal/diagnostics.js +594 -0
- package/dist/legacy.d.ts +160 -0
- package/dist/legacy.js +270 -0
- package/dist/manifest-compatibility.d.ts +8 -0
- package/dist/manifest-compatibility.js +87 -0
- package/dist/manifest.d.ts +3329 -0
- package/dist/manifest.js +757 -0
- package/dist/me.d.ts +46 -0
- package/dist/me.js +109 -0
- package/dist/metric-filters.d.ts +48 -0
- package/dist/metric-filters.js +252 -0
- package/dist/metric-routes.d.ts +132 -0
- package/dist/metric-routes.js +498 -0
- package/dist/metric.d.ts +172 -0
- package/dist/metric.js +132 -0
- package/dist/migrate/apply.d.ts +94 -0
- package/dist/migrate/apply.js +526 -0
- package/dist/migrate/errors.d.ts +46 -0
- package/dist/migrate/errors.js +38 -0
- package/dist/migrate/index.d.ts +10 -0
- package/dist/migrate/index.js +7 -0
- package/dist/migrate/model.d.ts +2311 -0
- package/dist/migrate/model.js +148 -0
- package/dist/migrate/plan.d.ts +51 -0
- package/dist/migrate/plan.js +1856 -0
- package/dist/migrate/preview.d.ts +13 -0
- package/dist/migrate/preview.js +65 -0
- package/dist/migrate/storage.d.ts +226 -0
- package/dist/migrate/storage.js +774 -0
- package/dist/model-metrics.d.ts +22 -0
- package/dist/model-metrics.js +545 -0
- package/dist/names.d.ts +49 -0
- package/dist/names.js +110 -0
- package/dist/navigation-artifact.d.ts +13 -0
- package/dist/navigation-artifact.js +11 -0
- package/dist/navigation-catalog.d.ts +55 -0
- package/dist/navigation-catalog.js +297 -0
- package/dist/nitro-navigation.d.ts +3 -0
- package/dist/nitro-navigation.js +64 -0
- package/dist/nitro-workflows.d.ts +108 -0
- package/dist/nitro-workflows.js +286 -0
- package/dist/nitro.d.ts +40 -0
- package/dist/nitro.js +50 -0
- package/dist/ontology.d.ts +41 -0
- package/dist/ontology.js +46 -0
- package/dist/permissions.d.ts +198 -0
- package/dist/permissions.js +272 -0
- package/dist/property.d.ts +188 -0
- package/dist/property.js +301 -0
- package/dist/query.d.ts +245 -0
- package/dist/query.js +615 -0
- package/dist/relationship.d.ts +99 -0
- package/dist/relationship.js +33 -0
- package/dist/render.d.ts +81 -0
- package/dist/render.js +512 -0
- package/dist/replication/baseline.d.ts +51 -0
- package/dist/replication/baseline.js +215 -0
- package/dist/replication/bigquery.d.ts +37 -0
- package/dist/replication/bigquery.js +211 -0
- package/dist/replication/coverage.d.ts +14 -0
- package/dist/replication/coverage.js +53 -0
- package/dist/replication/evolution.d.ts +25 -0
- package/dist/replication/evolution.js +184 -0
- package/dist/replication/identities.d.ts +6 -0
- package/dist/replication/identities.js +47 -0
- package/dist/replication/legacy-baseline.d.ts +27 -0
- package/dist/replication/legacy-baseline.js +109 -0
- package/dist/replication/legacy-store.d.ts +19 -0
- package/dist/replication/legacy-store.js +63 -0
- package/dist/replication/lineage.d.ts +36 -0
- package/dist/replication/lineage.js +72 -0
- package/dist/replication/migrate.d.ts +21 -0
- package/dist/replication/migrate.js +84 -0
- package/dist/replication/model.d.ts +52 -0
- package/dist/replication/model.js +99 -0
- package/dist/replication/scans.d.ts +34 -0
- package/dist/replication/scans.js +158 -0
- package/dist/replication/schema.d.ts +11 -0
- package/dist/replication/schema.js +226 -0
- package/dist/replication/shadow-schema.d.ts +4 -0
- package/dist/replication/shadow-schema.js +61 -0
- package/dist/replication/shadow.d.ts +127 -0
- package/dist/replication/shadow.js +614 -0
- package/dist/replication/source-replacement.d.ts +33 -0
- package/dist/replication/source-replacement.js +76 -0
- package/dist/replication/store.d.ts +36 -0
- package/dist/replication/store.js +382 -0
- package/dist/replication/transaction.d.ts +23 -0
- package/dist/replication/transaction.js +88 -0
- package/dist/role.d.ts +61 -0
- package/dist/role.js +76 -0
- package/dist/runtime/action-deadlocks.d.ts +21 -0
- package/dist/runtime/action-deadlocks.js +130 -0
- package/dist/runtime/action-transactions.d.ts +35 -0
- package/dist/runtime/action-transactions.js +54 -0
- package/dist/runtime/agent-counters.d.ts +26 -0
- package/dist/runtime/agent-counters.js +98 -0
- package/dist/runtime/agent-tasks.d.ts +63 -0
- package/dist/runtime/agent-tasks.js +120 -0
- package/dist/runtime/agents.d.ts +15 -0
- package/dist/runtime/agents.js +457 -0
- package/dist/runtime/batch-diagnostics.d.ts +22 -0
- package/dist/runtime/batch-diagnostics.js +89 -0
- package/dist/runtime/batch.d.ts +52 -0
- package/dist/runtime/batch.js +534 -0
- package/dist/runtime/channel-session-revocation.d.ts +3 -0
- package/dist/runtime/channel-session-revocation.js +5 -0
- package/dist/runtime/channel-sessions.d.ts +4 -0
- package/dist/runtime/channel-sessions.js +61 -0
- package/dist/runtime/confirmations.d.ts +29 -0
- package/dist/runtime/confirmations.js +57 -0
- package/dist/runtime/cursor.d.ts +23 -0
- package/dist/runtime/cursor.js +100 -0
- package/dist/runtime/deployment.d.ts +7 -0
- package/dist/runtime/deployment.js +4 -0
- package/dist/runtime/errors.d.ts +118 -0
- package/dist/runtime/errors.js +109 -0
- package/dist/runtime/federation-tables.d.ts +2 -0
- package/dist/runtime/federation-tables.js +20 -0
- package/dist/runtime/federation.d.ts +42 -0
- package/dist/runtime/federation.js +222 -0
- package/dist/runtime/files.d.ts +39 -0
- package/dist/runtime/files.js +44 -0
- package/dist/runtime/generated-actions.d.ts +37 -0
- package/dist/runtime/generated-actions.js +307 -0
- package/dist/runtime/history.d.ts +91 -0
- package/dist/runtime/history.js +77 -0
- package/dist/runtime/ids.d.ts +6 -0
- package/dist/runtime/ids.js +39 -0
- package/dist/runtime/member-tables.d.ts +8 -0
- package/dist/runtime/member-tables.js +33 -0
- package/dist/runtime/member-writes.d.ts +78 -0
- package/dist/runtime/member-writes.js +202 -0
- package/dist/runtime/metric-query.d.ts +19 -0
- package/dist/runtime/metric-query.js +411 -0
- package/dist/runtime/model.d.ts +67 -0
- package/dist/runtime/model.js +150 -0
- package/dist/runtime/new-user-hook.d.ts +6 -0
- package/dist/runtime/new-user-hook.js +37 -0
- package/dist/runtime/oauth.d.ts +9 -0
- package/dist/runtime/oauth.js +299 -0
- package/dist/runtime/pipeline.d.ts +155 -0
- package/dist/runtime/pipeline.js +597 -0
- package/dist/runtime/postgres-tls.d.ts +10 -0
- package/dist/runtime/postgres-tls.js +14 -0
- package/dist/runtime/principals.d.ts +302 -0
- package/dist/runtime/principals.js +1307 -0
- package/dist/runtime/reads.d.ts +55 -0
- package/dist/runtime/reads.js +313 -0
- package/dist/runtime/records.d.ts +42 -0
- package/dist/runtime/records.js +245 -0
- package/dist/runtime/resolve-agent-identity.d.ts +6 -0
- package/dist/runtime/resolve-agent-identity.js +181 -0
- package/dist/runtime/service-binding.d.ts +18 -0
- package/dist/runtime/service-binding.js +266 -0
- package/dist/runtime/sign-in-links.d.ts +68 -0
- package/dist/runtime/sign-in-links.js +147 -0
- package/dist/runtime/sql-runtime.d.ts +131 -0
- package/dist/runtime/sql-runtime.js +362 -0
- package/dist/runtime/statement.d.ts +18 -0
- package/dist/runtime/statement.js +31 -0
- package/dist/runtime/user-identities.d.ts +66 -0
- package/dist/runtime/user-identities.js +106 -0
- package/dist/runtime/user-identity-sql.d.ts +86 -0
- package/dist/runtime/user-identity-sql.js +297 -0
- package/dist/runtime/user-roles.d.ts +16 -0
- package/dist/runtime/user-roles.js +32 -0
- package/dist/runtime/validation.d.ts +16 -0
- package/dist/runtime/validation.js +26 -0
- package/dist/runtime/where.d.ts +57 -0
- package/dist/runtime/where.js +404 -0
- package/dist/runtime/workflow-admission.d.ts +49 -0
- package/dist/runtime/workflow-admission.js +92 -0
- package/dist/runtime/workflow-argument-codec.d.ts +10 -0
- package/dist/runtime/workflow-argument-codec.js +120 -0
- package/dist/runtime/workflow-arguments.d.ts +17 -0
- package/dist/runtime/workflow-arguments.js +99 -0
- package/dist/runtime/workflow-starts.d.ts +203 -0
- package/dist/runtime/workflow-starts.js +493 -0
- package/dist/runtime/workflow-users.d.ts +9 -0
- package/dist/runtime/workflow-users.js +17 -0
- package/dist/runtime/workload.d.ts +25 -0
- package/dist/runtime/workload.js +24 -0
- package/dist/runtime/writes.d.ts +108 -0
- package/dist/runtime/writes.js +491 -0
- package/dist/runtime-source.d.ts +22 -0
- package/dist/runtime-source.js +28 -0
- package/dist/runtime.d.ts +310 -0
- package/dist/runtime.js +31 -0
- package/dist/server.d.ts +23 -0
- package/dist/server.js +107 -0
- package/dist/service/agent/attachments.d.ts +33 -0
- package/dist/service/agent/attachments.js +228 -0
- package/dist/service/agent/authentication.d.ts +22 -0
- package/dist/service/agent/authentication.js +58 -0
- package/dist/service/agent/confirmations.d.ts +5 -0
- package/dist/service/agent/confirmations.js +73 -0
- package/dist/service/agent/conversation-routes.d.ts +14 -0
- package/dist/service/agent/conversation-routes.js +45 -0
- package/dist/service/agent/conversations.d.ts +40 -0
- package/dist/service/agent/conversations.js +69 -0
- package/dist/service/agent/files.d.ts +12 -0
- package/dist/service/agent/files.js +69 -0
- package/dist/service/agent/protocol.d.ts +90 -0
- package/dist/service/agent/protocol.js +114 -0
- package/dist/service/agent/server.d.ts +28 -0
- package/dist/service/agent/server.js +374 -0
- package/dist/service/agent/task-caller.d.ts +21 -0
- package/dist/service/agent/task-caller.js +35 -0
- package/dist/service/agent/task-start.d.ts +53 -0
- package/dist/service/agent/task-start.js +161 -0
- package/dist/service/agent/tasks.d.ts +40 -0
- package/dist/service/agent/tasks.js +155 -0
- package/dist/service/api.d.ts +50 -0
- package/dist/service/api.js +288 -0
- package/dist/service/authentication.d.ts +227 -0
- package/dist/service/authentication.js +767 -0
- package/dist/service/caller-context.d.ts +24 -0
- package/dist/service/caller-context.js +6 -0
- package/dist/service/catalog.d.ts +42 -0
- package/dist/service/catalog.js +66 -0
- package/dist/service/channel/provider.d.ts +10 -0
- package/dist/service/channel/provider.js +1 -0
- package/dist/service/channel/providers/telegram.d.ts +18 -0
- package/dist/service/channel/providers/telegram.js +108 -0
- package/dist/service/channel/sessions.d.ts +5 -0
- package/dist/service/channel/sessions.js +53 -0
- package/dist/service/channel/sign-in.d.ts +7 -0
- package/dist/service/channel/sign-in.js +78 -0
- package/dist/service/chat/archive.d.ts +64 -0
- package/dist/service/chat/archive.js +62 -0
- package/dist/service/chat/attribution.d.ts +26 -0
- package/dist/service/chat/attribution.js +28 -0
- package/dist/service/chat/delivery.d.ts +18 -0
- package/dist/service/chat/delivery.js +251 -0
- package/dist/service/chat/diagnostics.d.ts +2 -0
- package/dist/service/chat/diagnostics.js +35 -0
- package/dist/service/chat/envelope.d.ts +96 -0
- package/dist/service/chat/envelope.js +39 -0
- package/dist/service/chat/idempotency.d.ts +19 -0
- package/dist/service/chat/idempotency.js +37 -0
- package/dist/service/chat/providers/telegram.d.ts +36 -0
- package/dist/service/chat/providers/telegram.js +133 -0
- package/dist/service/chat/reads.d.ts +25 -0
- package/dist/service/chat/reads.js +75 -0
- package/dist/service/chat/resolve.d.ts +34 -0
- package/dist/service/chat/resolve.js +150 -0
- package/dist/service/chat/routes.d.ts +23 -0
- package/dist/service/chat/routes.js +75 -0
- package/dist/service/chat/schemas.d.ts +43 -0
- package/dist/service/chat/schemas.js +31 -0
- package/dist/service/config.d.ts +218 -0
- package/dist/service/config.js +265 -0
- package/dist/service/connection-stream.d.ts +10 -0
- package/dist/service/connection-stream.js +191 -0
- package/dist/service/connections.d.ts +60 -0
- package/dist/service/connections.js +271 -0
- package/dist/service/decisions.d.ts +35 -0
- package/dist/service/decisions.js +63 -0
- package/dist/service/descriptions.d.ts +8 -0
- package/dist/service/descriptions.js +20 -0
- package/dist/service/discovery-schemas.d.ts +92 -0
- package/dist/service/discovery-schemas.js +59 -0
- package/dist/service/discovery-search.d.ts +30 -0
- package/dist/service/discovery-search.js +95 -0
- package/dist/service/discovery.d.ts +37 -0
- package/dist/service/discovery.js +436 -0
- package/dist/service/docs.d.ts +9 -0
- package/dist/service/docs.js +197 -0
- package/dist/service/errors.d.ts +145 -0
- package/dist/service/errors.js +704 -0
- package/dist/service/federation-provider.d.ts +36 -0
- package/dist/service/federation-provider.js +110 -0
- package/dist/service/federation-server.d.ts +20 -0
- package/dist/service/federation-server.js +249 -0
- package/dist/service/federation-status.d.ts +40 -0
- package/dist/service/federation-status.js +151 -0
- package/dist/service/handlers.d.ts +18 -0
- package/dist/service/handlers.js +287 -0
- package/dist/service/mcp/confirmation.d.ts +68 -0
- package/dist/service/mcp/confirmation.js +178 -0
- package/dist/service/mcp/find-input.d.ts +12 -0
- package/dist/service/mcp/find-input.js +122 -0
- package/dist/service/mcp/input-schema.d.ts +6 -0
- package/dist/service/mcp/input-schema.js +126 -0
- package/dist/service/mcp/listing.d.ts +26 -0
- package/dist/service/mcp/listing.js +92 -0
- package/dist/service/mcp/metric-tools.d.ts +85 -0
- package/dist/service/mcp/metric-tools.js +258 -0
- package/dist/service/mcp/request-log.d.ts +5 -0
- package/dist/service/mcp/request-log.js +53 -0
- package/dist/service/mcp/runtime-policy.d.ts +27 -0
- package/dist/service/mcp/runtime-policy.js +62 -0
- package/dist/service/mcp/server.d.ts +52 -0
- package/dist/service/mcp/server.js +861 -0
- package/dist/service/mcp/tools.d.ts +99 -0
- package/dist/service/mcp/tools.js +938 -0
- package/dist/service/member-file-routes.d.ts +22 -0
- package/dist/service/member-file-routes.js +52 -0
- package/dist/service/member-files.d.ts +245 -0
- package/dist/service/member-files.js +258 -0
- package/dist/service/metric-query-platform.d.ts +77 -0
- package/dist/service/metric-query-platform.js +198 -0
- package/dist/service/metric-query-scopes.d.ts +43 -0
- package/dist/service/metric-query-scopes.js +147 -0
- package/dist/service/metric-query.d.ts +48 -0
- package/dist/service/metric-query.js +200 -0
- package/dist/service/name-suggestions.d.ts +3 -0
- package/dist/service/name-suggestions.js +38 -0
- package/dist/service/navigation-schemas.d.ts +80 -0
- package/dist/service/navigation-schemas.js +49 -0
- package/dist/service/navigation.d.ts +20 -0
- package/dist/service/navigation.js +165 -0
- package/dist/service/oauth/protocol.d.ts +70 -0
- package/dist/service/oauth/protocol.js +157 -0
- package/dist/service/oauth/refresh-replay.d.ts +2 -0
- package/dist/service/oauth/refresh-replay.js +20 -0
- package/dist/service/oauth/server.d.ts +28 -0
- package/dist/service/oauth/server.js +769 -0
- package/dist/service/operations.d.ts +170 -0
- package/dist/service/operations.js +392 -0
- package/dist/service/plan.d.ts +57 -0
- package/dist/service/plan.js +96 -0
- package/dist/service/rate-limit.d.ts +22 -0
- package/dist/service/rate-limit.js +52 -0
- package/dist/service/record-reads.d.ts +21 -0
- package/dist/service/record-reads.js +155 -0
- package/dist/service/replication.d.ts +5 -0
- package/dist/service/replication.js +39 -0
- package/dist/service/runtime-contract.d.ts +508 -0
- package/dist/service/runtime-contract.js +18 -0
- package/dist/service/runtime-identity.d.ts +71 -0
- package/dist/service/runtime-identity.js +122 -0
- package/dist/service/schemas.d.ts +961 -0
- package/dist/service/schemas.js +639 -0
- package/dist/service/service.d.ts +21 -0
- package/dist/service/service.js +526 -0
- package/dist/service/warehouse-platform.d.ts +17 -0
- package/dist/service/warehouse-platform.js +122 -0
- package/dist/service/warehouse-query.d.ts +24 -0
- package/dist/service/warehouse-query.js +280 -0
- package/dist/service/webhooks.d.ts +106 -0
- package/dist/service/webhooks.js +233 -0
- package/dist/service/workflow-admission-provider.d.ts +31 -0
- package/dist/service/workflow-admission-provider.js +205 -0
- package/dist/service/workflow-argument-serialization.d.ts +2 -0
- package/dist/service/workflow-argument-serialization.js +14 -0
- package/dist/service/workflow-callback.d.ts +22 -0
- package/dist/service/workflow-callback.js +75 -0
- package/dist/service/workflow-deployment.d.ts +8 -0
- package/dist/service/workflow-deployment.js +131 -0
- package/dist/service/workflow-diagnostics.d.ts +23 -0
- package/dist/service/workflow-diagnostics.js +263 -0
- package/dist/service/workflow-errors.d.ts +26 -0
- package/dist/service/workflow-errors.js +181 -0
- package/dist/service/workflow-logging.d.ts +2 -0
- package/dist/service/workflow-logging.js +50 -0
- package/dist/service/workflow-queue-fence.d.ts +6 -0
- package/dist/service/workflow-queue-fence.js +66 -0
- package/dist/service/workflows.d.ts +200 -0
- package/dist/service/workflows.js +1549 -0
- package/dist/sign-in.d.ts +58 -0
- package/dist/sign-in.js +57 -0
- package/dist/source.d.ts +30 -0
- package/dist/source.js +107 -0
- package/dist/start-recovery-contract.d.ts +49 -0
- package/dist/start-recovery-contract.js +26 -0
- package/dist/start-recovery.d.ts +27 -0
- package/dist/start-recovery.js +81 -0
- package/dist/storage/api.d.ts +4 -0
- package/dist/storage/api.js +40 -0
- package/dist/storage/attachments.d.ts +146 -0
- package/dist/storage/attachments.js +733 -0
- package/dist/storage/authorization.d.ts +38 -0
- package/dist/storage/authorization.js +83 -0
- package/dist/storage/file-access.d.ts +17 -0
- package/dist/storage/file-access.js +8 -0
- package/dist/storage/limits.d.ts +12 -0
- package/dist/storage/limits.js +17 -0
- package/dist/storage/maintenance-auth.d.ts +20 -0
- package/dist/storage/maintenance-auth.js +24 -0
- package/dist/storage/maintenance.d.ts +11 -0
- package/dist/storage/maintenance.js +67 -0
- package/dist/storage/neon.d.ts +4 -0
- package/dist/storage/neon.js +318 -0
- package/dist/storage/operator.d.ts +11 -0
- package/dist/storage/operator.js +30 -0
- package/dist/storage/provider.d.ts +93 -0
- package/dist/storage/provider.js +36 -0
- package/dist/storage/sessions.d.ts +184 -0
- package/dist/storage/sessions.js +688 -0
- package/dist/storage/tables.d.ts +54 -0
- package/dist/storage/tables.js +205 -0
- package/dist/storage/transfers.d.ts +16 -0
- package/dist/storage/transfers.js +153 -0
- package/dist/storage/writes.d.ts +7 -0
- package/dist/storage/writes.js +88 -0
- package/dist/telegram.d.ts +35 -0
- package/dist/telegram.js +173 -0
- package/dist/user-identity.d.ts +28 -0
- package/dist/user-identity.js +106 -0
- package/dist/user.d.ts +75 -0
- package/dist/user.js +111 -0
- package/dist/warehouse-backed.d.ts +6 -0
- package/dist/warehouse-backed.js +495 -0
- package/dist/webhook-token.d.ts +11 -0
- package/dist/webhook-token.js +18 -0
- package/dist/webhooks.d.ts +40 -0
- package/dist/webhooks.js +55 -0
- package/dist/wire.d.ts +10 -0
- package/dist/wire.js +35 -0
- package/dist/workflow-runtime.d.ts +116 -0
- package/dist/workflow-runtime.js +109 -0
- package/dist/workflow-topics.d.ts +28 -0
- package/dist/workflow-topics.js +28 -0
- package/dist/workflow.d.ts +284 -0
- package/dist/workflow.js +259 -0
- package/dist/workflows.d.ts +24 -0
- package/dist/workflows.js +18 -0
- package/package.json +127 -4
package/dist/query.js
ADDED
|
@@ -0,0 +1,615 @@
|
|
|
1
|
+
import { Schema, SchemaTransformation } from "effect";
|
|
2
|
+
import { expectedOneOf, wireStruct } from "./wire.js";
|
|
3
|
+
import { isValueMatched } from "./manifest.js";
|
|
4
|
+
import { BlobValue } from "./blob.js";
|
|
5
|
+
/**
|
|
6
|
+
* The query language of `find` and of the HTTP API's list and query endpoints.
|
|
7
|
+
*
|
|
8
|
+
* ```json
|
|
9
|
+
* {
|
|
10
|
+
* "where": {
|
|
11
|
+
* "status": { "in": ["new", "contacted"] },
|
|
12
|
+
* "owner": { "email": { "eq": "ada@example.com" } },
|
|
13
|
+
* "tags": { "some": { "name": { "eq": "priority" } } },
|
|
14
|
+
* "or": [{ "fitScore": { "gte": 80 } }, { "source": "pilot_request" }]
|
|
15
|
+
* },
|
|
16
|
+
* "orderBy": [{ "field": "created_at", "direction": "desc" }],
|
|
17
|
+
* "include": ["owner"],
|
|
18
|
+
* "limit": 50
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* {@link Query} checks the structure for any entity; {@link entityQuerySchema} builds the precise
|
|
23
|
+
* schema of one entity from the manifest, with its fields, their operators and its relationships.
|
|
24
|
+
* The runtime validates every query with the precise schema. `include` also takes the object form
|
|
25
|
+
* `{ "owner": true }`, which a list of names decodes into.
|
|
26
|
+
*/
|
|
27
|
+
export const DEFAULT_QUERY_LIMIT = 50;
|
|
28
|
+
export const MAX_QUERY_LIMIT = 200;
|
|
29
|
+
/** The most values an `in` filter takes. */
|
|
30
|
+
export const MAX_IN_VALUES = 1000;
|
|
31
|
+
/** Filter operators. A field's type decides which apply; see {@link entityQuerySchema}. */
|
|
32
|
+
export const FILTER_OPERATORS = [
|
|
33
|
+
"eq",
|
|
34
|
+
"ne",
|
|
35
|
+
"in",
|
|
36
|
+
"isNull",
|
|
37
|
+
"contains",
|
|
38
|
+
"startsWith",
|
|
39
|
+
"gt",
|
|
40
|
+
"gte",
|
|
41
|
+
"lt",
|
|
42
|
+
"lte",
|
|
43
|
+
"between",
|
|
44
|
+
];
|
|
45
|
+
/** Filter operators of a list field: it holds the value, or any of the values. */
|
|
46
|
+
export const LIST_FILTER_OPERATORS = ["has", "hasAny"];
|
|
47
|
+
/** Combinators of a `where`. They take the place of field names. */
|
|
48
|
+
export const WHERE_COMBINATORS = ["and", "or", "not"];
|
|
49
|
+
/** Quantifiers of a filter on a to-many relationship. */
|
|
50
|
+
export const MANY_QUANTIFIERS = ["some", "none", "every"];
|
|
51
|
+
export const SortDirection = Schema.Literals(["asc", "desc"]);
|
|
52
|
+
export const OrderBy = Schema.Struct({
|
|
53
|
+
field: Schema.String,
|
|
54
|
+
direction: Schema.optionalKey(SortDirection),
|
|
55
|
+
});
|
|
56
|
+
const Limit = Schema.Int.check(Schema.isBetween({ minimum: 1, maximum: MAX_QUERY_LIMIT })).annotate({
|
|
57
|
+
description: `How many records to return, ${DEFAULT_QUERY_LIMIT} by default.`,
|
|
58
|
+
});
|
|
59
|
+
const After = Schema.String.annotate({
|
|
60
|
+
description: "The nextCursor of the previous page. It is only valid for the same where and orderBy.",
|
|
61
|
+
});
|
|
62
|
+
/** Whether an `include` is the list form, `["owner", "tags"]`. */
|
|
63
|
+
export function isIncludeList(include) {
|
|
64
|
+
return Array.isArray(include);
|
|
65
|
+
}
|
|
66
|
+
/** The relationship names an `include` lists, in either form. */
|
|
67
|
+
export function includedRelationships(include) {
|
|
68
|
+
if (include === undefined) {
|
|
69
|
+
return [];
|
|
70
|
+
}
|
|
71
|
+
return isIncludeList(include) ? [...new Set(include)] : Object.keys(include);
|
|
72
|
+
}
|
|
73
|
+
/** `["owner", "tags"]` decoded as `{ owner: true, tags: true }`; duplicate names are harmless. */
|
|
74
|
+
function includeList(names, included) {
|
|
75
|
+
return Schema.Array(names).pipe(Schema.decodeTo(included, SchemaTransformation.transform({
|
|
76
|
+
decode: (list) => Object.fromEntries(list.map((name) => [name, true])),
|
|
77
|
+
encode: (relationships) => Object.keys(relationships),
|
|
78
|
+
})));
|
|
79
|
+
}
|
|
80
|
+
const AnyIncluded = Schema.Record(Schema.String, Schema.Literal(true));
|
|
81
|
+
const SelectedFields = Schema.Array(Schema.String).check(Schema.isMaxLength(200));
|
|
82
|
+
/** A query on any entity. The runtime checks the fields against the entity. */
|
|
83
|
+
export const Query = Schema.Struct({
|
|
84
|
+
where: Schema.optionalKey(Schema.Record(Schema.String, Schema.Json)),
|
|
85
|
+
orderBy: Schema.optionalKey(Schema.Array(OrderBy)),
|
|
86
|
+
select: Schema.optionalKey(SelectedFields),
|
|
87
|
+
include: Schema.optionalKey(
|
|
88
|
+
// The list member decodes into the object; the union's static type cannot say so.
|
|
89
|
+
Schema.Union([AnyIncluded, includeList(Schema.String, AnyIncluded)])),
|
|
90
|
+
after: Schema.optionalKey(After),
|
|
91
|
+
limit: Schema.optionalKey(Limit),
|
|
92
|
+
}).annotate({ identifier: "Query" });
|
|
93
|
+
/** A page of records of any entity. */
|
|
94
|
+
export const QueryResult = Schema.Struct({
|
|
95
|
+
items: Schema.Array(Schema.Record(Schema.String, Schema.Json)),
|
|
96
|
+
nextCursor: Schema.NullOr(Schema.String),
|
|
97
|
+
projected: Schema.optionalKey(Schema.Literal(true)),
|
|
98
|
+
}).annotate({ identifier: "QueryResult" });
|
|
99
|
+
/** A page of records described by `record`. */
|
|
100
|
+
export function queryResultSchema(record) {
|
|
101
|
+
return Schema.Struct({ items: Schema.Array(record), nextCursor: Schema.NullOr(Schema.String) });
|
|
102
|
+
}
|
|
103
|
+
/** Full pages keep their complete record contract; projections carry an explicit marker. */
|
|
104
|
+
export function projectedQueryResultSchema(record, projection, wire = false) {
|
|
105
|
+
const full = Schema.Struct({
|
|
106
|
+
items: Schema.Array(record),
|
|
107
|
+
nextCursor: Schema.NullOr(Schema.String),
|
|
108
|
+
projected: Schema.optionalKey(Schema.Never),
|
|
109
|
+
});
|
|
110
|
+
const selected = Schema.Struct({
|
|
111
|
+
items: Schema.Array(projection),
|
|
112
|
+
nextCursor: Schema.NullOr(Schema.String),
|
|
113
|
+
projected: Schema.Literal(true),
|
|
114
|
+
});
|
|
115
|
+
return Schema.Union(wire
|
|
116
|
+
? [
|
|
117
|
+
full.pipe(Schema.encodeKeys({ nextCursor: "next_cursor" })),
|
|
118
|
+
selected.pipe(Schema.encodeKeys({ nextCursor: "next_cursor" })),
|
|
119
|
+
]
|
|
120
|
+
: [full, selected]);
|
|
121
|
+
}
|
|
122
|
+
const SYSTEM_FIELDS = [
|
|
123
|
+
{ name: "id", storage: "uuid", nullable: false },
|
|
124
|
+
{ name: "created_at", storage: "timestamp", nullable: false },
|
|
125
|
+
{ name: "updated_at", storage: "timestamp", nullable: false },
|
|
126
|
+
{ name: "created_by", storage: "uuid", nullable: true },
|
|
127
|
+
{ name: "updated_by", storage: "uuid", nullable: true },
|
|
128
|
+
];
|
|
129
|
+
/**
|
|
130
|
+
* The fields of an entity's records, in record order. A value-matched relationship has no
|
|
131
|
+
* `<relationship>_id`: its reference is the property named in `on`.
|
|
132
|
+
*/
|
|
133
|
+
export function queryFields(entity) {
|
|
134
|
+
const properties = entity.properties.map((property) => ({
|
|
135
|
+
name: property.name,
|
|
136
|
+
storage: property.type,
|
|
137
|
+
nullable: entity.source !== undefined || property.optional,
|
|
138
|
+
...(property.options !== undefined
|
|
139
|
+
? { options: property.options.map((option) => option.value) }
|
|
140
|
+
: {}),
|
|
141
|
+
}));
|
|
142
|
+
const keys = entity.relationships
|
|
143
|
+
.filter((relationship) => relationship.cardinality === "one" && !isValueMatched(relationship))
|
|
144
|
+
.map((relationship) => ({
|
|
145
|
+
name: `${relationship.name}_id`,
|
|
146
|
+
storage: "uuid",
|
|
147
|
+
nullable: relationship.optional === true,
|
|
148
|
+
}));
|
|
149
|
+
return entity.source !== undefined
|
|
150
|
+
? [{ name: "id", storage: "text", nullable: false }, ...properties]
|
|
151
|
+
: [...SYSTEM_FIELDS, ...properties, ...keys];
|
|
152
|
+
}
|
|
153
|
+
/** The relationships of an entity, declared ones first, then the inverses landing on it. */
|
|
154
|
+
export function queryLinks(manifest, entityName, warehouseRecords = false) {
|
|
155
|
+
const links = [];
|
|
156
|
+
for (const owner of manifest.entities) {
|
|
157
|
+
if (owner.source !== undefined && !warehouseRecords) {
|
|
158
|
+
continue;
|
|
159
|
+
}
|
|
160
|
+
for (const relationship of owner.relationships) {
|
|
161
|
+
if (!warehouseRecords &&
|
|
162
|
+
findEntityManifest(manifest, relationship.to)?.source !== undefined) {
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
const common = {
|
|
166
|
+
declaredBy: owner.name,
|
|
167
|
+
relationship: relationship.name,
|
|
168
|
+
declared: relationship.cardinality,
|
|
169
|
+
};
|
|
170
|
+
if (owner.name === entityName) {
|
|
171
|
+
links.push({
|
|
172
|
+
...common,
|
|
173
|
+
name: relationship.name,
|
|
174
|
+
target: relationship.to,
|
|
175
|
+
cardinality: relationship.cardinality,
|
|
176
|
+
inverse: false,
|
|
177
|
+
});
|
|
178
|
+
}
|
|
179
|
+
if (relationship.to === entityName) {
|
|
180
|
+
links.push({
|
|
181
|
+
...common,
|
|
182
|
+
name: relationship.inverse,
|
|
183
|
+
target: owner.name,
|
|
184
|
+
cardinality: "many",
|
|
185
|
+
inverse: true,
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return [...links.filter((link) => !link.inverse), ...links.filter((link) => link.inverse)];
|
|
191
|
+
}
|
|
192
|
+
export function findEntityManifest(manifest, entityName) {
|
|
193
|
+
return manifest.entities.find((candidate) => candidate.name === entityName);
|
|
194
|
+
}
|
|
195
|
+
function requireEntity(manifest, entityName) {
|
|
196
|
+
const entity = findEntityManifest(manifest, entityName);
|
|
197
|
+
if (entity === undefined) {
|
|
198
|
+
throw new Error(`"${entityName}" is not an entity of this ontology.`);
|
|
199
|
+
}
|
|
200
|
+
return entity;
|
|
201
|
+
}
|
|
202
|
+
const DATE = /^(\d{4})-(\d{2})-(\d{2})$/;
|
|
203
|
+
const TIMESTAMP = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$/;
|
|
204
|
+
const UUID = /^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$/;
|
|
205
|
+
/** `YYYY-MM-DD` naming a day that exists. */
|
|
206
|
+
export function isCalendarDate(value) {
|
|
207
|
+
const match = DATE.exec(value);
|
|
208
|
+
if (match === null) {
|
|
209
|
+
return false;
|
|
210
|
+
}
|
|
211
|
+
const [year, month, day] = [Number(match[1]), Number(match[2]), Number(match[3])];
|
|
212
|
+
const date = new Date(Date.UTC(year, month - 1, day));
|
|
213
|
+
return (date.getUTCFullYear() === year && date.getUTCMonth() === month - 1 && date.getUTCDate() === day);
|
|
214
|
+
}
|
|
215
|
+
/** An ISO 8601 instant with a time zone, on a day that exists. PostgreSQL keeps microseconds. */
|
|
216
|
+
export function isInstant(value) {
|
|
217
|
+
return TIMESTAMP.test(value) && isCalendarDate(value.slice(0, 10)) && !isNaN(Date.parse(value));
|
|
218
|
+
}
|
|
219
|
+
export function isUuid(value) {
|
|
220
|
+
return UUID.test(value);
|
|
221
|
+
}
|
|
222
|
+
const DateValue = Schema.String.check(Schema.makeFilter((value) => isCalendarDate(value) || "Expected a date as YYYY-MM-DD")).annotate({ format: "date" });
|
|
223
|
+
const TimestampValue = Schema.String.check(Schema.makeFilter((value) => isInstant(value) || "Expected an ISO 8601 timestamp with a time zone")).annotate({ format: "date-time" });
|
|
224
|
+
const UuidValue = Schema.String.check(Schema.makeFilter((value) => isUuid(value) || "Expected a UUID")).annotate({ format: "uuid" });
|
|
225
|
+
/** Any JSON value but `null`, which `isNull` expresses. */
|
|
226
|
+
const JsonValue = Schema.Json.check(Schema.makeFilter((value) => value !== null || "Use isNull to match empty values"));
|
|
227
|
+
const TEXT_STORAGE = ["text", "email", "url"];
|
|
228
|
+
const ORDERED_STORAGE = ["integer", "number", "date", "timestamp"];
|
|
229
|
+
/** The schema of one value of a field, as filters and cursors carry it. */
|
|
230
|
+
export function fieldValueSchema(field) {
|
|
231
|
+
switch (field.storage) {
|
|
232
|
+
case "text":
|
|
233
|
+
case "email":
|
|
234
|
+
case "url":
|
|
235
|
+
return Schema.String;
|
|
236
|
+
case "integer":
|
|
237
|
+
return Schema.Int;
|
|
238
|
+
case "number":
|
|
239
|
+
return Schema.Finite;
|
|
240
|
+
case "boolean":
|
|
241
|
+
return Schema.Boolean;
|
|
242
|
+
case "date":
|
|
243
|
+
return DateValue;
|
|
244
|
+
case "timestamp":
|
|
245
|
+
return TimestampValue;
|
|
246
|
+
case "select":
|
|
247
|
+
return Schema.Literals(field.options ?? []);
|
|
248
|
+
case "json":
|
|
249
|
+
return JsonValue;
|
|
250
|
+
case "uuid":
|
|
251
|
+
case "blob":
|
|
252
|
+
return UuidValue;
|
|
253
|
+
case "list":
|
|
254
|
+
return Schema.String;
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
/** Fields a query can sort on: every field but `json`, `blob` and `list` properties. */
|
|
258
|
+
export function isOrderable(field) {
|
|
259
|
+
return field.storage !== "json" && field.storage !== "blob" && field.storage !== "list";
|
|
260
|
+
}
|
|
261
|
+
const FILTER_IDENTIFIERS = {
|
|
262
|
+
text: "TextFilter",
|
|
263
|
+
email: "TextFilter",
|
|
264
|
+
url: "TextFilter",
|
|
265
|
+
integer: "IntegerFilter",
|
|
266
|
+
number: "NumberFilter",
|
|
267
|
+
boolean: "BooleanFilter",
|
|
268
|
+
date: "DateFilter",
|
|
269
|
+
timestamp: "TimestampFilter",
|
|
270
|
+
json: "JsonFilter",
|
|
271
|
+
uuid: "IdFilter",
|
|
272
|
+
blob: "IdFilter",
|
|
273
|
+
list: "ListFilter",
|
|
274
|
+
};
|
|
275
|
+
const FILTER_DESCRIPTIONS = {
|
|
276
|
+
TextFilter: "contains and startsWith ignore case.",
|
|
277
|
+
DateFilter: "Dates are YYYY-MM-DD; between includes both ends.",
|
|
278
|
+
TimestampFilter: "Timestamps are ISO 8601 with a time zone; between includes both ends.",
|
|
279
|
+
JsonFilter: "eq compares JSON values; wrap an object whose keys are operator names in { eq }.",
|
|
280
|
+
};
|
|
281
|
+
/** Filters shared by every field of a type; `select` filters are per property. */
|
|
282
|
+
const sharedFilters = new Map();
|
|
283
|
+
function isOperatorObject(value) {
|
|
284
|
+
return (typeof value === "object" &&
|
|
285
|
+
value !== null &&
|
|
286
|
+
!Array.isArray(value) &&
|
|
287
|
+
Object.keys(value).every((key) => [...FILTER_OPERATORS, "is_null", "starts_with"].includes(key)));
|
|
288
|
+
}
|
|
289
|
+
/** The bare-value form of `eq`. For JSON, an object of operators is a filter, never a value. */
|
|
290
|
+
function shorthandSchema(field, value) {
|
|
291
|
+
if (field.storage !== "json") {
|
|
292
|
+
return value;
|
|
293
|
+
}
|
|
294
|
+
return JsonValue.check(Schema.makeFilter((candidate) => !isOperatorObject(candidate) || "Expected a filter"));
|
|
295
|
+
}
|
|
296
|
+
/** `has` and `hasAny`, the only conditions on a list: it has no empty value and no order. */
|
|
297
|
+
function listFilterSchema(field, identifier, wire) {
|
|
298
|
+
const value = fieldValueSchema(field);
|
|
299
|
+
const operators = {
|
|
300
|
+
has: Schema.optionalKey(value),
|
|
301
|
+
hasAny: Schema.optionalKey(Schema.Array(value).check(Schema.isMaxLength(MAX_IN_VALUES))),
|
|
302
|
+
};
|
|
303
|
+
const filter = wire
|
|
304
|
+
? wireStruct(operators, { hasAny: "has_any" }, "Unknown operator")
|
|
305
|
+
: closedStruct(operators, "Unknown operator");
|
|
306
|
+
return filter.annotate({
|
|
307
|
+
identifier,
|
|
308
|
+
description: `Conditions on the list, all of which must hold: has matches a list that holds the value, ` +
|
|
309
|
+
`${wire ? "has_any" : "hasAny"} one that holds any of the values.`,
|
|
310
|
+
});
|
|
311
|
+
}
|
|
312
|
+
function fieldFilterSchema(field, identifier, wire) {
|
|
313
|
+
if (field.storage === "list") {
|
|
314
|
+
return listFilterSchema(field, identifier, wire);
|
|
315
|
+
}
|
|
316
|
+
const value = fieldValueSchema(field);
|
|
317
|
+
const operators = {
|
|
318
|
+
eq: Schema.optionalKey(value),
|
|
319
|
+
ne: Schema.optionalKey(value),
|
|
320
|
+
in: Schema.optionalKey(Schema.Array(value).check(Schema.isMaxLength(MAX_IN_VALUES))),
|
|
321
|
+
isNull: Schema.optionalKey(Schema.Boolean),
|
|
322
|
+
};
|
|
323
|
+
if (TEXT_STORAGE.includes(field.storage)) {
|
|
324
|
+
operators.contains = Schema.optionalKey(Schema.String);
|
|
325
|
+
operators.startsWith = Schema.optionalKey(Schema.String);
|
|
326
|
+
}
|
|
327
|
+
if (ORDERED_STORAGE.includes(field.storage)) {
|
|
328
|
+
for (const operator of ["gt", "gte", "lt", "lte"]) {
|
|
329
|
+
operators[operator] = Schema.optionalKey(value);
|
|
330
|
+
}
|
|
331
|
+
operators.between = Schema.optionalKey(Schema.Tuple([value, value]));
|
|
332
|
+
}
|
|
333
|
+
const filter = wire
|
|
334
|
+
? wireStruct(operators, { isNull: "is_null", startsWith: "starts_with" }, "Unknown operator")
|
|
335
|
+
: closedStruct(operators, "Unknown operator");
|
|
336
|
+
const note = wire
|
|
337
|
+
? FILTER_DESCRIPTIONS[identifier]?.replaceAll("startsWith", "starts_with")
|
|
338
|
+
: FILTER_DESCRIPTIONS[identifier];
|
|
339
|
+
return Schema.Union([filter, shorthandSchema(field, value), Schema.Null]).annotate({
|
|
340
|
+
identifier,
|
|
341
|
+
description: "Conditions on the field, all of which must hold. A bare value means eq, null means " +
|
|
342
|
+
`${wire ? "is_null" : "isNull"}: true, and ne also matches empty values.${note === undefined ? "" : ` ${note}`}`,
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
function filterFor(entity, field, schemas, wire) {
|
|
346
|
+
if (field.storage === "select") {
|
|
347
|
+
const identifier = `${pascalCase(entity.name)}${pascalCase(field.name)}Filter`;
|
|
348
|
+
const key = `filter:${entity.name}:${field.name}`;
|
|
349
|
+
const existing = schemas.get(key) ?? fieldFilterSchema(field, identifier, wire);
|
|
350
|
+
schemas.set(key, existing);
|
|
351
|
+
return existing;
|
|
352
|
+
}
|
|
353
|
+
const identifier = FILTER_IDENTIFIERS[field.storage];
|
|
354
|
+
const existing = sharedFilters.get(`${identifier}:${wire}`) ?? fieldFilterSchema(field, identifier, wire);
|
|
355
|
+
sharedFilters.set(`${identifier}:${wire}`, existing);
|
|
356
|
+
return existing;
|
|
357
|
+
}
|
|
358
|
+
const fieldFilterGuards = new WeakMap();
|
|
359
|
+
/**
|
|
360
|
+
* Whether a value is a filter the field takes, as a query's `where` would accept it: operators by
|
|
361
|
+
* their query names, each with an operand of the field's type, or a bare value or `null`.
|
|
362
|
+
*/
|
|
363
|
+
export function isFieldFilterOf(field, value) {
|
|
364
|
+
let guard = fieldFilterGuards.get(field);
|
|
365
|
+
if (guard === undefined) {
|
|
366
|
+
guard = Schema.is(fieldFilterSchema(field, "FieldFilter", false));
|
|
367
|
+
fieldFilterGuards.set(field, guard);
|
|
368
|
+
}
|
|
369
|
+
return guard(value);
|
|
370
|
+
}
|
|
371
|
+
/** `pilot_request` → `PilotRequest`, `fitScore` → `FitScore`. */
|
|
372
|
+
function pascalCase(name) {
|
|
373
|
+
return name
|
|
374
|
+
.split("_")
|
|
375
|
+
.map((word) => word.charAt(0).toUpperCase() + word.slice(1))
|
|
376
|
+
.join("");
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* The `where` of an entity. With `links`, it includes the entity's relationships, whose targets are
|
|
380
|
+
* filtered by their own fields only: relationship paths are one level deep.
|
|
381
|
+
*/
|
|
382
|
+
function whereSchema(manifest, entity, links, schemas, wire) {
|
|
383
|
+
const identifier = `${pascalCase(entity.name)}${links ? "Where" : "FieldsWhere"}`;
|
|
384
|
+
const key = `where:${entity.name}:${links}`;
|
|
385
|
+
const existing = schemas.get(key);
|
|
386
|
+
if (existing !== undefined) {
|
|
387
|
+
return existing;
|
|
388
|
+
}
|
|
389
|
+
// The identifier sits on the suspension, so that JSON Schema emits the body once and refers to it.
|
|
390
|
+
// The body is built below; the suspension reads it only when the schema is used.
|
|
391
|
+
const self = Schema.suspend(() => body).annotate({
|
|
392
|
+
identifier,
|
|
393
|
+
description: links
|
|
394
|
+
? `Conditions on ${entity.plural}, all of which must hold.`
|
|
395
|
+
: `Conditions on the fields of ${entity.plural}, all of which must hold.`,
|
|
396
|
+
});
|
|
397
|
+
const fields = {};
|
|
398
|
+
schemas.set(key, self);
|
|
399
|
+
for (const field of queryFields(entity)) {
|
|
400
|
+
fields[field.name] = Schema.optionalKey(filterFor(entity, field, schemas, wire));
|
|
401
|
+
}
|
|
402
|
+
if (links) {
|
|
403
|
+
for (const link of queryLinks(manifest, entity.name)) {
|
|
404
|
+
const target = whereSchema(manifest, requireEntity(manifest, link.target), false, schemas, wire);
|
|
405
|
+
fields[link.name] = Schema.optionalKey(link.cardinality === "one" ? target : manyFilterSchema(link, target));
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
fields.and = Schema.optionalKey(Schema.Array(self));
|
|
409
|
+
fields.or = Schema.optionalKey(Schema.Array(self));
|
|
410
|
+
fields.not = Schema.optionalKey(self);
|
|
411
|
+
const body = closedStruct(fields, "Unknown field");
|
|
412
|
+
return self;
|
|
413
|
+
}
|
|
414
|
+
function manyFilterSchema(link, target) {
|
|
415
|
+
return closedStruct({
|
|
416
|
+
some: Schema.optionalKey(target),
|
|
417
|
+
none: Schema.optionalKey(target),
|
|
418
|
+
every: Schema.optionalKey(target),
|
|
419
|
+
}, "Unknown quantifier").annotate({
|
|
420
|
+
description: `Whether some, none or every one of the related ${link.target} records match.`,
|
|
421
|
+
});
|
|
422
|
+
}
|
|
423
|
+
const wireQuerySchemas = new WeakMap();
|
|
424
|
+
const querySchemas = new WeakMap();
|
|
425
|
+
// A related entity's field filters are identical wherever that entity is reached.
|
|
426
|
+
// Reuse immutable schema definitions within one manifest and spelling; callers'
|
|
427
|
+
// query values, permissions and authorization decisions never enter this cache.
|
|
428
|
+
const wireWhereSchemas = new WeakMap();
|
|
429
|
+
const whereSchemas = new WeakMap();
|
|
430
|
+
/**
|
|
431
|
+
* The precise query schemas of one entity: its fields with the operators of their types, its
|
|
432
|
+
* relationships (declared and inverse), the fields it can sort on and the relationships it can
|
|
433
|
+
* include. Every struct is closed: an unknown field, operator or key is an issue whatever the parse
|
|
434
|
+
* options, never a silently ignored filter.
|
|
435
|
+
*/
|
|
436
|
+
export function entityQuerySchemas(manifest, entityName, wire = false, warehouseRecords = false) {
|
|
437
|
+
const cache = wire ? wireQuerySchemas : querySchemas;
|
|
438
|
+
const cacheKey = `${entityName}:${warehouseRecords}`;
|
|
439
|
+
const cached = cache.get(manifest)?.get(cacheKey);
|
|
440
|
+
if (cached !== undefined) {
|
|
441
|
+
return cached;
|
|
442
|
+
}
|
|
443
|
+
const entity = requireEntity(manifest, entityName);
|
|
444
|
+
const pascal = pascalCase(entityName);
|
|
445
|
+
const fields = queryFields(entity).filter(isOrderable);
|
|
446
|
+
const relationships = queryLinks(manifest, entityName, warehouseRecords).map((link) => link.name);
|
|
447
|
+
const definitions = wire ? wireWhereSchemas : whereSchemas;
|
|
448
|
+
let shared = definitions.get(manifest);
|
|
449
|
+
if (shared === undefined) {
|
|
450
|
+
shared = new Map();
|
|
451
|
+
definitions.set(manifest, shared);
|
|
452
|
+
}
|
|
453
|
+
const where = whereSchema(manifest, entity, true, shared, wire);
|
|
454
|
+
const orderBy = Schema.Array(closedStruct({
|
|
455
|
+
field: Schema.Literals(fields.map((field) => field.name)),
|
|
456
|
+
direction: Schema.optionalKey(SortDirection),
|
|
457
|
+
}, "Unknown key")).annotate({ description: "Sort keys in order; the id breaks ties. Ascending by default." });
|
|
458
|
+
const included = includeSchema(relationships);
|
|
459
|
+
const select = Schema.Array(Schema.Literals(queryFields(entity).map((field) => field.name)))
|
|
460
|
+
.check(Schema.isMaxLength(200))
|
|
461
|
+
.annotate({
|
|
462
|
+
description: "Base-record fields to return; id is always included. Omit for complete records. Includes are unchanged.",
|
|
463
|
+
});
|
|
464
|
+
const queryMembers = {
|
|
465
|
+
where: Schema.optionalKey(where),
|
|
466
|
+
orderBy: Schema.optionalKey(orderBy),
|
|
467
|
+
select: Schema.optionalKey(select),
|
|
468
|
+
include: Schema.optionalKey(included),
|
|
469
|
+
after: Schema.optionalKey(After),
|
|
470
|
+
limit: Schema.optionalKey(Limit),
|
|
471
|
+
};
|
|
472
|
+
const query = (wire
|
|
473
|
+
? wireStruct(queryMembers, { orderBy: "order_by" })
|
|
474
|
+
: closedStruct(queryMembers, "Unknown key")).annotate({ identifier: `${pascal}Query`, description: `A query on ${entity.plural}.` });
|
|
475
|
+
// The structs are assembled from the manifest, so their static types are too wide to name; they
|
|
476
|
+
// accept exactly the Query shape and decode it unchanged.
|
|
477
|
+
const schemas = {
|
|
478
|
+
where,
|
|
479
|
+
orderBy,
|
|
480
|
+
select,
|
|
481
|
+
include: included,
|
|
482
|
+
limit: Limit,
|
|
483
|
+
after: After,
|
|
484
|
+
query,
|
|
485
|
+
};
|
|
486
|
+
const byEntity = cache.get(manifest) ?? new Map();
|
|
487
|
+
byEntity.set(cacheKey, schemas);
|
|
488
|
+
cache.set(manifest, byEntity);
|
|
489
|
+
return schemas;
|
|
490
|
+
}
|
|
491
|
+
/**
|
|
492
|
+
* The relationships a query includes: a list of names, `["owner", "tags"]`, or the object form
|
|
493
|
+
* `{ owner: true, tags: true }` that the list decodes into. Both reject an unknown relationship and
|
|
494
|
+
* name the ones there are.
|
|
495
|
+
*/
|
|
496
|
+
function includeSchema(relationships) {
|
|
497
|
+
const fields = {};
|
|
498
|
+
for (const name of relationships) {
|
|
499
|
+
fields[name] = Schema.optionalKey(Schema.Literal(true));
|
|
500
|
+
}
|
|
501
|
+
const included = closedStruct(fields, "Unknown relationship");
|
|
502
|
+
const name = Schema.String.check(Schema.makeFilter((candidate) => relationships.includes(candidate) ||
|
|
503
|
+
expectedOneOf(`Unknown relationship "${candidate}"`, relationships), { toJsonSchema: () => (relationships.length > 0 ? { enum: relationships } : { not: {} }) }));
|
|
504
|
+
const example = relationships[0];
|
|
505
|
+
const forms = example === undefined
|
|
506
|
+
? "a list of relationship names; there are none"
|
|
507
|
+
: `a list of relationship names, as in ["${example}"], or an object, as in {"${example}": true}`;
|
|
508
|
+
return Schema.Union([included, includeList(name, included)]).annotate({
|
|
509
|
+
description: `Related records to add to each record: ${forms}.`,
|
|
510
|
+
message: `Expected ${forms}`,
|
|
511
|
+
});
|
|
512
|
+
}
|
|
513
|
+
/** The query schema of one entity; see {@link entityQuerySchemas}. */
|
|
514
|
+
export function entityQuerySchema(manifest, entityName, warehouseRecords = false) {
|
|
515
|
+
return entityQuerySchemas(manifest, entityName, false, warehouseRecords).query;
|
|
516
|
+
}
|
|
517
|
+
function escapeRegExp(value) {
|
|
518
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
519
|
+
}
|
|
520
|
+
/**
|
|
521
|
+
* A struct that rejects keys it does not declare, whatever the parse options: decoding ignores
|
|
522
|
+
* unknown keys by default, which would turn a misspelled filter into no filter. JSON Schema says the
|
|
523
|
+
* same with a `patternProperties` entry that matches every undeclared key.
|
|
524
|
+
*/
|
|
525
|
+
function closedStruct(fields, unknownKey) {
|
|
526
|
+
const keys = Object.keys(fields);
|
|
527
|
+
const declared = keys.map(escapeRegExp).join("|");
|
|
528
|
+
const undeclared = Schema.String.check(Schema.isPattern(new RegExp(`^(?!(?:${declared})$)`)));
|
|
529
|
+
return Schema.StructWithRest(Schema.Struct(fields), [
|
|
530
|
+
Schema.Record(undeclared, Schema.Never.annotate({ message: expectedOneOf(unknownKey, keys) })),
|
|
531
|
+
]);
|
|
532
|
+
}
|
|
533
|
+
function recordValueSchema(field) {
|
|
534
|
+
const value = (() => {
|
|
535
|
+
switch (field.storage) {
|
|
536
|
+
case "integer":
|
|
537
|
+
return Schema.Int;
|
|
538
|
+
case "number":
|
|
539
|
+
return Schema.Finite;
|
|
540
|
+
case "boolean":
|
|
541
|
+
return Schema.Boolean;
|
|
542
|
+
case "select":
|
|
543
|
+
return Schema.Literals(field.options ?? []);
|
|
544
|
+
case "json":
|
|
545
|
+
return Schema.Json;
|
|
546
|
+
case "blob":
|
|
547
|
+
return BlobValue;
|
|
548
|
+
case "list":
|
|
549
|
+
return Schema.Array(Schema.String);
|
|
550
|
+
default:
|
|
551
|
+
return Schema.String;
|
|
552
|
+
}
|
|
553
|
+
})();
|
|
554
|
+
return field.nullable ? Schema.NullOr(value) : value;
|
|
555
|
+
}
|
|
556
|
+
/**
|
|
557
|
+
* The record of an entity as the runtime returns it: system fields, properties (`null` when empty;
|
|
558
|
+
* dates as `YYYY-MM-DD`, timestamps as ISO 8601 in UTC) and a `<relationship>_id` per `rel.one`. It
|
|
559
|
+
* checks the shape of stored values, not the refinements of the definition (`maxLength`, `min`,
|
|
560
|
+
* patterns), so that tightening a refinement never makes existing records unreadable.
|
|
561
|
+
*/
|
|
562
|
+
export function entityRecordSchema(entity) {
|
|
563
|
+
// Assembled from the manifest, the struct's static type is too wide to name.
|
|
564
|
+
return Schema.Struct(recordFields(entity)).annotate({
|
|
565
|
+
identifier: pascalCase(entity.name),
|
|
566
|
+
description: entity.description,
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
function recordFields(entity) {
|
|
570
|
+
const fields = {};
|
|
571
|
+
for (const field of queryFields(entity)) {
|
|
572
|
+
fields[field.name] = recordValueSchema(field);
|
|
573
|
+
}
|
|
574
|
+
return fields;
|
|
575
|
+
}
|
|
576
|
+
/** A page of an entity's records, with the relationships a query may include. */
|
|
577
|
+
export function entityQueryResultSchema(manifest, entityName, wire = false, warehouseRecords = false) {
|
|
578
|
+
const entity = requireEntity(manifest, entityName);
|
|
579
|
+
const fields = recordFields(entity);
|
|
580
|
+
const projected = Object.fromEntries(Object.entries(fields).map(([name, value]) => [
|
|
581
|
+
name,
|
|
582
|
+
name === "id" ? value : Schema.optionalKey(value),
|
|
583
|
+
]));
|
|
584
|
+
for (const link of queryLinks(manifest, entityName, warehouseRecords)) {
|
|
585
|
+
const target = entityRecordSchema(requireEntity(manifest, link.target));
|
|
586
|
+
fields[link.name] = Schema.optionalKey(link.cardinality === "one" ? Schema.NullOr(target) : Schema.Array(target));
|
|
587
|
+
projected[link.name] = fields[link.name];
|
|
588
|
+
}
|
|
589
|
+
const record = Schema.Struct(fields);
|
|
590
|
+
return projectedQueryResultSchema(record, Schema.Struct(projected), wire);
|
|
591
|
+
}
|
|
592
|
+
/** A JSON Schema whose root is the schema itself, not a `$ref`, as MCP tool inputs need it. */
|
|
593
|
+
function jsonSchema(schema) {
|
|
594
|
+
const document = Schema.toJsonSchemaDocument(schema, { onExcessProperty: "error" });
|
|
595
|
+
const definitions = document.definitions;
|
|
596
|
+
const reference = document.schema.$ref;
|
|
597
|
+
const referenced = typeof reference === "string" ? definitions[reference.replace("#/$defs/", "")] : undefined;
|
|
598
|
+
const root = referenced ?? document.schema;
|
|
599
|
+
return Object.keys(definitions).length === 0
|
|
600
|
+
? root
|
|
601
|
+
: { ...root, $defs: definitions };
|
|
602
|
+
}
|
|
603
|
+
/** The JSON Schema (draft 2020-12) of an entity's queries, for MCP tools, OpenAPI and the console. */
|
|
604
|
+
export function queryJsonSchema(manifest, entityName, warehouseRecords = false) {
|
|
605
|
+
return jsonSchema(entityQuerySchemas(manifest, entityName, true, warehouseRecords).query);
|
|
606
|
+
}
|
|
607
|
+
/** The JSON Schema (draft 2020-12) of a page of an entity's records. */
|
|
608
|
+
export function queryResultJsonSchema(manifest, entityName) {
|
|
609
|
+
// MCP requires an object at the root, including when its record variants form a union.
|
|
610
|
+
return {
|
|
611
|
+
type: "object",
|
|
612
|
+
required: ["items", "next_cursor"],
|
|
613
|
+
...jsonSchema(entityQueryResultSchema(manifest, entityName, true)),
|
|
614
|
+
};
|
|
615
|
+
}
|