@cloudflare/workers-utils 0.37.0 → 0.38.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/dist/browser.d.mts +1 -1
- package/dist/browser.mjs +1 -1
- package/dist/{chunk-XUGGRRBO.mjs → chunk-IYSONYTF.mjs} +10 -1
- package/dist/{chunk-CDB2RWUW.mjs → chunk-KBTXSRPS.mjs} +1 -1
- package/dist/{chunk-V6JSHOVJ.mjs → chunk-T5JQYOMX.mjs} +114 -1
- package/dist/{compliance-b1X-Ss7e.d.mts → compliance-Dta138UP.d.mts} +52 -4
- package/dist/compliance.d.mts +1 -1
- package/dist/compliance.mjs +1 -1
- package/dist/index.d.mts +25 -3
- package/dist/index.mjs +143 -16
- package/dist/metafile-esm.json +1 -1
- package/dist/test-helpers/index.d.mts +1 -1
- package/dist/test-helpers/index.mjs +1 -1
- package/package.json +3 -3
package/dist/index.mjs
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
export { MetricsRegistry } from './chunk-Z62CVNHJ.mjs';
|
|
2
2
|
export { _forceColour, formatZodError } from './chunk-7AX24RFK.mjs';
|
|
3
|
-
import { isRedirectedRawConfig, configFileName, formatConfigSnippet, getDurableObjectExports, getContainerNameToClassNameMap, parsePackageJSON, readFileSync, ParseError, parseJSON, APIError, dir, parseTOML, modify, applyEdits, format, dist_default, parseJSONC } from './chunk-
|
|
4
|
-
export { APIError, ENVIRONMENT_TAG_PREFIX, INHERIT_SYMBOL, JSON_CONFIG_FORMATS, PATH_TO_DEPLOY_CONFIG, ParseError, SERVICE_TAG_PREFIX, configFileName, configFormat, experimental_readRawConfig, findWranglerConfig, formatConfigSnippet, getContainerDurableObjectClassNames, getContainerNameToClassNameMap, getDurableObjectExports, hasDurableObjectExports, indexLocation, isRedirectedConfig, parseByteSize, parseHumanDuration, parseJSON, parseJSONC, parseNonHyphenedUuid, parsePackageJSON, parseTOML, partitionExports, readFileSync, readFileSyncToBuffer, resolveContainerClassName, resolveWranglerConfigPath, searchLocation } from './chunk-
|
|
5
|
-
import { assertNever } from './chunk-
|
|
6
|
-
export { DEFAULT_COMPAT_DATE, assertNever, constructWranglerConfig, mapWorkerMetadataBindings } from './chunk-
|
|
3
|
+
import { isRedirectedRawConfig, configFileName, formatConfigSnippet, getDurableObjectExports, getContainerNameToClassNameMap, parsePackageJSON, readFileSync, ParseError, parseJSON, APIError, CONTAINER_IMAGES_BINDING, dir, parseTOML, modify, applyEdits, format, dist_default, parseJSONC } from './chunk-T5JQYOMX.mjs';
|
|
4
|
+
export { APIError, CONTAINER_IMAGES_BINDING, ENVIRONMENT_TAG_PREFIX, INHERIT_SYMBOL, JSON_CONFIG_FORMATS, PATH_TO_DEPLOY_CONFIG, ParseError, SERVICE_TAG_PREFIX, configFileName, configFormat, experimental_readRawConfig, findWranglerConfig, formatConfigSnippet, getContainerDurableObjectClassNames, getContainerNameToClassNameMap, getDurableObjectClassNameToUseSQLiteMap, getDurableObjectContainerApps, getDurableObjectExports, hasDurableObjectExports, indexLocation, isDurableObjectContainerApp, isRedirectedConfig, parseByteSize, parseHumanDuration, parseJSON, parseJSONC, parseNonHyphenedUuid, parsePackageJSON, parseTOML, partitionExports, readFileSync, readFileSyncToBuffer, resolveContainerClassName, resolveWranglerConfigPath, searchLocation, validateDurableObjectContainerApplications } from './chunk-T5JQYOMX.mjs';
|
|
5
|
+
import { assertNever } from './chunk-KBTXSRPS.mjs';
|
|
6
|
+
export { DEFAULT_COMPAT_DATE, assertNever, constructWranglerConfig, mapWorkerMetadataBindings } from './chunk-KBTXSRPS.mjs';
|
|
7
7
|
export { NODEJS_COMPAT_DEFAULT_ON_DATE, NODEJS_COMPAT_V2_SWITCH_OVER_DATE, getTodaysCompatDate, isCompatDate, isNodejsCompatDefaultOn, resolveNodejsCompat, stripRedundantNodejsCompatFlags } from './chunk-C6O4ION7.mjs';
|
|
8
|
-
import { getCloudflareEnv, getCloudflareApiBaseUrl, getTraceHeader, getCloudflaredPathFromEnv, getOutputFilePathFromEnv, getOutputFileDirectoryFromEnv, getCIOverrideName, getWranglerCacheDirFromEnv } from './chunk-
|
|
9
|
-
export { COMPLIANCE_REGION_CONFIG_PUBLIC, COMPLIANCE_REGION_CONFIG_UNKNOWN, getBrowserRenderingHeadfulFromEnv, getBuildConditionsFromEnv, getBuildPlatformFromEnv, getC3CommandFromEnv, getCIGeneratePreviewAlias, getCIMatchTag, getCIOverrideName, getCIOverrideNetworkModeHost, getCfFetchEnabledFromEnv, getCfFetchPathFromEnv, getCloudflareApiBaseUrl, getCloudflareApiEnvironmentFromEnv, getCloudflareComplianceRegion, getCloudflareEnv, getCloudflareIncludeProcessEnvFromEnv, getCloudflareLoadDevVarsFromDotEnv, getCloudflaredPathFromEnv, getComplianceRegionSubdomain, getD1ExtraLocationChoices, getDisableConfigWatching, getLocalExplorerEnabledFromEnv, getLocalObservabilityEnabledFromEnv, getNoSkillsUpdatePromptsFromEnv, getOpenNextDeployFromEnv, getOutputFileDirectoryFromEnv, getOutputFilePathFromEnv, getRegistryPath, getSanitizeLogs, getSubdomainMixedStateCheckDisabled, getTraceHeader, getWorkersCIBranchName, getWranglerCacheDirFromEnv, getWranglerHideBanner, getWranglerSendErrorReportsFromEnv, getWranglerSendMetricsFromEnv, isDoNotTrackEnabled } from './chunk-
|
|
8
|
+
import { getCloudflareEnv, getCloudflareContainerRegistry, getCloudflareApiBaseUrl, getTraceHeader, getCloudflaredPathFromEnv, getOutputFilePathFromEnv, getOutputFileDirectoryFromEnv, getCIOverrideName, getWranglerCacheDirFromEnv } from './chunk-IYSONYTF.mjs';
|
|
9
|
+
export { COMPLIANCE_REGION_CONFIG_PUBLIC, COMPLIANCE_REGION_CONFIG_UNKNOWN, getBrowserRenderingHeadfulFromEnv, getBuildConditionsFromEnv, getBuildPlatformFromEnv, getC3CommandFromEnv, getCIGeneratePreviewAlias, getCIMatchTag, getCIOverrideName, getCIOverrideNetworkModeHost, getCfFetchEnabledFromEnv, getCfFetchPathFromEnv, getCloudflareApiBaseUrl, getCloudflareApiEnvironmentFromEnv, getCloudflareComplianceRegion, getCloudflareContainerRegistry, getCloudflareEnv, getCloudflareIncludeProcessEnvFromEnv, getCloudflareLoadDevVarsFromDotEnv, getCloudflaredPathFromEnv, getComplianceRegionSubdomain, getD1ExtraLocationChoices, getDisableConfigWatching, getLocalExplorerEnabledFromEnv, getLocalObservabilityEnabledFromEnv, getNoSkillsUpdatePromptsFromEnv, getOpenNextDeployFromEnv, getOutputFileDirectoryFromEnv, getOutputFilePathFromEnv, getRegistryPath, getSanitizeLogs, getSubdomainMixedStateCheckDisabled, getTraceHeader, getWorkersCIBranchName, getWranglerCacheDirFromEnv, getWranglerHideBanner, getWranglerSendErrorReportsFromEnv, getWranglerSendMetricsFromEnv, isDoNotTrackEnabled } from './chunk-IYSONYTF.mjs';
|
|
10
10
|
import { dedent } from './chunk-MCNIGVAF.mjs';
|
|
11
11
|
export { getBooleanEnvironmentVariableFactory, getDockerPath, getEnvironmentVariableFactory } from './chunk-3IYLA2JH.mjs';
|
|
12
12
|
import { UserError, FatalError } from './chunk-WO2IAW6M.mjs';
|
|
@@ -18451,7 +18451,16 @@ function normalizeAndValidateEnvironment(diagnostics, configPath, rawEnv, isDisp
|
|
|
18451
18451
|
// `name` is inheritable, so a named environment that doesn't redeclare it
|
|
18452
18452
|
// still runs under the top level Worker name — fall back to it so the
|
|
18453
18453
|
// generated container name isn't built from `undefined`.
|
|
18454
|
-
validateContainerApp(
|
|
18454
|
+
validateContainerApp(
|
|
18455
|
+
envName,
|
|
18456
|
+
rawEnv.name ?? rawConfig?.name,
|
|
18457
|
+
configPath,
|
|
18458
|
+
{
|
|
18459
|
+
complianceConfig: {
|
|
18460
|
+
compliance_region: rawEnv.compliance_region ?? topLevelEnv?.compliance_region
|
|
18461
|
+
}
|
|
18462
|
+
}
|
|
18463
|
+
),
|
|
18455
18464
|
void 0
|
|
18456
18465
|
),
|
|
18457
18466
|
send_email: notInheritable(
|
|
@@ -19903,6 +19912,15 @@ function validatePreviewsContainers(envName, configPath) {
|
|
|
19903
19912
|
});
|
|
19904
19913
|
return (diagnostics, field, value, config2) => {
|
|
19905
19914
|
if (Array.isArray(value)) {
|
|
19915
|
+
const durableObjectPolicyFields = [...value.entries()].filter(
|
|
19916
|
+
([, entry]) => entry && typeof entry === "object" && entry.scheduling_policy === "durable_object"
|
|
19917
|
+
).map(([index]) => `"${field}[${index}].scheduling_policy"`);
|
|
19918
|
+
if (durableObjectPolicyFields.length > 0) {
|
|
19919
|
+
diagnostics.errors.push(
|
|
19920
|
+
`${durableObjectPolicyFields.join(", ")} cannot be "durable_object". Durable Object-managed Containers are configured only in the top-level "containers" array.`
|
|
19921
|
+
);
|
|
19922
|
+
return false;
|
|
19923
|
+
}
|
|
19906
19924
|
const nameFields = [...value.entries()].filter(
|
|
19907
19925
|
([, entry]) => entry && typeof entry === "object" && "name" in entry
|
|
19908
19926
|
).map(([index]) => `"${field}[${index}].name"`);
|
|
@@ -19937,6 +19955,85 @@ function validatePreviewsContainers(envName, configPath) {
|
|
|
19937
19955
|
};
|
|
19938
19956
|
}
|
|
19939
19957
|
__name(validatePreviewsContainers, "validatePreviewsContainers");
|
|
19958
|
+
function validateDurableObjectContainerImages(diagnostics, field, images, complianceConfig) {
|
|
19959
|
+
if (images === void 0) {
|
|
19960
|
+
return true;
|
|
19961
|
+
}
|
|
19962
|
+
if (typeof images !== "object" || images === null || Array.isArray(images) || Object.keys(images).length === 0) {
|
|
19963
|
+
diagnostics.errors.push(
|
|
19964
|
+
`"${field}" must be a non-empty object when present.`
|
|
19965
|
+
);
|
|
19966
|
+
return false;
|
|
19967
|
+
}
|
|
19968
|
+
let valid = true;
|
|
19969
|
+
const entries = Object.entries(images);
|
|
19970
|
+
if (entries.length > 100) {
|
|
19971
|
+
diagnostics.errors.push(`"${field}" must contain at most 100 images.`);
|
|
19972
|
+
valid = false;
|
|
19973
|
+
}
|
|
19974
|
+
for (const [imageName, imageValue] of entries) {
|
|
19975
|
+
const imageField = `${field}.${imageName}`;
|
|
19976
|
+
if (imageName.length === 0 || imageName.length > 128) {
|
|
19977
|
+
diagnostics.errors.push(
|
|
19978
|
+
`"${field}" image names must be between 1 and 128 characters.`
|
|
19979
|
+
);
|
|
19980
|
+
valid = false;
|
|
19981
|
+
}
|
|
19982
|
+
if (typeof imageValue !== "object" || imageValue === null || Array.isArray(imageValue)) {
|
|
19983
|
+
diagnostics.errors.push(
|
|
19984
|
+
`"${imageField}" must be an object with either a "dockerfile" or "image" field.`
|
|
19985
|
+
);
|
|
19986
|
+
valid = false;
|
|
19987
|
+
continue;
|
|
19988
|
+
}
|
|
19989
|
+
const image = imageValue;
|
|
19990
|
+
const hasDockerfile = image.dockerfile !== void 0;
|
|
19991
|
+
const hasImage = image.image !== void 0;
|
|
19992
|
+
if (hasDockerfile === hasImage) {
|
|
19993
|
+
diagnostics.errors.push(
|
|
19994
|
+
`"${imageField}" must specify exactly one of "dockerfile" or "image".`
|
|
19995
|
+
);
|
|
19996
|
+
valid = false;
|
|
19997
|
+
}
|
|
19998
|
+
if (hasDockerfile && (typeof image.dockerfile !== "string" || image.dockerfile.length === 0)) {
|
|
19999
|
+
diagnostics.errors.push(
|
|
20000
|
+
`"${imageField}.dockerfile" must be a non-empty string.`
|
|
20001
|
+
);
|
|
20002
|
+
valid = false;
|
|
20003
|
+
}
|
|
20004
|
+
if (hasImage && (typeof image.image !== "string" || image.image.length === 0)) {
|
|
20005
|
+
diagnostics.errors.push(
|
|
20006
|
+
`"${imageField}.image" must be a non-empty string.`
|
|
20007
|
+
);
|
|
20008
|
+
valid = false;
|
|
20009
|
+
}
|
|
20010
|
+
if (typeof image.image === "string" && image.image.length > 0) {
|
|
20011
|
+
const registry2 = getCloudflareContainerRegistry(complianceConfig);
|
|
20012
|
+
const prefix = `${registry2}/`;
|
|
20013
|
+
const reference = image.image.slice(prefix.length);
|
|
20014
|
+
const digestReference = reference.match(
|
|
20015
|
+
/^[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*(?:\/[a-z0-9]+(?:(?:[._]|__|-+)[a-z0-9]+)*)+@sha256:[a-f0-9]{64}$/
|
|
20016
|
+
);
|
|
20017
|
+
if (!image.image.startsWith(prefix) || digestReference?.[0] !== reference) {
|
|
20018
|
+
diagnostics.errors.push(
|
|
20019
|
+
`"${imageField}.image" must be a digest-pinned image in the managed registry, in the form "${registry2}/<account-id>/<repository>@sha256:<64 lowercase hex characters>".`
|
|
20020
|
+
);
|
|
20021
|
+
valid = false;
|
|
20022
|
+
}
|
|
20023
|
+
}
|
|
20024
|
+
const unsupportedFields = Object.keys(image).filter(
|
|
20025
|
+
(property) => property !== "dockerfile" && property !== "image"
|
|
20026
|
+
);
|
|
20027
|
+
if (unsupportedFields.length > 0) {
|
|
20028
|
+
diagnostics.errors.push(
|
|
20029
|
+
`Unexpected fields found in ${imageField} field: ${unsupportedFields.map((property) => `"${property}"`).join(", ")}`
|
|
20030
|
+
);
|
|
20031
|
+
valid = false;
|
|
20032
|
+
}
|
|
20033
|
+
}
|
|
20034
|
+
return valid;
|
|
20035
|
+
}
|
|
20036
|
+
__name(validateDurableObjectContainerImages, "validateDurableObjectContainerImages");
|
|
19940
20037
|
function validateContainerApp(envName, topLevelName, configPath, options = {}) {
|
|
19941
20038
|
const { generateDefaultName = true } = options;
|
|
19942
20039
|
return (diagnostics, field, value, config2) => {
|
|
@@ -19950,13 +20047,23 @@ function validateContainerApp(envName, topLevelName, configPath, options = {}) {
|
|
|
19950
20047
|
return false;
|
|
19951
20048
|
}
|
|
19952
20049
|
for (const containerAppOptional of value) {
|
|
19953
|
-
|
|
19954
|
-
|
|
19955
|
-
|
|
19956
|
-
|
|
19957
|
-
|
|
19958
|
-
|
|
19959
|
-
|
|
20050
|
+
const isDurableObjectManaged = containerAppOptional.scheduling_policy === "durable_object";
|
|
20051
|
+
const hasValidDurableObjectClassName = typeof containerAppOptional.class_name === "string" && containerAppOptional.class_name.length > 0;
|
|
20052
|
+
if (isDurableObjectManaged) {
|
|
20053
|
+
if (!hasValidDurableObjectClassName) {
|
|
20054
|
+
diagnostics.errors.push(
|
|
20055
|
+
`"containers.class_name" must be a non-empty string when "containers.scheduling_policy" is "durable_object".`
|
|
20056
|
+
);
|
|
20057
|
+
}
|
|
20058
|
+
} else {
|
|
20059
|
+
validateOptionalProperty(
|
|
20060
|
+
diagnostics,
|
|
20061
|
+
field,
|
|
20062
|
+
"class_name",
|
|
20063
|
+
containerAppOptional.class_name,
|
|
20064
|
+
"string"
|
|
20065
|
+
);
|
|
20066
|
+
}
|
|
19960
20067
|
validateOptionalProperty(
|
|
19961
20068
|
diagnostics,
|
|
19962
20069
|
field,
|
|
@@ -19964,7 +20071,7 @@ function validateContainerApp(envName, topLevelName, configPath, options = {}) {
|
|
|
19964
20071
|
containerAppOptional.name,
|
|
19965
20072
|
"string"
|
|
19966
20073
|
);
|
|
19967
|
-
if (generateDefaultName && !containerAppOptional.name) {
|
|
20074
|
+
if (generateDefaultName && !containerAppOptional.name && (!isDurableObjectManaged || hasValidDurableObjectClassName)) {
|
|
19968
20075
|
if (containerAppOptional.class_name === void 0) {
|
|
19969
20076
|
diagnostics.errors.push(
|
|
19970
20077
|
`"containers.name" is required when "containers.class_name" is not defined, because there is no class name to derive a default name from. Either name this container and reference it from a Durable Object's \`exports\` entry, or set "containers.class_name".`
|
|
@@ -19979,6 +20086,23 @@ function validateContainerApp(envName, topLevelName, configPath, options = {}) {
|
|
|
19979
20086
|
containerAppOptional.name = name.toLowerCase().replace(/ /g, "-");
|
|
19980
20087
|
}
|
|
19981
20088
|
}
|
|
20089
|
+
if (isDurableObjectManaged) {
|
|
20090
|
+
validateDurableObjectContainerImages(
|
|
20091
|
+
diagnostics,
|
|
20092
|
+
`${field}.images`,
|
|
20093
|
+
containerAppOptional.images,
|
|
20094
|
+
options.complianceConfig
|
|
20095
|
+
);
|
|
20096
|
+
const unsupportedFields = Object.keys(containerAppOptional).filter(
|
|
20097
|
+
(key) => !["name", "class_name", "scheduling_policy", "images"].includes(key)
|
|
20098
|
+
);
|
|
20099
|
+
if (unsupportedFields.length > 0) {
|
|
20100
|
+
diagnostics.errors.push(
|
|
20101
|
+
`Unsupported fields for Durable Object-managed Containers in ${field}: ${unsupportedFields.map((key) => `"${key}"`).join(",")}. Only "name", "class_name", "scheduling_policy", and "images" are supported.`
|
|
20102
|
+
);
|
|
20103
|
+
}
|
|
20104
|
+
continue;
|
|
20105
|
+
}
|
|
19982
20106
|
if (!containerAppOptional.configuration?.image && !containerAppOptional.image) {
|
|
19983
20107
|
diagnostics.errors.push(
|
|
19984
20108
|
`"containers.image" field must be defined for each container app. This should be the path to your Dockerfile or an image URI pointing to the Cloudflare registry.`
|
|
@@ -20992,6 +21116,7 @@ var validateBindingsHaveUniqueNames = /* @__PURE__ */ __name((diagnostics, confi
|
|
|
20992
21116
|
])
|
|
20993
21117
|
);
|
|
20994
21118
|
bindingsGroupedByType["Secret"] = config2.secrets?.required ?? [];
|
|
21119
|
+
bindingsGroupedByType["Container images"] = [CONTAINER_IMAGES_BINDING];
|
|
20995
21120
|
const bindingsGroupedByName = {};
|
|
20996
21121
|
for (const bindingType in bindingsGroupedByType) {
|
|
20997
21122
|
const bindingNames = bindingsGroupedByType[bindingType];
|
|
@@ -24439,7 +24564,9 @@ ${allTailConsumers.map(({ service, streaming }) => {
|
|
|
24439
24564
|
}
|
|
24440
24565
|
log(
|
|
24441
24566
|
`${containersTitle}
|
|
24442
|
-
${containers.map(
|
|
24567
|
+
${containers.map(
|
|
24568
|
+
(container) => container.scheduling_policy === "durable_object" ? `- ${container.class_name} (durable_object)` : `- ${container.name} (${container.image})`
|
|
24569
|
+
).join("\n")}`
|
|
24443
24570
|
);
|
|
24444
24571
|
log("");
|
|
24445
24572
|
}
|