wrangler 0.0.0-e3a458e → 0.0.0-e3c036d7
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/Cloudflare_CA.pem +18 -0
- package/README.md +47 -14
- package/bin/wrangler.js +181 -29
- package/kv-asset-handler.js +1 -0
- package/miniflare-dist/index.mjs +6368 -0
- package/package.json +193 -142
- package/src/__tests__/access.test.ts +25 -0
- package/src/__tests__/api-dev.test.ts +238 -0
- package/src/__tests__/api-devregistry.test.js +64 -0
- package/src/__tests__/api.test.ts +80 -0
- package/src/__tests__/config-cache-without-cache-dir.test.ts +38 -0
- package/src/__tests__/config-cache.test.ts +42 -0
- package/src/__tests__/configuration.test.ts +4454 -2590
- package/src/__tests__/d1/d1.test.ts +82 -0
- package/src/__tests__/d1/execute.test.ts +64 -0
- package/src/__tests__/d1/migrate.test.ts +155 -0
- package/src/__tests__/d1/splitter.test.ts +255 -0
- package/src/__tests__/delete.test.ts +266 -0
- package/src/__tests__/deployments.test.ts +129 -0
- package/src/__tests__/dev.test.tsx +1589 -432
- package/src/__tests__/generate.test.ts +238 -0
- package/src/__tests__/get-host-from-url.test.ts +16 -0
- package/src/__tests__/guess-worker-format.test.ts +113 -51
- package/src/__tests__/helpers/cmd-shim.d.ts +6 -6
- package/src/__tests__/helpers/end-event-loop.ts +6 -0
- package/src/__tests__/helpers/mock-account-id.ts +24 -24
- package/src/__tests__/helpers/mock-auth-domain.ts +20 -0
- package/src/__tests__/helpers/mock-bin.ts +20 -20
- package/src/__tests__/helpers/mock-console.ts +68 -32
- package/src/__tests__/helpers/mock-dialogs.ts +107 -33
- package/src/__tests__/helpers/mock-get-pages-upload-token.ts +25 -0
- package/src/__tests__/helpers/mock-get-zone-from-host.ts +11 -0
- package/src/__tests__/helpers/mock-http-server.ts +46 -0
- package/src/__tests__/helpers/mock-istty.ts +74 -0
- package/src/__tests__/helpers/mock-known-routes.ts +12 -0
- package/src/__tests__/helpers/mock-kv.ts +41 -28
- package/src/__tests__/helpers/mock-oauth-flow.ts +263 -0
- package/src/__tests__/helpers/mock-process.ts +34 -0
- package/src/__tests__/helpers/mock-set-timeout.ts +16 -0
- package/src/__tests__/helpers/mock-stdin.ts +82 -77
- package/src/__tests__/helpers/mock-web-socket.ts +21 -21
- package/src/__tests__/helpers/msw/blob-worker.cjs +19 -0
- package/src/__tests__/helpers/msw/handlers/access.ts +13 -0
- package/src/__tests__/helpers/msw/handlers/deployments.ts +93 -0
- package/src/__tests__/helpers/msw/handlers/namespaces.ts +81 -0
- package/src/__tests__/helpers/msw/handlers/oauth.ts +31 -0
- package/src/__tests__/helpers/msw/handlers/r2.ts +60 -0
- package/src/__tests__/helpers/msw/handlers/script.ts +56 -0
- package/src/__tests__/helpers/msw/handlers/user.ts +52 -0
- package/src/__tests__/helpers/msw/handlers/zones.ts +20 -0
- package/src/__tests__/helpers/msw/index.ts +50 -0
- package/src/__tests__/helpers/msw/read-file-sync.js +61 -0
- package/src/__tests__/helpers/run-in-tmp.ts +28 -22
- package/src/__tests__/helpers/run-wrangler.ts +8 -8
- package/src/__tests__/helpers/string-dynamic-values-matcher.ts +28 -0
- package/src/__tests__/helpers/worker-scripts/child-wrangler.toml +1 -0
- package/src/__tests__/helpers/worker-scripts/hello-world-worker.js +5 -0
- package/src/__tests__/helpers/worker-scripts/hello-world-wrangler.toml +1 -0
- package/src/__tests__/helpers/worker-scripts/parent-worker.js +8 -0
- package/src/__tests__/helpers/worker-scripts/parent-wrangler.toml +5 -0
- package/src/__tests__/helpers/write-worker-source.ts +31 -0
- package/src/__tests__/helpers/write-wrangler-toml.ts +9 -9
- package/src/__tests__/https-options.test.ts +144 -108
- package/src/__tests__/index.test.ts +258 -975
- package/src/__tests__/init.test.ts +3165 -0
- package/src/__tests__/jest.setup.ts +154 -48
- package/src/__tests__/kv.test.ts +1789 -1372
- package/src/__tests__/logger.test.ts +141 -0
- package/src/__tests__/logout.test.ts +36 -41
- package/src/__tests__/metrics.test.ts +493 -0
- package/src/__tests__/middleware.scheduled.test.ts +145 -0
- package/src/__tests__/middleware.test.ts +816 -0
- package/src/__tests__/mtls-certificates.test.ts +585 -0
- package/src/__tests__/package-manager.test.ts +312 -165
- package/src/__tests__/pages/deployment-list.test.ts +78 -0
- package/src/__tests__/pages/functions-build.test.ts +453 -0
- package/src/__tests__/pages/pages.test.ts +81 -0
- package/src/__tests__/pages/project-create.test.ts +63 -0
- package/src/__tests__/pages/project-list.test.ts +108 -0
- package/src/__tests__/pages/project-upload.test.ts +481 -0
- package/src/__tests__/pages/publish.test.ts +2745 -0
- package/src/__tests__/pages-deployment-tail.test.ts +955 -0
- package/src/__tests__/parse.test.ts +359 -245
- package/src/__tests__/paths.test.ts +39 -0
- package/src/__tests__/publish.test.ts +8209 -2558
- package/src/__tests__/pubsub.test.ts +493 -0
- package/src/__tests__/queues.test.ts +529 -0
- package/src/__tests__/r2.test.ts +369 -193
- package/src/__tests__/route.test.ts +22 -22
- package/src/__tests__/secret.test.ts +683 -415
- package/src/__tests__/tail.test.ts +838 -444
- package/src/__tests__/test-old-node-version.js +31 -0
- package/src/__tests__/tsconfig-sanity.ts +12 -0
- package/src/__tests__/tsconfig.json +8 -0
- package/src/__tests__/tsconfig.tsbuildinfo +1 -0
- package/src/__tests__/type-generation.test.ts +234 -0
- package/src/__tests__/user.test.ts +118 -0
- package/src/__tests__/utils-collectKeyValues.test.ts +47 -0
- package/src/__tests__/validate-dev-props.test.ts +56 -0
- package/src/__tests__/version.test.ts +35 -0
- package/src/__tests__/whoami.test.tsx +166 -94
- package/src/__tests__/worker-namespace.test.ts +339 -0
- package/src/abort.d.ts +3 -0
- package/src/api/dev.ts +327 -0
- package/src/api/index.ts +11 -0
- package/src/api/mtls-certificate.ts +148 -0
- package/src/api/pages/create-worker-bundle-contents.ts +75 -0
- package/src/api/pages/index.ts +5 -0
- package/src/api/pages/publish.tsx +375 -0
- package/src/bundle-reporter.ts +68 -0
- package/src/bundle.ts +858 -110
- package/src/cfetch/index.ts +123 -69
- package/src/cfetch/internal.ts +217 -98
- package/src/cli.ts +23 -14
- package/src/config/README.md +7 -7
- package/src/config/config.ts +232 -229
- package/src/config/diagnostics.ts +61 -61
- package/src/config/environment.ts +542 -256
- package/src/config/index.ts +367 -34
- package/src/config/validation-helpers.ts +415 -286
- package/src/config/validation.ts +2137 -942
- package/src/config-cache.ts +85 -0
- package/src/create-worker-preview.ts +251 -124
- package/src/create-worker-upload-form.ts +326 -201
- package/src/d1/backups.tsx +215 -0
- package/src/d1/constants.ts +2 -0
- package/src/d1/create.tsx +64 -0
- package/src/d1/delete.ts +53 -0
- package/src/d1/execute.tsx +354 -0
- package/src/d1/formatTimeAgo.ts +14 -0
- package/src/d1/index.ts +100 -0
- package/src/d1/list.tsx +60 -0
- package/src/d1/migrations/apply.tsx +206 -0
- package/src/d1/migrations/create.tsx +76 -0
- package/src/d1/migrations/helpers.ts +172 -0
- package/src/d1/migrations/index.ts +3 -0
- package/src/d1/migrations/list.tsx +92 -0
- package/src/d1/migrations/options.ts +23 -0
- package/src/d1/options.ts +22 -0
- package/src/d1/splitter.ts +161 -0
- package/src/d1/types.ts +25 -0
- package/src/d1/utils.ts +49 -0
- package/src/delete.ts +100 -0
- package/src/deployments.ts +116 -0
- package/src/deprecated/index.ts +144 -0
- package/src/dev/dev-vars.ts +39 -0
- package/src/dev/dev.tsx +544 -306
- package/src/dev/get-local-persistence-path.ts +31 -0
- package/src/dev/local.tsx +906 -233
- package/src/dev/remote.tsx +621 -192
- package/src/dev/start-server.ts +540 -0
- package/src/dev/use-esbuild.ts +189 -80
- package/src/dev/validate-dev-props.ts +40 -0
- package/src/dev-registry.ts +201 -0
- package/src/dev.tsx +928 -0
- package/src/dialogs.ts +136 -0
- package/src/dispatch-namespace.ts +211 -0
- package/src/docs/index.ts +97 -0
- package/src/durable.ts +102 -0
- package/src/entry.ts +277 -109
- package/src/environment-variables/factory.ts +88 -0
- package/src/environment-variables/misc-variables.ts +30 -0
- package/src/errors.ts +11 -0
- package/src/generate/index.ts +298 -0
- package/src/git-client.ts +135 -0
- package/src/global-wrangler-config-path.ts +26 -0
- package/src/https-options.ts +85 -80
- package/src/index.ts +705 -0
- package/src/init.ts +1023 -0
- package/src/inspect.ts +722 -557
- package/src/intl-polyfill.d.ts +139 -0
- package/src/is-ci.ts +14 -0
- package/src/is-interactive.ts +16 -0
- package/src/jest.d.ts +4 -0
- package/src/kv/helpers.ts +430 -0
- package/src/kv/index.ts +594 -0
- package/src/logger.ts +104 -0
- package/src/metrics/index.ts +5 -0
- package/src/metrics/metrics-config.ts +239 -0
- package/src/metrics/metrics-dispatcher.ts +96 -0
- package/src/metrics/metrics-usage-headers.ts +24 -0
- package/src/metrics/send-event.ts +98 -0
- package/src/miniflare-cli/README.md +30 -0
- package/src/miniflare-cli/assets.ts +251 -0
- package/src/miniflare-cli/index.ts +210 -0
- package/src/miniflare-cli/request-context.ts +40 -0
- package/src/miniflare-cli/tsconfig.json +9 -0
- package/src/miniflare-cli/tsconfig.tsbuildinfo +1 -0
- package/src/miniflare-cli/types.ts +11 -0
- package/src/module-collection.ts +241 -227
- package/src/mtls-certificate/cli.ts +155 -0
- package/src/open-in-browser.ts +8 -16
- package/src/package-manager.ts +183 -90
- package/src/pages/build.ts +252 -0
- package/src/pages/buildFunctions.ts +133 -0
- package/src/pages/constants.ts +18 -0
- package/src/pages/deployment-tails.ts +281 -0
- package/src/pages/deployments.tsx +86 -0
- package/src/pages/dev.ts +726 -0
- package/src/pages/errors.ts +66 -0
- package/src/pages/functions/buildPlugin.ts +97 -0
- package/src/pages/functions/buildWorker.ts +294 -0
- package/src/pages/functions/filepath-routing.test.ts +234 -0
- package/src/pages/functions/filepath-routing.ts +189 -0
- package/src/pages/functions/identifiers.ts +78 -0
- package/src/pages/functions/routes-consolidation.test.ts +250 -0
- package/src/pages/functions/routes-consolidation.ts +73 -0
- package/src/pages/functions/routes-transformation.test.ts +282 -0
- package/src/pages/functions/routes-transformation.ts +115 -0
- package/src/pages/functions/routes-validation.test.ts +403 -0
- package/src/pages/functions/routes-validation.ts +202 -0
- package/src/pages/functions/routes.ts +151 -0
- package/src/pages/functions/tsconfig.json +8 -0
- package/src/pages/functions/tsconfig.tsbuildinfo +1 -0
- package/src/pages/functions.ts +86 -0
- package/src/pages/hash.ts +13 -0
- package/src/pages/index.ts +102 -0
- package/src/pages/projects.tsx +162 -0
- package/src/pages/prompt-select-project.tsx +31 -0
- package/src/pages/publish.tsx +276 -0
- package/src/pages/types.ts +46 -0
- package/src/pages/upload.tsx +449 -0
- package/src/pages/utils.ts +23 -0
- package/src/parse.ts +247 -122
- package/src/paths.ts +53 -8
- package/src/proxy.ts +629 -375
- package/src/publish/index.ts +274 -0
- package/src/publish/publish.ts +1076 -0
- package/src/pubsub/index.ts +286 -0
- package/src/pubsub/pubsub-commands.ts +623 -0
- package/src/queues/cli/commands/consumer/add.ts +65 -0
- package/src/queues/cli/commands/consumer/index.ts +19 -0
- package/src/queues/cli/commands/consumer/remove.ts +31 -0
- package/src/queues/cli/commands/create.ts +25 -0
- package/src/queues/cli/commands/delete.ts +26 -0
- package/src/queues/cli/commands/index.ts +35 -0
- package/src/queues/cli/commands/list.ts +25 -0
- package/src/queues/client.ts +135 -0
- package/src/queues/utils.ts +18 -0
- package/src/r2/constants.ts +4 -0
- package/src/r2/helpers.ts +132 -0
- package/src/r2/index.ts +289 -0
- package/src/routes.ts +140 -0
- package/src/secret/index.ts +375 -0
- package/src/selfsigned.d.ts +23 -23
- package/src/sites.ts +372 -0
- package/src/tail/createTail.ts +406 -0
- package/src/tail/filters.ts +109 -111
- package/src/tail/index.ts +208 -296
- package/src/tail/printing.ts +107 -47
- package/src/tsconfig-sanity.ts +16 -0
- package/src/type-generation.ts +181 -0
- package/src/update-check.ts +19 -0
- package/src/user/access.ts +68 -0
- package/src/user/auth-variables.ts +113 -0
- package/src/user/choose-account.tsx +39 -0
- package/src/user/generate-auth-url.ts +33 -0
- package/src/user/generate-random-state.ts +16 -0
- package/src/user/index.ts +2 -0
- package/src/user/user.ts +1233 -0
- package/src/utils/collectKeyValues.ts +14 -0
- package/src/whoami.ts +135 -0
- package/src/worker.ts +201 -100
- package/src/yargs-types.ts +37 -0
- package/src/zones.ts +191 -0
- package/templates/__tests__/pages-dev-util.test.ts +128 -0
- package/templates/__tests__/tsconfig-sanity.ts +12 -0
- package/templates/__tests__/tsconfig.json +8 -0
- package/templates/__tests__/tsconfig.tsbuildinfo +1 -0
- package/templates/checked-fetch.js +23 -0
- package/templates/d1-beta-facade.js +241 -0
- package/templates/facade.d.ts +14 -0
- package/templates/first-party-worker-module-facade.ts +19 -0
- package/templates/format-dev-errors.ts +34 -0
- package/templates/gitignore +172 -0
- package/templates/init-tests/test-jest-new-worker.js +23 -0
- package/templates/init-tests/test-vitest-new-worker.js +24 -0
- package/templates/init-tests/test-vitest-new-worker.ts +25 -0
- package/templates/middleware/common.ts +62 -0
- package/templates/middleware/loader-modules.ts +84 -0
- package/templates/middleware/loader-sw.ts +233 -0
- package/templates/middleware/middleware-miniflare3-json-error.ts +32 -0
- package/templates/middleware/middleware-pretty-error.ts +40 -0
- package/templates/middleware/middleware-scheduled.ts +15 -0
- package/templates/new-worker-scheduled.js +17 -0
- package/templates/new-worker-scheduled.ts +32 -0
- package/templates/new-worker.js +3 -3
- package/templates/new-worker.ts +21 -3
- package/templates/no-op-worker.js +10 -0
- package/templates/pages-dev-pipeline.ts +31 -0
- package/templates/pages-dev-util.ts +52 -0
- package/templates/pages-shim.ts +12 -0
- package/templates/pages-template-plugin.ts +180 -0
- package/templates/pages-template-worker.ts +189 -0
- package/templates/serve-static-assets.ts +66 -0
- package/templates/service-bindings-module-facade.js +55 -0
- package/templates/service-bindings-sw-facade.js +42 -0
- package/templates/tsconfig-sanity.ts +11 -0
- package/templates/tsconfig.init.json +106 -0
- package/templates/tsconfig.json +6 -103
- package/templates/tsconfig.tsbuildinfo +1 -0
- package/wrangler-dist/cli.d.ts +1624 -0
- package/wrangler-dist/cli.js +139300 -128984
- package/wrangler-dist/wasm-sync.wasm +0 -0
- package/pages/functions/buildWorker.ts +0 -62
- package/pages/functions/filepath-routing.test.ts +0 -223
- package/pages/functions/filepath-routing.ts +0 -181
- package/pages/functions/identifiers.ts +0 -78
- package/pages/functions/routes.ts +0 -151
- package/pages/functions/template-worker.ts +0 -130
- package/src/__tests__/dev2.test.tsx +0 -154
- package/src/__tests__/helpers/faye-websocket.d.ts +0 -6
- package/src/__tests__/helpers/mock-cfetch.ts +0 -207
- package/src/__tests__/pages.test.ts +0 -44
- package/src/__tests__/sentry.test.ts +0 -146
- package/src/dialogs.tsx +0 -77
- package/src/environment-variables.ts +0 -33
- package/src/index.tsx +0 -2365
- package/src/kv.ts +0 -339
- package/src/pages.tsx +0 -1045
- package/src/publish.ts +0 -354
- package/src/r2.ts +0 -50
- package/src/reporting.ts +0 -131
- package/src/sites.tsx +0 -273
- package/src/user.tsx +0 -1118
- package/src/whoami.tsx +0 -69
- package/templates/static-asset-facade.js +0 -47
- package/vendor/@cloudflare/kv-asset-handler/CHANGELOG.md +0 -332
- package/vendor/@cloudflare/kv-asset-handler/LICENSE_APACHE +0 -176
- package/vendor/@cloudflare/kv-asset-handler/LICENSE_MIT +0 -25
- package/vendor/@cloudflare/kv-asset-handler/README.md +0 -245
- package/vendor/@cloudflare/kv-asset-handler/dist/index.d.ts +0 -32
- package/vendor/@cloudflare/kv-asset-handler/dist/index.js +0 -354
- package/vendor/@cloudflare/kv-asset-handler/dist/mocks.d.ts +0 -13
- package/vendor/@cloudflare/kv-asset-handler/dist/mocks.js +0 -148
- package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.d.ts +0 -1
- package/vendor/@cloudflare/kv-asset-handler/dist/test/getAssetFromKV.js +0 -436
- package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.d.ts +0 -1
- package/vendor/@cloudflare/kv-asset-handler/dist/test/mapRequestToAsset.js +0 -40
- package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.d.ts +0 -1
- package/vendor/@cloudflare/kv-asset-handler/dist/test/serveSinglePageApp.js +0 -42
- package/vendor/@cloudflare/kv-asset-handler/dist/types.d.ts +0 -26
- package/vendor/@cloudflare/kv-asset-handler/dist/types.js +0 -31
- package/vendor/@cloudflare/kv-asset-handler/package.json +0 -52
- package/vendor/@cloudflare/kv-asset-handler/src/index.ts +0 -296
- package/vendor/@cloudflare/kv-asset-handler/src/mocks.ts +0 -136
- package/vendor/@cloudflare/kv-asset-handler/src/test/getAssetFromKV.ts +0 -464
- package/vendor/@cloudflare/kv-asset-handler/src/test/mapRequestToAsset.ts +0 -33
- package/vendor/@cloudflare/kv-asset-handler/src/test/serveSinglePageApp.ts +0 -42
- package/vendor/@cloudflare/kv-asset-handler/src/types.ts +0 -39
- package/vendor/wrangler-mime/CHANGELOG.md +0 -289
- package/vendor/wrangler-mime/LICENSE +0 -21
- package/vendor/wrangler-mime/Mime.js +0 -97
- package/vendor/wrangler-mime/README.md +0 -187
- package/vendor/wrangler-mime/cli.js +0 -46
- package/vendor/wrangler-mime/index.js +0 -4
- package/vendor/wrangler-mime/lite.js +0 -4
- package/vendor/wrangler-mime/package.json +0 -52
- package/vendor/wrangler-mime/types/other.js +0 -1
- package/vendor/wrangler-mime/types/standard.js +0 -1
- package/wrangler-dist/cli.js.map +0 -7
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { RawConfig } from "./config";
|
|
2
2
|
import type { Diagnostics } from "./diagnostics";
|
|
3
3
|
import type { Environment, RawEnvironment } from "./environment";
|
|
4
4
|
|
|
@@ -9,22 +9,24 @@ import type { Environment, RawEnvironment } from "./environment";
|
|
|
9
9
|
* The `fieldPath` is a dot separated property path, e.g. `"build.upload.format"`.
|
|
10
10
|
*/
|
|
11
11
|
export function deprecated<T extends object>(
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
12
|
+
diagnostics: Diagnostics,
|
|
13
|
+
config: T,
|
|
14
|
+
fieldPath: DeepKeyOf<T>,
|
|
15
|
+
message: string,
|
|
16
|
+
remove: boolean,
|
|
17
|
+
title = "Deprecation",
|
|
18
|
+
type: "warning" | "error" = "warning"
|
|
18
19
|
): void {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
20
|
+
const BOLD = "\x1b[1m";
|
|
21
|
+
const NORMAL = "\x1b[0m";
|
|
22
|
+
const diagnosticMessage = `${BOLD}${title}${NORMAL}: "${fieldPath}":\n${message}`;
|
|
23
|
+
const result = unwindPropertyPath(config, fieldPath);
|
|
24
|
+
if (result !== undefined && result.field in result.container) {
|
|
25
|
+
diagnostics[`${type}s`].push(diagnosticMessage);
|
|
26
|
+
if (remove) {
|
|
27
|
+
delete (result.container as Record<string, unknown>)[result.field];
|
|
28
|
+
}
|
|
29
|
+
}
|
|
28
30
|
}
|
|
29
31
|
|
|
30
32
|
/**
|
|
@@ -34,16 +36,16 @@ export function deprecated<T extends object>(
|
|
|
34
36
|
* The `fieldPath` is a dot separated property path, e.g. `"build.upload.format"`.
|
|
35
37
|
*/
|
|
36
38
|
export function experimental<T extends object>(
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
39
|
+
diagnostics: Diagnostics,
|
|
40
|
+
config: T,
|
|
41
|
+
fieldPath: DeepKeyOf<T>
|
|
40
42
|
): void {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
43
|
+
const result = unwindPropertyPath(config, fieldPath);
|
|
44
|
+
if (result !== undefined && result.field in result.container) {
|
|
45
|
+
diagnostics.warnings.push(
|
|
46
|
+
`"${fieldPath}" fields are experimental and may change or break at any time.`
|
|
47
|
+
);
|
|
48
|
+
}
|
|
47
49
|
}
|
|
48
50
|
|
|
49
51
|
/**
|
|
@@ -53,50 +55,83 @@ export function experimental<T extends object>(
|
|
|
53
55
|
* and then the `defaultValue`.
|
|
54
56
|
*/
|
|
55
57
|
export function inheritable<K extends keyof Environment>(
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
58
|
+
diagnostics: Diagnostics,
|
|
59
|
+
topLevelEnv: Environment | undefined,
|
|
60
|
+
rawEnv: RawEnvironment,
|
|
61
|
+
field: K,
|
|
62
|
+
validate: ValidatorFn,
|
|
63
|
+
defaultValue: Environment[K],
|
|
64
|
+
transformFn: TransformFn<Environment[K]> = (v) => v
|
|
62
65
|
): Environment[K] {
|
|
63
|
-
|
|
64
|
-
|
|
66
|
+
validate(diagnostics, field, rawEnv[field], topLevelEnv);
|
|
67
|
+
return (
|
|
68
|
+
(rawEnv[field] as Environment[K]) ??
|
|
69
|
+
transformFn(topLevelEnv?.[field]) ??
|
|
70
|
+
defaultValue
|
|
71
|
+
);
|
|
65
72
|
}
|
|
66
73
|
|
|
67
74
|
/**
|
|
68
75
|
* Get an inheritable environment field, but only if we are in legacy environments
|
|
69
76
|
*/
|
|
70
77
|
export function inheritableInLegacyEnvironments<K extends keyof Environment>(
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
78
|
+
diagnostics: Diagnostics,
|
|
79
|
+
isLegacyEnv: boolean | undefined,
|
|
80
|
+
topLevelEnv: Environment | undefined,
|
|
81
|
+
rawEnv: RawEnvironment,
|
|
82
|
+
field: K,
|
|
83
|
+
validate: ValidatorFn,
|
|
84
|
+
transformFn: TransformFn<Environment[K]> = (v) => v,
|
|
85
|
+
defaultValue: Environment[K]
|
|
77
86
|
): Environment[K] {
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
87
|
+
return topLevelEnv === undefined || isLegacyEnv === true
|
|
88
|
+
? inheritable(
|
|
89
|
+
diagnostics,
|
|
90
|
+
topLevelEnv,
|
|
91
|
+
rawEnv,
|
|
92
|
+
field,
|
|
93
|
+
validate,
|
|
94
|
+
defaultValue,
|
|
95
|
+
transformFn
|
|
96
|
+
)
|
|
97
|
+
: notAllowedInNamedServiceEnvironment(
|
|
98
|
+
diagnostics,
|
|
99
|
+
topLevelEnv,
|
|
100
|
+
rawEnv,
|
|
101
|
+
field
|
|
102
|
+
);
|
|
81
103
|
}
|
|
82
104
|
|
|
105
|
+
/**
|
|
106
|
+
* Type of function that is used to transform an inheritable environment field.
|
|
107
|
+
*/
|
|
108
|
+
type TransformFn<T> = (fieldValue: T | undefined) => T | undefined;
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Transform an environment field by appending current environment name to it.
|
|
112
|
+
*/
|
|
113
|
+
export const appendEnvName =
|
|
114
|
+
(envName: string): TransformFn<string | undefined> =>
|
|
115
|
+
(fieldValue) =>
|
|
116
|
+
fieldValue ? `${fieldValue}-${envName}` : undefined;
|
|
117
|
+
|
|
83
118
|
/**
|
|
84
119
|
* Log an error if this named environment is trying to override the value in the top-level
|
|
85
120
|
* environment, which is not allow for this field.
|
|
86
121
|
*/
|
|
87
122
|
function notAllowedInNamedServiceEnvironment<K extends keyof Environment>(
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
123
|
+
diagnostics: Diagnostics,
|
|
124
|
+
topLevelEnv: Environment,
|
|
125
|
+
rawEnv: RawEnvironment,
|
|
126
|
+
field: K
|
|
92
127
|
): Environment[K] {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
128
|
+
if (field in rawEnv) {
|
|
129
|
+
diagnostics.errors.push(
|
|
130
|
+
`The "${field}" field is not allowed in named service environments.\n` +
|
|
131
|
+
`Please remove the field from this environment.`
|
|
132
|
+
);
|
|
133
|
+
}
|
|
134
|
+
return topLevelEnv[field];
|
|
100
135
|
}
|
|
101
136
|
|
|
102
137
|
/**
|
|
@@ -106,39 +141,39 @@ function notAllowedInNamedServiceEnvironment<K extends keyof Environment>(
|
|
|
106
141
|
* then log a warning and return the `defaultValue`.
|
|
107
142
|
*/
|
|
108
143
|
export function notInheritable<K extends keyof Environment>(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
144
|
+
diagnostics: Diagnostics,
|
|
145
|
+
topLevelEnv: Environment | undefined,
|
|
146
|
+
rawConfig: RawConfig | undefined,
|
|
147
|
+
rawEnv: RawEnvironment,
|
|
148
|
+
envName: string,
|
|
149
|
+
field: K,
|
|
150
|
+
validate: ValidatorFn,
|
|
151
|
+
defaultValue: Environment[K]
|
|
117
152
|
): Environment[K] {
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
153
|
+
if (rawEnv[field] !== undefined) {
|
|
154
|
+
validate(diagnostics, field, rawEnv[field], topLevelEnv);
|
|
155
|
+
} else {
|
|
156
|
+
if (rawConfig?.[field] !== undefined) {
|
|
157
|
+
diagnostics.warnings.push(
|
|
158
|
+
`"${field}" exists at the top level, but not on "env.${envName}".\n` +
|
|
159
|
+
`This is not what you probably want, since "${field}" is not inherited by environments.\n` +
|
|
160
|
+
`Please add "${field}" to "env.${envName}".`
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return (rawEnv[field] as Environment[K]) ?? defaultValue;
|
|
130
165
|
}
|
|
131
166
|
|
|
132
167
|
// Idea taken from https://stackoverflow.com/a/66661477
|
|
133
168
|
type DeepKeyOf<T> = (
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
169
|
+
T extends object
|
|
170
|
+
? {
|
|
171
|
+
[K in Exclude<keyof T, symbol>]: `${K}${DotPrefix<DeepKeyOf<T[K]>>}`;
|
|
172
|
+
}[Exclude<keyof T, symbol>]
|
|
173
|
+
: ""
|
|
139
174
|
) extends infer D
|
|
140
|
-
|
|
141
|
-
|
|
175
|
+
? Extract<D, string>
|
|
176
|
+
: never;
|
|
142
177
|
|
|
143
178
|
type DotPrefix<T extends string> = T extends "" ? "" : `.${T}`;
|
|
144
179
|
|
|
@@ -153,117 +188,145 @@ type DotPrefix<T extends string> = T extends "" ? "" : `.${T}`;
|
|
|
153
188
|
* ```
|
|
154
189
|
*/
|
|
155
190
|
function unwindPropertyPath<T extends object>(
|
|
156
|
-
|
|
157
|
-
|
|
191
|
+
root: T,
|
|
192
|
+
path: DeepKeyOf<T>
|
|
158
193
|
): { container: object; field: string } | undefined {
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
194
|
+
let container: object = root;
|
|
195
|
+
const parts = (path as string).split(".");
|
|
196
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
197
|
+
if (!hasProperty(container, parts[i])) {
|
|
198
|
+
return;
|
|
199
|
+
}
|
|
200
|
+
container = container[parts[i]];
|
|
201
|
+
}
|
|
202
|
+
return { container, field: parts[parts.length - 1] };
|
|
168
203
|
}
|
|
169
204
|
|
|
170
205
|
/**
|
|
171
206
|
* The type of a function that can be used to validate a configuration field.
|
|
172
207
|
*/
|
|
173
208
|
export type ValidatorFn = (
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
209
|
+
diagnostics: Diagnostics,
|
|
210
|
+
field: string,
|
|
211
|
+
value: unknown,
|
|
212
|
+
topLevelEnv: Environment | undefined
|
|
178
213
|
) => boolean;
|
|
179
214
|
|
|
180
215
|
/**
|
|
181
216
|
* Validate that the field is a string.
|
|
182
217
|
*/
|
|
183
218
|
export const isString: ValidatorFn = (diagnostics, field, value) => {
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
219
|
+
if (value !== undefined && typeof value !== "string") {
|
|
220
|
+
diagnostics.errors.push(
|
|
221
|
+
`Expected "${field}" to be of type string but got ${JSON.stringify(
|
|
222
|
+
value
|
|
223
|
+
)}.`
|
|
224
|
+
);
|
|
225
|
+
return false;
|
|
226
|
+
}
|
|
227
|
+
return true;
|
|
228
|
+
};
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* Validate that the `name` field is compliant with EWC constraints.
|
|
232
|
+
*/
|
|
233
|
+
export const isValidName: ValidatorFn = (diagnostics, field, value) => {
|
|
234
|
+
if (
|
|
235
|
+
(typeof value === "string" && /^$|^[a-z0-9_ ][a-z0-9-_ ]*$/.test(value)) ||
|
|
236
|
+
value === undefined
|
|
237
|
+
) {
|
|
238
|
+
return true;
|
|
239
|
+
} else {
|
|
240
|
+
diagnostics.errors.push(
|
|
241
|
+
`Expected "${field}" to be of type string, alphanumeric and lowercase with dashes only but got ${JSON.stringify(
|
|
242
|
+
value
|
|
243
|
+
)}.`
|
|
244
|
+
);
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
193
247
|
};
|
|
194
248
|
|
|
195
249
|
/**
|
|
196
250
|
* Validate that the field is an array of strings.
|
|
197
251
|
*/
|
|
198
252
|
export const isStringArray: ValidatorFn = (diagnostics, field, value) => {
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
253
|
+
if (
|
|
254
|
+
value !== undefined &&
|
|
255
|
+
(!Array.isArray(value) || value.some((item) => typeof item !== "string"))
|
|
256
|
+
) {
|
|
257
|
+
diagnostics.errors.push(
|
|
258
|
+
`Expected "${field}" to be of type string array but got ${JSON.stringify(
|
|
259
|
+
value
|
|
260
|
+
)}.`
|
|
261
|
+
);
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
return true;
|
|
211
265
|
};
|
|
212
266
|
|
|
213
267
|
/**
|
|
214
268
|
* Validate that the field is an object containing the given properties.
|
|
215
269
|
*/
|
|
216
270
|
export const isObjectWith =
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
271
|
+
(...properties: string[]): ValidatorFn =>
|
|
272
|
+
(diagnostics, field, value) => {
|
|
273
|
+
if (
|
|
274
|
+
value !== undefined &&
|
|
275
|
+
(typeof value !== "object" ||
|
|
276
|
+
value === null ||
|
|
277
|
+
!properties.every((prop) => prop in value))
|
|
278
|
+
) {
|
|
279
|
+
diagnostics.errors.push(
|
|
280
|
+
`Expected "${field}" to be of type object, containing only properties ${properties}, but got ${JSON.stringify(
|
|
281
|
+
value
|
|
282
|
+
)}.`
|
|
283
|
+
);
|
|
284
|
+
return false;
|
|
285
|
+
}
|
|
286
|
+
// it's an object with the field as desired,
|
|
287
|
+
// but let's also check for unexpected fields
|
|
288
|
+
if (value !== undefined) {
|
|
289
|
+
const restFields = Object.keys(value).filter(
|
|
290
|
+
(key) => !properties.includes(key)
|
|
291
|
+
);
|
|
292
|
+
validateAdditionalProperties(diagnostics, field, restFields, []);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
return true;
|
|
296
|
+
};
|
|
234
297
|
|
|
235
298
|
/**
|
|
236
299
|
* Validate that the field value is one of the given choices.
|
|
237
300
|
*/
|
|
238
301
|
export const isOneOf =
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
302
|
+
(...choices: unknown[]): ValidatorFn =>
|
|
303
|
+
(diagnostics, field, value) => {
|
|
304
|
+
if (value !== undefined && !choices.some((choice) => value === choice)) {
|
|
305
|
+
diagnostics.errors.push(
|
|
306
|
+
`Expected "${field}" field to be one of ${JSON.stringify(
|
|
307
|
+
choices
|
|
308
|
+
)} but got ${JSON.stringify(value)}.`
|
|
309
|
+
);
|
|
310
|
+
return false;
|
|
311
|
+
}
|
|
312
|
+
return true;
|
|
313
|
+
};
|
|
251
314
|
|
|
252
315
|
/**
|
|
253
316
|
* Aggregate multiple validator functions
|
|
254
317
|
*/
|
|
255
318
|
export const all = (...validations: ValidatorFn[]): ValidatorFn => {
|
|
256
|
-
|
|
257
|
-
|
|
319
|
+
return (diagnostics, field, value, config) => {
|
|
320
|
+
let passedValidations = true;
|
|
258
321
|
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
322
|
+
for (const validate of validations) {
|
|
323
|
+
if (!validate(diagnostics, field, value, config)) {
|
|
324
|
+
passedValidations = false;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
264
327
|
|
|
265
|
-
|
|
266
|
-
|
|
328
|
+
return passedValidations;
|
|
329
|
+
};
|
|
267
330
|
};
|
|
268
331
|
|
|
269
332
|
/**
|
|
@@ -273,196 +336,262 @@ export const all = (...validations: ValidatorFn[]): ValidatorFn => {
|
|
|
273
336
|
* @param fields the names of the fields to check against.
|
|
274
337
|
*/
|
|
275
338
|
export const isMutuallyExclusiveWith = <T extends RawEnvironment | RawConfig>(
|
|
276
|
-
|
|
277
|
-
|
|
339
|
+
container: T,
|
|
340
|
+
...fields: (keyof T)[]
|
|
278
341
|
): ValidatorFn => {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
342
|
+
return (diagnostics, field, value) => {
|
|
343
|
+
if (value === undefined) {
|
|
344
|
+
return true;
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
for (const exclusiveWith of fields) {
|
|
348
|
+
if (container[exclusiveWith] !== undefined) {
|
|
349
|
+
diagnostics.errors.push(
|
|
350
|
+
`Expected exactly one of the following fields ${JSON.stringify([
|
|
351
|
+
field,
|
|
352
|
+
...fields,
|
|
353
|
+
])}.`
|
|
354
|
+
);
|
|
355
|
+
return false;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
return true;
|
|
360
|
+
};
|
|
295
361
|
};
|
|
296
362
|
|
|
297
363
|
/**
|
|
298
364
|
* Validate that the field is a boolean.
|
|
299
365
|
*/
|
|
300
366
|
export const isBoolean: ValidatorFn = (diagnostics, field, value) => {
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
367
|
+
if (value !== undefined && typeof value !== "boolean") {
|
|
368
|
+
diagnostics.errors.push(
|
|
369
|
+
`Expected "${field}" to be of type boolean but got ${JSON.stringify(
|
|
370
|
+
value
|
|
371
|
+
)}.`
|
|
372
|
+
);
|
|
373
|
+
return false;
|
|
374
|
+
}
|
|
375
|
+
return true;
|
|
310
376
|
};
|
|
311
377
|
|
|
312
378
|
/**
|
|
313
379
|
* Validate that the required field exists and has the expected type.
|
|
314
380
|
*/
|
|
315
381
|
export const validateRequiredProperty = (
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
382
|
+
diagnostics: Diagnostics,
|
|
383
|
+
container: string,
|
|
384
|
+
key: string,
|
|
385
|
+
value: unknown,
|
|
386
|
+
type: TypeofType,
|
|
387
|
+
choices?: unknown[]
|
|
322
388
|
): boolean => {
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
389
|
+
if (container) {
|
|
390
|
+
container += ".";
|
|
391
|
+
}
|
|
392
|
+
if (value === undefined) {
|
|
393
|
+
diagnostics.errors.push(`"${container}${key}" is a required field.`);
|
|
394
|
+
return false;
|
|
395
|
+
} else if (typeof value !== type) {
|
|
396
|
+
diagnostics.errors.push(
|
|
397
|
+
`Expected "${container}${key}" to be of type ${type} but got ${JSON.stringify(
|
|
398
|
+
value
|
|
399
|
+
)}.`
|
|
400
|
+
);
|
|
401
|
+
return false;
|
|
402
|
+
} else if (choices) {
|
|
403
|
+
if (
|
|
404
|
+
!isOneOf(...choices)(diagnostics, `${container}${key}`, value, undefined)
|
|
405
|
+
) {
|
|
406
|
+
return false;
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
return true;
|
|
344
410
|
};
|
|
345
411
|
|
|
346
412
|
/**
|
|
347
413
|
* Validate that, if the optional field exists, then it has the expected type.
|
|
348
414
|
*/
|
|
349
415
|
export const validateOptionalProperty = (
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
416
|
+
diagnostics: Diagnostics,
|
|
417
|
+
container: string,
|
|
418
|
+
key: string,
|
|
419
|
+
value: unknown,
|
|
420
|
+
type: TypeofType,
|
|
421
|
+
choices?: unknown[]
|
|
356
422
|
): boolean => {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
423
|
+
if (value !== undefined) {
|
|
424
|
+
return validateRequiredProperty(
|
|
425
|
+
diagnostics,
|
|
426
|
+
container,
|
|
427
|
+
key,
|
|
428
|
+
value,
|
|
429
|
+
type,
|
|
430
|
+
choices
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
return true;
|
|
368
434
|
};
|
|
369
435
|
|
|
370
436
|
/**
|
|
371
437
|
* Validate that the field is an array of elements of the given type.
|
|
372
438
|
*/
|
|
373
439
|
export const validateTypedArray = (
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
440
|
+
diagnostics: Diagnostics,
|
|
441
|
+
container: string,
|
|
442
|
+
value: unknown,
|
|
443
|
+
type: TypeofType
|
|
378
444
|
): boolean => {
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
445
|
+
let isValid = true;
|
|
446
|
+
if (!Array.isArray(value)) {
|
|
447
|
+
diagnostics.errors.push(
|
|
448
|
+
`Expected "${container}" to be an array of ${type}s but got ${JSON.stringify(
|
|
449
|
+
value
|
|
450
|
+
)}`
|
|
451
|
+
);
|
|
452
|
+
isValid = false;
|
|
453
|
+
} else {
|
|
454
|
+
for (let i = 0; i < value.length; i++) {
|
|
455
|
+
isValid =
|
|
456
|
+
validateRequiredProperty(
|
|
457
|
+
diagnostics,
|
|
458
|
+
container,
|
|
459
|
+
`[${i}]`,
|
|
460
|
+
value[i],
|
|
461
|
+
type
|
|
462
|
+
) && isValid;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
return isValid;
|
|
400
466
|
};
|
|
401
467
|
|
|
402
468
|
/**
|
|
403
469
|
* Validate that, if the optional field exists, it is an array of elements of the given type.
|
|
404
470
|
*/
|
|
405
471
|
export const validateOptionalTypedArray = (
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
472
|
+
diagnostics: Diagnostics,
|
|
473
|
+
container: string,
|
|
474
|
+
value: unknown,
|
|
475
|
+
type: TypeofType
|
|
410
476
|
) => {
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
477
|
+
if (value !== undefined) {
|
|
478
|
+
return validateTypedArray(diagnostics, container, value, type);
|
|
479
|
+
}
|
|
480
|
+
return true;
|
|
415
481
|
};
|
|
416
482
|
|
|
417
483
|
/**
|
|
418
484
|
* Test to see if `obj` has the required property `prop` of type `type`.
|
|
419
485
|
*/
|
|
420
486
|
export const isRequiredProperty = <T extends object>(
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
487
|
+
obj: object,
|
|
488
|
+
prop: keyof T,
|
|
489
|
+
type: TypeofType,
|
|
490
|
+
choices?: unknown[]
|
|
425
491
|
): obj is T =>
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
492
|
+
hasProperty<T>(obj, prop) &&
|
|
493
|
+
typeof obj[prop] === type &&
|
|
494
|
+
(choices === undefined || choices.includes(obj[prop]));
|
|
429
495
|
|
|
430
496
|
/**
|
|
431
497
|
* Test to see if `obj` has the optional property `prop` of type `type`.
|
|
432
498
|
*/
|
|
433
499
|
export const isOptionalProperty = <T extends object>(
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
500
|
+
obj: object,
|
|
501
|
+
prop: keyof T,
|
|
502
|
+
type: TypeofType
|
|
437
503
|
): obj is T => !hasProperty<T>(obj, prop) || typeof obj[prop] === type;
|
|
438
504
|
|
|
439
505
|
/**
|
|
440
506
|
* Test to see if `obj` has the property `prop`.
|
|
441
507
|
*/
|
|
442
508
|
export const hasProperty = <T extends object>(
|
|
443
|
-
|
|
444
|
-
|
|
509
|
+
obj: object,
|
|
510
|
+
property: keyof T
|
|
445
511
|
): obj is T => property in obj;
|
|
446
512
|
|
|
447
513
|
/**
|
|
448
514
|
* Add warning messages about any properties in the given field that are not expected to be there.
|
|
449
515
|
*/
|
|
450
516
|
export const validateAdditionalProperties = (
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
517
|
+
diagnostics: Diagnostics,
|
|
518
|
+
fieldPath: string,
|
|
519
|
+
restProps: Iterable<string>,
|
|
520
|
+
knownProps: Iterable<string>
|
|
455
521
|
): boolean => {
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
522
|
+
const restPropSet = new Set(restProps);
|
|
523
|
+
for (const knownProp of knownProps) {
|
|
524
|
+
restPropSet.delete(knownProp);
|
|
525
|
+
}
|
|
526
|
+
if (restPropSet.size > 0) {
|
|
527
|
+
const fields = Array.from(restPropSet.keys()).map((field) => `"${field}"`);
|
|
528
|
+
diagnostics.warnings.push(
|
|
529
|
+
`Unexpected fields found in ${fieldPath} field: ${fields}`
|
|
530
|
+
);
|
|
531
|
+
return false;
|
|
532
|
+
}
|
|
533
|
+
return true;
|
|
468
534
|
};
|
|
535
|
+
|
|
536
|
+
/**
|
|
537
|
+
* Get the names of the bindings collection in `value`.
|
|
538
|
+
*
|
|
539
|
+
* Will return an empty array if it doesn't understand the value
|
|
540
|
+
* passed in, so another form of validation should be
|
|
541
|
+
* performed externally.
|
|
542
|
+
*/
|
|
543
|
+
export const getBindingNames = (value: unknown): string[] => {
|
|
544
|
+
if (typeof value !== "object" || value === null) {
|
|
545
|
+
return [];
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
if (isBindingList(value)) {
|
|
549
|
+
return value.bindings.map(({ name }) => name);
|
|
550
|
+
} else if (isNamespaceList(value)) {
|
|
551
|
+
return value.map(({ binding }) => binding);
|
|
552
|
+
} else if (isRecord(value)) {
|
|
553
|
+
return Object.keys(value).filter((k) => value[k] !== undefined);
|
|
554
|
+
} else {
|
|
555
|
+
return [];
|
|
556
|
+
}
|
|
557
|
+
};
|
|
558
|
+
|
|
559
|
+
const isBindingList = (
|
|
560
|
+
value: unknown
|
|
561
|
+
): value is {
|
|
562
|
+
bindings: {
|
|
563
|
+
name: string;
|
|
564
|
+
}[];
|
|
565
|
+
} =>
|
|
566
|
+
isRecord(value) &&
|
|
567
|
+
"bindings" in value &&
|
|
568
|
+
Array.isArray(value.bindings) &&
|
|
569
|
+
value.bindings.every(
|
|
570
|
+
(binding) =>
|
|
571
|
+
isRecord(binding) && "name" in binding && typeof binding.name === "string"
|
|
572
|
+
);
|
|
573
|
+
|
|
574
|
+
const isNamespaceList = (value: unknown): value is { binding: string }[] =>
|
|
575
|
+
Array.isArray(value) &&
|
|
576
|
+
value.every(
|
|
577
|
+
(entry) =>
|
|
578
|
+
isRecord(entry) && "binding" in entry && typeof entry.binding === "string"
|
|
579
|
+
);
|
|
580
|
+
|
|
581
|
+
const isRecord = (
|
|
582
|
+
value: unknown
|
|
583
|
+
): value is Record<string | number | symbol, unknown> =>
|
|
584
|
+
typeof value === "object" && value !== null && !Array.isArray(value);
|
|
585
|
+
|
|
586
|
+
/**
|
|
587
|
+
* JavaScript `typeof` operator return values.
|
|
588
|
+
*/
|
|
589
|
+
type TypeofType =
|
|
590
|
+
| "string"
|
|
591
|
+
| "number"
|
|
592
|
+
| "bigint"
|
|
593
|
+
| "boolean"
|
|
594
|
+
| "symbol"
|
|
595
|
+
| "undefined"
|
|
596
|
+
| "object"
|
|
597
|
+
| "function";
|