Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/witty-ideas-rhyme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"wrangler": minor
---

Stabilise Worker Loader bindings
13 changes: 5 additions & 8 deletions fixtures/dynamic-worker-loading/wrangler.jsonc
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,9 @@
"name": "dynamic-worker-loading",
"main": "src/index.ts",
"compatibility_date": "2023-05-04",
"unsafe": {
"bindings": [
{
"name": "LOADER",
"type": "worker-loader",
},
],
},
"worker_loaders": [
{
"binding": "LOADER",
},
],
}
4 changes: 1 addition & 3 deletions packages/miniflare/src/plugins/worker-loader/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@ import { z } from "zod";
import { Worker_Binding } from "../../runtime";
import { Plugin } from "../shared";

export const WorkerLoaderConfigSchema = z.object({
id: z.string().optional(),
});
export const WorkerLoaderConfigSchema = z.object({});
export const WorkerLoaderOptionsSchema = z.object({
workerLoaders: z.record(WorkerLoaderConfigSchema).optional(),
});
Expand Down
106 changes: 102 additions & 4 deletions packages/wrangler/src/__tests__/config/configuration.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { normalizeString } from "../helpers/normalize";
import { runInTempDir } from "../helpers/run-in-tmp";
import { writeWranglerConfig } from "../helpers/write-wrangler-config";
import type {
Config,
ConfigFields,
RawConfig,
RawDevConfig,
Expand Down Expand Up @@ -78,6 +79,8 @@ describe("normalizeAndValidateConfig()", () => {
upstream_protocol: "http",
host: undefined,
enable_containers: true,
inspector_port: undefined,
container_engine: undefined,
},
containers: undefined,
cloudchamber: {},
Expand All @@ -92,7 +95,6 @@ describe("normalizeAndValidateConfig()", () => {
legacy_env: true,
logfwdr: {
bindings: [],
schema: undefined,
},
send_metrics: undefined,
main: undefined,
Expand Down Expand Up @@ -125,7 +127,6 @@ describe("normalizeAndValidateConfig()", () => {
},
dispatch_namespaces: [],
mtls_certificates: [],
usage_model: undefined,
vars: {},
define: {},
definedEnvironments: [],
Expand All @@ -134,18 +135,30 @@ describe("normalizeAndValidateConfig()", () => {
data_blobs: undefined,
workers_dev: undefined,
preview_urls: undefined,
zone_id: undefined,
no_bundle: undefined,
minify: undefined,
first_party_worker: undefined,
keep_vars: undefined,
logpush: undefined,
upload_source_maps: undefined,
placement: undefined,
worker_loaders: [],
tail_consumers: undefined,
pipelines: [],
workflows: [],
});
userConfigPath: undefined,
topLevelName: undefined,
alias: undefined,
find_additional_modules: undefined,
preserve_file_names: undefined,
base_dir: undefined,
limits: undefined,
keep_names: undefined,
assets: undefined,
observability: undefined,
compliance_region: undefined,
images: undefined,
} satisfies Config);
expect(diagnostics.hasErrors()).toBe(false);
expect(diagnostics.hasWarnings()).toBe(false);
});
Expand Down Expand Up @@ -3978,6 +3991,91 @@ describe("normalizeAndValidateConfig()", () => {
});
});

