primitive-admin 1.0.62 → 1.0.64
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 +132 -42
- package/assets/skill/skills/primitive-platform/SKILL.md +142 -661
- package/dist/bin/primitive.js +121 -41
- package/dist/bin/primitive.js.map +1 -1
- package/dist/src/commands/admins.js +37 -50
- package/dist/src/commands/admins.js.map +1 -1
- package/dist/src/commands/analytics.js +178 -9
- package/dist/src/commands/analytics.js.map +1 -1
- package/dist/src/commands/apps.js +17 -7
- 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.js +76 -116
- package/dist/src/commands/auth.js.map +1 -1
- package/dist/src/commands/blob-buckets.js +2 -1
- package/dist/src/commands/blob-buckets.js.map +1 -1
- package/dist/src/commands/catalog.js +26 -10
- package/dist/src/commands/catalog.js.map +1 -1
- package/dist/src/commands/collection-type-configs.js +3 -10
- package/dist/src/commands/collection-type-configs.js.map +1 -1
- package/dist/src/commands/collections.js +736 -19
- package/dist/src/commands/collections.js.map +1 -1
- package/dist/src/commands/config.js +13 -27
- package/dist/src/commands/config.js.map +1 -1
- package/dist/src/commands/connections.js +8 -9
- package/dist/src/commands/connections.js.map +1 -1
- package/dist/src/commands/cron-triggers.js +2 -1
- package/dist/src/commands/cron-triggers.js.map +1 -1
- package/dist/src/commands/database-type-configs.js +5 -12
- package/dist/src/commands/database-type-configs.js.map +1 -1
- package/dist/src/commands/databases.js +59 -72
- package/dist/src/commands/databases.js.map +1 -1
- package/dist/src/commands/documents.d.ts +58 -0
- package/dist/src/commands/documents.js +1623 -95
- package/dist/src/commands/documents.js.map +1 -1
- package/dist/src/commands/email-templates.js +5 -4
- package/dist/src/commands/email-templates.js.map +1 -1
- package/dist/src/commands/env.d.ts +1 -1
- package/dist/src/commands/env.js +106 -44
- package/dist/src/commands/env.js.map +1 -1
- package/dist/src/commands/feature-flags.js +2 -1
- package/dist/src/commands/feature-flags.js.map +1 -1
- 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.js +2 -1
- package/dist/src/commands/group-type-configs.js.map +1 -1
- package/dist/src/commands/groups.js +30 -17
- package/dist/src/commands/groups.js.map +1 -1
- package/dist/src/commands/guides.js +17 -11
- package/dist/src/commands/guides.js.map +1 -1
- package/dist/src/commands/init.d.ts +24 -12
- package/dist/src/commands/init.js +198 -110
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/integrations.js +65 -26
- package/dist/src/commands/integrations.js.map +1 -1
- package/dist/src/commands/locks.js +17 -2
- package/dist/src/commands/locks.js.map +1 -1
- package/dist/src/commands/metadata-category-configs.js +2 -1
- package/dist/src/commands/metadata-category-configs.js.map +1 -1
- package/dist/src/commands/metadata.js +8 -1
- package/dist/src/commands/metadata.js.map +1 -1
- package/dist/src/commands/prompts.js +106 -59
- package/dist/src/commands/prompts.js.map +1 -1
- package/dist/src/commands/rule-sets.js +3 -10
- package/dist/src/commands/rule-sets.js.map +1 -1
- package/dist/src/commands/scripts.d.ts +10 -0
- package/dist/src/commands/scripts.js +159 -25
- package/dist/src/commands/scripts.js.map +1 -1
- package/dist/src/commands/secrets.js +2 -1
- package/dist/src/commands/secrets.js.map +1 -1
- package/dist/src/commands/sessions.js +10 -9
- package/dist/src/commands/sessions.js.map +1 -1
- package/dist/src/commands/sync-app-settings.js +3 -5
- package/dist/src/commands/sync-app-settings.js.map +1 -1
- package/dist/src/commands/sync.d.ts +391 -44
- package/dist/src/commands/sync.js +2622 -534
- package/dist/src/commands/sync.js.map +1 -1
- package/dist/src/commands/tokens.js +2 -1
- package/dist/src/commands/tokens.js.map +1 -1
- package/dist/src/commands/users.js +19 -10
- package/dist/src/commands/users.js.map +1 -1
- package/dist/src/commands/vars.js +2 -1
- package/dist/src/commands/vars.js.map +1 -1
- package/dist/src/commands/waitlist.js +2 -1
- package/dist/src/commands/waitlist.js.map +1 -1
- package/dist/src/commands/webhooks.d.ts +29 -0
- package/dist/src/commands/webhooks.js +135 -64
- package/dist/src/commands/webhooks.js.map +1 -1
- package/dist/src/commands/workflows.d.ts +1 -29
- package/dist/src/commands/workflows.js +113 -179
- package/dist/src/commands/workflows.js.map +1 -1
- package/dist/src/lib/api-client.d.ts +628 -14
- package/dist/src/lib/api-client.js +776 -70
- package/dist/src/lib/api-client.js.map +1 -1
- package/dist/src/lib/app-settings-descriptor.d.ts +1 -1
- package/dist/src/lib/app-settings-descriptor.js +9 -1
- package/dist/src/lib/app-settings-descriptor.js.map +1 -1
- 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/codegen-shared/resolveCodegenSourceDir.d.ts +24 -54
- package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js +31 -153
- package/dist/src/lib/codegen-shared/resolveCodegenSourceDir.js.map +1 -1
- 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.js +88 -6
- package/dist/src/lib/config-object-descriptor.js.map +1 -1
- package/dist/src/lib/config-payload.d.ts +8 -1
- package/dist/src/lib/config-payload.js +49 -4
- package/dist/src/lib/config-payload.js.map +1 -1
- package/dist/src/lib/config-surface.d.ts +12 -1
- package/dist/src/lib/config-surface.js +71 -3
- package/dist/src/lib/config-surface.js.map +1 -1
- package/dist/src/lib/config.d.ts +31 -13
- package/dist/src/lib/config.js +34 -70
- package/dist/src/lib/config.js.map +1 -1
- package/dist/src/lib/credentials-store.d.ts +37 -22
- package/dist/src/lib/credentials-store.js +103 -97
- package/dist/src/lib/credentials-store.js.map +1 -1
- package/dist/src/lib/db-codegen/dbTypeIR.js +8 -0
- package/dist/src/lib/db-codegen/dbTypeIR.js.map +1 -1
- 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 +128 -17
- package/dist/src/lib/env-resolver-core.js +204 -22
- package/dist/src/lib/env-resolver-core.js.map +1 -1
- package/dist/src/lib/env-resolver.d.ts +18 -3
- package/dist/src/lib/env-resolver.js +23 -3
- package/dist/src/lib/env-resolver.js.map +1 -1
- 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.js +4 -0
- package/dist/src/lib/generated-allowlist.js.map +1 -1
- package/dist/src/lib/generated-config-surfaces.d.ts +2332 -78
- package/dist/src/lib/generated-config-surfaces.js +6979 -468
- package/dist/src/lib/generated-config-surfaces.js.map +1 -1
- 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/init-adopt.js +2 -2
- package/dist/src/lib/init-adopt.js.map +1 -1
- package/dist/src/lib/init-assets.js +3 -3
- 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 +1 -1
- 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 +41 -0
- package/dist/src/lib/init-ios-links.js +67 -1
- package/dist/src/lib/init-ios-links.js.map +1 -1
- package/dist/src/lib/init-plan.d.ts +1 -1
- package/dist/src/lib/init-plan.js +1 -1
- package/dist/src/lib/init-xcode.d.ts +6 -5
- package/dist/src/lib/init-xcode.js +34 -10
- package/dist/src/lib/init-xcode.js.map +1 -1
- 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 +1 -1
- package/dist/src/lib/local-state.js +1 -1
- 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 +152 -5
- package/dist/src/lib/log-inspection.js +179 -2
- package/dist/src/lib/log-inspection.js.map +1 -1
- 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/output.d.ts +15 -0
- package/dist/src/lib/output.js +28 -0
- package/dist/src/lib/output.js.map +1 -1
- package/dist/src/lib/paginate.d.ts +15 -0
- package/dist/src/lib/paginate.js +17 -0
- package/dist/src/lib/paginate.js.map +1 -1
- package/dist/src/lib/project-config.d.ts +46 -21
- package/dist/src/lib/project-config.js +74 -47
- package/dist/src/lib/project-config.js.map +1 -1
- 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/refresh-admin-credentials.d.ts +9 -1
- package/dist/src/lib/refresh-admin-credentials.js +22 -2
- package/dist/src/lib/refresh-admin-credentials.js.map +1 -1
- 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/skill-installer.d.ts +49 -3
- package/dist/src/lib/skill-installer.js +275 -100
- package/dist/src/lib/skill-installer.js.map +1 -1
- 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 +8 -9
- package/dist/src/lib/snapshots.js +20 -83
- package/dist/src/lib/snapshots.js.map +1 -1
- 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.js +19 -7
- package/dist/src/lib/swift-codegen/dbGenerator.js.map +1 -1
- 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 +7 -1
- package/dist/src/lib/swift-codegen/generator.js +28 -11
- package/dist/src/lib/swift-codegen/generator.js.map +1 -1
- package/dist/src/lib/swift-codegen/schemaToSwift.d.ts +15 -0
- package/dist/src/lib/swift-codegen/schemaToSwift.js +21 -4
- package/dist/src/lib/swift-codegen/schemaToSwift.js.map +1 -1
- package/dist/src/lib/sync-paths.d.ts +72 -55
- package/dist/src/lib/sync-paths.js +97 -100
- package/dist/src/lib/sync-paths.js.map +1 -1
- package/dist/src/lib/sync-resource-types.d.ts +23 -4
- package/dist/src/lib/sync-resource-types.js +106 -8
- package/dist/src/lib/sync-resource-types.js.map +1 -1
- package/dist/src/lib/sync-selectors.d.ts +45 -2
- package/dist/src/lib/sync-selectors.js +66 -5
- package/dist/src/lib/sync-selectors.js.map +1 -1
- package/dist/src/lib/template.d.ts +2 -2
- package/dist/src/lib/template.js +2 -2
- 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 +1 -1
- package/dist/src/lib/test-case-keys.js +1 -1
- package/dist/src/lib/test-case-variables.d.ts +14 -0
- package/dist/src/lib/test-case-variables.js +42 -0
- package/dist/src/lib/test-case-variables.js.map +1 -1
- package/dist/src/lib/toml-database-config.js +19 -2
- package/dist/src/lib/toml-database-config.js.map +1 -1
- 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-codegen/generator.d.ts +1 -1
- package/dist/src/lib/workflow-codegen/generator.js +1 -1
- package/dist/src/lib/workflow-toml-validator.d.ts +17 -8
- package/dist/src/lib/workflow-toml-validator.js +25 -12
- package/dist/src/lib/workflow-toml-validator.js.map +1 -1
- 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 +12 -2
- package/package.json +5 -4
|
@@ -109,6 +109,27 @@ export function stampCallbackScheme(clientDir, scheme) {
|
|
|
109
109
|
writeFileSync(plistPath, text.slice(0, dictStart) + rewritten + text.slice(dictEnd));
|
|
110
110
|
return { outcome: "stamped" };
|
|
111
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* How to point an environment at the app's web origin — in the shape that
|
|
114
|
+
* actually works (#2982).
|
|
115
|
+
*
|
|
116
|
+
* `primitive env add` CREATES an environment: it requires `--api-url` and
|
|
117
|
+
* `--app-id` (#3152), and refuses a name the config already has. Every
|
|
118
|
+
* environment anyone reads this about already exists (init wrote `dev`; `prod`
|
|
119
|
+
* was added when the app was deployed), so the instruction for those has to be
|
|
120
|
+
* the file, which is also what the docs describe as the way to edit one. The
|
|
121
|
+
* flag is worth naming only where a new environment is being created — and
|
|
122
|
+
* there it is shown with the flags the command will refuse to run without.
|
|
123
|
+
*
|
|
124
|
+
* `origin` is the placeholder or real origin to show.
|
|
125
|
+
*/
|
|
126
|
+
export function setWebUrlInstruction(origin, indent = " ") {
|
|
127
|
+
return [
|
|
128
|
+
`${indent}add "webUrl": "${origin}" to that environment in primitive/config.json`,
|
|
129
|
+
`${indent}(\`primitive env add <name> --api-url … --app-id … --web-url <origin>\` does this only for an`,
|
|
130
|
+
`${indent}environment it CREATES — it cannot edit one that already exists).`,
|
|
131
|
+
];
|
|
132
|
+
}
|
|
112
133
|
/**
|
|
113
134
|
* What init prints about email sign-in on the iOS path: it already works, and
|
|
114
135
|
* this is the one opt-in that adds the link.
|
|
@@ -128,7 +149,11 @@ export function linkOptInGuidance(scheme, options = {}) {
|
|
|
128
149
|
const redirectUri = iosMagicLinkRedirectUri(scheme);
|
|
129
150
|
return [
|
|
130
151
|
"Email sign-in works now: the email carries a 6-digit code and needs no app settings.",
|
|
131
|
-
|
|
152
|
+
"When this app gets a web client, prefer the https link: set the environment's `webUrl` —",
|
|
153
|
+
...setWebUrlInstruction("https://<your-web-domain>"),
|
|
154
|
+
" The email then carries that origin's /oauth/callback instead — one link that opens this",
|
|
155
|
+
" app where it is installed and signs in through the browser anywhere else.",
|
|
156
|
+
`Until then, to ALSO send a sign-in link that opens this app, add "${redirectUri}" to the existing`,
|
|
132
157
|
" [auth].emailRedirectUris array in config/app.toml (merge it in — run",
|
|
133
158
|
" `primitive config pull --only app` first if that file is not there yet), then run",
|
|
134
159
|
" `primitive config push --only app` and set `authManager.sendsEmailSignInLink = true`.",
|
|
@@ -140,6 +165,47 @@ export function linkOptInGuidance(scheme, options = {}) {
|
|
|
140
165
|
" authentication.md docs page — 'Make the emailed sign-in link open your app'.",
|
|
141
166
|
];
|
|
142
167
|
}
|
|
168
|
+
/**
|
|
169
|
+
* What init prints for an app with BOTH clients: the emailed sign-in link is
|
|
170
|
+
* already the web app's https callback, and this is what it takes to make that
|
|
171
|
+
* link open the iOS app in production (#2982).
|
|
172
|
+
*
|
|
173
|
+
* Everything here is a post-deploy step by necessity — the production web
|
|
174
|
+
* domain does not exist at init time, and the deploy script never learns the
|
|
175
|
+
* URL it deployed to. The order is load-bearing: the `applinks:` entitlement
|
|
176
|
+
* is the ONLY thing that makes Apple fetch the association document, and
|
|
177
|
+
* Apple's CDN caches what it gets, so it goes last — after the deployed
|
|
178
|
+
* document has been verified.
|
|
179
|
+
*
|
|
180
|
+
* `webOrigin` is the dev origin the run seeded — set only when the run also
|
|
181
|
+
* confirmed that origin's `/oauth/callback` is on the app's allow-list, since
|
|
182
|
+
* that is what makes the seeded link work.
|
|
183
|
+
*
|
|
184
|
+
* `unverifiedDevCallback` is the opposite case: a combined app whose allow-list
|
|
185
|
+
* this run could not vouch for (an adopted app, or no credentials to ask with).
|
|
186
|
+
* Nothing was seeded — the app keeps its working code-only email — and the two
|
|
187
|
+
* steps that turn the link on are printed instead. Neither is set for an
|
|
188
|
+
* adopting run, which does not own the project config at all.
|
|
189
|
+
*/
|
|
190
|
+
export function universalLinkGuidance(options = {}) {
|
|
191
|
+
const lines = [
|
|
192
|
+
"This app has both an iOS and a web client, so its sign-in email carries ONE https link:",
|
|
193
|
+
" the web app's /oauth/callback. Tapped where the iOS app is installed it opens the app;",
|
|
194
|
+
" anywhere else it is an ordinary web sign-in. The 6-digit code still works everywhere.",
|
|
195
|
+
];
|
|
196
|
+
if (options.webOrigin) {
|
|
197
|
+
lines.push(`In dev that link is ${options.webOrigin}/oauth/callback — seeded as the environment's`, " `webUrl`, and allow-listed on the app. Nothing to do.");
|
|
198
|
+
}
|
|
199
|
+
else if (options.unverifiedDevCallback) {
|
|
200
|
+
const origin = options.unverifiedDevCallback.replace(/\/oauth\/callback$/, "");
|
|
201
|
+
lines.push("The link is NOT on yet in dev: this app already existed, and its sign-in link allow-list", ` does not (or could not be checked to) carry ${options.unverifiedDevCallback}. Nothing was`, " changed — the email stays code-only, which works. To turn the link on:", ` 1. Merge "${options.unverifiedDevCallback}" into the existing [auth].emailRedirectUris`, " array in config/app.toml (run `primitive config pull --only app` first if that file is", " not there yet), then `primitive config push --only app`.", ` 2. Then ${setWebUrlInstruction(origin, "")[0]}`, " — the same edit the production steps below describe.");
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
lines.push("Set `webUrl` on this app's environment to turn it on (this run did not write the", " project config):", ...setWebUrlInstruction("https://<your-web-domain>"), " Allow-list that origin's /oauth/callback in [auth].emailRedirectUris too.");
|
|
205
|
+
}
|
|
206
|
+
lines.push("For production, once the web app is deployed:", " 1. Set that environment's `webUrl` to the deployed origin —", ...setWebUrlInstruction("https://<your-web-domain>", " "), " 2. Merge \"https://<your-web-domain>/oauth/callback\" into the existing", " [auth].emailRedirectUris array in config/app.toml (run `primitive config pull --only app`", " first if that file is not there yet), then `primitive config push --only app`.", " 3. Add `\"iosAppId\": \"ABCDE12345.com.example.app\"` beside that same environment's `webUrl`", " — the iOS client's Application Identifier Prefix (10 characters, usually your Team ID;", " verify it against the signed app's application-identifier entitlement) and its bundle id", " for THAT environment. `pnpm cf-deploy` generates the apple-app-site-association document", " from it per deploy, so each environment serves its own app id and none serves another's.", " 4. Deploy, then verify: `curl -i https://<your-web-domain>/.well-known/apple-app-site-association`", " must return 200, application/json and the JSON body — HTML means the SPA fallback answered.", " 5. Only then enable the `applinks:<your-web-domain>` entitlement in the iOS client's", " project.yml (it needs a real DEVELOPMENT_TEAM) and reinstall the app.", " Full checklist: the web client's public/.well-known/README.md, or the authentication", " docs page — 'Make the emailed sign-in link open your app'.");
|
|
207
|
+
return lines;
|
|
208
|
+
}
|
|
143
209
|
/** What init says when the template predates the `PrimitiveAuth` URL type. */
|
|
144
210
|
export function missingUrlTypeGuidance(scheme) {
|
|
145
211
|
return [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init-ios-links.js","sourceRoot":"","sources":["../../../src/lib/init-ios-links.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B;;;;GAIG;AACH,MAAM,CAAC,MAAM,4BAA4B,GAAG,eAAe,CAAC;AAE5D,wEAAwE;AACxE,MAAM,CAAC,MAAM,wBAAwB,GAAG,cAAc,CAAC;AAEvD,kEAAkE;AAClE,MAAM,iBAAiB,GAAG,EAAE,CAAC;AAE7B,yEAAyE;AACzE,MAAM,oBAAoB,GAAG,gBAAgB,CAAC;AAE9C;;;GAGG;AACH,SAAS,cAAc,CAAC,KAAyB,EAAE,SAAiB;IAClE,MAAM,SAAS,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IACxE,sEAAsE;IACtE,MAAM,WAAW,GAAG,SAAS,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACrD,OAAO,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,CAAC;AACzC,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,oBAAoB,CAClC,OAAe,EACf,KAAa,EACb,aAAsB;IAEtB,MAAM,KAAK,GAAG,OAAO,KAAK,oBAAoB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;IAC9D,MAAM,MAAM,GACV,cAAc,CAAC,KAAK,EAAE,iBAAiB,CAAC;QACxC,cAAc,CAAC,aAAa,EAAE,iBAAiB,CAAC;QAChD,KAAK,CAAC;IACR,+DAA+D;IAC/D,MAAM,MAAM,GAAG,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,YAAY,EAAE,EAAE,CAAC,CAAC;IACrE,MAAM,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,MAAM,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;IACvD,2EAA2E;IAC3E,8CAA8C;IAC9C,OAAO,MAAM,KAAK,wBAAwB,CAAC,CAAC,CAAC,GAAG,MAAM,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;AACxE,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,uBAAuB,CAAC,MAAc;IACpD,OAAO,GAAG,MAAM,oBAAoB,CAAC;AACvC,CAAC;AAOD;;;;;;;GAOG;AACH,MAAM,UAAU,mBAAmB,CAAC,SAAiB,EAAE,MAAc;IACnE,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,oBAAoB,CAAC,CAAC;IACxD,IAAI,CAAC,UAAU,CAAC,SAAS,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IAE5D,IAAI,IAAY,CAAC;IACjB,IAAI,CAAC;QACH,IAAI,GAAG,YAAY,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC1C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IAClC,CAAC;IAED,MAAM,MAAM,GAAG,WAAW,4BAA4B,WAAW,CAAC;IAClE,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;IACzC,IAAI,WAAW,KAAK,CAAC,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IAExD,4EAA4E;IAC5E,6EAA6E;IAC7E,MAAM,SAAS,GAAG,IAAI,CAAC,WAAW,CAAC,QAAQ,EAAE,WAAW,CAAC,CAAC;IAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;IACrD,IAAI,SAAS,KAAK,CAAC,CAAC,IAAI,OAAO,KAAK,CAAC,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IACxE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAC7C,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,4BAA4B,CAAC;QAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IAEnF,MAAM,cAAc,GAClB,0EAA0E,CAAC;IAC7E,MAAM,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzC,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,OAAO,EAAE,WAAW,EAAE,CAAC;IAC5C,IAAI,KAAK,CAAC,CAAC,CAAC,KAAK,MAAM;QAAE,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;IAEvD,MAAM,SAAS,GAAG,KAAK,CAAC,OAAO,CAAC,cAAc,EAAE,KAAK,MAAM,IAAI,CAAC,CAAC;IACjE,aAAa,CAAC,SAAS,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,SAAS,CAAC,GAAG,SAAS,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IACrF,OAAO,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC;AAChC,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,iBAAiB,CAC/B,MAAc,EACd,UAAoC,EAAE;IAEtC,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,KAAK,KAAK,CAAC;IAChD,MAAM,WAAW,GAAG,uBAAuB,CAAC,MAAM,CAAC,CAAC;IACpD,OAAO;QACL,sFAAsF;QACtF,
|
|
1
|
+
{"version":3,"file":"init-ios-links.js","sourceRoot":"","sources":["../../../src/lib/init-ios-links.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,7 +12,7 @@ export interface InitPlan {
|
|
|
12
12
|
/** The directory holding the ONE `.primitive/` for this app. */
|
|
13
13
|
projectRoot: string;
|
|
14
14
|
/**
|
|
15
|
-
* Whether this run writes
|
|
15
|
+
* Whether this run writes `primitive/config.json` and seeds the
|
|
16
16
|
* environment's credential slot. False when adopting: the config is already
|
|
17
17
|
* there and is not this run's to rewrite.
|
|
18
18
|
*/
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* multi-client — several clients, no surrounding project. Each client gets a
|
|
12
12
|
* platform-named subdirectory; the project config, the git
|
|
13
13
|
* repository and the canonical schema live at the root.
|
|
14
|
-
* add-client — an ancestor
|
|
14
|
+
* add-client — an ancestor `primitive/config.json` already exists. The run
|
|
15
15
|
* ADOPTS it: no nested project config, no nested git
|
|
16
16
|
* repository, no app creation, no commit. This is the path the
|
|
17
17
|
* issue opens with — running init in a subdirectory used to
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Retargets one `$(SRCROOT)`-relative build-phase path, in `project.yml
|
|
3
|
-
* every checked-in Xcode project
|
|
4
|
-
*
|
|
2
|
+
* Retargets one `$(SRCROOT)`-relative build-phase path, in `project.yml`, in
|
|
3
|
+
* every checked-in Xcode project, and in the committed codegen file lists. They
|
|
4
|
+
* all spell the path the same way, so one literal substitution covers the
|
|
5
|
+
* declared inputs and outputs alike.
|
|
5
6
|
*
|
|
6
7
|
* Returns the files it rewrote.
|
|
7
8
|
*/
|
|
@@ -17,11 +18,11 @@ export declare function retargetXcodePath(clientDir: string, fromRelative: strin
|
|
|
17
18
|
*/
|
|
18
19
|
export declare function xcodePathsLeftBehind(clientDir: string, fromRelative: string, toRelative: string): string[];
|
|
19
20
|
/**
|
|
20
|
-
* Points the Xcode build phases at the app's
|
|
21
|
+
* Points the Xcode build phases at the app's `primitive/config.json` when it
|
|
21
22
|
* lives above the client.
|
|
22
23
|
*
|
|
23
24
|
* Without this an Xcode build has no readable config: the phase declares
|
|
24
|
-
* `$(SRCROOT)
|
|
25
|
+
* `$(SRCROOT)/primitive/config.json`, which a composed client does not have,
|
|
25
26
|
* and the sandbox denies everything undeclared. A fresh clone (where
|
|
26
27
|
* `primitive.json` is gitignored) then cannot build at all, and a working copy
|
|
27
28
|
* that still has one keeps whichever environment generated it — so
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* CHECKED IN — that is what Xcode's Run button, a bare `xcodebuild` and a fresh
|
|
7
7
|
* clone all compile. A composed repository moves two files the Xcode build
|
|
8
8
|
* phases declare out of the client: the model schema (up to `models/` at the
|
|
9
|
-
* root) and
|
|
9
|
+
* root) and `primitive/config.json` (which the whole app shares). Rewriting
|
|
10
10
|
* only `project.yml` would leave the shipped project declaring paths that are
|
|
11
11
|
* no longer there — a build input error naming a file, with nothing saying the
|
|
12
12
|
* schema moved — so every rewrite here lands in both places.
|
|
@@ -17,15 +17,38 @@
|
|
|
17
17
|
*/
|
|
18
18
|
import { existsSync, readFileSync, readdirSync, writeFileSync } from "fs";
|
|
19
19
|
import { join, relative, sep } from "path";
|
|
20
|
+
import { LOCAL_STATE_FILENAME, PROJECT_CONFIG_FILENAME, PROJECT_LOCAL_STATE_DIR, PROJECT_TREE_DIR, } from "./env-resolver-core.js";
|
|
21
|
+
/**
|
|
22
|
+
* The committed Xcode files that spell a `$(SRCROOT)/`-relative path, beyond
|
|
23
|
+
* the spec and the checked-in project.
|
|
24
|
+
*
|
|
25
|
+
* The codegen phase declares its config-dependent inputs and outputs through
|
|
26
|
+
* these two lists (#3078), refreshed by `scripts/codegen.sh` on every build. A
|
|
27
|
+
* composed client's lists would otherwise ship naming a schema this run just
|
|
28
|
+
* removed — self-healed on the first build, but wrong in the committed tree
|
|
29
|
+
* until then, and invisible to the check that refuses to strand a declaration.
|
|
30
|
+
*/
|
|
31
|
+
const XCODE_FILE_LISTS = [
|
|
32
|
+
join("scripts", "codegen-inputs.xcfilelist"),
|
|
33
|
+
join("scripts", "codegen-outputs.xcfilelist"),
|
|
34
|
+
];
|
|
20
35
|
/** The build phase inputs that name the project config, relative to a client. */
|
|
21
36
|
const PROJECT_CONFIG_INPUTS = [
|
|
22
|
-
join(
|
|
23
|
-
join(
|
|
37
|
+
join(PROJECT_TREE_DIR, PROJECT_CONFIG_FILENAME),
|
|
38
|
+
join(PROJECT_LOCAL_STATE_DIR, LOCAL_STATE_FILENAME),
|
|
24
39
|
];
|
|
25
40
|
/** A POSIX-style path from `fromDir` to `toPath`, for a build-setting string. */
|
|
26
41
|
function posixRelative(fromDir, toPath) {
|
|
27
42
|
return relative(fromDir, toPath).split(sep).join("/");
|
|
28
43
|
}
|
|
44
|
+
/** Every file in `clientDir` that can declare a `$(SRCROOT)/`-relative path. */
|
|
45
|
+
function declaringFiles(clientDir) {
|
|
46
|
+
return [
|
|
47
|
+
join(clientDir, "project.yml"),
|
|
48
|
+
...findPbxprojFiles(clientDir),
|
|
49
|
+
...XCODE_FILE_LISTS.map((rel) => join(clientDir, rel)),
|
|
50
|
+
];
|
|
51
|
+
}
|
|
29
52
|
/** Every checked-in `project.pbxproj` beside the client's sources. */
|
|
30
53
|
function findPbxprojFiles(clientDir) {
|
|
31
54
|
let entries;
|
|
@@ -41,9 +64,10 @@ function findPbxprojFiles(clientDir) {
|
|
|
41
64
|
.filter((path) => existsSync(path));
|
|
42
65
|
}
|
|
43
66
|
/**
|
|
44
|
-
* Retargets one `$(SRCROOT)`-relative build-phase path, in `project.yml
|
|
45
|
-
* every checked-in Xcode project
|
|
46
|
-
*
|
|
67
|
+
* Retargets one `$(SRCROOT)`-relative build-phase path, in `project.yml`, in
|
|
68
|
+
* every checked-in Xcode project, and in the committed codegen file lists. They
|
|
69
|
+
* all spell the path the same way, so one literal substitution covers the
|
|
70
|
+
* declared inputs and outputs alike.
|
|
47
71
|
*
|
|
48
72
|
* Returns the files it rewrote.
|
|
49
73
|
*/
|
|
@@ -53,7 +77,7 @@ export function retargetXcodePath(clientDir, fromRelative, toRelative) {
|
|
|
53
77
|
if (from === to)
|
|
54
78
|
return [];
|
|
55
79
|
const rewritten = [];
|
|
56
|
-
for (const path of
|
|
80
|
+
for (const path of declaringFiles(clientDir)) {
|
|
57
81
|
if (!existsSync(path))
|
|
58
82
|
continue;
|
|
59
83
|
const before = readFileSync(path, "utf-8");
|
|
@@ -80,7 +104,7 @@ export function xcodePathsLeftBehind(clientDir, fromRelative, toRelative) {
|
|
|
80
104
|
if (from === to)
|
|
81
105
|
return [];
|
|
82
106
|
const stranded = [];
|
|
83
|
-
for (const path of
|
|
107
|
+
for (const path of declaringFiles(clientDir)) {
|
|
84
108
|
if (!existsSync(path))
|
|
85
109
|
continue;
|
|
86
110
|
const retargeted = readFileSync(path, "utf-8").split(from).join(to);
|
|
@@ -90,11 +114,11 @@ export function xcodePathsLeftBehind(clientDir, fromRelative, toRelative) {
|
|
|
90
114
|
return stranded;
|
|
91
115
|
}
|
|
92
116
|
/**
|
|
93
|
-
* Points the Xcode build phases at the app's
|
|
117
|
+
* Points the Xcode build phases at the app's `primitive/config.json` when it
|
|
94
118
|
* lives above the client.
|
|
95
119
|
*
|
|
96
120
|
* Without this an Xcode build has no readable config: the phase declares
|
|
97
|
-
* `$(SRCROOT)
|
|
121
|
+
* `$(SRCROOT)/primitive/config.json`, which a composed client does not have,
|
|
98
122
|
* and the sandbox denies everything undeclared. A fresh clone (where
|
|
99
123
|
* `primitive.json` is gitignored) then cannot build at all, and a working copy
|
|
100
124
|
* that still has one keeps whichever environment generated it — so
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init-xcode.js","sourceRoot":"","sources":["../../../src/lib/init-xcode.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,IAAI,CAAC;AAC1E,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"init-xcode.js","sourceRoot":"","sources":["../../../src/lib/init-xcode.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the identifier the `integrations tests` verbs take (issue #3000).
|
|
3
|
+
*
|
|
4
|
+
* The block-testing endpoints key on the composite `integration#<blockId>` and
|
|
5
|
+
* never check that the block exists, so an identifier that names no
|
|
6
|
+
* integration came back as an empty page rather than a 404: `tests list`
|
|
7
|
+
* printed "No test cases found." and `tests run-all` printed
|
|
8
|
+
* `Total Tests: 0 / Failed: 0` and exited 0. That is success-shaped in CI and
|
|
9
|
+
* indistinguishable from an integration that genuinely has no cases, so a
|
|
10
|
+
* typo, an integration KEY, or an ID from another app all read as "nothing to
|
|
11
|
+
* run".
|
|
12
|
+
*
|
|
13
|
+
* Resolving here — against the app's own integration list — is what makes
|
|
14
|
+
* `Total Tests: 0` mean "this integration exists and has no cases". The list
|
|
15
|
+
* is the one call that can answer both halves: it maps a key to its ID (keys
|
|
16
|
+
* are stored lowercased, so the match is case-insensitive) and it proves the
|
|
17
|
+
* identifier belongs to THIS app. Archived integrations are included, because
|
|
18
|
+
* their cases stay inspectable.
|
|
19
|
+
*/
|
|
20
|
+
export interface ResolvedIntegration {
|
|
21
|
+
integrationId: string;
|
|
22
|
+
/** The integration's key, when the summary carries one. */
|
|
23
|
+
integrationKey?: string;
|
|
24
|
+
}
|
|
25
|
+
/** The one method this resolver needs from `ApiClient`. */
|
|
26
|
+
export interface IntegrationLister {
|
|
27
|
+
listIntegrations(appId: string, params?: {
|
|
28
|
+
status?: string;
|
|
29
|
+
cursor?: string;
|
|
30
|
+
limit?: number;
|
|
31
|
+
}): Promise<{
|
|
32
|
+
items: any[];
|
|
33
|
+
nextCursor?: string | null;
|
|
34
|
+
}>;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Map an integration ID or key to its integration ID.
|
|
38
|
+
*
|
|
39
|
+
* Throws — naming the identifier — when nothing in the app matches, so the
|
|
40
|
+
* caller's existing catch prints the message and exits non-zero.
|
|
41
|
+
*/
|
|
42
|
+
export declare function resolveIntegrationSelector(client: IntegrationLister, appId: string, selector: string): Promise<ResolvedIntegration>;
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Resolve the identifier the `integrations tests` verbs take (issue #3000).
|
|
3
|
+
*
|
|
4
|
+
* The block-testing endpoints key on the composite `integration#<blockId>` and
|
|
5
|
+
* never check that the block exists, so an identifier that names no
|
|
6
|
+
* integration came back as an empty page rather than a 404: `tests list`
|
|
7
|
+
* printed "No test cases found." and `tests run-all` printed
|
|
8
|
+
* `Total Tests: 0 / Failed: 0` and exited 0. That is success-shaped in CI and
|
|
9
|
+
* indistinguishable from an integration that genuinely has no cases, so a
|
|
10
|
+
* typo, an integration KEY, or an ID from another app all read as "nothing to
|
|
11
|
+
* run".
|
|
12
|
+
*
|
|
13
|
+
* Resolving here — against the app's own integration list — is what makes
|
|
14
|
+
* `Total Tests: 0` mean "this integration exists and has no cases". The list
|
|
15
|
+
* is the one call that can answer both halves: it maps a key to its ID (keys
|
|
16
|
+
* are stored lowercased, so the match is case-insensitive) and it proves the
|
|
17
|
+
* identifier belongs to THIS app. Archived integrations are included, because
|
|
18
|
+
* their cases stay inspectable.
|
|
19
|
+
*/
|
|
20
|
+
import { paginateAll } from "./paginate.js";
|
|
21
|
+
/**
|
|
22
|
+
* Map an integration ID or key to its integration ID.
|
|
23
|
+
*
|
|
24
|
+
* Throws — naming the identifier — when nothing in the app matches, so the
|
|
25
|
+
* caller's existing catch prints the message and exits non-zero.
|
|
26
|
+
*/
|
|
27
|
+
export async function resolveIntegrationSelector(client, appId, selector) {
|
|
28
|
+
const identifier = (selector ?? "").trim();
|
|
29
|
+
if (!identifier) {
|
|
30
|
+
throw new Error("An integration ID or key is required.");
|
|
31
|
+
}
|
|
32
|
+
const items = await paginateAll((cursor) => client.listIntegrations(appId, cursor ? { cursor } : {}));
|
|
33
|
+
const lowered = identifier.toLowerCase();
|
|
34
|
+
const match = items.find((item) => item?.integrationId === identifier) ??
|
|
35
|
+
items.find((item) => typeof item?.integrationKey === "string" &&
|
|
36
|
+
item.integrationKey.toLowerCase() === lowered);
|
|
37
|
+
if (!match) {
|
|
38
|
+
throw new Error(`No integration '${identifier}' in app ${appId}. ` +
|
|
39
|
+
`Pass an integration key or ID from 'primitive integrations list'.`);
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
integrationId: match.integrationId ?? identifier,
|
|
43
|
+
...(match.integrationKey ? { integrationKey: match.integrationKey } : {}),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=integration-selector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"integration-selector.js","sourceRoot":"","sources":["../../../src/lib/integration-selector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,WAAW,EAAE,MAAM,eAAe,CAAC;AAgB5C;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,MAAyB,EACzB,KAAa,EACb,QAAgB;IAEhB,MAAM,UAAU,GAAG,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC3C,IAAI,CAAC,UAAU,EAAE,CAAC;QAChB,MAAM,IAAI,KAAK,CAAC,uCAAuC,CAAC,CAAC;IAC3D,CAAC;IAED,MAAM,KAAK,GAAG,MAAM,WAAW,CAAM,CAAC,MAAM,EAAE,EAAE,CAC9C,MAAM,CAAC,gBAAgB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CACzD,CAAC;IAEF,MAAM,OAAO,GAAG,UAAU,CAAC,WAAW,EAAE,CAAC;IACzC,MAAM,KAAK,GACT,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,aAAa,KAAK,UAAU,CAAC;QACxD,KAAK,CAAC,IAAI,CACR,CAAC,IAAI,EAAE,EAAE,CACP,OAAO,IAAI,EAAE,cAAc,KAAK,QAAQ;YACxC,IAAI,CAAC,cAAc,CAAC,WAAW,EAAE,KAAK,OAAO,CAChD,CAAC;IAEJ,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CACb,mBAAmB,UAAU,YAAY,KAAK,IAAI;YAChD,mEAAmE,CACtE,CAAC;IACJ,CAAC;IAED,OAAO;QACL,aAAa,EAAE,KAAK,CAAC,aAAa,IAAI,UAAU;QAChD,GAAG,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,cAAc,EAAE,KAAK,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;KAC1E,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The iOS client's Apple app identifier, per environment (#3081).
|
|
3
|
+
*
|
|
4
|
+
* Apple matches an association document against
|
|
5
|
+
* `<Application Identifier Prefix>.<Bundle Identifier>` — the prefix is ten
|
|
6
|
+
* alphanumerics, and it is USUALLY the Team ID but a legacy app's can differ
|
|
7
|
+
* (TN2311). Every message below therefore says "Application Identifier Prefix"
|
|
8
|
+
* and points at the signed app's `application-identifier` entitlement: a
|
|
9
|
+
* well-formed identifier with the wrong prefix produces a document that PARSES,
|
|
10
|
+
* so Apple caches it and both universal links and passkeys fail with nothing to
|
|
11
|
+
* read.
|
|
12
|
+
*
|
|
13
|
+
* One value per environment, because an app with alpha and production has one
|
|
14
|
+
* bundle id each. It is declared beside `webUrl` (#2982) — that pair is one
|
|
15
|
+
* cross-client link, the origin and the app it vouches for — and the Vue
|
|
16
|
+
* template's `scripts/deploy.mjs` generates the association document from it at
|
|
17
|
+
* deploy time.
|
|
18
|
+
*
|
|
19
|
+
* Returns the `string | true` shape `@inquirer/prompts` expects, like
|
|
20
|
+
* `validateWebUrl`, so the same function backs the flag check, the project
|
|
21
|
+
* config's field validation and any future prompt. `deploy.mjs` duplicates the
|
|
22
|
+
* shape rule (it is self-contained, node builtins only) but not these messages.
|
|
23
|
+
*/
|
|
24
|
+
/**
|
|
25
|
+
* Validates an Apple app identifier. Returns `true` when valid, otherwise the
|
|
26
|
+
* message to show the user.
|
|
27
|
+
*/
|
|
28
|
+
export declare function validateIosAppId(value: string): string | true;
|
|
29
|
+
/**
|
|
30
|
+
* The stored form of an already-validated identifier: trimmed, and otherwise
|
|
31
|
+
* byte-for-byte what Apple matches. Case is NOT folded — a bundle id is
|
|
32
|
+
* case-sensitive to Apple, and the prefix is uppercase already.
|
|
33
|
+
*/
|
|
34
|
+
export declare function normalizeIosAppId(value: string): string;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The iOS client's Apple app identifier, per environment (#3081).
|
|
3
|
+
*
|
|
4
|
+
* Apple matches an association document against
|
|
5
|
+
* `<Application Identifier Prefix>.<Bundle Identifier>` — the prefix is ten
|
|
6
|
+
* alphanumerics, and it is USUALLY the Team ID but a legacy app's can differ
|
|
7
|
+
* (TN2311). Every message below therefore says "Application Identifier Prefix"
|
|
8
|
+
* and points at the signed app's `application-identifier` entitlement: a
|
|
9
|
+
* well-formed identifier with the wrong prefix produces a document that PARSES,
|
|
10
|
+
* so Apple caches it and both universal links and passkeys fail with nothing to
|
|
11
|
+
* read.
|
|
12
|
+
*
|
|
13
|
+
* One value per environment, because an app with alpha and production has one
|
|
14
|
+
* bundle id each. It is declared beside `webUrl` (#2982) — that pair is one
|
|
15
|
+
* cross-client link, the origin and the app it vouches for — and the Vue
|
|
16
|
+
* template's `scripts/deploy.mjs` generates the association document from it at
|
|
17
|
+
* deploy time.
|
|
18
|
+
*
|
|
19
|
+
* Returns the `string | true` shape `@inquirer/prompts` expects, like
|
|
20
|
+
* `validateWebUrl`, so the same function backs the flag check, the project
|
|
21
|
+
* config's field validation and any future prompt. `deploy.mjs` duplicates the
|
|
22
|
+
* shape rule (it is self-contained, node builtins only) but not these messages.
|
|
23
|
+
*/
|
|
24
|
+
/** The example every message ends with, so a rejection is actionable. */
|
|
25
|
+
const SHAPE = "e.g. ABCDE12345.com.example.app";
|
|
26
|
+
/** Where the authoritative value is, when the Team ID is not the prefix. */
|
|
27
|
+
const VERIFY = "verify it against the signed app's application-identifier entitlement";
|
|
28
|
+
/** `<Application Identifier Prefix>.<Bundle Identifier>`, after trimming. */
|
|
29
|
+
const IOS_APP_ID = /^[A-Z0-9]{10}\.[A-Za-z0-9.-]+$/;
|
|
30
|
+
/** The placeholder the template's `.example` document ships with. */
|
|
31
|
+
const PLACEHOLDER_PREFIX = "TEAMID";
|
|
32
|
+
/**
|
|
33
|
+
* Validates an Apple app identifier. Returns `true` when valid, otherwise the
|
|
34
|
+
* message to show the user.
|
|
35
|
+
*/
|
|
36
|
+
export function validateIosAppId(value) {
|
|
37
|
+
if (typeof value !== "string" || !value.trim()) {
|
|
38
|
+
return `iOS app id cannot be empty — ${SHAPE}`;
|
|
39
|
+
}
|
|
40
|
+
const trimmed = value.trim();
|
|
41
|
+
const dot = trimmed.indexOf(".");
|
|
42
|
+
if (dot === -1) {
|
|
43
|
+
return `iOS app id must be <Application Identifier Prefix>.<bundle id> — ${SHAPE}`;
|
|
44
|
+
}
|
|
45
|
+
const prefix = trimmed.slice(0, dot);
|
|
46
|
+
const bundleId = trimmed.slice(dot + 1);
|
|
47
|
+
if (prefix === PLACEHOLDER_PREFIX || bundleId === "BUNDLEID") {
|
|
48
|
+
return `iOS app id is still the "${PLACEHOLDER_PREFIX}.BUNDLEID" placeholder — replace it with this environment's Application Identifier Prefix (usually your Team ID; ${VERIFY}) and the iOS client's bundle id (${SHAPE})`;
|
|
49
|
+
}
|
|
50
|
+
if (!/^[A-Z0-9]{10}$/.test(prefix)) {
|
|
51
|
+
return `iOS app id must start with the 10-character Application Identifier Prefix (usually your Team ID; ${VERIFY}), not "${prefix}" — ${SHAPE}`;
|
|
52
|
+
}
|
|
53
|
+
if (!bundleId) {
|
|
54
|
+
return `iOS app id has no bundle id after the Application Identifier Prefix — ${SHAPE}`;
|
|
55
|
+
}
|
|
56
|
+
if (!IOS_APP_ID.test(trimmed)) {
|
|
57
|
+
return `iOS app id's bundle id may only contain letters, digits, dots and dashes — ${SHAPE}`;
|
|
58
|
+
}
|
|
59
|
+
return true;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The stored form of an already-validated identifier: trimmed, and otherwise
|
|
63
|
+
* byte-for-byte what Apple matches. Case is NOT folded — a bundle id is
|
|
64
|
+
* case-sensitive to Apple, and the prefix is uppercase already.
|
|
65
|
+
*/
|
|
66
|
+
export function normalizeIosAppId(value) {
|
|
67
|
+
return value.trim();
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=ios-app-id.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ios-app-id.js","sourceRoot":"","sources":["../../../src/lib/ios-app-id.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,yEAAyE;AACzE,MAAM,KAAK,GAAG,iCAAiC,CAAC;AAEhD,4EAA4E;AAC5E,MAAM,MAAM,GACV,uEAAuE,CAAC;AAE1E,6EAA6E;AAC7E,MAAM,UAAU,GAAG,gCAAgC,CAAC;AAEpD,qEAAqE;AACrE,MAAM,kBAAkB,GAAG,QAAQ,CAAC;AAEpC;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAAa;IAC5C,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QAC/C,OAAO,gCAAgC,KAAK,EAAE,CAAC;IACjD,CAAC;IACD,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,GAAG,KAAK,CAAC,CAAC,EAAE,CAAC;QACf,OAAO,oEAAoE,KAAK,EAAE,CAAC;IACrF,CAAC;IACD,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACrC,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC;IACxC,IAAI,MAAM,KAAK,kBAAkB,IAAI,QAAQ,KAAK,UAAU,EAAE,CAAC;QAC7D,OAAO,4BAA4B,kBAAkB,oHAAoH,MAAM,qCAAqC,KAAK,GAAG,CAAC;IAC/N,CAAC;IACD,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACnC,OAAO,oGAAoG,MAAM,WAAW,MAAM,OAAO,KAAK,EAAE,CAAC;IACnJ,CAAC;IACD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,OAAO,yEAAyE,KAAK,EAAE,CAAC;IAC1F,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC9B,OAAO,8EAA8E,KAAK,EAAE,CAAC;IAC/F,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,iBAAiB,CAAC,KAAa;IAC7C,OAAO,KAAK,CAAC,IAAI,EAAE,CAAC;AACtB,CAAC"}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `--limit` / `--cursor` pair every paged `list` verb declares (#3646).
|
|
3
|
+
*
|
|
4
|
+
* Pagination is a property of the route, not of the verb that happens to have
|
|
5
|
+
* needed it first: a `list` backed by a paged server route carries both flags,
|
|
6
|
+
* prints exactly one page and reports the page boundary in its envelope; a
|
|
7
|
+
* `list` backed by an unpaged route carries neither. Declaring the pair from
|
|
8
|
+
* one place keeps the help text — and therefore the command manifest the docs
|
|
9
|
+
* gate reads — identical across the thirty-odd verbs that page.
|
|
10
|
+
*
|
|
11
|
+
* `cli/tests/unit/list-envelope-uniform-3646.test.ts` walks the manifest and
|
|
12
|
+
* fails a `list` that declares one of the two without the other.
|
|
13
|
+
*/
|
|
14
|
+
import { Option } from "commander";
|
|
15
|
+
/** `--limit <n>`, for a list whose route pages. */
|
|
16
|
+
export declare function pageLimitOption(): Option;
|
|
17
|
+
/** `--cursor <cursor>`, for a list whose route pages. */
|
|
18
|
+
export declare function pageCursorOption(): Option;
|
|
19
|
+
/**
|
|
20
|
+
* Read `--limit` as a positive integer, or exit naming the flag.
|
|
21
|
+
*
|
|
22
|
+
* Refuses before the action asks anything of the server, so a typo costs a
|
|
23
|
+
* message rather than a page of rows the caller did not ask for.
|
|
24
|
+
*
|
|
25
|
+
* Only an absent flag means "the route's own default": an empty value is a
|
|
26
|
+
* value, and `--limit "$LIMIT"` with `LIMIT` unset is the ordinary way a script
|
|
27
|
+
* supplies one. Reading it as an omission would answer a malformed request with
|
|
28
|
+
* a page the caller never asked for, so it takes the same refusal as `--limit
|
|
29
|
+
* zero`.
|
|
30
|
+
*/
|
|
31
|
+
export declare function parsePageLimit(raw: unknown): number | undefined;
|
|
32
|
+
/** A page as the human-readable half of a `list` verb reads it. */
|
|
33
|
+
interface PageBoundary {
|
|
34
|
+
nextCursor?: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* A cursor as it must appear after `--cursor` in a printed hint.
|
|
38
|
+
*
|
|
39
|
+
* A list cursor is the server's keyset position run through `JSON.stringify`
|
|
40
|
+
* (`encodeListCursor`, `src/app-api/helpers/list-params.ts`), so the token a
|
|
41
|
+
* page hands back is routinely `{"documentId":"01HXY…"}` — braces and quotes
|
|
42
|
+
* that a shell eats. The hint exists to be copied verbatim, so anything but a
|
|
43
|
+
* bare word is single-quoted POSIX-style (an embedded `'` closes, escapes and
|
|
44
|
+
* reopens the quoting).
|
|
45
|
+
*/
|
|
46
|
+
export declare function quoteCursorArg(cursor: string): string;
|
|
47
|
+
/**
|
|
48
|
+
* The "there is another page" hint, printed only when there is one.
|
|
49
|
+
*
|
|
50
|
+
* The counterpart of the envelope's `nextCursor` for a reader who is not
|
|
51
|
+
* parsing JSON: the same token, spelled as the argument that fetches the next
|
|
52
|
+
* page.
|
|
53
|
+
*/
|
|
54
|
+
export declare function printPageHint(page: PageBoundary): void;
|
|
55
|
+
/**
|
|
56
|
+
* The empty state for one page.
|
|
57
|
+
*
|
|
58
|
+
* An empty page is not the same thing as an empty listing: several routes cut
|
|
59
|
+
* the page from an index and filter it afterwards — `withoutFunctionOwned` and
|
|
60
|
+
* the status filter on webhooks, the bounded index scans — so a page can come
|
|
61
|
+
* back with no rows and a cursor pointing at matches further along. Before
|
|
62
|
+
* #3646 the draining readers hid that; now that a `list` prints one page,
|
|
63
|
+
* "No <subject> found." would be a lie in exactly that case, so it is said
|
|
64
|
+
* only when the server reported no next page, and the continuation is printed
|
|
65
|
+
* either way.
|
|
66
|
+
*/
|
|
67
|
+
export declare function printEmptyPage(page: PageBoundary, subject: string, emptyListing?: string): void;
|
|
68
|
+
export {};
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `--limit` / `--cursor` pair every paged `list` verb declares (#3646).
|
|
3
|
+
*
|
|
4
|
+
* Pagination is a property of the route, not of the verb that happens to have
|
|
5
|
+
* needed it first: a `list` backed by a paged server route carries both flags,
|
|
6
|
+
* prints exactly one page and reports the page boundary in its envelope; a
|
|
7
|
+
* `list` backed by an unpaged route carries neither. Declaring the pair from
|
|
8
|
+
* one place keeps the help text — and therefore the command manifest the docs
|
|
9
|
+
* gate reads — identical across the thirty-odd verbs that page.
|
|
10
|
+
*
|
|
11
|
+
* `cli/tests/unit/list-envelope-uniform-3646.test.ts` walks the manifest and
|
|
12
|
+
* fails a `list` that declares one of the two without the other.
|
|
13
|
+
*/
|
|
14
|
+
import { Option } from "commander";
|
|
15
|
+
import { error, info } from "./output.js";
|
|
16
|
+
/** `--limit <n>`, for a list whose route pages. */
|
|
17
|
+
export function pageLimitOption() {
|
|
18
|
+
return new Option("--limit <n>", "Maximum rows in one page (the route's own default when omitted)");
|
|
19
|
+
}
|
|
20
|
+
/** `--cursor <cursor>`, for a list whose route pages. */
|
|
21
|
+
export function pageCursorOption() {
|
|
22
|
+
return new Option("--cursor <cursor>", "Page to resume from: the `nextCursor` of a previous page");
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Read `--limit` as a positive integer, or exit naming the flag.
|
|
26
|
+
*
|
|
27
|
+
* Refuses before the action asks anything of the server, so a typo costs a
|
|
28
|
+
* message rather than a page of rows the caller did not ask for.
|
|
29
|
+
*
|
|
30
|
+
* Only an absent flag means "the route's own default": an empty value is a
|
|
31
|
+
* value, and `--limit "$LIMIT"` with `LIMIT` unset is the ordinary way a script
|
|
32
|
+
* supplies one. Reading it as an omission would answer a malformed request with
|
|
33
|
+
* a page the caller never asked for, so it takes the same refusal as `--limit
|
|
34
|
+
* zero`.
|
|
35
|
+
*/
|
|
36
|
+
export function parsePageLimit(raw) {
|
|
37
|
+
if (raw === undefined || raw === null)
|
|
38
|
+
return undefined;
|
|
39
|
+
const limit = Number(raw);
|
|
40
|
+
if (!Number.isInteger(limit) || limit <= 0) {
|
|
41
|
+
error("--limit must be a positive integer.");
|
|
42
|
+
process.exit(1);
|
|
43
|
+
}
|
|
44
|
+
return limit;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* A cursor as it must appear after `--cursor` in a printed hint.
|
|
48
|
+
*
|
|
49
|
+
* A list cursor is the server's keyset position run through `JSON.stringify`
|
|
50
|
+
* (`encodeListCursor`, `src/app-api/helpers/list-params.ts`), so the token a
|
|
51
|
+
* page hands back is routinely `{"documentId":"01HXY…"}` — braces and quotes
|
|
52
|
+
* that a shell eats. The hint exists to be copied verbatim, so anything but a
|
|
53
|
+
* bare word is single-quoted POSIX-style (an embedded `'` closes, escapes and
|
|
54
|
+
* reopens the quoting).
|
|
55
|
+
*/
|
|
56
|
+
export function quoteCursorArg(cursor) {
|
|
57
|
+
if (/^[A-Za-z0-9._:/=+-]+$/.test(cursor))
|
|
58
|
+
return cursor;
|
|
59
|
+
return `'${cursor.replace(/'/g, `'\\''`)}'`;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* The "there is another page" hint, printed only when there is one.
|
|
63
|
+
*
|
|
64
|
+
* The counterpart of the envelope's `nextCursor` for a reader who is not
|
|
65
|
+
* parsing JSON: the same token, spelled as the argument that fetches the next
|
|
66
|
+
* page.
|
|
67
|
+
*/
|
|
68
|
+
export function printPageHint(page) {
|
|
69
|
+
if (!page.nextCursor)
|
|
70
|
+
return;
|
|
71
|
+
info(`More results available. Re-run with --cursor ${quoteCursorArg(page.nextCursor)}`);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* The empty state for one page.
|
|
75
|
+
*
|
|
76
|
+
* An empty page is not the same thing as an empty listing: several routes cut
|
|
77
|
+
* the page from an index and filter it afterwards — `withoutFunctionOwned` and
|
|
78
|
+
* the status filter on webhooks, the bounded index scans — so a page can come
|
|
79
|
+
* back with no rows and a cursor pointing at matches further along. Before
|
|
80
|
+
* #3646 the draining readers hid that; now that a `list` prints one page,
|
|
81
|
+
* "No <subject> found." would be a lie in exactly that case, so it is said
|
|
82
|
+
* only when the server reported no next page, and the continuation is printed
|
|
83
|
+
* either way.
|
|
84
|
+
*/
|
|
85
|
+
export function printEmptyPage(page, subject, emptyListing = `No ${subject} found.`) {
|
|
86
|
+
info(page.nextCursor ? `No ${subject} on this page.` : emptyListing);
|
|
87
|
+
printPageHint(page);
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=list-options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-options.js","sourceRoot":"","sources":["../../../src/lib/list-options.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AACnC,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAE1C,mDAAmD;AACnD,MAAM,UAAU,eAAe;IAC7B,OAAO,IAAI,MAAM,CACf,aAAa,EACb,iEAAiE,CAClE,CAAC;AACJ,CAAC;AAED,yDAAyD;AACzD,MAAM,UAAU,gBAAgB;IAC9B,OAAO,IAAI,MAAM,CACf,mBAAmB,EACnB,0DAA0D,CAC3D,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAAC,GAAY;IACzC,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,SAAS,CAAC;IACxD,MAAM,KAAK,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;IAC1B,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;QAC3C,KAAK,CAAC,qCAAqC,CAAC,CAAC;QAC7C,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAOD;;;;;;;;;GASG;AACH,MAAM,UAAU,cAAc,CAAC,MAAc;IAC3C,IAAI,uBAAuB,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,OAAO,MAAM,CAAC;IACxD,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC;AAC9C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,IAAkB;IAC9C,IAAI,CAAC,IAAI,CAAC,UAAU;QAAE,OAAO;IAC7B,IAAI,CACF,gDAAgD,cAAc,CAAC,IAAI,CAAC,UAAU,CAAC,EAAE,CAClF,CAAC;AACJ,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,cAAc,CAC5B,IAAkB,EAClB,OAAe,EACf,YAAY,GAAG,MAAM,OAAO,SAAS;IAErC,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,MAAM,OAAO,gBAAgB,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IACrE,aAAa,CAAC,IAAI,CAAC,CAAC;AACtB,CAAC"}
|