wrangler 0.0.0-e3e3243 → 0.0.0-e4047cab
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 +166 -31
- package/kv-asset-handler.js +1 -0
- package/miniflare-dist/index.mjs +6263 -21
- package/package.json +191 -141
- package/src/__tests__/access.test.ts +25 -0
- package/src/__tests__/api-dev.test.ts +209 -0
- package/src/__tests__/api-devregistry.test.js +56 -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 +3971 -2810
- package/src/__tests__/d1.test.ts +80 -0
- package/src/__tests__/delete.test.ts +263 -0
- package/src/__tests__/deployments.test.ts +91 -0
- package/src/__tests__/dev.test.tsx +1521 -526
- package/src/__tests__/dialogs.test.tsx +40 -0
- package/src/__tests__/generate.test.ts +235 -0
- package/src/__tests__/get-host-from-url.test.ts +16 -0
- package/src/__tests__/guess-worker-format.test.ts +74 -57
- package/src/__tests__/helpers/cmd-shim.d.ts +6 -6
- package/src/__tests__/helpers/mock-account-id.ts +24 -24
- package/src/__tests__/helpers/mock-bin.ts +20 -20
- package/src/__tests__/helpers/mock-cfetch.ts +219 -93
- package/src/__tests__/helpers/mock-console.ts +68 -32
- package/src/__tests__/helpers/mock-dialogs.ts +121 -33
- package/src/__tests__/helpers/mock-get-zone-from-host.ts +8 -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 +7 -0
- package/src/__tests__/helpers/mock-kv.ts +27 -27
- package/src/__tests__/helpers/mock-oauth-flow.ts +256 -0
- package/src/__tests__/helpers/mock-process.ts +39 -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/handlers/access.ts +13 -0
- package/src/__tests__/helpers/msw/handlers/deployments.ts +59 -0
- package/src/__tests__/helpers/msw/handlers/namespaces.ts +104 -0
- package/src/__tests__/helpers/msw/handlers/oauth.ts +31 -0
- package/src/__tests__/helpers/msw/handlers/r2.ts +80 -0
- package/src/__tests__/helpers/msw/handlers/script.ts +75 -0
- package/src/__tests__/helpers/msw/handlers/user.ts +63 -0
- package/src/__tests__/helpers/msw/handlers/zones.ts +22 -0
- package/src/__tests__/helpers/msw/index.ts +21 -0
- package/src/__tests__/helpers/run-in-tmp.ts +28 -22
- package/src/__tests__/helpers/run-wrangler.ts +8 -8
- 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 +248 -967
- package/src/__tests__/init.test.ts +2900 -0
- package/src/__tests__/jest.setup.ts +167 -34
- package/src/__tests__/kv.test.ts +1661 -1366
- package/src/__tests__/logger.test.ts +141 -0
- package/src/__tests__/logout.test.ts +36 -41
- package/src/__tests__/metrics.test.ts +450 -0
- package/src/__tests__/middleware.scheduled.test.ts +135 -0
- package/src/__tests__/middleware.test.ts +726 -0
- package/src/__tests__/package-manager.test.ts +312 -165
- package/src/__tests__/pages-deployment-tail.test.ts +820 -0
- package/src/__tests__/pages.test.ts +2437 -77
- package/src/__tests__/parse.test.ts +253 -245
- package/src/__tests__/paths.test.ts +39 -0
- package/src/__tests__/publish.test.ts +7569 -3445
- package/src/__tests__/pubsub.test.ts +370 -0
- package/src/__tests__/queues.test.ts +522 -0
- package/src/__tests__/r2.test.ts +388 -193
- package/src/__tests__/route.test.ts +22 -22
- package/src/__tests__/secret.test.ts +626 -407
- package/src/__tests__/tail.test.ts +779 -442
- package/src/__tests__/test-old-node-version.js +31 -0
- package/src/__tests__/type-generation.test.ts +226 -0
- package/src/__tests__/user.test.ts +129 -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 +266 -88
- package/src/__tests__/worker-namespace.test.ts +326 -0
- package/src/abort.d.ts +3 -0
- package/src/api/dev.ts +210 -0
- package/src/api/index.ts +2 -0
- package/src/bundle-reporter.tsx +68 -0
- package/src/bundle.ts +791 -123
- package/src/cfetch/index.ts +123 -67
- package/src/cfetch/internal.ts +216 -92
- package/src/cli.ts +23 -14
- package/src/config/README.md +1 -1
- package/src/config/config.ts +236 -179
- package/src/config/diagnostics.ts +61 -61
- package/src/config/environment.ts +506 -316
- package/src/config/index.ts +310 -38
- package/src/config/validation-helpers.ts +385 -342
- package/src/config/validation.ts +1970 -1099
- package/src/config-cache.ts +85 -0
- package/src/create-worker-preview.ts +240 -124
- package/src/create-worker-upload-form.ts +300 -201
- package/src/d1/backups.tsx +223 -0
- package/src/d1/constants.ts +2 -0
- package/src/d1/create.tsx +63 -0
- package/src/d1/delete.tsx +56 -0
- package/src/d1/execute.tsx +352 -0
- package/src/d1/formatTimeAgo.ts +14 -0
- package/src/d1/index.ts +101 -0
- package/src/d1/list.tsx +48 -0
- package/src/d1/migrations/apply.tsx +184 -0
- package/src/d1/migrations/create.tsx +77 -0
- package/src/d1/migrations/helpers.ts +147 -0
- package/src/d1/migrations/index.tsx +3 -0
- package/src/d1/migrations/list.tsx +79 -0
- package/src/d1/migrations/options.ts +18 -0
- package/src/d1/options.ts +22 -0
- package/src/d1/types.tsx +24 -0
- package/src/d1/utils.ts +48 -0
- package/src/delete.ts +108 -0
- package/src/deployments.ts +77 -0
- package/src/deprecated/index.ts +438 -0
- package/src/dev/dev-vars.ts +39 -0
- package/src/dev/dev.tsx +550 -328
- package/src/dev/get-local-persistence-path.tsx +31 -0
- package/src/dev/local.tsx +871 -213
- package/src/dev/remote.tsx +592 -192
- package/src/dev/start-server.ts +539 -0
- package/src/dev/use-esbuild.ts +184 -84
- package/src/dev/validate-dev-props.ts +31 -0
- package/src/dev-registry.tsx +201 -0
- package/src/dev.tsx +904 -0
- package/src/dialogs.tsx +150 -59
- package/src/dispatch-namespace.ts +207 -0
- package/src/durable.ts +102 -0
- package/src/entry.ts +260 -171
- package/src/environment-variables.ts +40 -23
- package/src/errors.ts +11 -0
- package/src/git-client.ts +124 -0
- package/src/global-wrangler-config-path.ts +26 -0
- package/src/https-options.ts +85 -80
- package/src/index.tsx +639 -2341
- package/src/init.ts +970 -0
- package/src/inspect.ts +707 -557
- package/src/intl-polyfill.d.ts +123 -123
- package/src/is-ci.ts +14 -0
- package/src/is-interactive.ts +16 -0
- package/src/kv/helpers.ts +430 -0
- package/src/kv/index.ts +596 -0
- package/src/logger.ts +92 -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 +96 -0
- package/src/miniflare-cli/assets.ts +220 -0
- package/src/miniflare-cli/index.ts +206 -30
- package/src/miniflare-cli/request-context.ts +40 -0
- package/src/module-collection.ts +222 -213
- package/src/open-in-browser.ts +8 -16
- package/src/package-manager.ts +183 -90
- package/src/pages/build.tsx +270 -0
- package/src/pages/constants.ts +18 -0
- package/src/pages/deployment-tails.tsx +284 -0
- package/src/pages/deployments.tsx +84 -0
- package/src/pages/dev.tsx +706 -0
- package/src/pages/errors.ts +66 -0
- package/src/pages/functions/buildPlugin.ts +107 -0
- package/src/pages/functions/buildWorker.ts +166 -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.tsx +82 -0
- package/src/pages/hash.tsx +13 -0
- package/src/pages/index.tsx +102 -0
- package/src/pages/projects.tsx +169 -0
- package/src/pages/prompt-select-project.tsx +31 -0
- package/src/pages/publish.tsx +451 -0
- package/src/pages/types.ts +41 -0
- package/src/pages/upload.tsx +426 -0
- package/src/pages/utils.ts +23 -0
- package/src/parse.ts +224 -121
- package/src/paths.ts +53 -8
- package/src/proxy.ts +629 -375
- package/src/publish/index.ts +270 -0
- package/src/publish/publish.ts +1035 -0
- package/src/pubsub/index.ts +286 -0
- package/src/pubsub/pubsub-commands.tsx +624 -0
- package/src/queues/cli/commands/consumer/add.ts +71 -0
- package/src/queues/cli/commands/consumer/index.ts +22 -0
- package/src/queues/cli/commands/consumer/remove.ts +38 -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 +36 -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 +131 -0
- package/src/r2/index.ts +289 -0
- package/src/routes.ts +140 -0
- package/src/secret/index.ts +378 -0
- package/src/selfsigned.d.ts +23 -23
- package/src/sites.tsx +283 -191
- package/src/tail/createTail.ts +379 -0
- package/src/tail/filters.ts +108 -110
- package/src/tail/index.ts +211 -296
- package/src/tail/printing.ts +92 -47
- package/src/type-generation.ts +173 -0
- package/src/update-check.ts +19 -0
- package/src/user/access.ts +69 -0
- package/src/user/choose-account.tsx +69 -0
- package/src/user/env-vars.ts +46 -0
- package/src/user/generate-auth-url.ts +33 -0
- package/src/user/generate-random-state.ts +16 -0
- package/src/user/index.ts +3 -0
- package/src/user/user.tsx +1198 -0
- package/src/utils/collectKeyValues.ts +14 -0
- package/src/whoami.tsx +142 -42
- package/src/worker.ts +182 -100
- package/src/yargs-types.ts +24 -0
- package/src/zones.ts +191 -0
- package/templates/__tests__/pages-dev-util.test.ts +128 -0
- package/templates/checked-fetch.js +17 -0
- package/templates/d1-beta-facade.js +205 -0
- package/templates/first-party-worker-module-facade.ts +18 -0
- package/templates/format-dev-errors.ts +32 -0
- package/templates/gitignore +171 -0
- package/templates/init-tests/test-jest-new-worker.js +25 -0
- package/templates/init-tests/test-vitest-new-worker.js +26 -0
- package/templates/middleware/common.ts +62 -0
- package/templates/middleware/loader-modules.ts +84 -0
- package/templates/middleware/loader-sw.ts +227 -0
- package/templates/middleware/middleware-miniflare3-json-error.ts +20 -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 +18 -3
- package/templates/no-op-worker.js +10 -0
- package/templates/pages-dev-pipeline.ts +28 -0
- package/templates/pages-dev-util.ts +52 -0
- package/templates/pages-shim.ts +9 -0
- package/templates/pages-template-plugin.ts +171 -0
- package/templates/pages-template-worker.ts +189 -0
- package/templates/serve-static-assets.ts +63 -0
- package/templates/service-bindings-module-facade.js +54 -0
- package/templates/service-bindings-sw-facade.js +42 -0
- package/templates/tsconfig.json +96 -95
- package/wrangler-dist/cli.d.ts +893 -0
- package/wrangler-dist/cli.js +116816 -94969
- package/miniflare-dist/index.mjs.map +0 -7
- 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__/helpers/faye-websocket.d.ts +0 -6
- package/src/__tests__/sentry.test.ts +0 -146
- package/src/kv.ts +0 -319
- package/src/miniflare-cli/enum-keys.ts +0 -17
- package/src/pages.tsx +0 -1061
- package/src/publish.ts +0 -350
- package/src/r2.ts +0 -50
- package/src/reporting.ts +0 -131
- package/src/user.tsx +0 -1127
- 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
|
@@ -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,51 +55,51 @@ 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
|
-
|
|
62
|
-
|
|
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
|
|
63
65
|
): Environment[K] {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
66
|
+
validate(diagnostics, field, rawEnv[field], topLevelEnv);
|
|
67
|
+
return (
|
|
68
|
+
(rawEnv[field] as Environment[K]) ??
|
|
69
|
+
transformFn(topLevelEnv?.[field]) ??
|
|
70
|
+
defaultValue
|
|
71
|
+
);
|
|
70
72
|
}
|
|
71
73
|
|
|
72
74
|
/**
|
|
73
75
|
* Get an inheritable environment field, but only if we are in legacy environments
|
|
74
76
|
*/
|
|
75
77
|
export function inheritableInLegacyEnvironments<K extends keyof Environment>(
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
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]
|
|
84
86
|
): Environment[K] {
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
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
|
+
);
|
|
101
103
|
}
|
|
102
104
|
|
|
103
105
|
/**
|
|
@@ -109,27 +111,27 @@ type TransformFn<T> = (fieldValue: T | undefined) => T | undefined;
|
|
|
109
111
|
* Transform an environment field by appending current environment name to it.
|
|
110
112
|
*/
|
|
111
113
|
export const appendEnvName =
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
114
|
+
(envName: string): TransformFn<string | undefined> =>
|
|
115
|
+
(fieldValue) =>
|
|
116
|
+
fieldValue ? `${fieldValue}-${envName}` : undefined;
|
|
115
117
|
|
|
116
118
|
/**
|
|
117
119
|
* Log an error if this named environment is trying to override the value in the top-level
|
|
118
120
|
* environment, which is not allow for this field.
|
|
119
121
|
*/
|
|
120
122
|
function notAllowedInNamedServiceEnvironment<K extends keyof Environment>(
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
123
|
+
diagnostics: Diagnostics,
|
|
124
|
+
topLevelEnv: Environment,
|
|
125
|
+
rawEnv: RawEnvironment,
|
|
126
|
+
field: K
|
|
125
127
|
): Environment[K] {
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
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];
|
|
133
135
|
}
|
|
134
136
|
|
|
135
137
|
/**
|
|
@@ -139,39 +141,39 @@ function notAllowedInNamedServiceEnvironment<K extends keyof Environment>(
|
|
|
139
141
|
* then log a warning and return the `defaultValue`.
|
|
140
142
|
*/
|
|
141
143
|
export function notInheritable<K extends keyof Environment>(
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
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]
|
|
150
152
|
): Environment[K] {
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
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;
|
|
163
165
|
}
|
|
164
166
|
|
|
165
167
|
// Idea taken from https://stackoverflow.com/a/66661477
|
|
166
168
|
type DeepKeyOf<T> = (
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
169
|
+
T extends object
|
|
170
|
+
? {
|
|
171
|
+
[K in Exclude<keyof T, symbol>]: `${K}${DotPrefix<DeepKeyOf<T[K]>>}`;
|
|
172
|
+
}[Exclude<keyof T, symbol>]
|
|
173
|
+
: ""
|
|
172
174
|
) extends infer D
|
|
173
|
-
|
|
174
|
-
|
|
175
|
+
? Extract<D, string>
|
|
176
|
+
: never;
|
|
175
177
|
|
|
176
178
|
type DotPrefix<T extends string> = T extends "" ? "" : `.${T}`;
|
|
177
179
|
|
|
@@ -186,117 +188,145 @@ type DotPrefix<T extends string> = T extends "" ? "" : `.${T}`;
|
|
|
186
188
|
* ```
|
|
187
189
|
*/
|
|
188
190
|
function unwindPropertyPath<T extends object>(
|
|
189
|
-
|
|
190
|
-
|
|
191
|
+
root: T,
|
|
192
|
+
path: DeepKeyOf<T>
|
|
191
193
|
): { container: object; field: string } | undefined {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
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] };
|
|
201
203
|
}
|
|
202
204
|
|
|
203
205
|
/**
|
|
204
206
|
* The type of a function that can be used to validate a configuration field.
|
|
205
207
|
*/
|
|
206
208
|
export type ValidatorFn = (
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
209
|
+
diagnostics: Diagnostics,
|
|
210
|
+
field: string,
|
|
211
|
+
value: unknown,
|
|
212
|
+
topLevelEnv: Environment | undefined
|
|
211
213
|
) => boolean;
|
|
212
214
|
|
|
213
215
|
/**
|
|
214
216
|
* Validate that the field is a string.
|
|
215
217
|
*/
|
|
216
218
|
export const isString: ValidatorFn = (diagnostics, field, value) => {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
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
|
+
}
|
|
226
247
|
};
|
|
227
248
|
|
|
228
249
|
/**
|
|
229
250
|
* Validate that the field is an array of strings.
|
|
230
251
|
*/
|
|
231
252
|
export const isStringArray: ValidatorFn = (diagnostics, field, value) => {
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
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;
|
|
244
265
|
};
|
|
245
266
|
|
|
246
267
|
/**
|
|
247
268
|
* Validate that the field is an object containing the given properties.
|
|
248
269
|
*/
|
|
249
270
|
export const isObjectWith =
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
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
|
+
};
|
|
267
297
|
|
|
268
298
|
/**
|
|
269
299
|
* Validate that the field value is one of the given choices.
|
|
270
300
|
*/
|
|
271
301
|
export const isOneOf =
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
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
|
+
};
|
|
284
314
|
|
|
285
315
|
/**
|
|
286
316
|
* Aggregate multiple validator functions
|
|
287
317
|
*/
|
|
288
318
|
export const all = (...validations: ValidatorFn[]): ValidatorFn => {
|
|
289
|
-
|
|
290
|
-
|
|
319
|
+
return (diagnostics, field, value, config) => {
|
|
320
|
+
let passedValidations = true;
|
|
291
321
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
322
|
+
for (const validate of validations) {
|
|
323
|
+
if (!validate(diagnostics, field, value, config)) {
|
|
324
|
+
passedValidations = false;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
297
327
|
|
|
298
|
-
|
|
299
|
-
|
|
328
|
+
return passedValidations;
|
|
329
|
+
};
|
|
300
330
|
};
|
|
301
331
|
|
|
302
332
|
/**
|
|
@@ -306,201 +336,201 @@ export const all = (...validations: ValidatorFn[]): ValidatorFn => {
|
|
|
306
336
|
* @param fields the names of the fields to check against.
|
|
307
337
|
*/
|
|
308
338
|
export const isMutuallyExclusiveWith = <T extends RawEnvironment | RawConfig>(
|
|
309
|
-
|
|
310
|
-
|
|
339
|
+
container: T,
|
|
340
|
+
...fields: (keyof T)[]
|
|
311
341
|
): ValidatorFn => {
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
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
|
+
};
|
|
331
361
|
};
|
|
332
362
|
|
|
333
363
|
/**
|
|
334
364
|
* Validate that the field is a boolean.
|
|
335
365
|
*/
|
|
336
366
|
export const isBoolean: ValidatorFn = (diagnostics, field, value) => {
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
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;
|
|
346
376
|
};
|
|
347
377
|
|
|
348
378
|
/**
|
|
349
379
|
* Validate that the required field exists and has the expected type.
|
|
350
380
|
*/
|
|
351
381
|
export const validateRequiredProperty = (
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
382
|
+
diagnostics: Diagnostics,
|
|
383
|
+
container: string,
|
|
384
|
+
key: string,
|
|
385
|
+
value: unknown,
|
|
386
|
+
type: TypeofType,
|
|
387
|
+
choices?: unknown[]
|
|
358
388
|
): boolean => {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
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;
|
|
380
410
|
};
|
|
381
411
|
|
|
382
412
|
/**
|
|
383
413
|
* Validate that, if the optional field exists, then it has the expected type.
|
|
384
414
|
*/
|
|
385
415
|
export const validateOptionalProperty = (
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
416
|
+
diagnostics: Diagnostics,
|
|
417
|
+
container: string,
|
|
418
|
+
key: string,
|
|
419
|
+
value: unknown,
|
|
420
|
+
type: TypeofType,
|
|
421
|
+
choices?: unknown[]
|
|
392
422
|
): boolean => {
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
423
|
+
if (value !== undefined) {
|
|
424
|
+
return validateRequiredProperty(
|
|
425
|
+
diagnostics,
|
|
426
|
+
container,
|
|
427
|
+
key,
|
|
428
|
+
value,
|
|
429
|
+
type,
|
|
430
|
+
choices
|
|
431
|
+
);
|
|
432
|
+
}
|
|
433
|
+
return true;
|
|
404
434
|
};
|
|
405
435
|
|
|
406
436
|
/**
|
|
407
437
|
* Validate that the field is an array of elements of the given type.
|
|
408
438
|
*/
|
|
409
439
|
export const validateTypedArray = (
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
440
|
+
diagnostics: Diagnostics,
|
|
441
|
+
container: string,
|
|
442
|
+
value: unknown,
|
|
443
|
+
type: TypeofType
|
|
414
444
|
): boolean => {
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
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;
|
|
436
466
|
};
|
|
437
467
|
|
|
438
468
|
/**
|
|
439
469
|
* Validate that, if the optional field exists, it is an array of elements of the given type.
|
|
440
470
|
*/
|
|
441
471
|
export const validateOptionalTypedArray = (
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
472
|
+
diagnostics: Diagnostics,
|
|
473
|
+
container: string,
|
|
474
|
+
value: unknown,
|
|
475
|
+
type: TypeofType
|
|
446
476
|
) => {
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
477
|
+
if (value !== undefined) {
|
|
478
|
+
return validateTypedArray(diagnostics, container, value, type);
|
|
479
|
+
}
|
|
480
|
+
return true;
|
|
451
481
|
};
|
|
452
482
|
|
|
453
483
|
/**
|
|
454
484
|
* Test to see if `obj` has the required property `prop` of type `type`.
|
|
455
485
|
*/
|
|
456
486
|
export const isRequiredProperty = <T extends object>(
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
487
|
+
obj: object,
|
|
488
|
+
prop: keyof T,
|
|
489
|
+
type: TypeofType,
|
|
490
|
+
choices?: unknown[]
|
|
461
491
|
): obj is T =>
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
492
|
+
hasProperty<T>(obj, prop) &&
|
|
493
|
+
typeof obj[prop] === type &&
|
|
494
|
+
(choices === undefined || choices.includes(obj[prop]));
|
|
465
495
|
|
|
466
496
|
/**
|
|
467
497
|
* Test to see if `obj` has the optional property `prop` of type `type`.
|
|
468
498
|
*/
|
|
469
499
|
export const isOptionalProperty = <T extends object>(
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
500
|
+
obj: object,
|
|
501
|
+
prop: keyof T,
|
|
502
|
+
type: TypeofType
|
|
473
503
|
): obj is T => !hasProperty<T>(obj, prop) || typeof obj[prop] === type;
|
|
474
504
|
|
|
475
505
|
/**
|
|
476
506
|
* Test to see if `obj` has the property `prop`.
|
|
477
507
|
*/
|
|
478
508
|
export const hasProperty = <T extends object>(
|
|
479
|
-
|
|
480
|
-
|
|
509
|
+
obj: object,
|
|
510
|
+
property: keyof T
|
|
481
511
|
): obj is T => property in obj;
|
|
482
512
|
|
|
483
513
|
/**
|
|
484
514
|
* Add warning messages about any properties in the given field that are not expected to be there.
|
|
485
515
|
*/
|
|
486
516
|
export const validateAdditionalProperties = (
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
517
|
+
diagnostics: Diagnostics,
|
|
518
|
+
fieldPath: string,
|
|
519
|
+
restProps: Iterable<string>,
|
|
520
|
+
knownProps: Iterable<string>
|
|
491
521
|
): boolean => {
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
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;
|
|
504
534
|
};
|
|
505
535
|
|
|
506
536
|
/**
|
|
@@ -511,44 +541,57 @@ export const validateAdditionalProperties = (
|
|
|
511
541
|
* performed externally.
|
|
512
542
|
*/
|
|
513
543
|
export const getBindingNames = (value: unknown): string[] => {
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
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);
|
|
554
|
+
} else {
|
|
555
|
+
return [];
|
|
556
|
+
}
|
|
527
557
|
};
|
|
528
558
|
|
|
529
559
|
const isBindingList = (
|
|
530
|
-
|
|
560
|
+
value: unknown
|
|
531
561
|
): value is {
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
562
|
+
bindings: {
|
|
563
|
+
name: string;
|
|
564
|
+
}[];
|
|
535
565
|
} =>
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
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
|
+
);
|
|
543
573
|
|
|
544
574
|
const isNamespaceList = (value: unknown): value is { binding: string }[] =>
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
575
|
+
Array.isArray(value) &&
|
|
576
|
+
value.every(
|
|
577
|
+
(entry) =>
|
|
578
|
+
isRecord(entry) && "binding" in entry && typeof entry.binding === "string"
|
|
579
|
+
);
|
|
550
580
|
|
|
551
581
|
const isRecord = (
|
|
552
|
-
|
|
582
|
+
value: unknown
|
|
553
583
|
): value is Record<string | number | symbol, unknown> =>
|
|
554
|
-
|
|
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";
|