describe("[worker_loaders]", () => {
it("should error if worker_loaders is an object", () => {
const { diagnostics } = normalizeAndValidateConfig(
// @ts-expect-error purposely using an invalid value
{ worker_loaders: {} },
undefined,
undefined,
{ env: undefined }
);

expect(diagnostics.hasWarnings()).toBe(false);
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
"Processing wrangler configuration:
- The field \\"worker_loaders\\" should be an array but got {}."
`);
});

it("should error if worker_loaders is null", () => {
const { diagnostics } = normalizeAndValidateConfig(
// @ts-expect-error purposely using an invalid value
{ worker_loaders: null },
undefined,
undefined,
{ env: undefined }
);

expect(diagnostics.hasWarnings()).toBe(false);
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
"Processing wrangler configuration:
- The field \\"worker_loaders\\" should be an array but got null."
`);
});

it("should accept valid bindings", () => {
const { diagnostics } = normalizeAndValidateConfig(
{
worker_loaders: [
{
binding: "VALID",
},
],
},
undefined,
undefined,
{ env: undefined }
);

expect(diagnostics.hasErrors()).toBe(false);
});

it("should error if worker_loaders bindings are not valid", () => {
const { diagnostics } = normalizeAndValidateConfig(
{
worker_loaders: [
// @ts-expect-error Test if empty object is caught
{},
{
binding: "VALID",
},
{
// @ts-expect-error Test if binding is not a string
binding: null,
invalid: true,
},
],
},
undefined,
undefined,
{ env: undefined }
);

expect(diagnostics.hasWarnings()).toBe(true);
expect(diagnostics.renderWarnings()).toMatchInlineSnapshot(`
"Processing wrangler configuration:
- Unexpected fields found in worker_loaders[2] field: \\"invalid\\""
`);
expect(diagnostics.hasErrors()).toBe(true);
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
"Processing wrangler configuration:
- \\"worker_loaders[0]\\" bindings must have a string \\"binding\\" field but got {}.
- \\"worker_loaders[2]\\" bindings must have a string \\"binding\\" field but got {\\"binding\\":null,\\"invalid\\":true}."
`);
});
});

describe("[unsafe_hello_world]", () => {
it("should error if unsafe_hello_world is an object", () => {
const { diagnostics } = normalizeAndValidateConfig(
Expand Down
8 changes: 8 additions & 0 deletions packages/wrangler/src/__tests__/type-generation.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -263,6 +263,11 @@ const bindingsConfigMock: Omit<
},
},
],
worker_loaders: [
{
binding: "WORKER_LOADER_BINDING",
},
],
};

describe("generate types", () => {
Expand Down Expand Up @@ -480,6 +485,7 @@ describe("generate types", () => {
SECRET: SecretsStoreSecret;
HELLO_WORLD: HelloWorldBinding;
RATE_LIMITER: RateLimit;
WORKER_LOADER_BINDING: WorkerLoader;
SERVICE_BINDING: Fetcher /* service_name */;
OTHER_SERVICE_BINDING: Service /* entrypoint FakeEntrypoint from service_name_2 */;
OTHER_SERVICE_BINDING_ENTRYPOINT: Service /* entrypoint RealEntrypoint from service_name_2 */;
Expand Down Expand Up @@ -579,6 +585,7 @@ describe("generate types", () => {
SECRET: SecretsStoreSecret;
HELLO_WORLD: HelloWorldBinding;
RATE_LIMITER: RateLimit;
WORKER_LOADER_BINDING: WorkerLoader;
SERVICE_BINDING: Fetcher /* service_name */;
OTHER_SERVICE_BINDING: Service /* entrypoint FakeEntrypoint from service_name_2 */;
OTHER_SERVICE_BINDING_ENTRYPOINT: Service /* entrypoint RealEntrypoint from service_name_2 */;
Expand Down Expand Up @@ -742,6 +749,7 @@ describe("generate types", () => {
SECRET: SecretsStoreSecret;
HELLO_WORLD: HelloWorldBinding;
RATE_LIMITER: RateLimit;
WORKER_LOADER_BINDING: WorkerLoader;
SERVICE_BINDING: Service<typeof import(\\"../b/index\\").default>;
OTHER_SERVICE_BINDING: Service /* entrypoint FakeEntrypoint from service_name_2 */;
OTHER_SERVICE_BINDING_ENTRYPOINT: Service<typeof import(\\"../c/index\\").RealEntrypoint>;
Expand Down
2 changes: 2 additions & 0 deletions packages/wrangler/src/api/startDevWorker/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import type {
CfTailConsumer,
CfUnsafe,
CfVectorize,
CfWorkerLoader,
CfWorkflow,
} from "../../deployment-bundle/worker";
import type { CfAccount } from "../../dev/create-worker-preview";
Expand Down Expand Up @@ -304,6 +305,7 @@ export type Binding =
| ({ type: "logfwdr" } & NameOmit<CfLogfwdrBinding>)
| ({ type: "unsafe_hello_world" } & BindingOmit<CfHelloWorld>)
| ({ type: "ratelimit" } & NameOmit<CfRateLimit>)
| ({ type: "worker_loader" } & BindingOmit<CfWorkerLoader>)
| { type: `unsafe_${string}` }
| { type: "assets" };

Expand Down
10 changes: 10 additions & 0 deletions packages/wrangler/src/api/startDevWorker/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,12 @@ export function convertCfWorkerInitBindingsToBindings(
}
break;
}
case "worker_loaders": {
for (const { binding, ...x } of info) {
output[binding] = { type: "worker_loader", ...x };
}
break;
}
default: {
assertNever(type);
}
Expand Down Expand Up @@ -331,6 +337,7 @@ export async function convertBindingsToCfWorkerInitBindings(
pipelines: undefined,
unsafe_hello_world: undefined,
ratelimits: undefined,
worker_loaders: undefined,
};

const fetchers: Record<string, ServiceFetch> = {};
Expand Down Expand Up @@ -423,6 +430,9 @@ export async function convertBindingsToCfWorkerInitBindings(
} else if (binding.type === "ratelimit") {
bindings.ratelimits ??= [];
bindings.ratelimits.push({ ...binding, name: name });
} else if (binding.type === "worker_loader") {
bindings.worker_loaders ??= [];
bindings.worker_loaders.push({ ...binding, binding: name });
} else if (isUnsafeBindingType(binding.type)) {
bindings.unsafe ??= {
bindings: [],
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -335,6 +335,7 @@ export const defaultWranglerConfig: Config = {
version_metadata: undefined,
unsafe_hello_world: [],
ratelimits: [],
worker_loaders: [],

/*====================================================*/
/* Fields supported by Workers only */
Expand Down
14 changes: 14 additions & 0 deletions packages/wrangler/src/config/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1173,6 +1173,20 @@ export interface EnvironmentNonInheritable {
period: 10 | 60;
};
}[];

/**
* Specifies Worker Loader bindings that are bound to this Worker environment.
*
* NOTE: This field is not automatically inherited from the top level environment,
* and so must be specified in every named environment.
*
* @default []
* @nonInheritable
*/
worker_loaders: {
/** The binding name used to refer to the Worker Loader in the Worker. */
binding: string;
}[];
}

/**
Expand Down
39 changes: 39 additions & 0 deletions packages/wrangler/src/config/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1454,6 +1454,16 @@ function normalizeAndValidateEnvironment(
validateBindingArray(envName, validateHelloWorldBinding),
[]
),
worker_loaders: notInheritable(
diagnostics,
topLevelEnv,
rawConfig,
rawEnv,
envName,
"worker_loaders",
validateBindingArray(envName, validateWorkerLoaderBinding),
[]
),
ratelimits: notInheritable(
diagnostics,
topLevelEnv,
Expand Down Expand Up @@ -2385,6 +2395,7 @@ const validateUnsafeBinding: ValidatorFn = (diagnostics, field, value) => {
"logfwdr",
"mtls_certificate",
"pipeline",
"worker-loader",
];

if (safeBindings.includes(value.type)) {
Expand Down Expand Up @@ -3867,6 +3878,34 @@ const validateHelloWorldBinding: ValidatorFn = (diagnostics, field, value) => {
return isValid;
};

const validateWorkerLoaderBinding: ValidatorFn = (
diagnostics,
field,
value
) => {
if (typeof value !== "object" || value === null) {
diagnostics.errors.push(
`"worker_loader" bindings should be objects, but got ${JSON.stringify(value)}`
);
return false;
}
let isValid = true;
if (!isRequiredProperty(value, "binding", "string")) {
diagnostics.errors.push(
`"${field}" bindings must have a string "binding" field but got ${JSON.stringify(
value
)}.`
);
isValid = false;
}

validateAdditionalProperties(diagnostics, field, Object.keys(value), [
"binding",
]);

return isValid;
};

const validateRateLimitBinding: ValidatorFn = (diagnostics, field, value) => {
if (typeof value !== "object" || value === null) {
diagnostics.errors.push(
Expand Down
1 change: 1 addition & 0 deletions packages/wrangler/src/deployment-bundle/bindings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@ export function getBindings(
},
unsafe_hello_world: options?.pages ? undefined : config?.unsafe_hello_world,
ratelimits: config?.ratelimits,
worker_loaders: config?.worker_loaders,
};
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,10 @@ export type WorkerMetadataBinding =
namespace_id: string;
simple: { limit: number; period: 10 | 60 };
}
| {
type: "worker-loader";
name: string;
}
| {
type: "logfwdr";
name: string;
Expand Down Expand Up @@ -499,6 +503,13 @@ export function createWorkerUploadForm(worker: CfWorkerInit): FormData {
});
});

bindings.worker_loaders?.forEach(({ binding }) => {
metadataBindings.push({
name: binding,
type: "worker-loader",
});
});

bindings.logfwdr?.bindings.forEach(({ name, destination }) => {
metadataBindings.push({
name: name,
Expand Down
Loading
Loading