Skip to content
Draft
20 changes: 10 additions & 10 deletions packages/workers-utils/src/config/environment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -893,8 +893,8 @@ export interface EnvironmentNonInheritable {
/** The binding name used to refer to the Queue in the Worker. */
binding: string;

/** The name of this Queue. */
queue: string;
/** The name of this Queue. Omit to auto-provision. */
queue?: string;

/** The number of seconds to wait before delivering a message */
delivery_delay?: number;
Expand Down Expand Up @@ -1003,7 +1003,7 @@ export interface EnvironmentNonInheritable {
/** The binding name used to refer to the Vectorize index in the Worker. */
binding: string;
/** The name of the index. */
index_name: string;
index_name?: string;
/** Whether the Vectorize index should be remote or not in local development */
remote?: boolean;
}[];
Expand All @@ -1021,8 +1021,8 @@ export interface EnvironmentNonInheritable {
ai_search_namespaces: {
/** The binding name used to refer to the AI Search namespace in the Worker. */
binding: string;
/** The user-chosen namespace name. Must exist in Cloudflare at deploy time. */
namespace: string;
/** The user-chosen namespace name. Omit to auto-provision at deploy time. */
namespace?: string;
/** Whether the AI Search namespace binding should be remote in local development */
remote?: boolean;
}[];
Expand Down Expand Up @@ -1061,7 +1061,7 @@ export interface EnvironmentNonInheritable {
/** The binding name used to refer to the project in the Worker. */
binding: string;
/** The id of the database. */
id: string;
id?: string;
/** The local database connection string for `wrangler dev` */
localConnectionString?: string;
}[];
Expand Down Expand Up @@ -1277,7 +1277,7 @@ export interface EnvironmentNonInheritable {
/** The binding name used to refer to the certificate in the Worker */
binding: string;
/** The uuid of the uploaded mTLS certificate */
certificate_id: string;
certificate_id?: string;
/** Whether the mtls fetcher should be remote or not in local development */
remote?: boolean;
}[];
Expand Down Expand Up @@ -1319,7 +1319,7 @@ export interface EnvironmentNonInheritable {
/** The binding name used to refer to the bound service. */
binding: string;
/** The namespace to bind to. */
namespace: string;
namespace?: string;
/** Details about the outbound Worker which will handle outbound requests from your namespace */
outbound?: DispatchNamespaceOutbound;
/** Whether the Dispatch Namespace should be remote or not in local development */
Expand All @@ -1339,7 +1339,7 @@ export interface EnvironmentNonInheritable {
/** The binding name used to refer to the bound service. */
binding: string;
/** Name of the Pipeline to bind */
pipeline: string;
pipeline?: string;
/** Whether the pipeline should be remote or not in local development */
remote?: boolean;
}[];
Expand Down Expand Up @@ -1472,7 +1472,7 @@ export interface EnvironmentNonInheritable {
/** The binding name used to refer to the VPC service in the Worker. */
binding: string;
/** The service ID of the VPC connectivity service. */
service_id: string;
service_id?: string;
/** Whether the VPC service is remote or not */
remote?: boolean;
}[];
Expand Down
26 changes: 15 additions & 11 deletions packages/workers-utils/src/config/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3851,11 +3851,12 @@ const validateQueueBinding: ValidatorFn = (diagnostics, field, value) => {
}

if (
!isRequiredProperty(value, "queue", "string") ||
(value as { queue: string }).queue.length === 0
!isOptionalProperty(value, "queue", "string") ||
(isRequiredProperty(value, "queue", "string") &&
(value as { queue: string }).queue.length === 0)
) {
diagnostics.errors.push(
`"${field}" bindings should have a string "queue" field but got ${JSON.stringify(
`"${field}" bindings should, optionally, have a string "queue" field but got ${JSON.stringify(
value
)}.`
);
Expand Down Expand Up @@ -4040,7 +4041,7 @@ const validateVectorizeBinding: ValidatorFn = (diagnostics, field, value) => {
);
isValid = false;
}
if (!isRequiredProperty(value, "index_name", "string")) {
if (!isOptionalProperty(value, "index_name", "string")) {
diagnostics.errors.push(
`"${field}" bindings must have an "index_name" field but got ${JSON.stringify(
value
Expand Down Expand Up @@ -4080,7 +4081,9 @@ const validateAISearchNamespaceBinding: ValidatorFn = (
);
isValid = false;
}
if (!isRequiredProperty(value, "namespace", "string")) {
// Optional to support auto-provisioning (the handler will create a namespace
// with a generated name if none is specified).
if (!isOptionalProperty(value, "namespace", "string")) {
diagnostics.errors.push(
`"${field}" bindings must have a "namespace" field but got ${JSON.stringify(value)}.`
);
Expand Down Expand Up @@ -4152,7 +4155,7 @@ const validateHyperdriveBinding: ValidatorFn = (diagnostics, field, value) => {
);
isValid = false;
}
if (!isRequiredProperty(value, "id", "string")) {
if (!isOptionalProperty(value, "id", "string")) {
diagnostics.errors.push(
`"${field}" bindings must have a "id" field but got ${JSON.stringify(
value
Expand Down Expand Up @@ -4189,7 +4192,7 @@ const validateVpcServiceBinding: ValidatorFn = (diagnostics, field, value) => {
);
isValid = false;
}
if (!isRequiredProperty(value, "service_id", "string")) {
if (!isOptionalProperty(value, "service_id", "string")) {
diagnostics.errors.push(
`"${field}" bindings must have a "service_id" field but got ${JSON.stringify(
value
Expand Down Expand Up @@ -4481,7 +4484,7 @@ const validateWorkerNamespaceBinding: ValidatorFn = (
);
isValid = false;
}
if (!isRequiredProperty(value, "namespace", "string")) {
if (!isOptionalProperty(value, "namespace", "string")) {
diagnostics.errors.push(
`"${field}" should have a string "namespace" field but got ${JSON.stringify(
value
Expand Down Expand Up @@ -4577,8 +4580,9 @@ const validateMTlsCertificateBinding: ValidatorFn = (
isValid = false;
}
if (
!isRequiredProperty(value, "certificate_id", "string") ||
(value as { certificate_id: string }).certificate_id.length === 0
!isOptionalProperty(value, "certificate_id", "string") ||
((value as { certificate_id?: string }).certificate_id !== undefined &&
(value as { certificate_id: string }).certificate_id.length === 0)
) {
diagnostics.errors.push(
`"${field}" bindings should have a string "certificate_id" field but got ${JSON.stringify(
Expand Down Expand Up @@ -4770,7 +4774,7 @@ const validatePipelineBinding: ValidatorFn = (diagnostics, field, value) => {
);
isValid = false;
}
if (!isRequiredProperty(value, "pipeline", "string")) {
if (!isOptionalProperty(value, "pipeline", "string")) {
diagnostics.errors.push(
`"${field}" bindings must have a string "pipeline" field but got ${JSON.stringify(
value
Expand Down
16 changes: 8 additions & 8 deletions packages/workers-utils/src/worker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ export interface CfWorkflow {

export interface CfQueue {
binding: string;
queue_name: string;
queue_name?: string | typeof INHERIT_SYMBOL;
delivery_delay?: number;
remote?: boolean;
raw?: boolean;
Expand Down Expand Up @@ -225,14 +225,14 @@ export interface CfD1Database {

export interface CfVectorize {
binding: string;
index_name: string;
index_name?: string | typeof INHERIT_SYMBOL;
raw?: boolean;
remote?: boolean;
}

export interface CfAISearchNamespace {
binding: string;
namespace: string | typeof INHERIT_SYMBOL;
namespace?: string | typeof INHERIT_SYMBOL;
remote?: boolean;
}

Expand Down Expand Up @@ -280,7 +280,7 @@ export interface CfRateLimit {

export interface CfHyperdrive {
binding: string;
id: string;
id?: string | typeof INHERIT_SYMBOL;
localConnectionString?: string;
}

Expand All @@ -296,7 +296,7 @@ export interface CfService {

export interface CfVpcService {
binding: string;
service_id: string;
service_id?: string | typeof INHERIT_SYMBOL;
remote?: boolean;
}

Expand All @@ -314,7 +314,7 @@ export interface CfAnalyticsEngineDataset {

export interface CfDispatchNamespace {
binding: string;
namespace: string;
namespace?: string | typeof INHERIT_SYMBOL;
outbound?: {
service: string;
environment?: string;
Expand All @@ -325,7 +325,7 @@ export interface CfDispatchNamespace {

export interface CfMTlsCertificate {
binding: string;
certificate_id: string;
certificate_id?: string | typeof INHERIT_SYMBOL;
remote?: boolean;
}

Expand All @@ -344,7 +344,7 @@ export interface CfAssetsBinding {

export interface CfPipeline {
binding: string;
pipeline: string;
pipeline?: string | typeof INHERIT_SYMBOL;
remote?: boolean;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2041,7 +2041,6 @@ describe("normalizeAndValidateConfig()", () => {
{
vectorize: [
{},
{ binding: "VALID" },
{ binding: 2000, index_name: 2111 },
{
binding: "BINDING_2",
Expand All @@ -2059,10 +2058,8 @@ describe("normalizeAndValidateConfig()", () => {
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
"Processing wrangler configuration:
- "vectorize[0]" bindings should have a string "binding" field but got {}.
- "vectorize[0]" bindings must have an "index_name" field but got {}.
- "vectorize[1]" bindings must have an "index_name" field but got {"binding":"VALID"}.
- "vectorize[2]" bindings should have a string "binding" field but got {"binding":2000,"index_name":2111}.
- "vectorize[2]" bindings must have an "index_name" field but got {"binding":2000,"index_name":2111}."
- "vectorize[1]" bindings should have a string "binding" field but got {"binding":2000,"index_name":2111}.
- "vectorize[1]" bindings must have an "index_name" field but got {"binding":2000,"index_name":2111}."
`);
});

Expand Down Expand Up @@ -2152,8 +2149,6 @@ describe("normalizeAndValidateConfig()", () => {
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
"Processing wrangler configuration:
- "ai_search_namespaces[0]" bindings should have a string "binding" field but got {}.
- "ai_search_namespaces[0]" bindings must have a "namespace" field but got {}.
- "ai_search_namespaces[1]" bindings must have a "namespace" field but got {"binding":"VALID"}.
- "ai_search_namespaces[2]" bindings should have a string "binding" field but got {"binding":2000,"namespace":2111}.
- "ai_search_namespaces[2]" bindings must have a "namespace" field but got {"binding":2000,"namespace":2111}."
`);
Expand Down Expand Up @@ -3623,9 +3618,7 @@ describe("normalizeAndValidateConfig()", () => {
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
"Processing wrangler configuration:
- "hyperdrive[0]" bindings should have a string "binding" field but got {}.
- "hyperdrive[0]" bindings must have a "id" field but got {}.
- "hyperdrive[2]" bindings should have a string "binding" field but got {"binding":2000,"project":2111}.
- "hyperdrive[2]" bindings must have a "id" field but got {"binding":2000,"project":2111}."
- "hyperdrive[2]" bindings should have a string "binding" field but got {"binding":2000,"project":2111}."
`);
});
});
Expand Down Expand Up @@ -3683,11 +3676,9 @@ describe("normalizeAndValidateConfig()", () => {
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
"Processing wrangler configuration:
- "queues.producers[0]" bindings should have a string "binding" field but got {}.
- "queues.producers[0]" bindings should have a string "queue" field but got {}.
- "queues.producers[1]" bindings should have a string "queue" field but got {"binding":"QUEUE_BINDING_1"}.
- "queues.producers[2]" bindings should have a string "binding" field but got {"binding":2333,"queue":2444}.
- "queues.producers[2]" bindings should have a string "queue" field but got {"binding":2333,"queue":2444}.
- "queues.producers[3]" bindings should have a string "queue" field but got {"binding":"QUEUE_BINDING_3","queue":""}."
- "queues.producers[2]" bindings should, optionally, have a string "queue" field but got {"binding":2333,"queue":2444}.
- "queues.producers[3]" bindings should, optionally, have a string "queue" field but got {"binding":"QUEUE_BINDING_3","queue":""}."
`);
});

Expand Down Expand Up @@ -4208,8 +4199,7 @@ describe("normalizeAndValidateConfig()", () => {
- "dispatch_namespaces[2]" should have a string "namespace" field but got {"binding":123,"namespace":456}.
- "dispatch_namespaces[3]" should have a string "namespace" field but got {"binding":"DISPATCH_NAMESPACE_BINDING_1","namespace":456}.
- "dispatch_namespaces[5]" should have a string "binding" field but got {"binding":123,"namespace":"DISPATCH_NAMESPACE_BINDING_SERVICE_1"}.
- "dispatch_namespaces[6]" should have a string "binding" field but got {"binding":123,"service":456}.
- "dispatch_namespaces[6]" should have a string "namespace" field but got {"binding":123,"service":456}."
- "dispatch_namespaces[6]" should have a string "binding" field but got {"binding":123,"service":456}."
`);
});

Expand Down Expand Up @@ -4392,11 +4382,8 @@ describe("normalizeAndValidateConfig()", () => {
- "mtls_certificates" bindings should be objects, but got 123
- "mtls_certificates" bindings should be objects, but got false
- "mtls_certificates[3]" bindings should have a string "binding" field but got {"binding":123,"namespace":123}.
- "mtls_certificates[3]" bindings should have a string "certificate_id" field but got {"binding":123,"namespace":123}.
- "mtls_certificates[4]" bindings should have a string "certificate_id" field but got {"binding":"CERT_ONE","id":"1234"}.
- "mtls_certificates[5]" bindings should have a string "certificate_id" field but got {"binding":"CERT_TWO","certificate_id":1234}.
- "mtls_certificates[7]" bindings should have a string "binding" field but got {"binding":true,"service":"1234"}.
- "mtls_certificates[7]" bindings should have a string "certificate_id" field but got {"binding":true,"service":"1234"}."
- "mtls_certificates[7]" bindings should have a string "binding" field but got {"binding":true,"service":"1234"}."
`);
});
});
Expand Down Expand Up @@ -4508,9 +4495,7 @@ describe("normalizeAndValidateConfig()", () => {
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
"Processing wrangler configuration:
- "pipelines[0]" bindings must have a string "binding" field but got {}.
- "pipelines[0]" bindings must have a string "pipeline" field but got {}.
- "pipelines[2]" bindings must have a string "binding" field but got {"binding":2000,"project":2111}.
- "pipelines[2]" bindings must have a string "pipeline" field but got {"binding":2000,"project":2111}."
- "pipelines[2]" bindings must have a string "binding" field but got {"binding":2000,"project":2111}."
`);
});
});
Expand Down Expand Up @@ -5786,7 +5771,6 @@ describe("normalizeAndValidateConfig()", () => {
service_id: "0199295b-b3ac-7760-8246-bca40877b3e9",
},
{ binding: null, service_id: 123, invalid: true },
{ binding: "MISSING_SERVICE_ID" },
],
} as unknown as RawConfig,
undefined,
Expand All @@ -5798,10 +5782,8 @@ describe("normalizeAndValidateConfig()", () => {
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
"Processing wrangler configuration:
- "vpc_services[0]" bindings should have a string "binding" field but got {}.
- "vpc_services[0]" bindings must have a "service_id" field but got {}.
- "vpc_services[2]" bindings should have a string "binding" field but got {"binding":null,"service_id":123,"invalid":true}.
- "vpc_services[2]" bindings must have a "service_id" field but got {"binding":null,"service_id":123,"invalid":true}.
- "vpc_services[3]" bindings must have a "service_id" field but got {"binding":"MISSING_SERVICE_ID"}."
- "vpc_services[2]" bindings must have a "service_id" field but got {"binding":null,"service_id":123,"invalid":true}."
`);
});
});
Expand Down
16 changes: 15 additions & 1 deletion packages/wrangler/src/__tests__/deploy/bindings.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,21 @@ describe("deploy", () => {
msw.use(
http.get("*/accounts/:accountId/r2/buckets/:bucketName", async () => {
return HttpResponse.json(createFetchResult({}));
})
}),
// Same for dispatch namespaces — the provisioning flow calls
// listWorkerNamespaces to check existence. Return every namespace
// referenced by any test so existence checks pass.
http.get(
"*/accounts/:accountId/workers/dispatch/namespaces",
async () => {
return HttpResponse.json(
createFetchResult([
{ namespace_id: "ns-foo-id", namespace_name: "Foo" },
{ namespace_id: "ns-bar-id", namespace_name: "Bar" },
])
);
}
)
);
vi.mocked(fetchSecrets).mockResolvedValue([]);
vi.mocked(getInstalledPackageVersion).mockReturnValue(undefined);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,10 @@ describe("deploy", () => {
msw.use(
http.get("*/accounts/:accountId/r2/buckets/:bucketName", async () => {
return HttpResponse.json(createFetchResult({}));
}),
// Pretend all pipelines referenced by tests exist.
http.get("*/accounts/:accountId/pipelines/v1/pipelines", async () => {
return HttpResponse.json(createFetchResult([{ name: "my-pipeline" }]));
})
);
vi.mocked(fetchSecrets).mockResolvedValue([]);
Expand Down
Loading
Loading