primitive-admin 1.1.0-alpha.9 → 1.1.0
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 +523 -109
- package/assets/skill/skills/primitive-platform/SKILL.md +289 -0
- package/dist/bin/primitive.d.ts +2 -0
- package/dist/bin/primitive.js +372 -21
- package/dist/bin/primitive.js.map +1 -1
- package/dist/src/commands/admins.d.ts +2 -0
- package/dist/src/commands/admins.js +136 -30
- package/dist/src/commands/admins.js.map +1 -1
- package/dist/src/commands/analytics.d.ts +2 -0
- package/dist/src/commands/analytics.js +713 -55
- package/dist/src/commands/analytics.js.map +1 -1
- package/dist/src/commands/apps.d.ts +2 -0
- package/dist/src/commands/apps.js +65 -100
- package/dist/src/commands/apps.js.map +1 -1
- package/dist/src/commands/auth-sessions.d.ts +7 -0
- package/dist/src/commands/auth-sessions.js +144 -0
- package/dist/src/commands/auth-sessions.js.map +1 -0
- package/dist/src/commands/auth.d.ts +2 -0
- package/dist/src/commands/auth.js +238 -108
- package/dist/src/commands/auth.js.map +1 -1
- package/dist/src/commands/blob-buckets.d.ts +2 -0
- package/dist/src/commands/blob-buckets.js +331 -0
- package/dist/src/commands/blob-buckets.js.map +1 -0
- package/dist/src/commands/catalog.d.ts +2 -0
- package/dist/src/commands/catalog.js +63 -48
- package/dist/src/commands/catalog.js.map +1 -1
- package/dist/src/commands/collection-type-configs.d.ts +2 -0
- package/dist/src/commands/collection-type-configs.js +85 -0
- package/dist/src/commands/collection-type-configs.js.map +1 -0
- package/dist/src/commands/collections.d.ts +2 -0
- package/dist/src/commands/collections.js +1282 -0
- package/dist/src/commands/collections.js.map +1 -0
- package/dist/src/commands/comparisons.d.ts +2 -0
- package/dist/src/commands/comparisons.js +6 -6
- package/dist/src/commands/comparisons.js.map +1 -1
- package/dist/src/commands/config.d.ts +46 -0
- package/dist/src/commands/config.js +465 -0
- package/dist/src/commands/config.js.map +1 -0
- package/dist/src/commands/connections.d.ts +2 -0
- package/dist/src/commands/connections.js +99 -0
- package/dist/src/commands/connections.js.map +1 -0
- package/dist/src/commands/cron-triggers.d.ts +2 -0
- package/dist/src/commands/cron-triggers.js +266 -0
- package/dist/src/commands/cron-triggers.js.map +1 -0
- package/dist/src/commands/database-type-configs.d.ts +2 -0
- package/dist/src/commands/database-type-configs.js +164 -0
- package/dist/src/commands/database-type-configs.js.map +1 -0
- package/dist/src/commands/database-types.d.ts +2 -0
- package/dist/src/commands/database-types.js +471 -0
- package/dist/src/commands/database-types.js.map +1 -0
- package/dist/src/commands/databases.d.ts +65 -0
- package/dist/src/commands/databases.js +1887 -243
- package/dist/src/commands/databases.js.map +1 -1
- package/dist/src/commands/documents.d.ts +60 -0
- package/dist/src/commands/documents.js +2888 -22
- package/dist/src/commands/documents.js.map +1 -1
- package/dist/src/commands/email-templates.d.ts +2 -0
- package/dist/src/commands/email-templates.js +175 -0
- package/dist/src/commands/email-templates.js.map +1 -0
- package/dist/src/commands/env.d.ts +23 -0
- package/dist/src/commands/env.js +395 -0
- package/dist/src/commands/env.js.map +1 -0
- package/dist/src/commands/feature-flags.d.ts +14 -0
- package/dist/src/commands/feature-flags.js +117 -0
- package/dist/src/commands/feature-flags.js.map +1 -0
- package/dist/src/commands/functions.d.ts +20 -0
- package/dist/src/commands/functions.js +1630 -0
- package/dist/src/commands/functions.js.map +1 -0
- package/dist/src/commands/group-type-configs.d.ts +2 -0
- package/dist/src/commands/group-type-configs.js +87 -0
- package/dist/src/commands/group-type-configs.js.map +1 -0
- package/dist/src/commands/groups.d.ts +2 -0
- package/dist/src/commands/groups.js +65 -113
- package/dist/src/commands/groups.js.map +1 -1
- package/dist/src/commands/guides.d.ts +223 -0
- package/dist/src/commands/guides.js +627 -69
- package/dist/src/commands/guides.js.map +1 -1
- package/dist/src/commands/init.d.ts +37 -0
- package/dist/src/commands/init.js +1693 -208
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/integrations.d.ts +2 -0
- package/dist/src/commands/integrations.js +428 -187
- package/dist/src/commands/integrations.js.map +1 -1
- package/dist/src/commands/llm.d.ts +2 -0
- package/dist/src/commands/llm.js +4 -2
- package/dist/src/commands/llm.js.map +1 -1
- package/dist/src/commands/locks.d.ts +8 -0
- package/dist/src/commands/locks.js +175 -0
- package/dist/src/commands/locks.js.map +1 -0
- package/dist/src/commands/metadata-category-configs.d.ts +12 -0
- package/dist/src/commands/metadata-category-configs.js +113 -0
- package/dist/src/commands/metadata-category-configs.js.map +1 -0
- package/dist/src/commands/metadata.d.ts +2 -0
- package/dist/src/commands/metadata.js +288 -0
- package/dist/src/commands/metadata.js.map +1 -0
- package/dist/src/commands/prompts.d.ts +2 -0
- package/dist/src/commands/prompts.js +322 -634
- package/dist/src/commands/prompts.js.map +1 -1
- package/dist/src/commands/rule-sets.d.ts +3 -0
- package/dist/src/commands/rule-sets.js +139 -148
- package/dist/src/commands/rule-sets.js.map +1 -1
- package/dist/src/commands/scripts.d.ts +30 -0
- package/dist/src/commands/scripts.js +688 -0
- package/dist/src/commands/scripts.js.map +1 -0
- package/dist/src/commands/secrets.d.ts +2 -0
- package/dist/src/commands/secrets.js +109 -0
- package/dist/src/commands/secrets.js.map +1 -0
- package/dist/src/commands/sessions.d.ts +2 -0
- package/dist/src/commands/sessions.js +76 -0
- package/dist/src/commands/sessions.js.map +1 -0
- package/dist/src/commands/skill.d.ts +2 -0
- package/dist/src/commands/skill.js +29 -0
- package/dist/src/commands/skill.js.map +1 -0
- package/dist/src/commands/sync-app-settings.d.ts +158 -0
- package/dist/src/commands/sync-app-settings.js +328 -0
- package/dist/src/commands/sync-app-settings.js.map +1 -0
- package/dist/src/commands/sync.d.ts +2670 -0
- package/dist/src/commands/sync.js +17144 -834
- package/dist/src/commands/sync.js.map +1 -1
- package/dist/src/commands/tokens.d.ts +2 -0
- package/dist/src/commands/tokens.js +132 -22
- package/dist/src/commands/tokens.js.map +1 -1
- package/dist/src/commands/users.d.ts +2 -0
- package/dist/src/commands/users.js +542 -24
- package/dist/src/commands/users.js.map +1 -1
- package/dist/src/commands/vars.d.ts +8 -0
- package/dist/src/commands/vars.js +97 -0
- package/dist/src/commands/vars.js.map +1 -0
- package/dist/src/commands/waitlist.d.ts +2 -0
- package/dist/src/commands/waitlist.js +12 -11
- package/dist/src/commands/waitlist.js.map +1 -1
- package/dist/src/commands/webhooks.d.ts +31 -0
- package/dist/src/commands/webhooks.js +633 -0
- package/dist/src/commands/webhooks.js.map +1 -0
- package/dist/src/commands/workflows.d.ts +88 -0
- package/dist/src/commands/workflows.js +1568 -742
- package/dist/src/commands/workflows.js.map +1 -1
- package/dist/src/lib/access-rule-display.d.ts +21 -0
- package/dist/src/lib/access-rule-display.js +34 -0
- package/dist/src/lib/access-rule-display.js.map +1 -0
- package/dist/src/lib/api-client.d.ts +2550 -0
- package/dist/src/lib/api-client.js +2503 -160
- package/dist/src/lib/api-client.js.map +1 -1
- package/dist/src/lib/app-settings-descriptor.d.ts +263 -0
- package/dist/src/lib/app-settings-descriptor.js +583 -0
- package/dist/src/lib/app-settings-descriptor.js.map +1 -0
- package/dist/src/lib/auth-flow.d.ts +8 -0
- package/dist/src/lib/batch.d.ts +26 -0
- package/dist/src/lib/batch.js +32 -0
- package/dist/src/lib/batch.js.map +1 -0
- package/dist/src/lib/block-layout.d.ts +160 -0
- package/dist/src/lib/block-layout.js +451 -0
- package/dist/src/lib/block-layout.js.map +1 -0
- package/dist/src/lib/block-selector.d.ts +58 -0
- package/dist/src/lib/block-selector.js +92 -0
- package/dist/src/lib/block-selector.js.map +1 -0
- package/dist/src/lib/canonical-json.d.ts +12 -0
- package/dist/src/lib/canonical-json.js +35 -0
- package/dist/src/lib/canonical-json.js.map +1 -0
- package/dist/src/lib/channel.d.ts +30 -0
- package/dist/src/lib/channel.js +68 -0
- package/dist/src/lib/channel.js.map +1 -0
- package/dist/src/lib/cli-manifest.d.ts +68 -0
- package/dist/src/lib/cli-manifest.js +71 -0
- package/dist/src/lib/cli-manifest.js.map +1 -0
- package/dist/src/lib/codegen-shared/generatedFiles.d.ts +101 -0
- package/dist/src/lib/codegen-shared/generatedFiles.js +191 -0
- package/dist/src/lib/codegen-shared/generatedFiles.js.map +1 -0
- package/dist/src/lib/codegen-shared/prettierStable.d.ts +262 -0
- package/dist/src/lib/codegen-shared/prettierStable.js +610 -0
- package/dist/src/lib/codegen-shared/prettierStable.js.map +1 -0
- package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.d.ts +38 -0
- package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js +46 -0
- package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js.map +1 -0
- package/dist/src/lib/collection-export.d.ts +184 -0
- package/dist/src/lib/collection-export.js +252 -0
- package/dist/src/lib/collection-export.js.map +1 -0
- package/dist/src/lib/config-json-field.d.ts +28 -0
- package/dist/src/lib/config-json-field.js +56 -0
- package/dist/src/lib/config-json-field.js.map +1 -0
- package/dist/src/lib/config-object-descriptor.d.ts +127 -0
- package/dist/src/lib/config-object-descriptor.js +740 -0
- package/dist/src/lib/config-object-descriptor.js.map +1 -0
- package/dist/src/lib/config-payload.d.ts +92 -0
- package/dist/src/lib/config-payload.js +161 -0
- package/dist/src/lib/config-payload.js.map +1 -0
- package/dist/src/lib/config-surface.d.ts +141 -0
- package/dist/src/lib/config-surface.js +368 -0
- package/dist/src/lib/config-surface.js.map +1 -0
- package/dist/src/lib/config-toml.d.ts +10 -0
- package/dist/src/lib/config-toml.js +42 -0
- package/dist/src/lib/config-toml.js.map +1 -0
- package/dist/src/lib/config.d.ts +71 -0
- package/dist/src/lib/config.js +71 -68
- package/dist/src/lib/config.js.map +1 -1
- package/dist/src/lib/confirm-prompt.d.ts +83 -0
- package/dist/src/lib/confirm-prompt.js +110 -0
- package/dist/src/lib/confirm-prompt.js.map +1 -0
- package/dist/src/lib/constants.d.ts +11 -0
- package/dist/src/lib/constants.js +12 -0
- package/dist/src/lib/constants.js.map +1 -0
- package/dist/src/lib/crash-handlers.d.ts +20 -0
- package/dist/src/lib/crash-handlers.js +49 -0
- package/dist/src/lib/crash-handlers.js.map +1 -0
- package/dist/src/lib/credentials-store.d.ts +104 -0
- package/dist/src/lib/credentials-store.js +336 -0
- package/dist/src/lib/credentials-store.js.map +1 -0
- package/dist/src/lib/csv.d.ts +47 -0
- package/dist/src/lib/csv.js +172 -0
- package/dist/src/lib/csv.js.map +1 -0
- package/dist/src/lib/data-input.d.ts +23 -0
- package/dist/src/lib/data-input.js +50 -0
- package/dist/src/lib/data-input.js.map +1 -0
- package/dist/src/lib/db-codegen/dbFingerprint.d.ts +10 -0
- package/dist/src/lib/db-codegen/dbFingerprint.js +17 -0
- package/dist/src/lib/db-codegen/dbFingerprint.js.map +1 -0
- package/dist/src/lib/db-codegen/dbGenerator.d.ts +67 -0
- package/dist/src/lib/db-codegen/dbGenerator.js +170 -0
- package/dist/src/lib/db-codegen/dbGenerator.js.map +1 -0
- package/dist/src/lib/db-codegen/dbNaming.d.ts +87 -0
- package/dist/src/lib/db-codegen/dbNaming.js +180 -0
- package/dist/src/lib/db-codegen/dbNaming.js.map +1 -0
- package/dist/src/lib/db-codegen/dbTemplates.d.ts +272 -0
- package/dist/src/lib/db-codegen/dbTemplates.js +480 -0
- package/dist/src/lib/db-codegen/dbTemplates.js.map +1 -0
- package/dist/src/lib/db-codegen/dbTsTypes.d.ts +73 -0
- package/dist/src/lib/db-codegen/dbTsTypes.js +139 -0
- package/dist/src/lib/db-codegen/dbTsTypes.js.map +1 -0
- package/dist/src/lib/db-codegen/dbTypeIR.d.ts +146 -0
- package/dist/src/lib/db-codegen/dbTypeIR.js +525 -0
- package/dist/src/lib/db-codegen/dbTypeIR.js.map +1 -0
- package/dist/src/lib/db-codegen/generated-operation-def-descriptor.d.ts +112 -0
- package/dist/src/lib/db-codegen/generated-operation-def-descriptor.js +211 -0
- package/dist/src/lib/db-codegen/generated-operation-def-descriptor.js.map +1 -0
- package/dist/src/lib/deprecation.d.ts +22 -0
- package/dist/src/lib/deprecation.js +43 -0
- package/dist/src/lib/deprecation.js.map +1 -0
- package/dist/src/lib/document-export-permissions.d.ts +30 -0
- package/dist/src/lib/document-export-permissions.js +54 -0
- package/dist/src/lib/document-export-permissions.js.map +1 -0
- package/dist/src/lib/document-ingest-artifact.d.ts +120 -0
- package/dist/src/lib/document-ingest-artifact.js +505 -0
- package/dist/src/lib/document-ingest-artifact.js.map +1 -0
- package/dist/src/lib/document-ingest-input.d.ts +51 -0
- package/dist/src/lib/document-ingest-input.js +132 -0
- package/dist/src/lib/document-ingest-input.js.map +1 -0
- package/dist/src/lib/document-ingest-rows.d.ts +137 -0
- package/dist/src/lib/document-ingest-rows.js +181 -0
- package/dist/src/lib/document-ingest-rows.js.map +1 -0
- package/dist/src/lib/document-ingest.d.ts +101 -0
- package/dist/src/lib/document-ingest.js +384 -0
- package/dist/src/lib/document-ingest.js.map +1 -0
- package/dist/src/lib/env-resolver-core.d.ts +258 -0
- package/dist/src/lib/env-resolver-core.js +447 -0
- package/dist/src/lib/env-resolver-core.js.map +1 -0
- package/dist/src/lib/env-resolver.d.ts +99 -0
- package/dist/src/lib/env-resolver.js +153 -0
- package/dist/src/lib/env-resolver.js.map +1 -0
- package/dist/src/lib/fetch.d.ts +5 -0
- package/dist/src/lib/function-bundle.d.ts +147 -0
- package/dist/src/lib/function-bundle.js +341 -0
- package/dist/src/lib/function-bundle.js.map +1 -0
- package/dist/src/lib/function-collect.d.ts +123 -0
- package/dist/src/lib/function-collect.js +610 -0
- package/dist/src/lib/function-collect.js.map +1 -0
- package/dist/src/lib/function-db-types.d.ts +202 -0
- package/dist/src/lib/function-db-types.js +870 -0
- package/dist/src/lib/function-db-types.js.map +1 -0
- package/dist/src/lib/function-document-types.d.ts +144 -0
- package/dist/src/lib/function-document-types.js +370 -0
- package/dist/src/lib/function-document-types.js.map +1 -0
- package/dist/src/lib/function-grants-preflight.d.ts +64 -0
- package/dist/src/lib/function-grants-preflight.js +105 -0
- package/dist/src/lib/function-grants-preflight.js.map +1 -0
- package/dist/src/lib/function-log-lines.d.ts +76 -0
- package/dist/src/lib/function-log-lines.js +160 -0
- package/dist/src/lib/function-log-lines.js.map +1 -0
- package/dist/src/lib/function-log-row.d.ts +29 -0
- package/dist/src/lib/function-log-row.js +73 -0
- package/dist/src/lib/function-log-row.js.map +1 -0
- package/dist/src/lib/function-log-tail.d.ts +132 -0
- package/dist/src/lib/function-log-tail.js +262 -0
- package/dist/src/lib/function-log-tail.js.map +1 -0
- package/dist/src/lib/function-run.d.ts +289 -0
- package/dist/src/lib/function-run.js +389 -0
- package/dist/src/lib/function-run.js.map +1 -0
- package/dist/src/lib/function-schema-codegen.d.ts +143 -0
- package/dist/src/lib/function-schema-codegen.js +420 -0
- package/dist/src/lib/function-schema-codegen.js.map +1 -0
- package/dist/src/lib/function-sync.d.ts +459 -0
- package/dist/src/lib/function-sync.js +1258 -0
- package/dist/src/lib/function-sync.js.map +1 -0
- package/dist/src/lib/function-trigger-listing.d.ts +27 -0
- package/dist/src/lib/function-trigger-listing.js +70 -0
- package/dist/src/lib/function-trigger-listing.js.map +1 -0
- package/dist/src/lib/function-typecheck.d.ts +86 -0
- package/dist/src/lib/function-typecheck.js +370 -0
- package/dist/src/lib/function-typecheck.js.map +1 -0
- package/dist/src/lib/function-versions.d.ts +122 -0
- package/dist/src/lib/function-versions.js +182 -0
- package/dist/src/lib/function-versions.js.map +1 -0
- package/dist/src/lib/generated-allowlist.d.ts +28 -0
- package/dist/src/lib/generated-allowlist.js +281 -0
- package/dist/src/lib/generated-allowlist.js.map +1 -0
- package/dist/src/lib/generated-config-surfaces.d.ts +2936 -0
- package/dist/src/lib/generated-config-surfaces.js +10569 -0
- package/dist/src/lib/generated-config-surfaces.js.map +1 -0
- package/dist/src/lib/generated-sdk-types.d.ts +12 -0
- package/dist/src/lib/generated-sdk-types.js +13 -0
- package/dist/src/lib/generated-sdk-types.js.map +1 -0
- package/dist/src/lib/generated-template-lint.d.ts +212 -0
- package/dist/src/lib/generated-template-lint.js +624 -0
- package/dist/src/lib/generated-template-lint.js.map +1 -0
- package/dist/src/lib/init-adopt.d.ts +16 -0
- package/dist/src/lib/init-adopt.js +34 -0
- package/dist/src/lib/init-adopt.js.map +1 -0
- package/dist/src/lib/init-assets.d.ts +39 -0
- package/dist/src/lib/init-assets.js +97 -0
- package/dist/src/lib/init-assets.js.map +1 -0
- package/dist/src/lib/init-client-platforms.d.ts +14 -0
- package/dist/src/lib/init-client-platforms.js +71 -0
- package/dist/src/lib/init-client-platforms.js.map +1 -0
- package/dist/src/lib/init-config.d.ts +98 -0
- package/dist/src/lib/init-config.js +186 -0
- package/dist/src/lib/init-config.js.map +1 -0
- package/dist/src/lib/init-email-redirect-uris.d.ts +37 -0
- package/dist/src/lib/init-email-redirect-uris.js +46 -0
- package/dist/src/lib/init-email-redirect-uris.js.map +1 -0
- package/dist/src/lib/init-ios-links.d.ts +91 -0
- package/dist/src/lib/init-ios-links.js +219 -0
- package/dist/src/lib/init-ios-links.js.map +1 -0
- package/dist/src/lib/init-plan.d.ts +80 -0
- package/dist/src/lib/init-plan.js +95 -0
- package/dist/src/lib/init-plan.js.map +1 -0
- package/dist/src/lib/init-production-env.d.ts +48 -0
- package/dist/src/lib/init-production-env.js +59 -0
- package/dist/src/lib/init-production-env.js.map +1 -0
- package/dist/src/lib/init-schema.d.ts +74 -0
- package/dist/src/lib/init-schema.js +358 -0
- package/dist/src/lib/init-schema.js.map +1 -0
- package/dist/src/lib/init-xcode.d.ts +34 -0
- package/dist/src/lib/init-xcode.js +138 -0
- package/dist/src/lib/init-xcode.js.map +1 -0
- package/dist/src/lib/integration-request-config.d.ts +30 -0
- package/dist/src/lib/integration-request-config.js +145 -0
- package/dist/src/lib/integration-request-config.js.map +1 -0
- package/dist/src/lib/integration-selector.d.ts +42 -0
- package/dist/src/lib/integration-selector.js +46 -0
- package/dist/src/lib/integration-selector.js.map +1 -0
- package/dist/src/lib/ios-app-id.d.ts +34 -0
- package/dist/src/lib/ios-app-id.js +69 -0
- package/dist/src/lib/ios-app-id.js.map +1 -0
- package/dist/src/lib/list-options.d.ts +68 -0
- package/dist/src/lib/list-options.js +89 -0
- package/dist/src/lib/list-options.js.map +1 -0
- package/dist/src/lib/local-state.d.ts +55 -0
- package/dist/src/lib/local-state.js +167 -0
- package/dist/src/lib/local-state.js.map +1 -0
- package/dist/src/lib/local-test-cases.d.ts +63 -0
- package/dist/src/lib/local-test-cases.js +136 -0
- package/dist/src/lib/local-test-cases.js.map +1 -0
- package/dist/src/lib/log-inspection.d.ts +715 -0
- package/dist/src/lib/log-inspection.js +816 -0
- package/dist/src/lib/log-inspection.js.map +1 -0
- package/dist/src/lib/logout-admin-session.d.ts +33 -0
- package/dist/src/lib/logout-admin-session.js +70 -0
- package/dist/src/lib/logout-admin-session.js.map +1 -0
- package/dist/src/lib/migration-nag.d.ts +49 -0
- package/dist/src/lib/migration-nag.js +163 -0
- package/dist/src/lib/migration-nag.js.map +1 -0
- package/dist/src/lib/object-status-filter.d.ts +22 -0
- package/dist/src/lib/object-status-filter.js +45 -0
- package/dist/src/lib/object-status-filter.js.map +1 -0
- package/dist/src/lib/output.d.ts +124 -0
- package/dist/src/lib/output.js +219 -8
- package/dist/src/lib/output.js.map +1 -1
- package/dist/src/lib/package-manager.d.ts +140 -0
- package/dist/src/lib/package-manager.js +305 -0
- package/dist/src/lib/package-manager.js.map +1 -0
- package/dist/src/lib/paginate.d.ts +98 -0
- package/dist/src/lib/paginate.js +112 -0
- package/dist/src/lib/paginate.js.map +1 -0
- package/dist/src/lib/platform-owned.d.ts +63 -0
- package/dist/src/lib/platform-owned.js +85 -0
- package/dist/src/lib/platform-owned.js.map +1 -0
- package/dist/src/lib/project-config.d.ts +122 -0
- package/dist/src/lib/project-config.js +244 -0
- package/dist/src/lib/project-config.js.map +1 -0
- package/dist/src/lib/prompt-cost-format.d.ts +11 -0
- package/dist/src/lib/prompt-cost-format.js +41 -0
- package/dist/src/lib/prompt-cost-format.js.map +1 -0
- package/dist/src/lib/prompt-schema-codegen.d.ts +147 -0
- package/dist/src/lib/prompt-schema-codegen.js +462 -0
- package/dist/src/lib/prompt-schema-codegen.js.map +1 -0
- package/dist/src/lib/query-operators.d.ts +43 -0
- package/dist/src/lib/query-operators.js +80 -0
- package/dist/src/lib/query-operators.js.map +1 -0
- package/dist/src/lib/record-filter.d.ts +18 -0
- package/dist/src/lib/record-filter.js +55 -0
- package/dist/src/lib/record-filter.js.map +1 -0
- package/dist/src/lib/refresh-admin-credentials.d.ts +73 -0
- package/dist/src/lib/refresh-admin-credentials.js +123 -0
- package/dist/src/lib/refresh-admin-credentials.js.map +1 -0
- package/dist/src/lib/resolve-init-dev-port.d.ts +56 -0
- package/dist/src/lib/resolve-init-dev-port.js +55 -0
- package/dist/src/lib/resolve-init-dev-port.js.map +1 -0
- package/dist/src/lib/resolve-init-server.d.ts +64 -0
- package/dist/src/lib/resolve-init-server.js +77 -0
- package/dist/src/lib/resolve-init-server.js.map +1 -0
- package/dist/src/lib/resolve-owner.d.ts +19 -0
- package/dist/src/lib/resolve-owner.js +20 -0
- package/dist/src/lib/resolve-owner.js.map +1 -0
- package/dist/src/lib/resolve-platform.d.ts +74 -0
- package/dist/src/lib/resolve-platform.js +105 -0
- package/dist/src/lib/resolve-platform.js.map +1 -0
- package/dist/src/lib/run-status.d.ts +19 -0
- package/dist/src/lib/run-status.generated.d.ts +39 -0
- package/dist/src/lib/run-status.generated.js +66 -0
- package/dist/src/lib/run-status.generated.js.map +1 -0
- package/dist/src/lib/run-status.js +19 -0
- package/dist/src/lib/run-status.js.map +1 -0
- package/dist/src/lib/server-text-normalization.d.ts +51 -0
- package/dist/src/lib/server-text-normalization.js +90 -0
- package/dist/src/lib/server-text-normalization.js.map +1 -0
- package/dist/src/lib/server-url.d.ts +22 -0
- package/dist/src/lib/server-url.js +33 -0
- package/dist/src/lib/server-url.js.map +1 -0
- package/dist/src/lib/signing-secret-status.d.ts +81 -0
- package/dist/src/lib/signing-secret-status.js +116 -0
- package/dist/src/lib/signing-secret-status.js.map +1 -0
- package/dist/src/lib/skill-installer.d.ts +71 -0
- package/dist/src/lib/skill-installer.js +441 -0
- package/dist/src/lib/skill-installer.js.map +1 -0
- package/dist/src/lib/snapshot-audit-source.d.ts +45 -0
- package/dist/src/lib/snapshot-audit-source.js +58 -0
- package/dist/src/lib/snapshot-audit-source.js.map +1 -0
- package/dist/src/lib/snapshot-audit-store.d.ts +52 -0
- package/dist/src/lib/snapshot-audit-store.js +196 -0
- package/dist/src/lib/snapshot-audit-store.js.map +1 -0
- package/dist/src/lib/snapshot-audit.d.ts +207 -0
- package/dist/src/lib/snapshot-audit.js +431 -0
- package/dist/src/lib/snapshot-audit.js.map +1 -0
- package/dist/src/lib/snapshot-build-rows.d.ts +60 -0
- package/dist/src/lib/snapshot-build-rows.js +87 -0
- package/dist/src/lib/snapshot-build-rows.js.map +1 -0
- package/dist/src/lib/snapshot-build.d.ts +50 -0
- package/dist/src/lib/snapshot-build.js +111 -0
- package/dist/src/lib/snapshot-build.js.map +1 -0
- package/dist/src/lib/snapshot-manifest-layout.d.ts +61 -0
- package/dist/src/lib/snapshot-manifest-layout.js +70 -0
- package/dist/src/lib/snapshot-manifest-layout.js.map +1 -0
- package/dist/src/lib/snapshots.d.ts +98 -0
- package/dist/src/lib/snapshots.js +294 -0
- package/dist/src/lib/snapshots.js.map +1 -0
- package/dist/src/lib/step-run-table.d.ts +43 -0
- package/dist/src/lib/step-run-table.js +129 -0
- package/dist/src/lib/step-run-table.js.map +1 -0
- package/dist/src/lib/storage-pending-retry.d.ts +26 -0
- package/dist/src/lib/storage-pending-retry.js +42 -0
- package/dist/src/lib/storage-pending-retry.js.map +1 -0
- package/dist/src/lib/swift-codegen/agentGenerator.d.ts +42 -0
- package/dist/src/lib/swift-codegen/agentGenerator.js +118 -0
- package/dist/src/lib/swift-codegen/agentGenerator.js.map +1 -0
- package/dist/src/lib/swift-codegen/banners.d.ts +24 -0
- package/dist/src/lib/swift-codegen/banners.js +25 -0
- package/dist/src/lib/swift-codegen/banners.js.map +1 -0
- package/dist/src/lib/swift-codegen/dbGenerator.d.ts +113 -0
- package/dist/src/lib/swift-codegen/dbGenerator.js +926 -0
- package/dist/src/lib/swift-codegen/dbGenerator.js.map +1 -0
- package/dist/src/lib/swift-codegen/dbSwiftTypes.d.ts +42 -0
- package/dist/src/lib/swift-codegen/dbSwiftTypes.js +100 -0
- package/dist/src/lib/swift-codegen/dbSwiftTypes.js.map +1 -0
- package/dist/src/lib/swift-codegen/functionGenerator.d.ts +139 -0
- package/dist/src/lib/swift-codegen/functionGenerator.js +462 -0
- package/dist/src/lib/swift-codegen/functionGenerator.js.map +1 -0
- package/dist/src/lib/swift-codegen/generator.d.ts +100 -0
- package/dist/src/lib/swift-codegen/generator.js +457 -0
- package/dist/src/lib/swift-codegen/generator.js.map +1 -0
- package/dist/src/lib/swift-codegen/schemaToSwift.d.ts +87 -0
- package/dist/src/lib/swift-codegen/schemaToSwift.js +661 -0
- package/dist/src/lib/swift-codegen/schemaToSwift.js.map +1 -0
- package/dist/src/lib/swift-codegen/siblingSymbols.d.ts +94 -0
- package/dist/src/lib/swift-codegen/siblingSymbols.js +155 -0
- package/dist/src/lib/swift-codegen/siblingSymbols.js.map +1 -0
- package/dist/src/lib/swift-codegen/swiftNaming.d.ts +85 -0
- package/dist/src/lib/swift-codegen/swiftNaming.js +198 -0
- package/dist/src/lib/swift-codegen/swiftNaming.js.map +1 -0
- package/dist/src/lib/sync-dir-selector.d.ts +21 -0
- package/dist/src/lib/sync-dir-selector.js +30 -0
- package/dist/src/lib/sync-dir-selector.js.map +1 -0
- package/dist/src/lib/sync-paths.d.ts +128 -0
- package/dist/src/lib/sync-paths.js +195 -0
- package/dist/src/lib/sync-paths.js.map +1 -0
- package/dist/src/lib/sync-resource-types.d.ts +563 -0
- package/dist/src/lib/sync-resource-types.js +1073 -0
- package/dist/src/lib/sync-resource-types.js.map +1 -0
- package/dist/src/lib/sync-selectors.d.ts +138 -0
- package/dist/src/lib/sync-selectors.js +289 -0
- package/dist/src/lib/sync-selectors.js.map +1 -0
- package/dist/src/lib/template.d.ts +170 -0
- package/dist/src/lib/template.js +484 -68
- package/dist/src/lib/template.js.map +1 -1
- package/dist/src/lib/test-case-file-names.d.ts +40 -0
- package/dist/src/lib/test-case-file-names.js +91 -0
- package/dist/src/lib/test-case-file-names.js.map +1 -0
- package/dist/src/lib/test-case-keys.d.ts +29 -0
- package/dist/src/lib/test-case-keys.js +55 -0
- package/dist/src/lib/test-case-keys.js.map +1 -0
- package/dist/src/lib/test-case-variables.d.ts +29 -0
- package/dist/src/lib/test-case-variables.js +71 -0
- package/dist/src/lib/test-case-variables.js.map +1 -0
- package/dist/src/lib/token-inject.d.ts +56 -0
- package/dist/src/lib/token-inject.js +204 -0
- package/dist/src/lib/token-inject.js.map +1 -0
- package/dist/src/lib/toml-database-config.d.ts +123 -0
- package/dist/src/lib/toml-database-config.js +544 -0
- package/dist/src/lib/toml-database-config.js.map +1 -0
- package/dist/src/lib/toml-metadata-config.d.ts +151 -0
- package/dist/src/lib/toml-metadata-config.js +476 -0
- package/dist/src/lib/toml-metadata-config.js.map +1 -0
- package/dist/src/lib/toml-native-form.d.ts +46 -0
- package/dist/src/lib/toml-native-form.js +78 -0
- package/dist/src/lib/toml-native-form.js.map +1 -0
- package/dist/src/lib/toml-params-validator.d.ts +129 -0
- package/dist/src/lib/toml-params-validator.js +298 -0
- package/dist/src/lib/toml-params-validator.js.map +1 -0
- package/dist/src/lib/toml-scalar-edit.d.ts +43 -0
- package/dist/src/lib/toml-scalar-edit.js +283 -0
- package/dist/src/lib/toml-scalar-edit.js.map +1 -0
- package/dist/src/lib/user-selector.d.ts +24 -0
- package/dist/src/lib/user-selector.js +33 -0
- package/dist/src/lib/user-selector.js.map +1 -0
- package/dist/src/lib/version-check.d.ts +35 -0
- package/dist/src/lib/version-check.js +241 -0
- package/dist/src/lib/version-check.js.map +1 -0
- package/dist/src/lib/watch.d.ts +121 -0
- package/dist/src/lib/watch.js +169 -0
- package/dist/src/lib/watch.js.map +1 -0
- package/dist/src/lib/web-url.d.ts +40 -0
- package/dist/src/lib/web-url.js +76 -0
- package/dist/src/lib/web-url.js.map +1 -0
- package/dist/src/lib/webhook-deliver.d.ts +209 -0
- package/dist/src/lib/webhook-deliver.js +519 -0
- package/dist/src/lib/webhook-deliver.js.map +1 -0
- package/dist/src/lib/workflow-apply.d.ts +110 -0
- package/dist/src/lib/workflow-apply.js +164 -0
- package/dist/src/lib/workflow-apply.js.map +1 -0
- package/dist/src/lib/workflow-codegen/generated-schema-descriptor.d.ts +129 -0
- package/dist/src/lib/workflow-codegen/generated-schema-descriptor.js +269 -0
- package/dist/src/lib/workflow-codegen/generated-schema-descriptor.js.map +1 -0
- package/dist/src/lib/workflow-codegen/generator.d.ts +96 -0
- package/dist/src/lib/workflow-codegen/generator.js +361 -0
- package/dist/src/lib/workflow-codegen/generator.js.map +1 -0
- package/dist/src/lib/workflow-codegen/invokerIR.d.ts +94 -0
- package/dist/src/lib/workflow-codegen/invokerIR.js +76 -0
- package/dist/src/lib/workflow-codegen/invokerIR.js.map +1 -0
- package/dist/src/lib/workflow-codegen/naming.d.ts +33 -0
- package/dist/src/lib/workflow-codegen/naming.js +81 -0
- package/dist/src/lib/workflow-codegen/naming.js.map +1 -0
- package/dist/src/lib/workflow-codegen/schemaToTs.d.ts +80 -0
- package/dist/src/lib/workflow-codegen/schemaToTs.js +303 -0
- package/dist/src/lib/workflow-codegen/schemaToTs.js.map +1 -0
- package/dist/src/lib/workflow-config-apply.d.ts +70 -0
- package/dist/src/lib/workflow-config-apply.js +137 -0
- package/dist/src/lib/workflow-config-apply.js.map +1 -0
- package/dist/src/lib/workflow-config-sidecar.d.ts +63 -0
- package/dist/src/lib/workflow-config-sidecar.js +96 -0
- package/dist/src/lib/workflow-config-sidecar.js.map +1 -0
- package/dist/src/lib/workflow-defaults.d.ts +29 -0
- package/dist/src/lib/workflow-defaults.js +41 -0
- package/dist/src/lib/workflow-defaults.js.map +1 -0
- package/dist/src/lib/workflow-fragments.d.ts +64 -0
- package/dist/src/lib/workflow-fragments.js +342 -0
- package/dist/src/lib/workflow-fragments.js.map +1 -0
- package/dist/src/lib/workflow-include-preserve.d.ts +76 -0
- package/dist/src/lib/workflow-include-preserve.js +286 -0
- package/dist/src/lib/workflow-include-preserve.js.map +1 -0
- package/dist/src/lib/workflow-payload.d.ts +98 -0
- package/dist/src/lib/workflow-payload.js +178 -0
- package/dist/src/lib/workflow-payload.js.map +1 -0
- package/dist/src/lib/workflow-toml-validator.d.ts +211 -0
- package/dist/src/lib/workflow-toml-validator.js +770 -0
- package/dist/src/lib/workflow-toml-validator.js.map +1 -0
- package/dist/src/lib/workflow-usage.d.ts +196 -0
- package/dist/src/lib/workflow-usage.js +310 -0
- package/dist/src/lib/workflow-usage.js.map +1 -0
- package/dist/src/types/index.d.ts +591 -0
- package/dist/src/validators.d.ts +65 -0
- package/dist/src/validators.js +64 -0
- package/dist/src/validators.js.map +1 -0
- package/package.json +34 -9
|
@@ -0,0 +1,926 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `databases codegen --lang swift` orchestrator (issue #1547, Phase 4).
|
|
3
|
+
*
|
|
4
|
+
* The Swift counterpart of `db-codegen/dbGenerator.ts`. Reads the SAME synced
|
|
5
|
+
* `database-type-configs/*.toml` and emits ONE `<type>.generated.swift` per database
|
|
6
|
+
* type. Each file carries the type's record structs (read shape), per-op params
|
|
7
|
+
* structs (write shape), per-op result typealiases, and a typed `<Type>Ops`
|
|
8
|
+
* factory over the additive generic `executeOperation` overload on
|
|
9
|
+
* `DatabasesAPI` (the only published SDK surface for this generator).
|
|
10
|
+
*
|
|
11
|
+
* Design decisions realized (issue #1547):
|
|
12
|
+
* - Operation + record metadata (which ops exist, their params, their result
|
|
13
|
+
* descriptor, and per-model fields) is read from the SHARED `describeDbType`
|
|
14
|
+
* IR — the SAME source the TS renderer (`db-codegen/dbGenerator.ts`) reads.
|
|
15
|
+
* The Swift renderer reconstructs none of it (binding item 5), so the two
|
|
16
|
+
* clients can never disagree on a type's surface.
|
|
17
|
+
* - The generic result envelopes (`DBQueryResult<T>`, `DBMutationResult`, …)
|
|
18
|
+
* live in the JsBaoClient SDK, NOT emitted per file — a Swift package
|
|
19
|
+
* compiles all generated files into one module, so a per-file copy would
|
|
20
|
+
* collide. Generated files reference the SDK envelopes (mirrors how Phase 3
|
|
21
|
+
* put the workflow result envelopes in the SDK).
|
|
22
|
+
* - Swift has no analog of TS `Pick<M, …>` / `Partial<M>`, so a query op with
|
|
23
|
+
* a `pick`/`partial` projection types its rows as the open `JSONValue`
|
|
24
|
+
* rather than a narrowed record (the same Fork-4 "no clean analog →
|
|
25
|
+
* JSONValue" fallback the emitter uses for un-descended schema nodes). A
|
|
26
|
+
* `full` projection over a known record types as `DBQueryResult<Record>`.
|
|
27
|
+
* - Disk lifecycle (write / `--check` / orphan cleanup) delegates to the
|
|
28
|
+
* shared `writeOrCheckGeneratedFiles`, scoped by an ownership BANNER
|
|
29
|
+
* distinct from both the workflow Swift banner and the model codegen's, so
|
|
30
|
+
* a shared Swift output dir stays safe.
|
|
31
|
+
*/
|
|
32
|
+
import * as path from "path";
|
|
33
|
+
import { writeOrCheckGeneratedFiles, } from "../codegen-shared/generatedFiles.js";
|
|
34
|
+
import { describeDbType, } from "../db-codegen/dbTypeIR.js";
|
|
35
|
+
import { resolveRecordInterfaceName, opParamsInterfaceName, opResultAliasName, } from "../db-codegen/dbNaming.js";
|
|
36
|
+
import { GENERATED_SWIFT_FILE_SUFFIX, SWIFT_BANNER_PREFIX } from "./generator.js";
|
|
37
|
+
// The third Swift generator's banner (#3344), from a leaf module so this adds
|
|
38
|
+
// no import cycle.
|
|
39
|
+
import { AGENT_SWIFT_BANNER_PREFIX, FUNCTION_SWIFT_BANNER_PREFIX, } from "./banners.js";
|
|
40
|
+
import { assertNoRetainedSiblingCollision, assertNoForeignGeneratorSymbolCollision, } from "./siblingSymbols.js";
|
|
41
|
+
import { SwiftCodegenError } from "./schemaToSwift.js";
|
|
42
|
+
import { structTypeName, enumTypeName, enumCaseNames, swiftPropertyName, unescapeIdentifier, } from "./swiftNaming.js";
|
|
43
|
+
import { swiftTypeForDbFieldType, swiftTypeForDbParamType, } from "./dbSwiftTypes.js";
|
|
44
|
+
/**
|
|
45
|
+
* Banner prefix stamped on every CLI-emitted database `.generated.swift` file.
|
|
46
|
+
* Distinct from both the workflow Swift banner (`// AUTO-GENERATED FROM
|
|
47
|
+
* workflows/`) and the model codegen's (`// Generated by swift-bao-codegen`),
|
|
48
|
+
* so none of the three generators' stale-sweeps ever deletes another's files
|
|
49
|
+
* when they share an output dir.
|
|
50
|
+
*/
|
|
51
|
+
export const DB_SWIFT_BANNER_PREFIX = "// AUTO-GENERATED FROM database-type-configs/";
|
|
52
|
+
/**
|
|
53
|
+
* The banner this generator stamped before issue #2760 renamed the source
|
|
54
|
+
* directory. RECOGNITION ONLY — nothing emits it.
|
|
55
|
+
*
|
|
56
|
+
* Ownership everywhere is `contents.startsWith(banner)`, so without this a file
|
|
57
|
+
* generated before the rename would match neither the db banner nor the
|
|
58
|
+
* workflow one: it would survive the db stale sweep as a stranger, stay
|
|
59
|
+
* invisible to the sibling-symbol scans, and be silently overwritten by
|
|
60
|
+
* `workflows codegen --lang swift` on a name collision instead of refused.
|
|
61
|
+
*/
|
|
62
|
+
export const LEGACY_DB_SWIFT_BANNER_PREFIX = "// AUTO-GENERATED FROM database-types/";
|
|
63
|
+
/** Both spellings, for every ownership check this generator performs. */
|
|
64
|
+
export const DB_SWIFT_BANNER_PREFIXES = [
|
|
65
|
+
DB_SWIFT_BANNER_PREFIX,
|
|
66
|
+
LEGACY_DB_SWIFT_BANNER_PREFIX,
|
|
67
|
+
];
|
|
68
|
+
/** Swift module the generated types + factory import. */
|
|
69
|
+
const CLIENT_MODULE = "JsBaoClient";
|
|
70
|
+
const INDENT = " ";
|
|
71
|
+
const CONFORMANCES = "Codable, Equatable, Sendable";
|
|
72
|
+
/**
|
|
73
|
+
* A Swift string literal (runtime call passes the op / subscription key
|
|
74
|
+
* verbatim). Every remaining control character is escaped as `\u{…}` too:
|
|
75
|
+
* Swift rejects a raw unprintable ASCII byte anywhere in a source file
|
|
76
|
+
* ("unprintable ASCII character found in source file"), and a subscription key
|
|
77
|
+
* is validated server-side only for `#` (#2805).
|
|
78
|
+
*/
|
|
79
|
+
function swiftStringLiteral(s) {
|
|
80
|
+
const escaped = s
|
|
81
|
+
.replace(/\\/g, "\\\\")
|
|
82
|
+
.replace(/"/g, '\\"')
|
|
83
|
+
.replace(/\n/g, "\\n")
|
|
84
|
+
.replace(/\r/g, "\\r")
|
|
85
|
+
.replace(/\t/g, "\\t")
|
|
86
|
+
.replace(/[\x00-\x1f\x7f]/g, (ch) => `\\u{${ch.codePointAt(0).toString(16)}}`);
|
|
87
|
+
return `"${escaped}"`;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Render an arbitrary server-supplied key for a SINGLE-LINE `///` doc comment
|
|
91
|
+
* (#2805). A subscription key is validated server-side only for `#`
|
|
92
|
+
* (`database-type-subscriptions-controller.ts`), so a key can carry a newline,
|
|
93
|
+
* a carriage return, or any other control character. Interpolated raw, the
|
|
94
|
+
* first line terminator ends the comment and the rest of the key lands in the
|
|
95
|
+
* file as source — a corrupt file at best, injected declarations at worst.
|
|
96
|
+
*
|
|
97
|
+
* Line terminators and control characters are therefore rendered as escapes
|
|
98
|
+
* here. This is a DISPLAY form: the wire key still travels verbatim through
|
|
99
|
+
* `swiftStringLiteral` into the runtime call.
|
|
100
|
+
*/
|
|
101
|
+
function swiftCommentText(s) {
|
|
102
|
+
let out = "";
|
|
103
|
+
for (const ch of s) {
|
|
104
|
+
const code = ch.codePointAt(0);
|
|
105
|
+
if (ch === "\n")
|
|
106
|
+
out += "\\n";
|
|
107
|
+
else if (ch === "\r")
|
|
108
|
+
out += "\\r";
|
|
109
|
+
else if (ch === "\t")
|
|
110
|
+
out += "\\t";
|
|
111
|
+
else if (code < 0x20 || code === 0x7f || code === 0x2028 || code === 0x2029)
|
|
112
|
+
out += `\\u{${code.toString(16)}}`;
|
|
113
|
+
else
|
|
114
|
+
out += ch;
|
|
115
|
+
}
|
|
116
|
+
return out;
|
|
117
|
+
}
|
|
118
|
+
/** Swift record struct type name for a model (shared naming + Swift sanitize). */
|
|
119
|
+
export function dbRecordSwiftTypeName(modelName, className) {
|
|
120
|
+
return structTypeName(resolveRecordInterfaceName(modelName, className));
|
|
121
|
+
}
|
|
122
|
+
/** `<Op>Params` Swift struct name (shared PascalCase + Swift sanitize). */
|
|
123
|
+
function dbParamsSwiftTypeName(opName) {
|
|
124
|
+
return structTypeName(opParamsInterfaceName(opName));
|
|
125
|
+
}
|
|
126
|
+
/** `<Op>Result` Swift typealias name. */
|
|
127
|
+
function dbResultSwiftTypeName(opName) {
|
|
128
|
+
return structTypeName(opResultAliasName(opName));
|
|
129
|
+
}
|
|
130
|
+
/**
|
|
131
|
+
* `<Sub>Row` Swift struct name for one subscription's change payload (#2805).
|
|
132
|
+
* `my-tasks` → `MyTasksRow`. The `Row` suffix is appended BEFORE PascalCasing
|
|
133
|
+
* so a key that lands on a Swift keyword (`self`) is lifted out of keyword
|
|
134
|
+
* space by the suffix rather than by `structTypeName`'s `_` escape.
|
|
135
|
+
*/
|
|
136
|
+
function dbSubscriptionRowSwiftTypeName(subscriptionKey) {
|
|
137
|
+
return structTypeName(`${subscriptionKey}Row`);
|
|
138
|
+
}
|
|
139
|
+
/** Swift method name for one subscription on the `Subscriptions` factory. */
|
|
140
|
+
function dbSubscriptionMethodName(subscriptionKey) {
|
|
141
|
+
return swiftPropertyName(subscriptionKey);
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Namespace `enum` name for a database type (issue #1687). Every symbol a type
|
|
145
|
+
* emits is nested under `public enum <Type>` (`securities-ref` →
|
|
146
|
+
* `SecuritiesRef`), so two DB types can never collide on a shared op symbol.
|
|
147
|
+
* Reuses the same `structTypeName` sanitizer (keyword suffixing + digit-leading
|
|
148
|
+
* `_` guard) the old `<Type>Ops` derivation used, so the namespace name is a
|
|
149
|
+
* legal Swift type identifier.
|
|
150
|
+
*/
|
|
151
|
+
export function dbNamespaceName(databaseType) {
|
|
152
|
+
return structTypeName(databaseType);
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Swift standard-library / Foundation / `JsBaoClient` SDK type names that the
|
|
156
|
+
* generated `enum <Type>` body references UNQUALIFIED. If a database type's
|
|
157
|
+
* namespace enum takes one of these names, Swift name lookup inside the enum
|
|
158
|
+
* resolves the nested namespace first and shadows the real type — e.g. a
|
|
159
|
+
* `string` database emits `public enum String { … }`, and every `String`
|
|
160
|
+
* field, `CodingKeys` raw type, and string argument inside now resolves to the
|
|
161
|
+
* empty namespace enum instead of `Swift.String`, breaking `Codable` synthesis
|
|
162
|
+
* and rejecting string values (Codex [P1], #1687). The generated code never
|
|
163
|
+
* qualifies these references (`Swift.String`, `JsBaoClient.SortDirection`), so
|
|
164
|
+
* the only safe fix is to reject the namespace name at codegen time and have
|
|
165
|
+
* the user rename the database type — consistent with #1653's "clear
|
|
166
|
+
* codegen-time error, the user renames" decision.
|
|
167
|
+
*
|
|
168
|
+
* The set is the union of every type the emitter can reference inside the enum:
|
|
169
|
+
* the scalar/collection types from `dbSwiftTypes.ts`, the protocol conformances
|
|
170
|
+
* stamped on emitted structs/enums, and the SDK envelope + factory types.
|
|
171
|
+
*/
|
|
172
|
+
const RESERVED_NAMESPACE_NAMES = new Set([
|
|
173
|
+
// Swift stdlib scalars emitted for record fields / op params.
|
|
174
|
+
"String",
|
|
175
|
+
"Int",
|
|
176
|
+
"Double",
|
|
177
|
+
"Bool",
|
|
178
|
+
// Foundation types a field/param mapping could resolve to (defensive: the
|
|
179
|
+
// current mappings widen date → String, but keep these reserved so a future
|
|
180
|
+
// mapping can't be silently shadowed).
|
|
181
|
+
"Data",
|
|
182
|
+
"Date",
|
|
183
|
+
// Collection types behind the `[…]` / `?` sugar the emitter uses. Sugar isn't
|
|
184
|
+
// shadowed by a nested type, but an explicit reference would be — reserved as
|
|
185
|
+
// defense-in-depth, and a database type normalizing to one of these is a
|
|
186
|
+
// dangerous name regardless.
|
|
187
|
+
"Array",
|
|
188
|
+
"Dictionary",
|
|
189
|
+
"Optional",
|
|
190
|
+
"Set",
|
|
191
|
+
// Protocol conformances stamped on every emitted struct / nested enum.
|
|
192
|
+
"Codable",
|
|
193
|
+
"Decodable",
|
|
194
|
+
"Encodable",
|
|
195
|
+
"Equatable",
|
|
196
|
+
"Hashable",
|
|
197
|
+
"Sendable",
|
|
198
|
+
"CaseIterable",
|
|
199
|
+
"CodingKey",
|
|
200
|
+
// JsBaoClient SDK types the ops factory + result typealiases reference.
|
|
201
|
+
"JsBaoClient",
|
|
202
|
+
"JSONValue",
|
|
203
|
+
"SortDirection",
|
|
204
|
+
// SDK types the typed-subscriptions factory references unqualified (#2805).
|
|
205
|
+
"DatabaseSubscribeOptions",
|
|
206
|
+
"TypedDatabaseChangePayload",
|
|
207
|
+
"TypedDatabaseChangeEvent",
|
|
208
|
+
"EventSubscription",
|
|
209
|
+
"DBQueryResult",
|
|
210
|
+
"DBMutationResult",
|
|
211
|
+
"DBCountResult",
|
|
212
|
+
"DBAggregateResult",
|
|
213
|
+
"DBApplyToQueryResult",
|
|
214
|
+
"DBPipelineResult",
|
|
215
|
+
]);
|
|
216
|
+
/**
|
|
217
|
+
* Validate that a database type's derived namespace enum name is safe to emit,
|
|
218
|
+
* and return it. Throws a named `SwiftCodegenError` (with a rename hint) for
|
|
219
|
+
* the whole class of unsafe names a server-accepted database type can produce
|
|
220
|
+
* (#1687):
|
|
221
|
+
*
|
|
222
|
+
* 1. **Degenerate `_`** — a type with no retained identifier characters
|
|
223
|
+
* (empty after sanitize, or separator/emoji/punctuation-only, e.g. `--`,
|
|
224
|
+
* `🎉`) normalizes to `_` via `structTypeName`. Swift reserves `_` as the
|
|
225
|
+
* wildcard and rejects `public enum _` (Codex [P2]).
|
|
226
|
+
* 2. **Stdlib/SDK shadowing** — a name in `RESERVED_NAMESPACE_NAMES` shadows
|
|
227
|
+
* a type the generated body references unqualified (Codex [P1]).
|
|
228
|
+
*
|
|
229
|
+
* Leading-digit residue (`123` → `_123`) and Swift reserved words (`self` →
|
|
230
|
+
* `Self_`, `any` → `Any_`) are already lifted into legal, non-shadowing
|
|
231
|
+
* identifiers by `structTypeName` (digit-leading `_` guard + keyword suffix),
|
|
232
|
+
* so they need no rejection here — only names that survive that sanitizer as
|
|
233
|
+
* `_` or as a real type identifier remain unsafe. The two in-run / retained-
|
|
234
|
+
* sibling namespace-NAME collision guards (two database types whose names
|
|
235
|
+
* normalize to the SAME enum) live in `generateDbSwiftTypes`; this check
|
|
236
|
+
* covers the single-type unsafe-name class.
|
|
237
|
+
*/
|
|
238
|
+
export function assertSafeNamespaceName(databaseType, sourceFile) {
|
|
239
|
+
const namespaceName = dbNamespaceName(databaseType);
|
|
240
|
+
if (namespaceName === "_") {
|
|
241
|
+
throw new SwiftCodegenError(`swift db codegen: database type "${databaseType}" has no letters or ` +
|
|
242
|
+
`digits to form a Swift type identifier, so it normalizes to the ` +
|
|
243
|
+
`reserved wildcard "_" — the compiler rejects "public enum _". Rename ` +
|
|
244
|
+
`the database type to include at least one letter.`, { sourceFile });
|
|
245
|
+
}
|
|
246
|
+
if (RESERVED_NAMESPACE_NAMES.has(namespaceName)) {
|
|
247
|
+
throw new SwiftCodegenError(`swift db codegen: database type "${databaseType}" normalizes to the ` +
|
|
248
|
+
`Swift namespace "public enum ${namespaceName}", which shadows the ` +
|
|
249
|
+
`standard-library / JsBaoClient SDK type "${namespaceName}" that the ` +
|
|
250
|
+
`generated code references unqualified (record fields, op results, or ` +
|
|
251
|
+
`the ops factory). Inside the enum "${namespaceName}" would resolve to ` +
|
|
252
|
+
`the empty namespace instead of the real type, breaking compilation. ` +
|
|
253
|
+
`Rename the database type so it does not normalize to "${namespaceName}".`, { sourceFile });
|
|
254
|
+
}
|
|
255
|
+
return namespaceName;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Nested factory struct name inside a DB-type namespace: `Orders.Ops` (issue
|
|
259
|
+
* #1687). Fixed leaf name — the enclosing `enum <Type>` supplies the
|
|
260
|
+
* qualification, so it no longer needs the `<Type>` prefix.
|
|
261
|
+
*/
|
|
262
|
+
const DB_OPS_STRUCT_NAME = "Ops";
|
|
263
|
+
/**
|
|
264
|
+
* Nested static factory func name: `Orders.ops(client, databaseId:)` (issue
|
|
265
|
+
* #1687). Replaces the old top-level free `<type>Ops(...)` function.
|
|
266
|
+
*/
|
|
267
|
+
const DB_OPS_FACTORY_NAME = "ops";
|
|
268
|
+
/**
|
|
269
|
+
* Nested typed-subscriptions struct + its static factory (#2805), the Swift
|
|
270
|
+
* counterpart of the JS `<type>Subscriptions` factory. Same shape as the ops
|
|
271
|
+
* pair above: `Orders.Subscriptions` obtained from
|
|
272
|
+
* `Orders.subscriptions(client, databaseId:)`.
|
|
273
|
+
*/
|
|
274
|
+
const DB_SUBSCRIPTIONS_STRUCT_NAME = "Subscriptions";
|
|
275
|
+
const DB_SUBSCRIPTIONS_FACTORY_NAME = "subscriptions";
|
|
276
|
+
/**
|
|
277
|
+
* Render a nested `String`-raw enum for a field/param declaring `enum = [...]`.
|
|
278
|
+
* Matches the JSON-Schema emitter's + model codegen's nested-enum shape.
|
|
279
|
+
*/
|
|
280
|
+
function renderStringEnum(typeName, values, indent) {
|
|
281
|
+
const pad = INDENT.repeat(indent);
|
|
282
|
+
const inner = INDENT.repeat(indent + 1);
|
|
283
|
+
const cases = enumCaseNames(values);
|
|
284
|
+
const lines = [
|
|
285
|
+
`${pad}public enum ${typeName}: String, Codable, CaseIterable, Sendable {`,
|
|
286
|
+
];
|
|
287
|
+
for (const c of cases)
|
|
288
|
+
lines.push(`${inner}case ${c.name} = ${swiftStringLiteral(c.raw)}`);
|
|
289
|
+
lines.push(`${pad}}`);
|
|
290
|
+
return lines.join("\n");
|
|
291
|
+
}
|
|
292
|
+
/**
|
|
293
|
+
* Render a Swift `struct` from resolved members + nested-enum declarations. A
|
|
294
|
+
* public memberwise initializer is always emitted (the synthesized one is not
|
|
295
|
+
* public across module boundaries); `CodingKeys` only when a wire key isn't a
|
|
296
|
+
* legal/idiomatic Swift identifier. No custom Codable is needed — DB records /
|
|
297
|
+
* params have no oneOf / open-object / required-nullable cases.
|
|
298
|
+
*/
|
|
299
|
+
function renderStruct(typeName, members, nestedEnumDecls) {
|
|
300
|
+
const b = INDENT;
|
|
301
|
+
const needsCodingKeys = members.some((m) => unescapeIdentifier(m.swiftName) !== m.wireKey);
|
|
302
|
+
const out = [`public struct ${typeName}: ${CONFORMANCES} {`];
|
|
303
|
+
for (const decl of nestedEnumDecls)
|
|
304
|
+
out.push(decl);
|
|
305
|
+
if (nestedEnumDecls.length > 0)
|
|
306
|
+
out.push("");
|
|
307
|
+
for (const m of members) {
|
|
308
|
+
out.push(`${b}public var ${m.swiftName}: ${m.type}${m.optional ? "?" : ""}`);
|
|
309
|
+
}
|
|
310
|
+
if (members.length > 0)
|
|
311
|
+
out.push("");
|
|
312
|
+
// Public memberwise initializer.
|
|
313
|
+
if (members.length === 0) {
|
|
314
|
+
out.push(`${b}public init() {}`);
|
|
315
|
+
}
|
|
316
|
+
else {
|
|
317
|
+
out.push(`${b}public init(`);
|
|
318
|
+
members.forEach((m, i) => {
|
|
319
|
+
const type = `${m.type}${m.optional ? "?" : ""}`;
|
|
320
|
+
const def = m.optional ? " = nil" : "";
|
|
321
|
+
out.push(`${b}${b}${m.swiftName}: ${type}${def}${i < members.length - 1 ? "," : ""}`);
|
|
322
|
+
});
|
|
323
|
+
out.push(`${b}) {`);
|
|
324
|
+
for (const m of members)
|
|
325
|
+
out.push(`${b}${b}self.${m.swiftName} = ${m.swiftName}`);
|
|
326
|
+
out.push(`${b}}`);
|
|
327
|
+
}
|
|
328
|
+
if (needsCodingKeys) {
|
|
329
|
+
out.push("");
|
|
330
|
+
out.push(`${b}public enum CodingKeys: String, CodingKey {`);
|
|
331
|
+
for (const m of members) {
|
|
332
|
+
const bare = unescapeIdentifier(m.swiftName);
|
|
333
|
+
const rhs = bare !== m.wireKey ? ` = ${swiftStringLiteral(m.wireKey)}` : "";
|
|
334
|
+
out.push(`${b}${b}case ${m.swiftName}${rhs}`);
|
|
335
|
+
}
|
|
336
|
+
out.push(`${b}}`);
|
|
337
|
+
}
|
|
338
|
+
out.push(`}`);
|
|
339
|
+
return out.join("\n");
|
|
340
|
+
}
|
|
341
|
+
/**
|
|
342
|
+
* Render one record model. Empty (no declared fields and no stamped fields) →
|
|
343
|
+
* an open typealias (`[String: JSONValue]`), mirroring the TS empty-record
|
|
344
|
+
* `Record<string, unknown>` — a Database-DO record is schemaless, so the empty
|
|
345
|
+
* shape stays open.
|
|
346
|
+
*/
|
|
347
|
+
function renderRecordStruct(typeName, fields, stampedFields) {
|
|
348
|
+
const members = [];
|
|
349
|
+
const nestedEnums = [];
|
|
350
|
+
const declared = new Set();
|
|
351
|
+
for (const f of fields) {
|
|
352
|
+
declared.add(f.name);
|
|
353
|
+
let type;
|
|
354
|
+
if (f.type === "string" && Array.isArray(f.enum) && f.enum.length > 0) {
|
|
355
|
+
const enumName = enumTypeName(f.name);
|
|
356
|
+
nestedEnums.push(renderStringEnum(enumName, f.enum, 1));
|
|
357
|
+
type = enumName;
|
|
358
|
+
}
|
|
359
|
+
else {
|
|
360
|
+
type = swiftTypeForDbFieldType(f.type);
|
|
361
|
+
}
|
|
362
|
+
members.push({
|
|
363
|
+
wireKey: f.name,
|
|
364
|
+
swiftName: swiftPropertyName(f.name),
|
|
365
|
+
type,
|
|
366
|
+
optional: !f.required,
|
|
367
|
+
});
|
|
368
|
+
}
|
|
369
|
+
// Server-stamped fields → optional String props if not already declared.
|
|
370
|
+
for (const stamped of stampedFields) {
|
|
371
|
+
if (declared.has(stamped))
|
|
372
|
+
continue;
|
|
373
|
+
declared.add(stamped);
|
|
374
|
+
members.push({
|
|
375
|
+
wireKey: stamped,
|
|
376
|
+
swiftName: swiftPropertyName(stamped),
|
|
377
|
+
type: "String",
|
|
378
|
+
optional: true,
|
|
379
|
+
});
|
|
380
|
+
}
|
|
381
|
+
if (members.length === 0) {
|
|
382
|
+
return `public typealias ${typeName} = [String: JSONValue]`;
|
|
383
|
+
}
|
|
384
|
+
return renderStruct(typeName, members, nestedEnums);
|
|
385
|
+
}
|
|
386
|
+
/** Render one op-params struct (write shape). */
|
|
387
|
+
function renderParamsStruct(typeName, op) {
|
|
388
|
+
const members = [];
|
|
389
|
+
const nestedEnums = [];
|
|
390
|
+
for (const p of op.params) {
|
|
391
|
+
let type;
|
|
392
|
+
if (p.type === "string" && Array.isArray(p.enum) && p.enum.length > 0) {
|
|
393
|
+
const enumName = enumTypeName(p.name);
|
|
394
|
+
nestedEnums.push(renderStringEnum(enumName, p.enum, 1));
|
|
395
|
+
type = swiftTypeForDbParamType(p.type, enumName, p.items);
|
|
396
|
+
}
|
|
397
|
+
else if (p.type === "array" &&
|
|
398
|
+
p.items === "string" &&
|
|
399
|
+
Array.isArray(p.enum) &&
|
|
400
|
+
p.enum.length > 0) {
|
|
401
|
+
const enumName = enumTypeName(p.name);
|
|
402
|
+
nestedEnums.push(renderStringEnum(enumName, p.enum, 1));
|
|
403
|
+
type = swiftTypeForDbParamType(p.type, enumName, p.items);
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
type = swiftTypeForDbParamType(p.type, undefined, p.items);
|
|
407
|
+
}
|
|
408
|
+
members.push({
|
|
409
|
+
wireKey: p.name,
|
|
410
|
+
swiftName: swiftPropertyName(p.name),
|
|
411
|
+
type,
|
|
412
|
+
optional: !p.required,
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
// A no-param op still gets an empty struct so the factory can construct `()`.
|
|
416
|
+
return renderStruct(typeName, members, nestedEnums);
|
|
417
|
+
}
|
|
418
|
+
/**
|
|
419
|
+
* Swift `DBQueryResult<…>` element for a query op / returning pipeline step.
|
|
420
|
+
* A known record with a `full` projection → `DBQueryResult<Record>`. A
|
|
421
|
+
* `pick`/`partial` projection has no Swift Pick/Partial analog → open rows
|
|
422
|
+
* (`DBQueryResult<JSONValue>`); a null record likewise.
|
|
423
|
+
*/
|
|
424
|
+
function queryResultSwift(recordTypeName, projection) {
|
|
425
|
+
if (recordTypeName === null)
|
|
426
|
+
return "DBQueryResult<JSONValue>";
|
|
427
|
+
const kind = projection?.kind ?? "full";
|
|
428
|
+
return kind === "full"
|
|
429
|
+
? `DBQueryResult<${recordTypeName}>`
|
|
430
|
+
: "DBQueryResult<JSONValue>";
|
|
431
|
+
}
|
|
432
|
+
/** Resolve the Swift result type expression for an op. */
|
|
433
|
+
function resultSwiftType(op, recordTypeByModel) {
|
|
434
|
+
const recordFor = (model) => model ? recordTypeByModel[model] ?? null : null;
|
|
435
|
+
switch (op.opType) {
|
|
436
|
+
case "query":
|
|
437
|
+
return queryResultSwift(recordFor(op.resultModelName), op.projection);
|
|
438
|
+
case "mutation":
|
|
439
|
+
return "DBMutationResult";
|
|
440
|
+
case "count":
|
|
441
|
+
return "DBCountResult";
|
|
442
|
+
case "aggregate":
|
|
443
|
+
return "DBAggregateResult";
|
|
444
|
+
case "applyToQuery":
|
|
445
|
+
return "DBApplyToQueryResult";
|
|
446
|
+
case "pipeline": {
|
|
447
|
+
const d = op.pipelineReturn ?? { kind: "opaque" };
|
|
448
|
+
switch (d.kind) {
|
|
449
|
+
case "query":
|
|
450
|
+
return queryResultSwift(recordFor(d.modelName), d.projection);
|
|
451
|
+
case "count":
|
|
452
|
+
return "DBCountResult";
|
|
453
|
+
case "aggregate":
|
|
454
|
+
return "DBAggregateResult";
|
|
455
|
+
case "opaque":
|
|
456
|
+
default:
|
|
457
|
+
return "DBPipelineResult";
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
default:
|
|
461
|
+
// Unknown op type → the opaque JSONValue (parity with the TS `unknown`).
|
|
462
|
+
return "JSONValue";
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
/**
|
|
466
|
+
* Render the typed `Ops` factory nested under the type's namespace enum: a
|
|
467
|
+
* struct with one `async throws` method per op, each binding `<Op>Params` in
|
|
468
|
+
* and `<Op>Result` out over the generic `DatabasesAPI.executeOperation`
|
|
469
|
+
* overload, plus a static `ops(client, databaseId:)` factory on the namespace
|
|
470
|
+
* (issue #1687). Returns "" for a type with no operations. The emitted block is
|
|
471
|
+
* un-indented here; `renderDbTypeSwiftFile` wraps the whole per-type body in
|
|
472
|
+
* `public enum <Type> { … }` and indents it one level.
|
|
473
|
+
*/
|
|
474
|
+
function renderOpsFactory(databaseType, ops) {
|
|
475
|
+
if (ops.length === 0)
|
|
476
|
+
return "";
|
|
477
|
+
const namespaceName = dbNamespaceName(databaseType);
|
|
478
|
+
const b = INDENT;
|
|
479
|
+
const lines = [
|
|
480
|
+
`/// Typed accessor for \`${databaseType}\` operations. Obtain one with`,
|
|
481
|
+
`/// \`${namespaceName}.${DB_OPS_FACTORY_NAME}(client, databaseId:)\`.`,
|
|
482
|
+
`public struct ${DB_OPS_STRUCT_NAME}: Sendable {`,
|
|
483
|
+
`${b}public let client: JsBaoClient`,
|
|
484
|
+
`${b}public let databaseId: String`,
|
|
485
|
+
``,
|
|
486
|
+
`${b}public init(client: JsBaoClient, databaseId: String) {`,
|
|
487
|
+
`${b}${b}self.client = client`,
|
|
488
|
+
`${b}${b}self.databaseId = databaseId`,
|
|
489
|
+
`${b}}`,
|
|
490
|
+
];
|
|
491
|
+
for (const op of ops) {
|
|
492
|
+
const method = swiftPropertyName(op.opName);
|
|
493
|
+
const paramsType = dbParamsSwiftTypeName(op.opName);
|
|
494
|
+
const resultType = dbResultSwiftTypeName(op.opName);
|
|
495
|
+
const nameLiteral = swiftStringLiteral(op.opName);
|
|
496
|
+
// With params: `method(_ params:, options…)`. Without: options only, and
|
|
497
|
+
// the empty params struct is constructed for the call.
|
|
498
|
+
const paramLine = op.hasParams ? `${b}${b}_ params: ${paramsType},` : null;
|
|
499
|
+
const paramsArg = op.hasParams ? "params" : `${paramsType}()`;
|
|
500
|
+
lines.push(``, `${b}/// Execute the \`${op.opName}\` operation.`, `${b}public func ${method}(`);
|
|
501
|
+
if (paramLine)
|
|
502
|
+
lines.push(paramLine);
|
|
503
|
+
lines.push(`${b}${b}limit: Int? = nil,`, `${b}${b}cursor: String? = nil,`, `${b}${b}direction: SortDirection? = nil,`, `${b}${b}timing: Bool? = nil`, `${b}) async throws -> ${resultType} {`, `${b}${b}try await client.databases.executeOperation(`, `${b}${b}${b}databaseId: databaseId,`, `${b}${b}${b}name: ${nameLiteral},`, `${b}${b}${b}params: ${paramsArg},`, `${b}${b}${b}limit: limit,`, `${b}${b}${b}cursor: cursor,`, `${b}${b}${b}direction: direction,`, `${b}${b}${b}timing: timing`, `${b}${b})`, `${b}}`);
|
|
504
|
+
}
|
|
505
|
+
lines.push(`}`, ``);
|
|
506
|
+
lines.push(`/// Typed operations factory for the \`${databaseType}\` database type.`, `public static func ${DB_OPS_FACTORY_NAME}(_ client: JsBaoClient, databaseId: String) -> ${DB_OPS_STRUCT_NAME} {`, `${b}${DB_OPS_STRUCT_NAME}(client: client, databaseId: databaseId)`, `}`);
|
|
507
|
+
return lines.join("\n");
|
|
508
|
+
}
|
|
509
|
+
/**
|
|
510
|
+
* Render one subscription's change-payload ROW struct (#2805).
|
|
511
|
+
*
|
|
512
|
+
* Deliberately NOT the model's record struct, and deliberately not the JS
|
|
513
|
+
* factory's shape: a `db.change` frame carries only the fields the write
|
|
514
|
+
* touched (`patch` / `increment` / `addToSet` / `removeFromSet` send just the
|
|
515
|
+
* delta, `save` merges onto the stored row), narrowed further by the
|
|
516
|
+
* subscription's `select`. So every member is OPTIONAL, and a `select`
|
|
517
|
+
* projection drops the unselected members entirely — the Swift analog of the
|
|
518
|
+
* TS `Pick<Record, …>`, minus the JS factory's claim that a delta is a full
|
|
519
|
+
* record (#1772).
|
|
520
|
+
*
|
|
521
|
+
* Enum fields reference the enum the RECORD struct already declares
|
|
522
|
+
* (`Task.StatusValue`) rather than re-declaring it, so the two types agree on
|
|
523
|
+
* the closed value set. A model with no members (the schemaless record, which
|
|
524
|
+
* renders as `[String: JSONValue]`) has nothing to narrow, so its rows stay
|
|
525
|
+
* open too.
|
|
526
|
+
*/
|
|
527
|
+
function renderSubscriptionRowStruct(typeName, sub, record, recordTypeName, stampedFields) {
|
|
528
|
+
const selected = sub.select ? new Set(sub.select) : null;
|
|
529
|
+
const members = [];
|
|
530
|
+
const declared = new Set();
|
|
531
|
+
for (const f of record.fields) {
|
|
532
|
+
declared.add(f.name);
|
|
533
|
+
if (selected && !selected.has(f.name))
|
|
534
|
+
continue;
|
|
535
|
+
const type = f.type === "string" && Array.isArray(f.enum) && f.enum.length > 0
|
|
536
|
+
? `${recordTypeName}.${enumTypeName(f.name)}`
|
|
537
|
+
: swiftTypeForDbFieldType(f.type);
|
|
538
|
+
members.push({
|
|
539
|
+
wireKey: f.name,
|
|
540
|
+
swiftName: swiftPropertyName(f.name),
|
|
541
|
+
type,
|
|
542
|
+
optional: true,
|
|
543
|
+
});
|
|
544
|
+
}
|
|
545
|
+
// Server-stamped fields arrive on the payload like any other column.
|
|
546
|
+
for (const stamped of stampedFields) {
|
|
547
|
+
if (declared.has(stamped))
|
|
548
|
+
continue;
|
|
549
|
+
declared.add(stamped);
|
|
550
|
+
if (selected && !selected.has(stamped))
|
|
551
|
+
continue;
|
|
552
|
+
members.push({
|
|
553
|
+
wireKey: stamped,
|
|
554
|
+
swiftName: swiftPropertyName(stamped),
|
|
555
|
+
type: "String",
|
|
556
|
+
optional: true,
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
const doc = [
|
|
560
|
+
`/// Change rows delivered by the \`${swiftCommentText(sub.subscriptionKey)}\` subscription ` +
|
|
561
|
+
`(model \`${recordTypeName}\`${sub.select ? ", `select` projection" : ""}).`,
|
|
562
|
+
`///`,
|
|
563
|
+
`/// Every field is optional even where the record requires it: a change`,
|
|
564
|
+
`/// frame carries only the fields the write touched, narrowed further by`,
|
|
565
|
+
`/// the subscription's \`select\`. Typing one non-optional would claim a`,
|
|
566
|
+
`/// value the frame need not carry — the JS factory's #1772 soundness bug,`,
|
|
567
|
+
`/// which this emitter does not reproduce.`,
|
|
568
|
+
].join("\n");
|
|
569
|
+
// Nothing to narrow (schemaless record) → open rows, same fallback the record
|
|
570
|
+
// struct takes.
|
|
571
|
+
if (members.length === 0) {
|
|
572
|
+
return `${doc}\npublic typealias ${typeName} = [String: JSONValue]`;
|
|
573
|
+
}
|
|
574
|
+
return `${doc}\n${renderStruct(typeName, members, [])}`;
|
|
575
|
+
}
|
|
576
|
+
/**
|
|
577
|
+
* Render the typed `Subscriptions` factory nested under the type's namespace
|
|
578
|
+
* enum (#2805): a struct with one `throws` method per registered subscription,
|
|
579
|
+
* each binding the subscription's row type over the SDK's typed
|
|
580
|
+
* `DatabasesAPI.subscribe` overload, plus a static
|
|
581
|
+
* `subscriptions(client, databaseId:)` factory on the namespace. Mirrors
|
|
582
|
+
* `renderOpsFactory`; returns "" for a type with no subscriptions.
|
|
583
|
+
*/
|
|
584
|
+
function renderSubscriptionsFactory(databaseType, subscriptions) {
|
|
585
|
+
if (subscriptions.length === 0)
|
|
586
|
+
return "";
|
|
587
|
+
const namespaceName = dbNamespaceName(databaseType);
|
|
588
|
+
const b = INDENT;
|
|
589
|
+
const lines = [
|
|
590
|
+
`/// Typed accessor for \`${databaseType}\` realtime subscriptions. Obtain one`,
|
|
591
|
+
`/// with \`${namespaceName}.${DB_SUBSCRIPTIONS_FACTORY_NAME}(client, databaseId:)\`.`,
|
|
592
|
+
`public struct ${DB_SUBSCRIPTIONS_STRUCT_NAME}: Sendable {`,
|
|
593
|
+
`${b}public let client: JsBaoClient`,
|
|
594
|
+
`${b}public let databaseId: String`,
|
|
595
|
+
``,
|
|
596
|
+
`${b}public init(client: JsBaoClient, databaseId: String) {`,
|
|
597
|
+
`${b}${b}self.client = client`,
|
|
598
|
+
`${b}${b}self.databaseId = databaseId`,
|
|
599
|
+
`${b}}`,
|
|
600
|
+
];
|
|
601
|
+
for (const sub of subscriptions) {
|
|
602
|
+
const method = dbSubscriptionMethodName(sub.subscriptionKey);
|
|
603
|
+
const rowType = dbSubscriptionRowSwiftTypeName(sub.subscriptionKey);
|
|
604
|
+
const keyLiteral = swiftStringLiteral(sub.subscriptionKey);
|
|
605
|
+
lines.push(``, `${b}/// Subscribe to the \`${swiftCommentText(sub.subscriptionKey)}\` subscription.`, `${b}///`, `${b}/// Hold the returned handle for as long as you want changes — it`, `${b}/// unsubscribes when released.`, `${b}public func ${method}(`, `${b}${b}options: DatabaseSubscribeOptions = DatabaseSubscribeOptions(),`, `${b}${b}onChange: @escaping @Sendable (TypedDatabaseChangePayload<${rowType}>) -> Void`, `${b}) throws -> EventSubscription {`, `${b}${b}try client.databases.subscribe(`, `${b}${b}${b}databaseId: databaseId,`, `${b}${b}${b}subscriptionKey: ${keyLiteral},`, `${b}${b}${b}rowType: ${rowType}.self,`, `${b}${b}${b}options: options,`, `${b}${b}${b}onChange: onChange`, `${b}${b})`, `${b}}`);
|
|
606
|
+
}
|
|
607
|
+
lines.push(`}`, ``);
|
|
608
|
+
lines.push(`/// Typed subscriptions factory for the \`${databaseType}\` database type.`, `public static func ${DB_SUBSCRIPTIONS_FACTORY_NAME}(_ client: JsBaoClient, databaseId: String) -> ${DB_SUBSCRIPTIONS_STRUCT_NAME} {`, `${b}${DB_SUBSCRIPTIONS_STRUCT_NAME}(client: client, databaseId: databaseId)`, `}`);
|
|
609
|
+
return lines.join("\n");
|
|
610
|
+
}
|
|
611
|
+
/**
|
|
612
|
+
* Indent every non-empty line of a rendered Swift block by `levels` levels
|
|
613
|
+
* (blank lines stay blank, preserving struct-internal spacing). Used to nest a
|
|
614
|
+
* type's declarations one level inside its `enum <Type>` namespace (#1687).
|
|
615
|
+
*/
|
|
616
|
+
function indentSwiftLines(text, levels) {
|
|
617
|
+
const pad = INDENT.repeat(levels);
|
|
618
|
+
return text
|
|
619
|
+
.split("\n")
|
|
620
|
+
.map((line) => (line.length === 0 ? line : pad + line))
|
|
621
|
+
.join("\n");
|
|
622
|
+
}
|
|
623
|
+
/**
|
|
624
|
+
* Render the full `<type>.generated.swift` content for one database-type TOML.
|
|
625
|
+
* Pure — exported so tests can assert on the string directly. Throws on a Swift
|
|
626
|
+
* record type-name collision between two models (mirrors the TS collision guard).
|
|
627
|
+
*/
|
|
628
|
+
export function renderDbTypeSwiftFile(input) {
|
|
629
|
+
const ir = describeDbType(input);
|
|
630
|
+
const sourceFile = `database-type-configs/${ir.databaseType}.toml`;
|
|
631
|
+
// Reject an unsafe namespace enum name (empty/separator-only `_`, or a name
|
|
632
|
+
// that shadows a stdlib/SDK type the body references) before any rendering,
|
|
633
|
+
// with a clear rename hint (#1687). `structTypeName` already lifts leading
|
|
634
|
+
// digits and Swift keywords into legal identifiers, so only the degenerate
|
|
635
|
+
// and shadowing cases remain. The validated name is reused at emission below.
|
|
636
|
+
const namespaceName = assertSafeNamespaceName(ir.databaseType, sourceFile);
|
|
637
|
+
// Within-file collision guards (issue #1653). A single
|
|
638
|
+
// `<type>.generated.swift` compiles as one Swift file, so every TOP-LEVEL
|
|
639
|
+
// symbol it declares — record structs, per-op `<Op>Params` structs,
|
|
640
|
+
// `<Op>Result` typealiases, and (for a type with operations) the `<Type>Ops`
|
|
641
|
+
// struct plus its free-function factory — shares ONE namespace and must be
|
|
642
|
+
// unique. The earlier guards kept records and op-params in SEPARATE maps, so a
|
|
643
|
+
// record whose `class_name` resolves to `<Type>Ops` (or to an op's
|
|
644
|
+
// params/result name) slipped through uncaught (Codex [P2]). Track them all in
|
|
645
|
+
// one registry keyed on the emitted symbol.
|
|
646
|
+
//
|
|
647
|
+
// The `<Type>Ops` METHODS live in a SEPARATE (struct-member) namespace, and
|
|
648
|
+
// Swift permits overloading a method name as long as the parameter lists
|
|
649
|
+
// differ. So two ops that normalize to the same method name are tracked apart
|
|
650
|
+
// by their emitted overload SIGNATURE, not the bare method basename: `get.user`
|
|
651
|
+
// and `getuser` produce DISTINCT `<Op>Params` types (`GetUserParams` via
|
|
652
|
+
// `dbNaming.pascalCase`, which splits on `.`, vs `GetuserParams`) but the SAME
|
|
653
|
+
// `getuser` method name (via `swiftPropertyName`, which drops `.`). When both
|
|
654
|
+
// ops take params, each emits `getuser(_ params: <distinct type>, …)` — legal
|
|
655
|
+
// Swift overloads that compile, so the check must ALLOW them (issue #1704). A
|
|
656
|
+
// bare method-name check rejected them as a false positive. Two ops truly
|
|
657
|
+
// redeclare only when the method name AND the parameter signature match — e.g.
|
|
658
|
+
// two PARAM-LESS ops that both emit `getuser(limit:…)` (no `_ params:` at all).
|
|
659
|
+
// The params-type guard alone could never catch that case (Codex [P1]).
|
|
660
|
+
const recordTypeByModel = {};
|
|
661
|
+
// symbol → who declares it, and whether that owner is a subscription (which
|
|
662
|
+
// has no `class_name` override, so it needs a different rename hint).
|
|
663
|
+
const topLevelSymbol = new Map();
|
|
664
|
+
const methodOwner = new Map(); // op method signature → opName
|
|
665
|
+
const registerTopLevel = (symbol, owner, schemaPath, fromSubscription = false) => {
|
|
666
|
+
const prior = topLevelSymbol.get(symbol);
|
|
667
|
+
if (prior !== undefined && prior.owner !== owner) {
|
|
668
|
+
// The fix depends on what collided: only models carry a `class_name`
|
|
669
|
+
// override, so pointing a subscription author at one sends them looking
|
|
670
|
+
// for a knob their TOML does not have (#2805).
|
|
671
|
+
const bothSubscriptions = prior.fromSubscription && fromSubscription;
|
|
672
|
+
const anySubscription = prior.fromSubscription || fromSubscription;
|
|
673
|
+
const hint = bothSubscriptions
|
|
674
|
+
? `Rename one subscription key so the two differ after Swift normalization.`
|
|
675
|
+
: anySubscription
|
|
676
|
+
? `Rename the subscription key, or rename the other declaration, so ` +
|
|
677
|
+
`the two differ after Swift normalization.`
|
|
678
|
+
: `Rename one, or add a class_name override, so the two differ after ` +
|
|
679
|
+
`Swift normalization.`;
|
|
680
|
+
throw new SwiftCodegenError(`swift db codegen: symbol collision in database type "${ir.databaseType}" — ` +
|
|
681
|
+
`${prior.owner} and ${owner} both produce Swift symbol "${symbol}" in the ` +
|
|
682
|
+
`"${dbNamespaceName(ir.databaseType)}" namespace, ` +
|
|
683
|
+
`which redeclares when the file compiles. ${hint}`, { sourceFile, schemaPath });
|
|
684
|
+
}
|
|
685
|
+
topLevelSymbol.set(symbol, { owner, fromSubscription });
|
|
686
|
+
};
|
|
687
|
+
// Record structs.
|
|
688
|
+
for (const rec of ir.records) {
|
|
689
|
+
const typeName = dbRecordSwiftTypeName(rec.modelName, rec.className);
|
|
690
|
+
registerTopLevel(typeName, `record "${rec.modelName}"`, "models");
|
|
691
|
+
recordTypeByModel[rec.modelName] = typeName;
|
|
692
|
+
}
|
|
693
|
+
// Per-op params structs, result typealiases, and factory method names.
|
|
694
|
+
for (const op of ir.ops) {
|
|
695
|
+
registerTopLevel(dbParamsSwiftTypeName(op.opName), `operation "${op.opName}" params`, "operations");
|
|
696
|
+
registerTopLevel(dbResultSwiftTypeName(op.opName), `operation "${op.opName}" result`, "operations");
|
|
697
|
+
const method = swiftPropertyName(op.opName);
|
|
698
|
+
// Key on the emitted Swift overload signature, not the bare method name. All
|
|
699
|
+
// ops share the same trailing `limit`/`cursor`/`direction`/`timing` labels
|
|
700
|
+
// and types, so the only thing that distinguishes two same-named methods is
|
|
701
|
+
// the leading `_ params:` parameter: a param-taking op emits its distinct
|
|
702
|
+
// `<Op>Params` type, a param-less op emits none. Ops with distinct param
|
|
703
|
+
// structs are therefore legal overloads (issue #1704); only ops that match
|
|
704
|
+
// on BOTH the method name and this signature redeclare.
|
|
705
|
+
const signature = op.hasParams
|
|
706
|
+
? `${method}(${dbParamsSwiftTypeName(op.opName)})`
|
|
707
|
+
: `${method}()`;
|
|
708
|
+
const priorOp = methodOwner.get(signature);
|
|
709
|
+
if (priorOp !== undefined && priorOp !== op.opName) {
|
|
710
|
+
throw new SwiftCodegenError(`swift db codegen: operation method-signature collision in database type ` +
|
|
711
|
+
`"${ir.databaseType}" — operations "${priorOp}" and "${op.opName}" ` +
|
|
712
|
+
`both emit the Swift method "${method}" with the same parameter ` +
|
|
713
|
+
`signature in the "${dbNamespaceName(ir.databaseType)}.${DB_OPS_STRUCT_NAME}" factory, which redeclares when the file ` +
|
|
714
|
+
`compiles. Rename one ` +
|
|
715
|
+
`operation, or give them distinct parameters, so the two differ ` +
|
|
716
|
+
`after Swift normalization.`, { sourceFile, schemaPath: "operations" });
|
|
717
|
+
}
|
|
718
|
+
methodOwner.set(signature, op.opName);
|
|
719
|
+
}
|
|
720
|
+
// The nested `Ops` struct + its static `ops` factory (emitted only when the
|
|
721
|
+
// type has operations — see `renderOpsFactory`). Both live inside the type's
|
|
722
|
+
// `enum <Type>` namespace alongside the records/params/results, so a record
|
|
723
|
+
// whose name resolves to `Ops` collides here instead of at `swift build`.
|
|
724
|
+
if (ir.ops.length > 0) {
|
|
725
|
+
registerTopLevel(DB_OPS_STRUCT_NAME, `the \`${DB_OPS_STRUCT_NAME}\` operations struct`, "operations");
|
|
726
|
+
registerTopLevel(DB_OPS_FACTORY_NAME, `the \`${DB_OPS_FACTORY_NAME}\` operations factory`, "operations");
|
|
727
|
+
}
|
|
728
|
+
// Per-subscription row structs + the `Subscriptions` struct and its static
|
|
729
|
+
// factory (#2805) — all top-level symbols inside the type's namespace enum,
|
|
730
|
+
// so a record or op that normalizes onto one collides here with a rename hint
|
|
731
|
+
// instead of at `swift build`. Two subscription keys that normalize to the
|
|
732
|
+
// same row type collide here too, which also covers the method-name case: the
|
|
733
|
+
// row name and the method name run through the same sanitizer, so keys that
|
|
734
|
+
// produce one produce the other.
|
|
735
|
+
for (const sub of ir.subscriptions) {
|
|
736
|
+
// A key with no letters or digits (`_`, `--`, `🎉`) sanitizes to the bare
|
|
737
|
+
// `_`, and `public func _(` is rejected by the compiler ("keyword '_'
|
|
738
|
+
// cannot be used as an identifier here"). Same degenerate class the
|
|
739
|
+
// namespace guard rejects for a database-type name (#1687), same fix: a
|
|
740
|
+
// codegen-time error with a rename hint rather than an uncompilable file.
|
|
741
|
+
if (dbSubscriptionMethodName(sub.subscriptionKey) === "_") {
|
|
742
|
+
throw new SwiftCodegenError(`swift db codegen: subscription key "${sub.subscriptionKey}" in database ` +
|
|
743
|
+
`type "${ir.databaseType}" has no letters or digits to form a Swift ` +
|
|
744
|
+
`method identifier, so it normalizes to the reserved wildcard "_" — ` +
|
|
745
|
+
`the compiler rejects "public func _". Rename the subscription key to ` +
|
|
746
|
+
`include at least one letter.`, { sourceFile, schemaPath: "subscriptions" });
|
|
747
|
+
}
|
|
748
|
+
registerTopLevel(dbSubscriptionRowSwiftTypeName(sub.subscriptionKey), `subscription "${sub.subscriptionKey}" change rows`, "subscriptions", true);
|
|
749
|
+
}
|
|
750
|
+
if (ir.subscriptions.length > 0) {
|
|
751
|
+
registerTopLevel(DB_SUBSCRIPTIONS_STRUCT_NAME, `the \`${DB_SUBSCRIPTIONS_STRUCT_NAME}\` subscriptions struct`, "subscriptions");
|
|
752
|
+
registerTopLevel(DB_SUBSCRIPTIONS_FACTORY_NAME, `the \`${DB_SUBSCRIPTIONS_FACTORY_NAME}\` subscriptions factory`, "subscriptions");
|
|
753
|
+
}
|
|
754
|
+
const banner = [
|
|
755
|
+
`// AUTO-GENERATED FROM database-type-configs/${ir.databaseType}.toml — DO NOT EDIT.`,
|
|
756
|
+
"// Run `primitive databases codegen --lang swift` to regenerate.",
|
|
757
|
+
`// fingerprint: ${ir.fingerprint}`,
|
|
758
|
+
].join("\n");
|
|
759
|
+
const imports = ["import Foundation", `import ${CLIENT_MODULE}`].join("\n");
|
|
760
|
+
const bodyBlocks = [];
|
|
761
|
+
// Record structs, sorted by Swift type name for deterministic output.
|
|
762
|
+
const sortedRecords = [...ir.records].sort((a, b) => recordTypeByModel[a.modelName].localeCompare(recordTypeByModel[b.modelName]));
|
|
763
|
+
for (const rec of sortedRecords) {
|
|
764
|
+
bodyBlocks.push(renderRecordStruct(recordTypeByModel[rec.modelName], rec.fields, ir.stampedFields));
|
|
765
|
+
}
|
|
766
|
+
// Per-op params structs + result aliases (ops already sorted by op name).
|
|
767
|
+
for (const op of ir.ops) {
|
|
768
|
+
bodyBlocks.push(renderParamsStruct(dbParamsSwiftTypeName(op.opName), op));
|
|
769
|
+
bodyBlocks.push(`public typealias ${dbResultSwiftTypeName(op.opName)} = ${resultSwiftType(op, recordTypeByModel)}`);
|
|
770
|
+
}
|
|
771
|
+
const factory = renderOpsFactory(ir.databaseType, ir.ops);
|
|
772
|
+
if (factory)
|
|
773
|
+
bodyBlocks.push(factory);
|
|
774
|
+
// Per-subscription row structs, then the subscriptions factory (#2805).
|
|
775
|
+
// Subscriptions are already key-sorted by the IR, so the emitted order is
|
|
776
|
+
// deterministic.
|
|
777
|
+
const recordByModel = new Map(ir.records.map((rec) => [rec.modelName, rec]));
|
|
778
|
+
for (const sub of ir.subscriptions) {
|
|
779
|
+
// `describeDbType` guarantees the model resolves to a record on this type.
|
|
780
|
+
const record = recordByModel.get(sub.modelName);
|
|
781
|
+
bodyBlocks.push(renderSubscriptionRowStruct(dbSubscriptionRowSwiftTypeName(sub.subscriptionKey), sub, record, recordTypeByModel[sub.modelName], ir.stampedFields));
|
|
782
|
+
}
|
|
783
|
+
const subscriptionsFactory = renderSubscriptionsFactory(ir.databaseType, ir.subscriptions);
|
|
784
|
+
if (subscriptionsFactory)
|
|
785
|
+
bodyBlocks.push(subscriptionsFactory);
|
|
786
|
+
// Nest every symbol under a caseless `public enum <Type>` namespace (#1687),
|
|
787
|
+
// so `Orders.ListParams` and `Invoices.ListParams` can never collide when all
|
|
788
|
+
// `.generated.swift` files compile into one module. An empty database type
|
|
789
|
+
// still emits `public enum <Type> {}` — stable, deterministic type presence
|
|
790
|
+
// (sponsor decision 2026-07-19). `namespaceName` was validated + derived at
|
|
791
|
+
// the top of this function via `assertSafeNamespaceName`.
|
|
792
|
+
const namespaced = bodyBlocks.length === 0
|
|
793
|
+
? `public enum ${namespaceName} {}`
|
|
794
|
+
: `public enum ${namespaceName} {\n${indentSwiftLines(bodyBlocks.join("\n\n"), 1)}\n}`;
|
|
795
|
+
return [banner, imports, namespaced].join("\n\n") + "\n";
|
|
796
|
+
}
|
|
797
|
+
/**
|
|
798
|
+
* Run Swift database codegen end-to-end. One `<type>.generated.swift` per
|
|
799
|
+
* database type; delegates the disk lifecycle to the shared writer/checker with
|
|
800
|
+
* banner-scoped ownership so a shared Swift output dir stays safe.
|
|
801
|
+
*/
|
|
802
|
+
export async function generateDbSwiftTypes(options) {
|
|
803
|
+
const outAbs = path.resolve(options.outputDir);
|
|
804
|
+
// Run-scoped namespace registry: normalized namespace enum name → the
|
|
805
|
+
// database type that emitted it. Namespacing every symbol under
|
|
806
|
+
// `public enum <Type>` (issue #1687) makes cross-type symbol collisions
|
|
807
|
+
// structurally impossible — `Orders.ListParams` and `Invoices.ListParams`
|
|
808
|
+
// can never redeclare. The ONE collision that survives is two DB types whose
|
|
809
|
+
// NAMES normalize to the SAME namespace enum identifier (e.g. `my-type` and
|
|
810
|
+
// `my_type` both → `MyType`); they emit two `enum MyType` blocks that
|
|
811
|
+
// redeclare when the files compile into one module. Fork 3 (sponsor decision
|
|
812
|
+
// 2026-07-19): scope this guard to DB namespaces within the run, and drop the
|
|
813
|
+
// old cross-type OP-SYMBOL registry (that collision class no longer exists
|
|
814
|
+
// after namespacing).
|
|
815
|
+
//
|
|
816
|
+
// This in-run map only catches the namespace-name clash when BOTH colliding
|
|
817
|
+
// types are in `options.inputs` — i.e. a full run. A filtered / single-type
|
|
818
|
+
// run (`singleType: true`) has just the selected type in `inputs` and keeps
|
|
819
|
+
// its siblings on disk untouched (`fullOwnership: false`), so a retained
|
|
820
|
+
// `my_type.generated.swift` already declaring `public enum MyType` would
|
|
821
|
+
// never enter this map and would still redeclare at `swift build`. The
|
|
822
|
+
// retained-sibling guard below closes that residual for filtered runs — it
|
|
823
|
+
// compares the NAMESPACE NAME (not the old op symbols) against siblings'
|
|
824
|
+
// declared top-level symbols.
|
|
825
|
+
const namespaceOwner = new Map();
|
|
826
|
+
const filesToWrite = new Map();
|
|
827
|
+
for (const input of options.inputs) {
|
|
828
|
+
// renderDbTypeSwiftFile throws on the within-file record/op collisions
|
|
829
|
+
// (classes 2 + record guard) before we reach the namespace registry.
|
|
830
|
+
const content = renderDbTypeSwiftFile(input);
|
|
831
|
+
const namespace = dbNamespaceName(input.databaseType);
|
|
832
|
+
const prior = namespaceOwner.get(namespace);
|
|
833
|
+
if (prior !== undefined && prior !== input.databaseType) {
|
|
834
|
+
throw new SwiftCodegenError(`swift db codegen: namespace collision — database types "${prior}" and ` +
|
|
835
|
+
`"${input.databaseType}" both normalize to the Swift namespace ` +
|
|
836
|
+
`"${namespace}", so each emits a "public enum ${namespace}" that ` +
|
|
837
|
+
`redeclares when all .generated.swift files compile into one module. ` +
|
|
838
|
+
`Rename one database type so the two differ after Swift normalization.`, { sourceFile: `database-type-configs/${input.databaseType}.toml` });
|
|
839
|
+
}
|
|
840
|
+
namespaceOwner.set(namespace, input.databaseType);
|
|
841
|
+
const filePath = path.join(outAbs, `${input.databaseType}${GENERATED_SWIFT_FILE_SUFFIX}`);
|
|
842
|
+
filesToWrite.set(filePath, content);
|
|
843
|
+
}
|
|
844
|
+
// Filtered-run retained-sibling namespace-name collision (issue #1687). A
|
|
845
|
+
// `singleType` run renders only the selected type; its sibling
|
|
846
|
+
// `.generated.swift` files stay on disk but never enter `namespaceOwner`
|
|
847
|
+
// above, so this run's `public enum <Type>` could still redeclare against a
|
|
848
|
+
// retained sibling that declares the SAME enum (e.g. this run emits
|
|
849
|
+
// `enum MyType` for `my-type` while `my_type.generated.swift` on disk already
|
|
850
|
+
// declares `enum MyType`). Each DB file nests everything under one
|
|
851
|
+
// `public enum <Type>`, so a sibling's ONLY top-level symbol IS its namespace
|
|
852
|
+
// name — comparing the run's emitted namespace names against the siblings'
|
|
853
|
+
// parsed top-level symbols is exactly the namespace-name check. `emitted` is
|
|
854
|
+
// the run's namespace-name → owning database type map; the run's own output
|
|
855
|
+
// paths are excluded, so a filtered re-run of the same type never
|
|
856
|
+
// self-collides. (Full runs are already covered by `namespaceOwner` above.)
|
|
857
|
+
if (options.singleType === true) {
|
|
858
|
+
await assertNoRetainedSiblingCollision({
|
|
859
|
+
outputDir: outAbs,
|
|
860
|
+
ownershipBanner: DB_SWIFT_BANNER_PREFIXES,
|
|
861
|
+
suffix: GENERATED_SWIFT_FILE_SUFFIX,
|
|
862
|
+
emitted: namespaceOwner,
|
|
863
|
+
ownPaths: filesToWrite.keys(),
|
|
864
|
+
makeError: ({ symbol, owner, siblingStem }) => new SwiftCodegenError(`swift db codegen: namespace collision with a retained sibling — ` +
|
|
865
|
+
`database type "${owner}" (this run) and the existing ` +
|
|
866
|
+
`"${siblingStem}${GENERATED_SWIFT_FILE_SUFFIX}" both declare the ` +
|
|
867
|
+
`Swift namespace "public enum ${symbol}", which redeclares when all ` +
|
|
868
|
+
`.generated.swift files compile into one module. A filtered ` +
|
|
869
|
+
`(single-type) run does not regenerate siblings, so both files ` +
|
|
870
|
+
`coexist. Rename one database type so the two differ after Swift ` +
|
|
871
|
+
`normalization, or regenerate the whole output directory.`, { sourceFile: `database-type-configs/${owner}.toml` }),
|
|
872
|
+
});
|
|
873
|
+
}
|
|
874
|
+
// Cross-generator namespace collision (issue #1857). A database type's
|
|
875
|
+
// namespace enum name can match a top-level symbol a WORKFLOW-generated file
|
|
876
|
+
// already declares in a shared output dir — e.g. db type `foo-input` emits
|
|
877
|
+
// `public enum FooInput` while workflow `foo` emits a top-level struct
|
|
878
|
+
// `FooInput`. Their filenames differ, so the foreign-banner WRITE guard below
|
|
879
|
+
// (path-only) never trips, and the retained-sibling guard above only scans
|
|
880
|
+
// DB-owned files. This scan reads the workflow-owned siblings' declared
|
|
881
|
+
// top-level symbols and throws if the run's namespace name collides with any.
|
|
882
|
+
// It runs on every db run (not just filtered), because a full db run does not
|
|
883
|
+
// regenerate workflow files — they coexist regardless of ordering.
|
|
884
|
+
await assertNoForeignGeneratorSymbolCollision({
|
|
885
|
+
outputDir: outAbs,
|
|
886
|
+
foreignBanner: [
|
|
887
|
+
SWIFT_BANNER_PREFIX,
|
|
888
|
+
FUNCTION_SWIFT_BANNER_PREFIX,
|
|
889
|
+
AGENT_SWIFT_BANNER_PREFIX,
|
|
890
|
+
],
|
|
891
|
+
suffix: GENERATED_SWIFT_FILE_SUFFIX,
|
|
892
|
+
emitted: namespaceOwner,
|
|
893
|
+
makeError: ({ symbol, owner, siblingStem }) => new SwiftCodegenError(`swift db codegen: namespace collision with another generator's file — ` +
|
|
894
|
+
`database type "${owner}" emits the Swift namespace ` +
|
|
895
|
+
`"public enum ${symbol}", but the existing ` +
|
|
896
|
+
`"${siblingStem}${GENERATED_SWIFT_FILE_SUFFIX}" (owned by the workflow ` +
|
|
897
|
+
`or functions Swift generator) already declares a top-level "${symbol}" in the same ` +
|
|
898
|
+
`output directory, which redeclares when all .generated.swift files ` +
|
|
899
|
+
`compile into one module. Rename the database type or the "${siblingStem}" ` +
|
|
900
|
+
`workflow so the two differ after Swift normalization, or give one ` +
|
|
901
|
+
`generator a separate --output directory.`, { sourceFile: `database-type-configs/${owner}.toml` }),
|
|
902
|
+
});
|
|
903
|
+
return await writeOrCheckGeneratedFiles({
|
|
904
|
+
outputDir: outAbs,
|
|
905
|
+
filesToWrite,
|
|
906
|
+
check: options.check,
|
|
907
|
+
fullOwnership: options.singleType !== true,
|
|
908
|
+
generatedSuffix: GENERATED_SWIFT_FILE_SUFFIX,
|
|
909
|
+
// Pre-#2760 files are ours too, so the sweep still reaches them.
|
|
910
|
+
ownershipBanner: DB_SWIFT_BANNER_PREFIXES,
|
|
911
|
+
// Class 3b: never clobber a file owned by the workflow or functions Swift
|
|
912
|
+
// generator.
|
|
913
|
+
foreignOwnershipBanners: [
|
|
914
|
+
SWIFT_BANNER_PREFIX,
|
|
915
|
+
FUNCTION_SWIFT_BANNER_PREFIX,
|
|
916
|
+
AGENT_SWIFT_BANNER_PREFIX,
|
|
917
|
+
],
|
|
918
|
+
onForeignBannerCollision: ({ filePath, foreignBanner }) => new SwiftCodegenError(`swift codegen: output collision — this run would overwrite ` +
|
|
919
|
+
`"${path.basename(filePath)}" in the shared output directory, which ` +
|
|
920
|
+
`is already owned by a different generator (banner ` +
|
|
921
|
+
`"${foreignBanner.trim()}"). A database type and a workflow or function ` +
|
|
922
|
+
`key with the same name cannot share an output directory; give one generator a ` +
|
|
923
|
+
`separate --output directory.`),
|
|
924
|
+
});
|
|
925
|
+
}
|
|
926
|
+
//# sourceMappingURL=dbGenerator.js.map
|