@zuplo/cli 7.11.0 → 7.11.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/node_modules/@hono/node-server/README.md +2 -0
- package/node_modules/@hono/node-server/dist/index.cjs +1 -1
- package/node_modules/@hono/node-server/dist/index.mjs +1 -1
- package/node_modules/@hono/node-server/dist/serve-static.cjs +2 -1
- package/node_modules/@hono/node-server/dist/serve-static.mjs +2 -1
- package/node_modules/@hono/node-server/package.json +1 -1
- package/node_modules/@posthog/core/dist/metrics/index.d.ts +9 -0
- package/node_modules/@posthog/core/dist/metrics/index.d.ts.map +1 -1
- package/node_modules/@posthog/core/dist/metrics/index.js +38 -3
- package/node_modules/@posthog/core/dist/metrics/index.mjs +38 -3
- package/node_modules/@posthog/core/dist/metrics/types.d.ts +7 -2
- package/node_modules/@posthog/core/dist/metrics/types.d.ts.map +1 -1
- package/node_modules/@posthog/core/dist/traces/ids.d.ts.map +1 -1
- package/node_modules/@posthog/core/dist/traces/ids.js +2 -2
- package/node_modules/@posthog/core/dist/traces/ids.mjs +2 -2
- package/node_modules/@posthog/core/package.json +2 -2
- package/node_modules/@posthog/core/src/metrics/index.spec.ts +75 -0
- package/node_modules/@posthog/core/src/metrics/index.ts +60 -0
- package/node_modules/@posthog/core/src/metrics/types.ts +7 -1
- package/node_modules/@posthog/core/src/traces/ids.ts +4 -2
- package/node_modules/@posthog/types/dist/capture-metric.d.ts +10 -0
- package/node_modules/@posthog/types/dist/capture-metric.d.ts.map +1 -1
- package/node_modules/@posthog/types/dist/index.d.ts +1 -1
- package/node_modules/@posthog/types/dist/index.d.ts.map +1 -1
- package/node_modules/@posthog/types/package.json +1 -1
- package/node_modules/@posthog/types/src/capture-metric.ts +11 -0
- package/node_modules/@posthog/types/src/index.ts +1 -0
- package/node_modules/@zuplo/core/customer.cli.minified.js +2 -2
- package/node_modules/@zuplo/core/index.minified.js +2 -2
- package/node_modules/@zuplo/core/package.json +1 -1
- package/node_modules/@zuplo/graphql/package.json +1 -1
- package/node_modules/@zuplo/openapi-tools/package.json +5 -2
- package/node_modules/@zuplo/otel/package.json +1 -1
- package/node_modules/@zuplo/runtime/out/esm/{chunk-YJ2BHVUH.js → chunk-CDEAY3VY.js} +2 -2
- package/node_modules/@zuplo/runtime/out/esm/chunk-LVSZ3WTO.js +37 -0
- package/node_modules/@zuplo/runtime/out/esm/chunk-LVSZ3WTO.js.map +1 -0
- package/node_modules/@zuplo/runtime/out/esm/{chunk-VTO3F6DK.js → chunk-NUVXDVLJ.js} +2 -2
- package/node_modules/@zuplo/runtime/out/esm/{chunk-6YPRGG62.js → chunk-RHU3Z7DA.js} +108 -108
- package/node_modules/@zuplo/runtime/out/esm/chunk-RHU3Z7DA.js.map +1 -0
- package/node_modules/@zuplo/runtime/out/esm/index.js +1 -1
- package/node_modules/@zuplo/runtime/out/esm/internal/index.js +1 -1
- package/node_modules/@zuplo/runtime/out/esm/mcp-gateway/index.js +1 -1
- package/node_modules/@zuplo/runtime/out/esm/mocks/index.js +1 -1
- package/node_modules/@zuplo/runtime/out/esm/sdks/aws/index.js +1 -1
- package/node_modules/@zuplo/runtime/out/types/index.d.ts +15 -24
- package/node_modules/@zuplo/runtime/out/types/internal/index.d.ts +14 -0
- package/node_modules/@zuplo/runtime/package.json +1 -1
- package/package.json +15 -12
- package/dist/__tests__/archive-utils.test.d.ts +0 -2
- package/dist/__tests__/archive-utils.test.d.ts.map +0 -1
- package/dist/__tests__/archive-utils.test.js +0 -50
- package/dist/__tests__/archive-utils.test.js.map +0 -1
- package/dist/__tests__/import-openapi.test.d.ts +0 -2
- package/dist/__tests__/import-openapi.test.d.ts.map +0 -1
- package/dist/__tests__/import-openapi.test.js +0 -251
- package/dist/__tests__/import-openapi.test.js.map +0 -1
- package/dist/__tests__/integration/confirm-linked-config.integration.test.d.ts +0 -2
- package/dist/__tests__/integration/confirm-linked-config.integration.test.d.ts.map +0 -1
- package/dist/__tests__/integration/confirm-linked-config.integration.test.js +0 -202
- package/dist/__tests__/integration/confirm-linked-config.integration.test.js.map +0 -1
- package/dist/__tests__/integration/confirm-production-deploy.integration.test.d.ts +0 -2
- package/dist/__tests__/integration/confirm-production-deploy.integration.test.d.ts.map +0 -1
- package/dist/__tests__/integration/confirm-production-deploy.integration.test.js +0 -184
- package/dist/__tests__/integration/confirm-production-deploy.integration.test.js.map +0 -1
- package/dist/__tests__/integration/custom-domain.integration.test.d.ts +0 -2
- package/dist/__tests__/integration/custom-domain.integration.test.d.ts.map +0 -1
- package/dist/__tests__/integration/custom-domain.integration.test.js +0 -563
- package/dist/__tests__/integration/custom-domain.integration.test.js.map +0 -1
- package/dist/__tests__/integration/delete.integration.test.d.ts +0 -2
- package/dist/__tests__/integration/delete.integration.test.d.ts.map +0 -1
- package/dist/__tests__/integration/delete.integration.test.js +0 -262
- package/dist/__tests__/integration/delete.integration.test.js.map +0 -1
- package/dist/__tests__/integration/deploy.integration.test.d.ts +0 -2
- package/dist/__tests__/integration/deploy.integration.test.d.ts.map +0 -1
- package/dist/__tests__/integration/deploy.integration.test.js +0 -519
- package/dist/__tests__/integration/deploy.integration.test.js.map +0 -1
- package/dist/__tests__/integration/get-project-param.integration.test.d.ts +0 -2
- package/dist/__tests__/integration/get-project-param.integration.test.d.ts.map +0 -1
- package/dist/__tests__/integration/get-project-param.integration.test.js +0 -305
- package/dist/__tests__/integration/get-project-param.integration.test.js.map +0 -1
- package/dist/__tests__/integration/info.integration.test.d.ts +0 -2
- package/dist/__tests__/integration/info.integration.test.d.ts.map +0 -1
- package/dist/__tests__/integration/info.integration.test.js +0 -293
- package/dist/__tests__/integration/info.integration.test.js.map +0 -1
- package/dist/__tests__/integration/jest-mocks-setup.d.ts +0 -2
- package/dist/__tests__/integration/jest-mocks-setup.d.ts.map +0 -1
- package/dist/__tests__/integration/jest-mocks-setup.js +0 -104
- package/dist/__tests__/integration/jest-mocks-setup.js.map +0 -1
- package/dist/__tests__/integration/jest-setup.d.ts +0 -2
- package/dist/__tests__/integration/jest-setup.d.ts.map +0 -1
- package/dist/__tests__/integration/jest-setup.js +0 -12
- package/dist/__tests__/integration/jest-setup.js.map +0 -1
- package/dist/__tests__/integration/link.integration.test.d.ts +0 -2
- package/dist/__tests__/integration/link.integration.test.d.ts.map +0 -1
- package/dist/__tests__/integration/link.integration.test.js +0 -395
- package/dist/__tests__/integration/link.integration.test.js.map +0 -1
- package/dist/__tests__/integration/linked-config-cascade.integration.test.d.ts +0 -2
- package/dist/__tests__/integration/linked-config-cascade.integration.test.d.ts.map +0 -1
- package/dist/__tests__/integration/linked-config-cascade.integration.test.js +0 -179
- package/dist/__tests__/integration/linked-config-cascade.integration.test.js.map +0 -1
- package/dist/__tests__/integration/list.integration.test.d.ts +0 -2
- package/dist/__tests__/integration/list.integration.test.d.ts.map +0 -1
- package/dist/__tests__/integration/list.integration.test.js +0 -300
- package/dist/__tests__/integration/list.integration.test.js.map +0 -1
- package/dist/__tests__/integration/source-upgrade.integration.test.d.ts +0 -2
- package/dist/__tests__/integration/source-upgrade.integration.test.d.ts.map +0 -1
- package/dist/__tests__/integration/source-upgrade.integration.test.js +0 -100
- package/dist/__tests__/integration/source-upgrade.integration.test.js.map +0 -1
- package/dist/__tests__/integration/test-utils.d.ts +0 -30
- package/dist/__tests__/integration/test-utils.d.ts.map +0 -1
- package/dist/__tests__/integration/test-utils.js +0 -82
- package/dist/__tests__/integration/test-utils.js.map +0 -1
- package/dist/__tests__/integration/tunnel.integration.test.d.ts +0 -2
- package/dist/__tests__/integration/tunnel.integration.test.d.ts.map +0 -1
- package/dist/__tests__/integration/tunnel.integration.test.js +0 -486
- package/dist/__tests__/integration/tunnel.integration.test.js.map +0 -1
- package/dist/__tests__/integration/variable.integration.test.d.ts +0 -2
- package/dist/__tests__/integration/variable.integration.test.d.ts.map +0 -1
- package/dist/__tests__/integration/variable.integration.test.js +0 -258
- package/dist/__tests__/integration/variable.integration.test.js.map +0 -1
- package/dist/__tests__/integration/whoami.integration.test.d.ts +0 -2
- package/dist/__tests__/integration/whoami.integration.test.d.ts.map +0 -1
- package/dist/__tests__/integration/whoami.integration.test.js +0 -116
- package/dist/__tests__/integration/whoami.integration.test.js.map +0 -1
- package/dist/__tests__/outdated.test.d.ts +0 -2
- package/dist/__tests__/outdated.test.d.ts.map +0 -1
- package/dist/__tests__/outdated.test.js +0 -67
- package/dist/__tests__/outdated.test.js.map +0 -1
- package/dist/__tests__/populate.test.d.ts +0 -2
- package/dist/__tests__/populate.test.d.ts.map +0 -1
- package/dist/__tests__/populate.test.js +0 -445
- package/dist/__tests__/populate.test.js.map +0 -1
- package/dist/__tests__/tsconfig-upgrader.test.d.ts +0 -2
- package/dist/__tests__/tsconfig-upgrader.test.d.ts.map +0 -1
- package/dist/__tests__/tsconfig-upgrader.test.js +0 -31
- package/dist/__tests__/tsconfig-upgrader.test.js.map +0 -1
- package/dist/ca-certificate/validation.test.d.ts +0 -2
- package/dist/ca-certificate/validation.test.d.ts.map +0 -1
- package/dist/ca-certificate/validation.test.js +0 -131
- package/dist/ca-certificate/validation.test.js.map +0 -1
- package/dist/common/analytics/cli-invocation.test.d.ts +0 -2
- package/dist/common/analytics/cli-invocation.test.d.ts.map +0 -1
- package/dist/common/analytics/cli-invocation.test.js +0 -51
- package/dist/common/analytics/cli-invocation.test.js.map +0 -1
- package/dist/common/analytics/package-manager.test.d.ts +0 -2
- package/dist/common/analytics/package-manager.test.d.ts.map +0 -1
- package/dist/common/analytics/package-manager.test.js +0 -163
- package/dist/common/analytics/package-manager.test.js.map +0 -1
- package/dist/common/cli-dispatcher.test.d.ts +0 -2
- package/dist/common/cli-dispatcher.test.d.ts.map +0 -1
- package/dist/common/cli-dispatcher.test.js +0 -80
- package/dist/common/cli-dispatcher.test.js.map +0 -1
- package/dist/common/middleware/check-pnpm-lifecycle.test.d.ts +0 -2
- package/dist/common/middleware/check-pnpm-lifecycle.test.d.ts.map +0 -1
- package/dist/common/middleware/check-pnpm-lifecycle.test.js +0 -125
- package/dist/common/middleware/check-pnpm-lifecycle.test.js.map +0 -1
- package/dist/common/middleware/get-environment-param.test.d.ts +0 -2
- package/dist/common/middleware/get-environment-param.test.d.ts.map +0 -1
- package/dist/common/middleware/get-environment-param.test.js +0 -57
- package/dist/common/middleware/get-environment-param.test.js.map +0 -1
- package/dist/common/read-linked-config.test.d.ts +0 -2
- package/dist/common/read-linked-config.test.d.ts.map +0 -1
- package/dist/common/read-linked-config.test.js +0 -363
- package/dist/common/read-linked-config.test.js.map +0 -1
- package/dist/common/terminal.test.d.ts +0 -2
- package/dist/common/terminal.test.d.ts.map +0 -1
- package/dist/common/terminal.test.js +0 -101
- package/dist/common/terminal.test.js.map +0 -1
- package/dist/common/utils/build-environment-prompt-choices.test.d.ts +0 -2
- package/dist/common/utils/build-environment-prompt-choices.test.d.ts.map +0 -1
- package/dist/common/utils/build-environment-prompt-choices.test.js +0 -97
- package/dist/common/utils/build-environment-prompt-choices.test.js.map +0 -1
- package/dist/common/utils/format-environment-type.test.d.ts +0 -2
- package/dist/common/utils/format-environment-type.test.d.ts.map +0 -1
- package/dist/common/utils/format-environment-type.test.js +0 -32
- package/dist/common/utils/format-environment-type.test.js.map +0 -1
- package/dist/common/utils/pnpm-lifecycle.test.d.ts +0 -2
- package/dist/common/utils/pnpm-lifecycle.test.d.ts.map +0 -1
- package/dist/common/utils/pnpm-lifecycle.test.js +0 -196
- package/dist/common/utils/pnpm-lifecycle.test.js.map +0 -1
- package/dist/common/utils/pretty-print-environment-prompt.test.d.ts +0 -2
- package/dist/common/utils/pretty-print-environment-prompt.test.d.ts.map +0 -1
- package/dist/common/utils/pretty-print-environment-prompt.test.js +0 -42
- package/dist/common/utils/pretty-print-environment-prompt.test.js.map +0 -1
- package/dist/common/utils/sort-environments-for-prompt.test.d.ts +0 -2
- package/dist/common/utils/sort-environments-for-prompt.test.d.ts.map +0 -1
- package/dist/common/utils/sort-environments-for-prompt.test.js +0 -82
- package/dist/common/utils/sort-environments-for-prompt.test.js.map +0 -1
- package/dist/common/utils/stringify-config.test.d.ts +0 -2
- package/dist/common/utils/stringify-config.test.d.ts.map +0 -1
- package/dist/common/utils/stringify-config.test.js +0 -80
- package/dist/common/utils/stringify-config.test.js.map +0 -1
- package/dist/common/validators/argument-validators.spec.d.ts +0 -2
- package/dist/common/validators/argument-validators.spec.d.ts.map +0 -1
- package/dist/common/validators/argument-validators.spec.js +0 -181
- package/dist/common/validators/argument-validators.spec.js.map +0 -1
- package/dist/common/worker-output.test.d.ts +0 -2
- package/dist/common/worker-output.test.d.ts.map +0 -1
- package/dist/common/worker-output.test.js +0 -32
- package/dist/common/worker-output.test.js.map +0 -1
- package/dist/deploy/archive.local-registry.test.d.ts +0 -2
- package/dist/deploy/archive.local-registry.test.d.ts.map +0 -1
- package/dist/deploy/archive.local-registry.test.js +0 -100
- package/dist/deploy/archive.local-registry.test.js.map +0 -1
- package/dist/deploy/archive.test.d.ts +0 -2
- package/dist/deploy/archive.test.d.ts.map +0 -1
- package/dist/deploy/archive.test.js +0 -248
- package/dist/deploy/archive.test.js.map +0 -1
- package/dist/deploy/classify-build-probe.test.d.ts +0 -2
- package/dist/deploy/classify-build-probe.test.d.ts.map +0 -1
- package/dist/deploy/classify-build-probe.test.js +0 -51
- package/dist/deploy/classify-build-probe.test.js.map +0 -1
- package/dist/deploy/poll-deployment.test.d.ts +0 -2
- package/dist/deploy/poll-deployment.test.d.ts.map +0 -1
- package/dist/deploy/poll-deployment.test.js +0 -158
- package/dist/deploy/poll-deployment.test.js.map +0 -1
- package/dist/dev/zuplo-local-gitignore.test.d.ts +0 -2
- package/dist/dev/zuplo-local-gitignore.test.d.ts.map +0 -1
- package/dist/dev/zuplo-local-gitignore.test.js +0 -58
- package/dist/dev/zuplo-local-gitignore.test.js.map +0 -1
- package/dist/editor/e2e/editor.spec.d.ts +0 -2
- package/dist/editor/e2e/editor.spec.d.ts.map +0 -1
- package/dist/editor/e2e/editor.spec.js +0 -44
- package/dist/editor/e2e/editor.spec.js.map +0 -1
- package/dist/link/project-type.test.d.ts +0 -2
- package/dist/link/project-type.test.d.ts.map +0 -1
- package/dist/link/project-type.test.js +0 -225
- package/dist/link/project-type.test.js.map +0 -1
- package/dist/lint/resolve-binary.test.d.ts +0 -2
- package/dist/lint/resolve-binary.test.d.ts.map +0 -1
- package/dist/lint/resolve-binary.test.js +0 -155
- package/dist/lint/resolve-binary.test.js.map +0 -1
- package/dist/open-api/convert/handler.spec.d.ts +0 -2
- package/dist/open-api/convert/handler.spec.d.ts.map +0 -1
- package/dist/open-api/convert/handler.spec.js +0 -301
- package/dist/open-api/convert/handler.spec.js.map +0 -1
- package/dist/open-api/merge/handler.spec.d.ts +0 -2
- package/dist/open-api/merge/handler.spec.d.ts.map +0 -1
- package/dist/open-api/merge/handler.spec.js +0 -673
- package/dist/open-api/merge/handler.spec.js.map +0 -1
- package/dist/open-api/overlay/handler.spec.d.ts +0 -2
- package/dist/open-api/overlay/handler.spec.d.ts.map +0 -1
- package/dist/open-api/overlay/handler.spec.js +0 -346
- package/dist/open-api/overlay/handler.spec.js.map +0 -1
- package/dist/source/ai-gateway/files.test.d.ts +0 -2
- package/dist/source/ai-gateway/files.test.d.ts.map +0 -1
- package/dist/source/ai-gateway/files.test.js +0 -135
- package/dist/source/ai-gateway/files.test.js.map +0 -1
- package/dist/source/ai-gateway/handler.test.d.ts +0 -2
- package/dist/source/ai-gateway/handler.test.d.ts.map +0 -1
- package/dist/source/ai-gateway/handler.test.js +0 -113
- package/dist/source/ai-gateway/handler.test.js.map +0 -1
- package/dist/source/ai-gateway/package.test.d.ts +0 -2
- package/dist/source/ai-gateway/package.test.d.ts.map +0 -1
- package/dist/source/ai-gateway/package.test.js +0 -30
- package/dist/source/ai-gateway/package.test.js.map +0 -1
- package/dist/source/ai-gateway/planner.test.d.ts +0 -2
- package/dist/source/ai-gateway/planner.test.d.ts.map +0 -1
- package/dist/source/ai-gateway/planner.test.js +0 -330
- package/dist/source/ai-gateway/planner.test.js.map +0 -1
- package/dist/source/ai-gateway/release.test.d.ts +0 -2
- package/dist/source/ai-gateway/release.test.d.ts.map +0 -1
- package/dist/source/ai-gateway/release.test.js +0 -62
- package/dist/source/ai-gateway/release.test.js.map +0 -1
- package/dist/test/invoke-test.test.d.ts +0 -2
- package/dist/test/invoke-test.test.d.ts.map +0 -1
- package/dist/test/invoke-test.test.js +0 -150
- package/dist/test/invoke-test.test.js.map +0 -1
- package/dist/test/test-files.test.d.ts +0 -2
- package/dist/test/test-files.test.d.ts.map +0 -1
- package/dist/test/test-files.test.js +0 -57
- package/dist/test/test-files.test.js.map +0 -1
- package/node_modules/@zuplo/openapi-tools/dist/file-format.spec.d.ts +0 -2
- package/node_modules/@zuplo/openapi-tools/dist/file-format.spec.d.ts.map +0 -1
- package/node_modules/@zuplo/openapi-tools/dist/file-format.spec.js +0 -289
- package/node_modules/@zuplo/openapi-tools/dist/file-format.spec.js.map +0 -1
- package/node_modules/@zuplo/openapi-tools/dist/merge-fixtures.spec.d.ts +0 -2
- package/node_modules/@zuplo/openapi-tools/dist/merge-fixtures.spec.d.ts.map +0 -1
- package/node_modules/@zuplo/openapi-tools/dist/merge-fixtures.spec.js +0 -181
- package/node_modules/@zuplo/openapi-tools/dist/merge-fixtures.spec.js.map +0 -1
- package/node_modules/@zuplo/openapi-tools/dist/merge.spec.d.ts +0 -2
- package/node_modules/@zuplo/openapi-tools/dist/merge.spec.d.ts.map +0 -1
- package/node_modules/@zuplo/openapi-tools/dist/merge.spec.js +0 -399
- package/node_modules/@zuplo/openapi-tools/dist/merge.spec.js.map +0 -1
- package/node_modules/@zuplo/openapi-tools/dist/overlay.spec.d.ts +0 -2
- package/node_modules/@zuplo/openapi-tools/dist/overlay.spec.d.ts.map +0 -1
- package/node_modules/@zuplo/openapi-tools/dist/overlay.spec.js +0 -779
- package/node_modules/@zuplo/openapi-tools/dist/overlay.spec.js.map +0 -1
- package/node_modules/@zuplo/openapi-tools/dist/path-transform.spec.d.ts +0 -2
- package/node_modules/@zuplo/openapi-tools/dist/path-transform.spec.d.ts.map +0 -1
- package/node_modules/@zuplo/openapi-tools/dist/path-transform.spec.js +0 -269
- package/node_modules/@zuplo/openapi-tools/dist/path-transform.spec.js.map +0 -1
- package/node_modules/@zuplo/openapi-tools/dist/url-utils.spec.d.ts +0 -2
- package/node_modules/@zuplo/openapi-tools/dist/url-utils.spec.d.ts.map +0 -1
- package/node_modules/@zuplo/openapi-tools/dist/url-utils.spec.js +0 -93
- package/node_modules/@zuplo/openapi-tools/dist/url-utils.spec.js.map +0 -1
- package/node_modules/@zuplo/runtime/out/esm/chunk-6YPRGG62.js.map +0 -1
- package/node_modules/@zuplo/runtime/out/esm/chunk-PBDT4FDO.js +0 -37
- package/node_modules/@zuplo/runtime/out/esm/chunk-PBDT4FDO.js.map +0 -1
- /package/node_modules/@zuplo/runtime/out/esm/{chunk-YJ2BHVUH.js.map → chunk-CDEAY3VY.js.map} +0 -0
- /package/node_modules/@zuplo/runtime/out/esm/{chunk-PBDT4FDO.js.LEGAL.txt → chunk-LVSZ3WTO.js.LEGAL.txt} +0 -0
- /package/node_modules/@zuplo/runtime/out/esm/{chunk-VTO3F6DK.js.map → chunk-NUVXDVLJ.js.map} +0 -0
- /package/node_modules/@zuplo/runtime/out/esm/{chunk-6YPRGG62.js.LEGAL.txt → chunk-RHU3Z7DA.js.LEGAL.txt} +0 -0
|
@@ -1,67 +0,0 @@
|
|
|
1
|
-
import { rm, writeFile } from "node:fs/promises";
|
|
2
|
-
import { join } from "node:path";
|
|
3
|
-
import { afterEach, beforeEach, describe, it } from "node:test";
|
|
4
|
-
import { assert } from "chai";
|
|
5
|
-
import { getGlobalDispatcher, MockAgent, setGlobalDispatcher, } from "undici";
|
|
6
|
-
import { ZUPLO_VERSION_CHECK_FILE } from "../common/constants.js";
|
|
7
|
-
import { warnIfOutdatedVersion } from "../common/outdated.js";
|
|
8
|
-
import { ZUPLO_XDG_STATE_HOME } from "../common/xdg/lib.js";
|
|
9
|
-
const versionCheckPath = join(ZUPLO_XDG_STATE_HOME, ZUPLO_VERSION_CHECK_FILE);
|
|
10
|
-
process.env.ZUPLO_OVERRIDE_CI_TO_TEST = "true";
|
|
11
|
-
describe("Outdated CLI check", function () {
|
|
12
|
-
let mockAgent;
|
|
13
|
-
let previousDispatcher;
|
|
14
|
-
beforeEach(() => {
|
|
15
|
-
previousDispatcher = getGlobalDispatcher();
|
|
16
|
-
mockAgent = new MockAgent();
|
|
17
|
-
mockAgent.disableNetConnect();
|
|
18
|
-
mockAgent
|
|
19
|
-
.get("https://registry.npmjs.org")
|
|
20
|
-
.intercept({
|
|
21
|
-
path: "/@zuplo/cli/latest",
|
|
22
|
-
method: "GET",
|
|
23
|
-
})
|
|
24
|
-
.reply(200, {
|
|
25
|
-
name: "@zuplo/cli",
|
|
26
|
-
version: "1.109.0",
|
|
27
|
-
});
|
|
28
|
-
setGlobalDispatcher(mockAgent);
|
|
29
|
-
});
|
|
30
|
-
afterEach(async () => {
|
|
31
|
-
await mockAgent.close();
|
|
32
|
-
setGlobalDispatcher(previousDispatcher);
|
|
33
|
-
});
|
|
34
|
-
it("should warn on outdated version", async function () {
|
|
35
|
-
await rm(versionCheckPath, { recursive: true, force: true });
|
|
36
|
-
const result = await warnIfOutdatedVersion("1.0.0");
|
|
37
|
-
assert.isTrue(result);
|
|
38
|
-
assert.equal(mockAgent.pendingInterceptors.length, 0);
|
|
39
|
-
});
|
|
40
|
-
it("should not warn if current version", async function () {
|
|
41
|
-
const result = await warnIfOutdatedVersion("1.109.0");
|
|
42
|
-
assert.isFalse(result);
|
|
43
|
-
});
|
|
44
|
-
it("should not warn if still has cached result", async function () {
|
|
45
|
-
const state = { lastCheck: Date.now() - 1000, latestVersion: "1.108.0" };
|
|
46
|
-
await writeFile(versionCheckPath, JSON.stringify(state), "utf-8");
|
|
47
|
-
const result = await warnIfOutdatedVersion("1.108.0");
|
|
48
|
-
assert.isFalse(result);
|
|
49
|
-
});
|
|
50
|
-
it("should warn when time expired on outdated version", async function () {
|
|
51
|
-
const state = {
|
|
52
|
-
lastCheck: Date.now() - 1000 * 60 * 60 * 24 - 100,
|
|
53
|
-
latestVersion: "1.0.0",
|
|
54
|
-
};
|
|
55
|
-
await writeFile(versionCheckPath, JSON.stringify(state), "utf-8");
|
|
56
|
-
const result = await warnIfOutdatedVersion("1.0.0");
|
|
57
|
-
assert.isTrue(result);
|
|
58
|
-
assert.equal(mockAgent.pendingInterceptors.length, 0);
|
|
59
|
-
});
|
|
60
|
-
it("should handle invalid state", async function () {
|
|
61
|
-
await writeFile(versionCheckPath, "hello", "utf-8");
|
|
62
|
-
const result = await warnIfOutdatedVersion("0.0.1");
|
|
63
|
-
assert.isTrue(result);
|
|
64
|
-
assert.equal(mockAgent.pendingInterceptors.length, 0);
|
|
65
|
-
});
|
|
66
|
-
});
|
|
67
|
-
//# sourceMappingURL=outdated.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"outdated.test.js","sourceRoot":"","sources":["../../src/__tests__/outdated.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { rm, writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { afterEach, beforeEach, describe, it } from \"node:test\";\nimport { assert } from \"chai\";\nimport {\n type Dispatcher,\n getGlobalDispatcher,\n MockAgent,\n setGlobalDispatcher,\n} from \"undici\";\nimport { ZUPLO_VERSION_CHECK_FILE } from \"../common/constants.js\";\nimport { warnIfOutdatedVersion } from \"../common/outdated.js\";\nimport { ZUPLO_XDG_STATE_HOME } from \"../common/xdg/lib.js\";\n\nconst versionCheckPath = join(ZUPLO_XDG_STATE_HOME, ZUPLO_VERSION_CHECK_FILE);\n\nprocess.env.ZUPLO_OVERRIDE_CI_TO_TEST = \"true\";\n\ndescribe(\"Outdated CLI check\", function () {\n let mockAgent: MockAgent;\n let previousDispatcher: Dispatcher;\n\n beforeEach(() => {\n // This suite installs a net-connect-disabled MockAgent as the undici\n // process-global dispatcher. It had no afterEach, so the agent stayed\n // installed for the rest of this file's process; any later test doing real\n // network I/O would have failed with an unexplained \"fetch failed\".\n previousDispatcher = getGlobalDispatcher();\n mockAgent = new MockAgent();\n mockAgent.disableNetConnect();\n mockAgent\n .get(\"https://registry.npmjs.org\")\n .intercept({\n path: \"/@zuplo/cli/latest\",\n method: \"GET\",\n })\n .reply(200, {\n name: \"@zuplo/cli\",\n version: \"1.109.0\",\n });\n\n setGlobalDispatcher(mockAgent);\n });\n\n afterEach(async () => {\n await mockAgent.close();\n setGlobalDispatcher(previousDispatcher);\n });\n\n it(\"should warn on outdated version\", async function () {\n await rm(versionCheckPath, { recursive: true, force: true });\n\n const result = await warnIfOutdatedVersion(\"1.0.0\");\n assert.isTrue(result);\n assert.equal(mockAgent.pendingInterceptors.length, 0);\n });\n it(\"should not warn if current version\", async function () {\n const result = await warnIfOutdatedVersion(\"1.109.0\");\n assert.isFalse(result);\n });\n it(\"should not warn if still has cached result\", async function () {\n // Set the cache to still be valid, so even though the version is outdated\n // we dont return a warning since we dont fetch the latest version\n const state = { lastCheck: Date.now() - 1000, latestVersion: \"1.108.0\" };\n await writeFile(versionCheckPath, JSON.stringify(state), \"utf-8\");\n\n const result = await warnIfOutdatedVersion(\"1.108.0\");\n assert.isFalse(result);\n });\n it(\"should warn when time expired on outdated version\", async function () {\n const state = {\n lastCheck: Date.now() - 1000 * 60 * 60 * 24 - 100,\n latestVersion: \"1.0.0\",\n };\n await writeFile(versionCheckPath, JSON.stringify(state), \"utf-8\");\n\n const result = await warnIfOutdatedVersion(\"1.0.0\");\n assert.isTrue(result);\n assert.equal(mockAgent.pendingInterceptors.length, 0);\n });\n it(\"should handle invalid state\", async function () {\n await writeFile(versionCheckPath, \"hello\", \"utf-8\");\n\n const result = await warnIfOutdatedVersion(\"0.0.1\");\n assert.isTrue(result);\n assert.equal(mockAgent.pendingInterceptors.length, 0);\n });\n});\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"populate.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/populate.test.ts"],"names":[],"mappings":""}
|
|
@@ -1,445 +0,0 @@
|
|
|
1
|
-
import { strict as nodeAssert } from "node:assert";
|
|
2
|
-
import { mkdtemp, readFile, rm } from "node:fs/promises";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
|
-
import { join } from "node:path";
|
|
5
|
-
import { afterEach, beforeEach, describe, it } from "node:test";
|
|
6
|
-
import { assert } from "chai";
|
|
7
|
-
import { parse as dotenvParse } from "dotenv";
|
|
8
|
-
import { getGlobalDispatcher, MockAgent, setGlobalDispatcher, } from "undici";
|
|
9
|
-
const TEST_ENVIRONMENT = "test-env-123";
|
|
10
|
-
const TEST_AUTH_TOKEN = "test-auth-token-456";
|
|
11
|
-
const TEST_API_ENDPOINT = "https://dev.zuplo.com";
|
|
12
|
-
const SYSTEM_PAYLOAD_KEYS = [
|
|
13
|
-
"accountName",
|
|
14
|
-
"projectName",
|
|
15
|
-
"environmentType",
|
|
16
|
-
"systemConfigurations",
|
|
17
|
-
];
|
|
18
|
-
describe("pullSystemConfig", () => {
|
|
19
|
-
let mockAgent;
|
|
20
|
-
let previousDispatcher;
|
|
21
|
-
let testDir;
|
|
22
|
-
beforeEach(async () => {
|
|
23
|
-
previousDispatcher = getGlobalDispatcher();
|
|
24
|
-
mockAgent = new MockAgent();
|
|
25
|
-
mockAgent.disableNetConnect();
|
|
26
|
-
setGlobalDispatcher(mockAgent);
|
|
27
|
-
testDir = await mkdtemp(join(tmpdir(), "zuplo-test-"));
|
|
28
|
-
});
|
|
29
|
-
afterEach(async () => {
|
|
30
|
-
await mockAgent.close();
|
|
31
|
-
setGlobalDispatcher(previousDispatcher);
|
|
32
|
-
await rm(testDir, { recursive: true, force: true });
|
|
33
|
-
});
|
|
34
|
-
it("should write account and project name to .env.zuplo", async () => {
|
|
35
|
-
const mockPayload = {
|
|
36
|
-
accountName: "test-account",
|
|
37
|
-
projectName: "test-project",
|
|
38
|
-
environmentType: "development",
|
|
39
|
-
systemConfigurations: "config-123",
|
|
40
|
-
};
|
|
41
|
-
mockAgent
|
|
42
|
-
.get(TEST_API_ENDPOINT)
|
|
43
|
-
.intercept({
|
|
44
|
-
path: `/v1/environments/${TEST_ENVIRONMENT}/configurations`,
|
|
45
|
-
method: "GET",
|
|
46
|
-
headers: {
|
|
47
|
-
authorization: `Bearer ${TEST_AUTH_TOKEN}`,
|
|
48
|
-
},
|
|
49
|
-
})
|
|
50
|
-
.reply(200, mockPayload);
|
|
51
|
-
const { pullSystemConfig } = await import("../common/populate.js");
|
|
52
|
-
await pullSystemConfig({
|
|
53
|
-
dir: testDir,
|
|
54
|
-
environment: TEST_ENVIRONMENT,
|
|
55
|
-
authToken: TEST_AUTH_TOKEN,
|
|
56
|
-
});
|
|
57
|
-
const content = await readFile(join(testDir, ".env.zuplo"), "utf-8");
|
|
58
|
-
assert.include(content, "ZUPLO_ACCOUNT_NAME=test-account");
|
|
59
|
-
assert.include(content, "ZUPLO_PROJECT_NAME=test-project");
|
|
60
|
-
assert.include(content, "ZUPLO_ENVIRONMENT_TYPE=development");
|
|
61
|
-
assert.include(content, "ZUPLO_SYSTEM_CONFIGURATIONS=config-123");
|
|
62
|
-
assert.notInclude(content, "ZUPLO_ENVIRONMENT_NAME");
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
describe("pullLocalConfig", () => {
|
|
66
|
-
let mockAgent;
|
|
67
|
-
let previousDispatcher;
|
|
68
|
-
let testDir;
|
|
69
|
-
beforeEach(async () => {
|
|
70
|
-
previousDispatcher = getGlobalDispatcher();
|
|
71
|
-
mockAgent = new MockAgent();
|
|
72
|
-
mockAgent.disableNetConnect();
|
|
73
|
-
setGlobalDispatcher(mockAgent);
|
|
74
|
-
testDir = await mkdtemp(join(tmpdir(), "zuplo-test-"));
|
|
75
|
-
});
|
|
76
|
-
afterEach(async () => {
|
|
77
|
-
await mockAgent.close();
|
|
78
|
-
setGlobalDispatcher(previousDispatcher);
|
|
79
|
-
await rm(testDir, { recursive: true, force: true });
|
|
80
|
-
});
|
|
81
|
-
it("should generate correct .env.zuplo file with system variables", async () => {
|
|
82
|
-
const mockPayload = {
|
|
83
|
-
accountName: "test-account",
|
|
84
|
-
projectName: "test-project",
|
|
85
|
-
environmentType: "development",
|
|
86
|
-
systemConfigurations: "config-123",
|
|
87
|
-
};
|
|
88
|
-
mockAgent
|
|
89
|
-
.get(TEST_API_ENDPOINT)
|
|
90
|
-
.intercept({
|
|
91
|
-
path: `/v1/environments/${TEST_ENVIRONMENT}/local-configurations`,
|
|
92
|
-
method: "GET",
|
|
93
|
-
headers: {
|
|
94
|
-
authorization: `Bearer ${TEST_AUTH_TOKEN}`,
|
|
95
|
-
},
|
|
96
|
-
})
|
|
97
|
-
.reply(200, mockPayload);
|
|
98
|
-
const { pullLocalConfig } = await import("../common/populate.js");
|
|
99
|
-
await pullLocalConfig({
|
|
100
|
-
dir: testDir,
|
|
101
|
-
environment: TEST_ENVIRONMENT,
|
|
102
|
-
authToken: TEST_AUTH_TOKEN,
|
|
103
|
-
});
|
|
104
|
-
const envFilePath = join(testDir, ".env.zuplo");
|
|
105
|
-
const content = await readFile(envFilePath, "utf-8");
|
|
106
|
-
assert.include(content, "# This file is auto-generated from zuplo link. Please do not edit it manually.");
|
|
107
|
-
assert.include(content, "# It will be auto-generated afresh the next time you run zuplo link.");
|
|
108
|
-
assert.include(content, "# If you wish to add your own environment variables, create a separate .env file.");
|
|
109
|
-
assert.include(content, "ZUPLO_ACCOUNT_NAME=test-account");
|
|
110
|
-
assert.include(content, "ZUPLO_PROJECT_NAME=test-project");
|
|
111
|
-
assert.include(content, "ZUPLO_ENVIRONMENT_TYPE=development");
|
|
112
|
-
assert.include(content, "ZUPLO_SYSTEM_CONFIGURATIONS=config-123");
|
|
113
|
-
assert.notInclude(content, "ZUPLO_ENVIRONMENT_NAME");
|
|
114
|
-
assert.notInclude(content, "# Public Zuplo environment variables");
|
|
115
|
-
assert.notInclude(content, "# Environment variables defined in the Zuplo UI for the environment");
|
|
116
|
-
await rm(testDir, { recursive: true, force: true });
|
|
117
|
-
});
|
|
118
|
-
it("should handle payload with public and user environment variables", async () => {
|
|
119
|
-
const mockPayload = {
|
|
120
|
-
accountName: "my-account",
|
|
121
|
-
projectName: "my-project",
|
|
122
|
-
environmentType: "production",
|
|
123
|
-
systemConfigurations: "prod-config-456",
|
|
124
|
-
ZUPLO_PUBLIC_API_URL: "https://api.example.com",
|
|
125
|
-
ZUPLO_PUBLIC_DOCS_URL: "https://docs.example.com",
|
|
126
|
-
DATABASE_URL: "postgres://localhost:5432/db",
|
|
127
|
-
API_KEY: "secret-key-123",
|
|
128
|
-
REDIS_URL: "redis://localhost:6379",
|
|
129
|
-
};
|
|
130
|
-
mockAgent
|
|
131
|
-
.get(TEST_API_ENDPOINT)
|
|
132
|
-
.intercept({
|
|
133
|
-
path: `/v1/environments/${TEST_ENVIRONMENT}/local-configurations`,
|
|
134
|
-
method: "GET",
|
|
135
|
-
headers: {
|
|
136
|
-
authorization: `Bearer ${TEST_AUTH_TOKEN}`,
|
|
137
|
-
},
|
|
138
|
-
})
|
|
139
|
-
.reply(200, mockPayload);
|
|
140
|
-
const { pullLocalConfig } = await import("../common/populate.js");
|
|
141
|
-
await pullLocalConfig({
|
|
142
|
-
dir: testDir,
|
|
143
|
-
environment: TEST_ENVIRONMENT,
|
|
144
|
-
authToken: TEST_AUTH_TOKEN,
|
|
145
|
-
});
|
|
146
|
-
const envFilePath = join(testDir, ".env.zuplo");
|
|
147
|
-
const content = await readFile(envFilePath, "utf-8");
|
|
148
|
-
assert.include(content, "ZUPLO_ACCOUNT_NAME=my-account");
|
|
149
|
-
assert.include(content, "ZUPLO_PROJECT_NAME=my-project");
|
|
150
|
-
assert.include(content, "ZUPLO_ENVIRONMENT_TYPE=production");
|
|
151
|
-
assert.include(content, "ZUPLO_SYSTEM_CONFIGURATIONS=prod-config-456");
|
|
152
|
-
const publicSectionRegex = /# Public Zuplo environment variables[\s\S]*?(?=# Environment variables defined in the Zuplo UI|$)/;
|
|
153
|
-
const publicSection = content.match(publicSectionRegex)?.[0] || "";
|
|
154
|
-
assert.include(publicSection, 'ZUPLO_PUBLIC_API_URL="https://api.example.com"');
|
|
155
|
-
assert.include(publicSection, 'ZUPLO_PUBLIC_DOCS_URL="https://docs.example.com"');
|
|
156
|
-
const userSectionRegex = /# Environment variables defined in the Zuplo UI[\s\S]*$/;
|
|
157
|
-
const userSection = content.match(userSectionRegex)?.[0] || "";
|
|
158
|
-
assert.include(userSection, 'DATABASE_URL="postgres://localhost:5432/db"');
|
|
159
|
-
assert.include(userSection, 'API_KEY="secret-key-123"');
|
|
160
|
-
assert.include(userSection, 'REDIS_URL="redis://localhost:6379"');
|
|
161
|
-
assert.notInclude(userSection, "accountName=");
|
|
162
|
-
assert.notInclude(userSection, "projectName=");
|
|
163
|
-
assert.notInclude(userSection, "environmentType=");
|
|
164
|
-
assert.notInclude(userSection, "systemConfigurations=");
|
|
165
|
-
await rm(testDir, { recursive: true, force: true });
|
|
166
|
-
});
|
|
167
|
-
it("should handle empty environment variables gracefully", async () => {
|
|
168
|
-
const mockPayload = {
|
|
169
|
-
accountName: "test-account",
|
|
170
|
-
projectName: "test-project",
|
|
171
|
-
environmentType: "development",
|
|
172
|
-
systemConfigurations: "config-789",
|
|
173
|
-
};
|
|
174
|
-
mockAgent
|
|
175
|
-
.get(TEST_API_ENDPOINT)
|
|
176
|
-
.intercept({
|
|
177
|
-
path: `/v1/environments/${TEST_ENVIRONMENT}/local-configurations`,
|
|
178
|
-
method: "GET",
|
|
179
|
-
headers: {
|
|
180
|
-
authorization: `Bearer ${TEST_AUTH_TOKEN}`,
|
|
181
|
-
},
|
|
182
|
-
})
|
|
183
|
-
.reply(200, mockPayload);
|
|
184
|
-
const { pullLocalConfig } = await import("../common/populate.js");
|
|
185
|
-
await pullLocalConfig({
|
|
186
|
-
dir: testDir,
|
|
187
|
-
environment: TEST_ENVIRONMENT,
|
|
188
|
-
authToken: TEST_AUTH_TOKEN,
|
|
189
|
-
});
|
|
190
|
-
const envFilePath = join(testDir, ".env.zuplo");
|
|
191
|
-
const content = await readFile(envFilePath, "utf-8");
|
|
192
|
-
assert.include(content, "ZUPLO_ACCOUNT_NAME=test-account");
|
|
193
|
-
assert.include(content, "ZUPLO_PROJECT_NAME=test-project");
|
|
194
|
-
assert.include(content, "ZUPLO_ENVIRONMENT_TYPE=development");
|
|
195
|
-
assert.include(content, "ZUPLO_SYSTEM_CONFIGURATIONS=config-789");
|
|
196
|
-
assert.notInclude(content, "# Public Zuplo environment variables");
|
|
197
|
-
assert.notInclude(content, "# Environment variables defined in the Zuplo UI for the environment");
|
|
198
|
-
await rm(testDir, { recursive: true, force: true });
|
|
199
|
-
});
|
|
200
|
-
it("should handle special characters in environment variable values", async () => {
|
|
201
|
-
const mockPayload = {
|
|
202
|
-
accountName: "test-account",
|
|
203
|
-
projectName: "test-project",
|
|
204
|
-
environmentType: "development",
|
|
205
|
-
systemConfigurations: "config-123",
|
|
206
|
-
DATABASE_URL: "postgres://user:p@ssw0rd!@localhost:5432/db?ssl=true",
|
|
207
|
-
API_SECRET: "secret-with-special-chars!@#$%^&*()",
|
|
208
|
-
JSON_CONFIG: '{"key": "value", "nested": {"array": [1, 2, 3]}}',
|
|
209
|
-
};
|
|
210
|
-
mockAgent
|
|
211
|
-
.get(TEST_API_ENDPOINT)
|
|
212
|
-
.intercept({
|
|
213
|
-
path: `/v1/environments/${TEST_ENVIRONMENT}/local-configurations`,
|
|
214
|
-
method: "GET",
|
|
215
|
-
headers: {
|
|
216
|
-
authorization: `Bearer ${TEST_AUTH_TOKEN}`,
|
|
217
|
-
},
|
|
218
|
-
})
|
|
219
|
-
.reply(200, mockPayload);
|
|
220
|
-
const { pullLocalConfig } = await import("../common/populate.js");
|
|
221
|
-
await pullLocalConfig({
|
|
222
|
-
dir: testDir,
|
|
223
|
-
environment: TEST_ENVIRONMENT,
|
|
224
|
-
authToken: TEST_AUTH_TOKEN,
|
|
225
|
-
});
|
|
226
|
-
const envFilePath = join(testDir, ".env.zuplo");
|
|
227
|
-
const content = await readFile(envFilePath, "utf-8");
|
|
228
|
-
assert.include(content, 'DATABASE_URL="postgres://user:p@ssw0rd!@localhost:5432/db?ssl=true"');
|
|
229
|
-
assert.include(content, 'API_SECRET="secret-with-special-chars!@#$%^&*()"');
|
|
230
|
-
assert.include(content, 'JSON_CONFIG=`{"key": "value", "nested": {"array": [1, 2, 3]}}`');
|
|
231
|
-
const userSectionRegex = /# Environment variables defined in the Zuplo UI[\s\S]*$/;
|
|
232
|
-
const userSection = content.match(userSectionRegex)?.[0] || "";
|
|
233
|
-
assert.include(userSection, "DATABASE_URL=");
|
|
234
|
-
assert.include(userSection, "API_SECRET=");
|
|
235
|
-
assert.include(userSection, "JSON_CONFIG=");
|
|
236
|
-
const parsedEnv = dotenvParse(content);
|
|
237
|
-
assert.equal(parsedEnv.DATABASE_URL, mockPayload.DATABASE_URL);
|
|
238
|
-
assert.equal(parsedEnv.API_SECRET, mockPayload.API_SECRET);
|
|
239
|
-
assert.equal(parsedEnv.JSON_CONFIG, mockPayload.JSON_CONFIG);
|
|
240
|
-
await rm(testDir, { recursive: true, force: true });
|
|
241
|
-
});
|
|
242
|
-
it("should preserve a Google service account JSON value", async () => {
|
|
243
|
-
const serviceAccount = {
|
|
244
|
-
type: "service_account",
|
|
245
|
-
project_id: "test-project",
|
|
246
|
-
private_key_id: "test-key-id",
|
|
247
|
-
private_key: "-----BEGIN PRIVATE KEY-----\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASC\n-----END PRIVATE KEY-----\n",
|
|
248
|
-
client_email: "test-service-account@test-project.iam.gserviceaccount.com",
|
|
249
|
-
client_id: "1234567890",
|
|
250
|
-
auth_uri: "https://accounts.google.com/o/oauth2/auth",
|
|
251
|
-
token_uri: "https://oauth2.googleapis.com/token",
|
|
252
|
-
auth_provider_x509_cert_url: "https://www.googleapis.com/oauth2/v1/certs",
|
|
253
|
-
client_x509_cert_url: "https://www.googleapis.com/robot/v1/metadata/x509/test-service-account%40test-project.iam.gserviceaccount.com",
|
|
254
|
-
universe_domain: "googleapis.com",
|
|
255
|
-
};
|
|
256
|
-
const mockPayload = {
|
|
257
|
-
accountName: "test-account",
|
|
258
|
-
projectName: "test-project",
|
|
259
|
-
environmentType: "development",
|
|
260
|
-
systemConfigurations: "config-123",
|
|
261
|
-
GOOGLE_SERVICE_ACCOUNT: JSON.stringify(serviceAccount, null, 2),
|
|
262
|
-
};
|
|
263
|
-
mockAgent
|
|
264
|
-
.get(TEST_API_ENDPOINT)
|
|
265
|
-
.intercept({
|
|
266
|
-
path: `/v1/environments/${TEST_ENVIRONMENT}/local-configurations`,
|
|
267
|
-
method: "GET",
|
|
268
|
-
headers: {
|
|
269
|
-
authorization: `Bearer ${TEST_AUTH_TOKEN}`,
|
|
270
|
-
},
|
|
271
|
-
})
|
|
272
|
-
.reply(200, mockPayload);
|
|
273
|
-
const { pullLocalConfig } = await import("../common/populate.js");
|
|
274
|
-
await pullLocalConfig({
|
|
275
|
-
dir: testDir,
|
|
276
|
-
environment: TEST_ENVIRONMENT,
|
|
277
|
-
authToken: TEST_AUTH_TOKEN,
|
|
278
|
-
});
|
|
279
|
-
const content = await readFile(join(testDir, ".env.zuplo"), "utf-8");
|
|
280
|
-
assert.include(content, 'GOOGLE_SERVICE_ACCOUNT=`{\n "type": "service_account"');
|
|
281
|
-
const parsedEnv = dotenvParse(content);
|
|
282
|
-
assert.equal(parsedEnv.GOOGLE_SERVICE_ACCOUNT, mockPayload.GOOGLE_SERVICE_ACCOUNT);
|
|
283
|
-
assert.deepEqual(JSON.parse(parsedEnv.GOOGLE_SERVICE_ACCOUNT), serviceAccount);
|
|
284
|
-
});
|
|
285
|
-
it("should create the env file without values that dotenv cannot preserve", async () => {
|
|
286
|
-
const mockPayload = {
|
|
287
|
-
accountName: "test-account",
|
|
288
|
-
projectName: "test-project",
|
|
289
|
-
environmentType: "development",
|
|
290
|
-
systemConfigurations: "config-123",
|
|
291
|
-
SERIALIZABLE_VALUE: "still written",
|
|
292
|
-
UNSERIALIZABLE_VALUE: "a physical\rcarriage return, a \"double quote\", a 'single quote', and a `backtick`",
|
|
293
|
-
};
|
|
294
|
-
mockAgent
|
|
295
|
-
.get(TEST_API_ENDPOINT)
|
|
296
|
-
.intercept({
|
|
297
|
-
path: `/v1/environments/${TEST_ENVIRONMENT}/local-configurations`,
|
|
298
|
-
method: "GET",
|
|
299
|
-
headers: {
|
|
300
|
-
authorization: `Bearer ${TEST_AUTH_TOKEN}`,
|
|
301
|
-
},
|
|
302
|
-
})
|
|
303
|
-
.reply(200, mockPayload);
|
|
304
|
-
const { pullLocalConfig } = await import("../common/populate.js");
|
|
305
|
-
await nodeAssert.rejects(pullLocalConfig({
|
|
306
|
-
dir: testDir,
|
|
307
|
-
environment: TEST_ENVIRONMENT,
|
|
308
|
-
authToken: TEST_AUTH_TOKEN,
|
|
309
|
-
}), {
|
|
310
|
-
message: 'Environment variable "UNSERIALIZABLE_VALUE" was not written to .env.zuplo because its value contains a combination of single quotes, double quotes, backticks, or line breaks that dotenv cannot preserve. The file was still created without this variable.',
|
|
311
|
-
});
|
|
312
|
-
const content = await readFile(join(testDir, ".env.zuplo"), "utf-8");
|
|
313
|
-
const parsedEnv = dotenvParse(content);
|
|
314
|
-
assert.equal(parsedEnv.SERIALIZABLE_VALUE, mockPayload.SERIALIZABLE_VALUE);
|
|
315
|
-
assert.notInclude(content, "UNSERIALIZABLE_VALUE");
|
|
316
|
-
});
|
|
317
|
-
it("should only include public variables section when public variables exist", async () => {
|
|
318
|
-
const mockPayload = {
|
|
319
|
-
accountName: "test-account",
|
|
320
|
-
projectName: "test-project",
|
|
321
|
-
environmentType: "development",
|
|
322
|
-
systemConfigurations: "config-123",
|
|
323
|
-
ZUPLO_PUBLIC_API_URL: "https://api.example.com",
|
|
324
|
-
ZUPLO_PUBLIC_DOCS_URL: "https://docs.example.com",
|
|
325
|
-
};
|
|
326
|
-
mockAgent
|
|
327
|
-
.get(TEST_API_ENDPOINT)
|
|
328
|
-
.intercept({
|
|
329
|
-
path: `/v1/environments/${TEST_ENVIRONMENT}/local-configurations`,
|
|
330
|
-
method: "GET",
|
|
331
|
-
headers: {
|
|
332
|
-
authorization: `Bearer ${TEST_AUTH_TOKEN}`,
|
|
333
|
-
},
|
|
334
|
-
})
|
|
335
|
-
.reply(200, mockPayload);
|
|
336
|
-
const { pullLocalConfig } = await import("../common/populate.js");
|
|
337
|
-
await pullLocalConfig({
|
|
338
|
-
dir: testDir,
|
|
339
|
-
environment: TEST_ENVIRONMENT,
|
|
340
|
-
authToken: TEST_AUTH_TOKEN,
|
|
341
|
-
});
|
|
342
|
-
const envFilePath = join(testDir, ".env.zuplo");
|
|
343
|
-
const content = await readFile(envFilePath, "utf-8");
|
|
344
|
-
assert.include(content, "ZUPLO_ACCOUNT_NAME=test-account");
|
|
345
|
-
assert.include(content, "ZUPLO_PROJECT_NAME=test-project");
|
|
346
|
-
assert.include(content, "ZUPLO_ENVIRONMENT_TYPE=development");
|
|
347
|
-
assert.include(content, "ZUPLO_SYSTEM_CONFIGURATIONS=config-123");
|
|
348
|
-
assert.include(content, "# Public Zuplo environment variables");
|
|
349
|
-
assert.include(content, 'ZUPLO_PUBLIC_API_URL="https://api.example.com"');
|
|
350
|
-
assert.include(content, 'ZUPLO_PUBLIC_DOCS_URL="https://docs.example.com"');
|
|
351
|
-
assert.notInclude(content, "# Environment variables defined in the Zuplo UI for the environment");
|
|
352
|
-
await rm(testDir, { recursive: true, force: true });
|
|
353
|
-
});
|
|
354
|
-
it("should only include user variables section when user variables exist", async () => {
|
|
355
|
-
const mockPayload = {
|
|
356
|
-
accountName: "test-account",
|
|
357
|
-
projectName: "test-project",
|
|
358
|
-
environmentType: "development",
|
|
359
|
-
systemConfigurations: "config-123",
|
|
360
|
-
DATABASE_URL: "postgres://localhost:5432/db",
|
|
361
|
-
API_KEY: "secret-key-123",
|
|
362
|
-
};
|
|
363
|
-
mockAgent
|
|
364
|
-
.get(TEST_API_ENDPOINT)
|
|
365
|
-
.intercept({
|
|
366
|
-
path: `/v1/environments/${TEST_ENVIRONMENT}/local-configurations`,
|
|
367
|
-
method: "GET",
|
|
368
|
-
headers: {
|
|
369
|
-
authorization: `Bearer ${TEST_AUTH_TOKEN}`,
|
|
370
|
-
},
|
|
371
|
-
})
|
|
372
|
-
.reply(200, mockPayload);
|
|
373
|
-
const { pullLocalConfig } = await import("../common/populate.js");
|
|
374
|
-
await pullLocalConfig({
|
|
375
|
-
dir: testDir,
|
|
376
|
-
environment: TEST_ENVIRONMENT,
|
|
377
|
-
authToken: TEST_AUTH_TOKEN,
|
|
378
|
-
});
|
|
379
|
-
const envFilePath = join(testDir, ".env.zuplo");
|
|
380
|
-
const content = await readFile(envFilePath, "utf-8");
|
|
381
|
-
assert.include(content, "ZUPLO_ACCOUNT_NAME=test-account");
|
|
382
|
-
assert.include(content, "ZUPLO_PROJECT_NAME=test-project");
|
|
383
|
-
assert.include(content, "ZUPLO_ENVIRONMENT_TYPE=development");
|
|
384
|
-
assert.include(content, "ZUPLO_SYSTEM_CONFIGURATIONS=config-123");
|
|
385
|
-
assert.notInclude(content, "# Public Zuplo environment variables");
|
|
386
|
-
assert.include(content, "# Environment variables defined in the Zuplo UI for the environment");
|
|
387
|
-
assert.include(content, 'DATABASE_URL="postgres://localhost:5432/db"');
|
|
388
|
-
assert.include(content, 'API_KEY="secret-key-123"');
|
|
389
|
-
await rm(testDir, { recursive: true, force: true });
|
|
390
|
-
});
|
|
391
|
-
it("should preserve quoted and multiline environment variable values", async () => {
|
|
392
|
-
const mockPayload = {
|
|
393
|
-
accountName: "test-account",
|
|
394
|
-
projectName: "test-project",
|
|
395
|
-
environmentType: "development",
|
|
396
|
-
systemConfigurations: "config-123",
|
|
397
|
-
DATABASE_URL: "postgres://user:p'assw'ord@localhost:5432/db",
|
|
398
|
-
API_KEY: "secret'with'quotes",
|
|
399
|
-
JSON_CONFIG: '{"message": "Hello \'world\'", "nested": {"value": "test\'s"}}',
|
|
400
|
-
ZUPLO_PUBLIC_MESSAGE: "Welcome to Zuplo's platform!",
|
|
401
|
-
COMPLEX_VALUE: "?\\\"!##==A_special_chars'''",
|
|
402
|
-
EDGE_CASE_1: "value with 'single' and \"double\" quotes",
|
|
403
|
-
EDGE_CASE_2: "path\\to\\file's location",
|
|
404
|
-
EDGE_CASE_3: "it's a $pecial @#$%^&*() value!",
|
|
405
|
-
EDGE_CASE_4: "multi\nline\nwith'quotes",
|
|
406
|
-
EDGE_CASE_5: "tabs\tand\tspaces and 'quotes'",
|
|
407
|
-
EDGE_CASE_6: 'value with "double quotes", a `backtick`, and a literal\\nnewline',
|
|
408
|
-
EDGE_CASE_7: "value with \"double quotes\", a `backtick`, a 'single quote', and a literal\\nnewline",
|
|
409
|
-
CARRIAGE_RETURN: "before\rafter",
|
|
410
|
-
};
|
|
411
|
-
mockAgent
|
|
412
|
-
.get(TEST_API_ENDPOINT)
|
|
413
|
-
.intercept({
|
|
414
|
-
path: `/v1/environments/${TEST_ENVIRONMENT}/local-configurations`,
|
|
415
|
-
method: "GET",
|
|
416
|
-
headers: {
|
|
417
|
-
authorization: `Bearer ${TEST_AUTH_TOKEN}`,
|
|
418
|
-
},
|
|
419
|
-
})
|
|
420
|
-
.reply(200, mockPayload);
|
|
421
|
-
const { pullLocalConfig } = await import("../common/populate.js");
|
|
422
|
-
await pullLocalConfig({
|
|
423
|
-
dir: testDir,
|
|
424
|
-
environment: TEST_ENVIRONMENT,
|
|
425
|
-
authToken: TEST_AUTH_TOKEN,
|
|
426
|
-
});
|
|
427
|
-
const envFilePath = join(testDir, ".env.zuplo");
|
|
428
|
-
const content = await readFile(envFilePath, "utf-8");
|
|
429
|
-
assert.include(content, "DATABASE_URL=\"postgres://user:p'assw'ord@localhost:5432/db\"");
|
|
430
|
-
assert.include(content, "API_KEY=\"secret'with'quotes\"");
|
|
431
|
-
assert.include(content, 'JSON_CONFIG=`{"message": "Hello \'world\'", "nested": {"value": "test\'s"}}`');
|
|
432
|
-
assert.include(content, 'ZUPLO_PUBLIC_MESSAGE="Welcome to Zuplo\'s platform!"');
|
|
433
|
-
assert.include(content, "EDGE_CASE_1=`value with 'single' and \"double\" quotes`");
|
|
434
|
-
assert.include(content, `EDGE_CASE_7=${mockPayload.EDGE_CASE_7}`);
|
|
435
|
-
assert.include(content, 'CARRIAGE_RETURN="before\\rafter"');
|
|
436
|
-
const parsedEnv = dotenvParse(content);
|
|
437
|
-
for (const [key, value] of Object.entries(mockPayload)) {
|
|
438
|
-
if (!SYSTEM_PAYLOAD_KEYS.includes(key)) {
|
|
439
|
-
assert.equal(parsedEnv[key], value, `${key} should round trip exactly`);
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
await rm(testDir, { recursive: true, force: true });
|
|
443
|
-
});
|
|
444
|
-
});
|
|
445
|
-
//# sourceMappingURL=populate.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"populate.test.js","sourceRoot":"","sources":["../../src/__tests__/populate.test.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Unit tests for the pullLocalConfig and pullSystemConfig functions\n * Focuses on testing the parsing logic and environment file generation\n */\n\nimport { strict as nodeAssert } from \"node:assert\";\nimport { mkdtemp, readFile, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\n// biome-ignore lint/correctness/noUnusedImports: Migrated from ESLint\nimport { join, parse } from \"node:path\";\nimport { afterEach, beforeEach, describe, it } from \"node:test\";\nimport { assert } from \"chai\";\nimport { parse as dotenvParse } from \"dotenv\";\nimport {\n type Dispatcher,\n getGlobalDispatcher,\n MockAgent,\n setGlobalDispatcher,\n} from \"undici\";\n\n// Test constants\nconst TEST_ENVIRONMENT = \"test-env-123\";\nconst TEST_AUTH_TOKEN = \"test-auth-token-456\";\nconst TEST_API_ENDPOINT = \"https://dev.zuplo.com\";\nconst SYSTEM_PAYLOAD_KEYS = [\n \"accountName\",\n \"projectName\",\n \"environmentType\",\n \"systemConfigurations\",\n];\n\ndescribe(\"pullSystemConfig\", () => {\n let mockAgent: MockAgent;\n let previousDispatcher: Dispatcher;\n let testDir: string;\n\n beforeEach(async () => {\n // `setGlobalDispatcher` replaces process-global state, and this MockAgent\n // has net-connect disabled. This package runs `node --test`, which gives\n // each test *file* its own process, so the blast radius is the rest of\n // this file rather than the whole package — but a later suite here that\n // performed real network I/O would fail with a bare \"fetch failed\" and no\n // hint as to why. Capture what was installed and put it back, as\n // packages/runtime and packages/cloudflare-workers now do.\n previousDispatcher = getGlobalDispatcher();\n mockAgent = new MockAgent();\n mockAgent.disableNetConnect();\n setGlobalDispatcher(mockAgent);\n\n testDir = await mkdtemp(join(tmpdir(), \"zuplo-test-\"));\n });\n\n afterEach(async () => {\n await mockAgent.close();\n setGlobalDispatcher(previousDispatcher);\n await rm(testDir, { recursive: true, force: true });\n });\n\n it(\"should write account and project name to .env.zuplo\", async () => {\n const mockPayload = {\n accountName: \"test-account\",\n projectName: \"test-project\",\n environmentType: \"development\",\n systemConfigurations: \"config-123\",\n };\n\n mockAgent\n .get(TEST_API_ENDPOINT)\n .intercept({\n path: `/v1/environments/${TEST_ENVIRONMENT}/configurations`,\n method: \"GET\",\n headers: {\n authorization: `Bearer ${TEST_AUTH_TOKEN}`,\n },\n })\n .reply(200, mockPayload);\n\n const { pullSystemConfig } = await import(\"../common/populate.js\");\n\n await pullSystemConfig({\n dir: testDir,\n environment: TEST_ENVIRONMENT,\n authToken: TEST_AUTH_TOKEN,\n });\n\n const content = await readFile(join(testDir, \".env.zuplo\"), \"utf-8\");\n\n assert.include(content, \"ZUPLO_ACCOUNT_NAME=test-account\");\n assert.include(content, \"ZUPLO_PROJECT_NAME=test-project\");\n assert.include(content, \"ZUPLO_ENVIRONMENT_TYPE=development\");\n assert.include(content, \"ZUPLO_SYSTEM_CONFIGURATIONS=config-123\");\n assert.notInclude(content, \"ZUPLO_ENVIRONMENT_NAME\");\n });\n});\n\ndescribe(\"pullLocalConfig\", () => {\n let mockAgent: MockAgent;\n let previousDispatcher: Dispatcher;\n let testDir: string;\n\n beforeEach(async () => {\n // Setup HTTP mocking. See the note in `pullSystemConfig` above for why the\n // previous dispatcher is captured rather than simply overwritten.\n previousDispatcher = getGlobalDispatcher();\n mockAgent = new MockAgent();\n mockAgent.disableNetConnect();\n setGlobalDispatcher(mockAgent);\n\n // Create a temporary directory for testing\n testDir = await mkdtemp(join(tmpdir(), \"zuplo-test-\"));\n });\n\n // This suite previously had no afterEach at all: it leaked both the\n // net-connect-disabled dispatcher and (when a test failed before its inline\n // cleanup) the temp directory.\n afterEach(async () => {\n await mockAgent.close();\n setGlobalDispatcher(previousDispatcher);\n await rm(testDir, { recursive: true, force: true });\n });\n\n it(\"should generate correct .env.zuplo file with system variables\", async () => {\n const mockPayload = {\n accountName: \"test-account\",\n projectName: \"test-project\",\n environmentType: \"development\",\n systemConfigurations: \"config-123\",\n };\n\n // Mock successful API response\n mockAgent\n .get(TEST_API_ENDPOINT)\n .intercept({\n path: `/v1/environments/${TEST_ENVIRONMENT}/local-configurations`,\n method: \"GET\",\n headers: {\n authorization: `Bearer ${TEST_AUTH_TOKEN}`,\n },\n })\n .reply(200, mockPayload);\n\n const { pullLocalConfig } = await import(\"../common/populate.js\");\n\n await pullLocalConfig({\n dir: testDir,\n environment: TEST_ENVIRONMENT,\n authToken: TEST_AUTH_TOKEN,\n });\n\n // Verify the .env.zuplo file was created\n const envFilePath = join(testDir, \".env.zuplo\");\n const content = await readFile(envFilePath, \"utf-8\");\n\n // Verify file header\n assert.include(\n content,\n \"# This file is auto-generated from zuplo link. Please do not edit it manually.\"\n );\n assert.include(\n content,\n \"# It will be auto-generated afresh the next time you run zuplo link.\"\n );\n assert.include(\n content,\n \"# If you wish to add your own environment variables, create a separate .env file.\"\n );\n\n // Verify system variables are present\n assert.include(content, \"ZUPLO_ACCOUNT_NAME=test-account\");\n assert.include(content, \"ZUPLO_PROJECT_NAME=test-project\");\n assert.include(content, \"ZUPLO_ENVIRONMENT_TYPE=development\");\n assert.include(content, \"ZUPLO_SYSTEM_CONFIGURATIONS=config-123\");\n assert.notInclude(content, \"ZUPLO_ENVIRONMENT_NAME\");\n\n // Verify sections are NOT present when there are no variables for them\n assert.notInclude(content, \"# Public Zuplo environment variables\");\n assert.notInclude(\n content,\n \"# Environment variables defined in the Zuplo UI for the environment\"\n );\n\n // Clean up\n await rm(testDir, { recursive: true, force: true });\n });\n\n it(\"should handle payload with public and user environment variables\", async () => {\n const mockPayload = {\n accountName: \"my-account\",\n projectName: \"my-project\",\n environmentType: \"production\",\n systemConfigurations: \"prod-config-456\",\n // Public variables (should be in public section)\n ZUPLO_PUBLIC_API_URL: \"https://api.example.com\",\n ZUPLO_PUBLIC_DOCS_URL: \"https://docs.example.com\",\n // User variables (should be in user section)\n DATABASE_URL: \"postgres://localhost:5432/db\",\n API_KEY: \"secret-key-123\",\n REDIS_URL: \"redis://localhost:6379\",\n };\n\n // Mock successful API response\n mockAgent\n .get(TEST_API_ENDPOINT)\n .intercept({\n path: `/v1/environments/${TEST_ENVIRONMENT}/local-configurations`,\n method: \"GET\",\n headers: {\n authorization: `Bearer ${TEST_AUTH_TOKEN}`,\n },\n })\n .reply(200, mockPayload);\n\n const { pullLocalConfig } = await import(\"../common/populate.js\");\n\n await pullLocalConfig({\n dir: testDir,\n environment: TEST_ENVIRONMENT,\n authToken: TEST_AUTH_TOKEN,\n });\n\n // Read the generated file\n const envFilePath = join(testDir, \".env.zuplo\");\n const content = await readFile(envFilePath, \"utf-8\");\n\n // Verify system variables\n assert.include(content, \"ZUPLO_ACCOUNT_NAME=my-account\");\n assert.include(content, \"ZUPLO_PROJECT_NAME=my-project\");\n assert.include(content, \"ZUPLO_ENVIRONMENT_TYPE=production\");\n assert.include(content, \"ZUPLO_SYSTEM_CONFIGURATIONS=prod-config-456\");\n\n // Verify public variables are in the public section\n const publicSectionRegex =\n /# Public Zuplo environment variables[\\s\\S]*?(?=# Environment variables defined in the Zuplo UI|$)/;\n const publicSection = content.match(publicSectionRegex)?.[0] || \"\";\n assert.include(\n publicSection,\n 'ZUPLO_PUBLIC_API_URL=\"https://api.example.com\"'\n );\n assert.include(\n publicSection,\n 'ZUPLO_PUBLIC_DOCS_URL=\"https://docs.example.com\"'\n );\n\n // Verify user variables are in the user section\n const userSectionRegex =\n /# Environment variables defined in the Zuplo UI[\\s\\S]*$/;\n const userSection = content.match(userSectionRegex)?.[0] || \"\";\n assert.include(userSection, 'DATABASE_URL=\"postgres://localhost:5432/db\"');\n assert.include(userSection, 'API_KEY=\"secret-key-123\"');\n assert.include(userSection, 'REDIS_URL=\"redis://localhost:6379\"');\n\n // Verify system variables are NOT in user section\n assert.notInclude(userSection, \"accountName=\");\n assert.notInclude(userSection, \"projectName=\");\n assert.notInclude(userSection, \"environmentType=\");\n assert.notInclude(userSection, \"systemConfigurations=\");\n\n // Clean up\n await rm(testDir, { recursive: true, force: true });\n });\n\n it(\"should handle empty environment variables gracefully\", async () => {\n const mockPayload = {\n accountName: \"test-account\",\n projectName: \"test-project\",\n environmentType: \"development\",\n systemConfigurations: \"config-789\",\n // No additional environment variables\n };\n\n // Mock successful API response\n mockAgent\n .get(TEST_API_ENDPOINT)\n .intercept({\n path: `/v1/environments/${TEST_ENVIRONMENT}/local-configurations`,\n method: \"GET\",\n headers: {\n authorization: `Bearer ${TEST_AUTH_TOKEN}`,\n },\n })\n .reply(200, mockPayload);\n\n const { pullLocalConfig } = await import(\"../common/populate.js\");\n\n await pullLocalConfig({\n dir: testDir,\n environment: TEST_ENVIRONMENT,\n authToken: TEST_AUTH_TOKEN,\n });\n\n // Read the generated file\n const envFilePath = join(testDir, \".env.zuplo\");\n const content = await readFile(envFilePath, \"utf-8\");\n\n // Verify system variables are still present\n assert.include(content, \"ZUPLO_ACCOUNT_NAME=test-account\");\n assert.include(content, \"ZUPLO_PROJECT_NAME=test-project\");\n assert.include(content, \"ZUPLO_ENVIRONMENT_TYPE=development\");\n assert.include(content, \"ZUPLO_SYSTEM_CONFIGURATIONS=config-789\");\n\n // Verify sections are NOT present when there are no variables for them\n assert.notInclude(content, \"# Public Zuplo environment variables\");\n assert.notInclude(\n content,\n \"# Environment variables defined in the Zuplo UI for the environment\"\n );\n\n // Clean up\n await rm(testDir, { recursive: true, force: true });\n });\n\n it(\"should handle special characters in environment variable values\", async () => {\n const mockPayload = {\n accountName: \"test-account\",\n projectName: \"test-project\",\n environmentType: \"development\",\n systemConfigurations: \"config-123\",\n DATABASE_URL: \"postgres://user:p@ssw0rd!@localhost:5432/db?ssl=true\",\n API_SECRET: \"secret-with-special-chars!@#$%^&*()\",\n JSON_CONFIG: '{\"key\": \"value\", \"nested\": {\"array\": [1, 2, 3]}}',\n };\n\n // Mock successful API response\n mockAgent\n .get(TEST_API_ENDPOINT)\n .intercept({\n path: `/v1/environments/${TEST_ENVIRONMENT}/local-configurations`,\n method: \"GET\",\n headers: {\n authorization: `Bearer ${TEST_AUTH_TOKEN}`,\n },\n })\n .reply(200, mockPayload);\n\n const { pullLocalConfig } = await import(\"../common/populate.js\");\n\n await pullLocalConfig({\n dir: testDir,\n environment: TEST_ENVIRONMENT,\n authToken: TEST_AUTH_TOKEN,\n });\n\n // Read the generated file\n const envFilePath = join(testDir, \".env.zuplo\");\n const content = await readFile(envFilePath, \"utf-8\");\n\n // Simple values remain double quoted, while JSON uses backticks so its\n // double quotes are preserved without escaping.\n assert.include(\n content,\n 'DATABASE_URL=\"postgres://user:p@ssw0rd!@localhost:5432/db?ssl=true\"'\n );\n assert.include(content, 'API_SECRET=\"secret-with-special-chars!@#$%^&*()\"');\n assert.include(\n content,\n 'JSON_CONFIG=`{\"key\": \"value\", \"nested\": {\"array\": [1, 2, 3]}}`'\n );\n\n // Verify these are in the user section (not public section)\n const userSectionRegex =\n /# Environment variables defined in the Zuplo UI[\\s\\S]*$/;\n const userSection = content.match(userSectionRegex)?.[0] || \"\";\n assert.include(userSection, \"DATABASE_URL=\");\n assert.include(userSection, \"API_SECRET=\");\n assert.include(userSection, \"JSON_CONFIG=\");\n\n const parsedEnv = dotenvParse(content);\n assert.equal(parsedEnv.DATABASE_URL, mockPayload.DATABASE_URL);\n assert.equal(parsedEnv.API_SECRET, mockPayload.API_SECRET);\n assert.equal(parsedEnv.JSON_CONFIG, mockPayload.JSON_CONFIG);\n\n // Clean up\n await rm(testDir, { recursive: true, force: true });\n });\n\n it(\"should preserve a Google service account JSON value\", async () => {\n const serviceAccount = {\n type: \"service_account\",\n project_id: \"test-project\",\n private_key_id: \"test-key-id\",\n private_key:\n \"-----BEGIN PRIVATE KEY-----\\nMIIEvQIBADANBgkqhkiG9w0BAQEFAASC\\n-----END PRIVATE KEY-----\\n\",\n client_email: \"test-service-account@test-project.iam.gserviceaccount.com\",\n client_id: \"1234567890\",\n auth_uri: \"https://accounts.google.com/o/oauth2/auth\",\n token_uri: \"https://oauth2.googleapis.com/token\",\n auth_provider_x509_cert_url: \"https://www.googleapis.com/oauth2/v1/certs\",\n client_x509_cert_url:\n \"https://www.googleapis.com/robot/v1/metadata/x509/test-service-account%40test-project.iam.gserviceaccount.com\",\n universe_domain: \"googleapis.com\",\n };\n const mockPayload = {\n accountName: \"test-account\",\n projectName: \"test-project\",\n environmentType: \"development\",\n systemConfigurations: \"config-123\",\n GOOGLE_SERVICE_ACCOUNT: JSON.stringify(serviceAccount, null, 2),\n };\n\n mockAgent\n .get(TEST_API_ENDPOINT)\n .intercept({\n path: `/v1/environments/${TEST_ENVIRONMENT}/local-configurations`,\n method: \"GET\",\n headers: {\n authorization: `Bearer ${TEST_AUTH_TOKEN}`,\n },\n })\n .reply(200, mockPayload);\n\n const { pullLocalConfig } = await import(\"../common/populate.js\");\n\n await pullLocalConfig({\n dir: testDir,\n environment: TEST_ENVIRONMENT,\n authToken: TEST_AUTH_TOKEN,\n });\n\n const content = await readFile(join(testDir, \".env.zuplo\"), \"utf-8\");\n assert.include(\n content,\n 'GOOGLE_SERVICE_ACCOUNT=`{\\n \"type\": \"service_account\"'\n );\n\n const parsedEnv = dotenvParse(content);\n assert.equal(\n parsedEnv.GOOGLE_SERVICE_ACCOUNT,\n mockPayload.GOOGLE_SERVICE_ACCOUNT\n );\n assert.deepEqual(\n JSON.parse(parsedEnv.GOOGLE_SERVICE_ACCOUNT),\n serviceAccount\n );\n });\n\n it(\"should create the env file without values that dotenv cannot preserve\", async () => {\n const mockPayload = {\n accountName: \"test-account\",\n projectName: \"test-project\",\n environmentType: \"development\",\n systemConfigurations: \"config-123\",\n SERIALIZABLE_VALUE: \"still written\",\n UNSERIALIZABLE_VALUE:\n \"a physical\\rcarriage return, a \\\"double quote\\\", a 'single quote', and a `backtick`\",\n };\n\n mockAgent\n .get(TEST_API_ENDPOINT)\n .intercept({\n path: `/v1/environments/${TEST_ENVIRONMENT}/local-configurations`,\n method: \"GET\",\n headers: {\n authorization: `Bearer ${TEST_AUTH_TOKEN}`,\n },\n })\n .reply(200, mockPayload);\n\n const { pullLocalConfig } = await import(\"../common/populate.js\");\n\n await nodeAssert.rejects(\n pullLocalConfig({\n dir: testDir,\n environment: TEST_ENVIRONMENT,\n authToken: TEST_AUTH_TOKEN,\n }),\n {\n message:\n 'Environment variable \"UNSERIALIZABLE_VALUE\" was not written to .env.zuplo because its value contains a combination of single quotes, double quotes, backticks, or line breaks that dotenv cannot preserve. The file was still created without this variable.',\n }\n );\n\n const content = await readFile(join(testDir, \".env.zuplo\"), \"utf-8\");\n const parsedEnv = dotenvParse(content);\n\n assert.equal(parsedEnv.SERIALIZABLE_VALUE, mockPayload.SERIALIZABLE_VALUE);\n assert.notInclude(content, \"UNSERIALIZABLE_VALUE\");\n });\n\n it(\"should only include public variables section when public variables exist\", async () => {\n const mockPayload = {\n accountName: \"test-account\",\n projectName: \"test-project\",\n environmentType: \"development\",\n systemConfigurations: \"config-123\",\n // Only public variables, no user variables\n ZUPLO_PUBLIC_API_URL: \"https://api.example.com\",\n ZUPLO_PUBLIC_DOCS_URL: \"https://docs.example.com\",\n };\n\n // Mock successful API response\n mockAgent\n .get(TEST_API_ENDPOINT)\n .intercept({\n path: `/v1/environments/${TEST_ENVIRONMENT}/local-configurations`,\n method: \"GET\",\n headers: {\n authorization: `Bearer ${TEST_AUTH_TOKEN}`,\n },\n })\n .reply(200, mockPayload);\n\n const { pullLocalConfig } = await import(\"../common/populate.js\");\n\n await pullLocalConfig({\n dir: testDir,\n environment: TEST_ENVIRONMENT,\n authToken: TEST_AUTH_TOKEN,\n });\n\n // Read the generated file\n const envFilePath = join(testDir, \".env.zuplo\");\n const content = await readFile(envFilePath, \"utf-8\");\n\n // Verify system variables are present\n assert.include(content, \"ZUPLO_ACCOUNT_NAME=test-account\");\n assert.include(content, \"ZUPLO_PROJECT_NAME=test-project\");\n assert.include(content, \"ZUPLO_ENVIRONMENT_TYPE=development\");\n assert.include(content, \"ZUPLO_SYSTEM_CONFIGURATIONS=config-123\");\n\n // Verify public section is present with variables\n assert.include(content, \"# Public Zuplo environment variables\");\n assert.include(content, 'ZUPLO_PUBLIC_API_URL=\"https://api.example.com\"');\n assert.include(content, 'ZUPLO_PUBLIC_DOCS_URL=\"https://docs.example.com\"');\n\n // Verify user section is NOT present since there are no user variables\n assert.notInclude(\n content,\n \"# Environment variables defined in the Zuplo UI for the environment\"\n );\n\n // Clean up\n await rm(testDir, { recursive: true, force: true });\n });\n\n it(\"should only include user variables section when user variables exist\", async () => {\n const mockPayload = {\n accountName: \"test-account\",\n projectName: \"test-project\",\n environmentType: \"development\",\n systemConfigurations: \"config-123\",\n // Only user variables, no public variables\n DATABASE_URL: \"postgres://localhost:5432/db\",\n API_KEY: \"secret-key-123\",\n };\n\n // Mock successful API response\n mockAgent\n .get(TEST_API_ENDPOINT)\n .intercept({\n path: `/v1/environments/${TEST_ENVIRONMENT}/local-configurations`,\n method: \"GET\",\n headers: {\n authorization: `Bearer ${TEST_AUTH_TOKEN}`,\n },\n })\n .reply(200, mockPayload);\n\n const { pullLocalConfig } = await import(\"../common/populate.js\");\n\n await pullLocalConfig({\n dir: testDir,\n environment: TEST_ENVIRONMENT,\n authToken: TEST_AUTH_TOKEN,\n });\n\n // Read the generated file\n const envFilePath = join(testDir, \".env.zuplo\");\n const content = await readFile(envFilePath, \"utf-8\");\n\n // Verify system variables are present\n assert.include(content, \"ZUPLO_ACCOUNT_NAME=test-account\");\n assert.include(content, \"ZUPLO_PROJECT_NAME=test-project\");\n assert.include(content, \"ZUPLO_ENVIRONMENT_TYPE=development\");\n assert.include(content, \"ZUPLO_SYSTEM_CONFIGURATIONS=config-123\");\n\n // Verify public section is NOT present since there are no public variables\n assert.notInclude(content, \"# Public Zuplo environment variables\");\n\n // Verify user section is present with variables\n assert.include(\n content,\n \"# Environment variables defined in the Zuplo UI for the environment\"\n );\n assert.include(content, 'DATABASE_URL=\"postgres://localhost:5432/db\"');\n assert.include(content, 'API_KEY=\"secret-key-123\"');\n\n // Clean up\n await rm(testDir, { recursive: true, force: true });\n });\n\n it(\"should preserve quoted and multiline environment variable values\", async () => {\n const mockPayload = {\n accountName: \"test-account\",\n projectName: \"test-project\",\n environmentType: \"development\",\n systemConfigurations: \"config-123\",\n // Environment variables with double quotes that need escaping\n DATABASE_URL: \"postgres://user:p'assw'ord@localhost:5432/db\",\n API_KEY: \"secret'with'quotes\",\n JSON_CONFIG:\n '{\"message\": \"Hello \\'world\\'\", \"nested\": {\"value\": \"test\\'s\"}}',\n ZUPLO_PUBLIC_MESSAGE: \"Welcome to Zuplo's platform!\",\n COMPLEX_VALUE: \"?\\\\\\\"!##==A_special_chars'''\",\n // Additional special character test cases\n EDGE_CASE_1: \"value with 'single' and \\\"double\\\" quotes\",\n EDGE_CASE_2: \"path\\\\to\\\\file's location\",\n EDGE_CASE_3: \"it's a $pecial @#$%^&*() value!\",\n EDGE_CASE_4: \"multi\\nline\\nwith'quotes\",\n EDGE_CASE_5: \"tabs\\tand\\tspaces and 'quotes'\",\n EDGE_CASE_6:\n 'value with \"double quotes\", a `backtick`, and a literal\\\\nnewline',\n EDGE_CASE_7:\n \"value with \\\"double quotes\\\", a `backtick`, a 'single quote', and a literal\\\\nnewline\",\n CARRIAGE_RETURN: \"before\\rafter\",\n };\n\n // Mock successful API response\n mockAgent\n .get(TEST_API_ENDPOINT)\n .intercept({\n path: `/v1/environments/${TEST_ENVIRONMENT}/local-configurations`,\n method: \"GET\",\n headers: {\n authorization: `Bearer ${TEST_AUTH_TOKEN}`,\n },\n })\n .reply(200, mockPayload);\n\n const { pullLocalConfig } = await import(\"../common/populate.js\");\n\n await pullLocalConfig({\n dir: testDir,\n environment: TEST_ENVIRONMENT,\n authToken: TEST_AUTH_TOKEN,\n });\n\n // Read the generated file\n const envFilePath = join(testDir, \".env.zuplo\");\n const content = await readFile(envFilePath, \"utf-8\");\n\n // Simple values use double quotes. Values containing double quotes use\n // backticks so dotenv can parse them without changing their contents.\n assert.include(\n content,\n \"DATABASE_URL=\\\"postgres://user:p'assw'ord@localhost:5432/db\\\"\"\n );\n assert.include(content, \"API_KEY=\\\"secret'with'quotes\\\"\");\n assert.include(\n content,\n 'JSON_CONFIG=`{\"message\": \"Hello \\'world\\'\", \"nested\": {\"value\": \"test\\'s\"}}`'\n );\n assert.include(\n content,\n 'ZUPLO_PUBLIC_MESSAGE=\"Welcome to Zuplo\\'s platform!\"'\n );\n assert.include(\n content,\n \"EDGE_CASE_1=`value with 'single' and \\\"double\\\" quotes`\"\n );\n assert.include(content, `EDGE_CASE_7=${mockPayload.EDGE_CASE_7}`);\n assert.include(content, 'CARRIAGE_RETURN=\"before\\\\rafter\"');\n\n const parsedEnv = dotenvParse(content);\n for (const [key, value] of Object.entries(mockPayload)) {\n if (!SYSTEM_PAYLOAD_KEYS.includes(key)) {\n assert.equal(parsedEnv[key], value, `${key} should round trip exactly`);\n }\n }\n\n // Clean up\n await rm(testDir, { recursive: true, force: true });\n });\n});\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"tsconfig-upgrader.test.d.ts","sourceRoot":"","sources":["../../src/__tests__/tsconfig-upgrader.test.ts"],"names":[],"mappings":""}
|