Skip to content

Commit

Permalink
Validate duplicate bindings across all binding types
Browse files Browse the repository at this point in the history
  • Loading branch information
penalosa committed May 1, 2024
1 parent da634d5 commit cd5eb7a
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 55 deletions.
78 changes: 53 additions & 25 deletions packages/wrangler/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,34 @@ export function findWranglerToml(
return findUpSync(`wrangler.toml`, { cwd: referencePath });
}

export const friendlyBindingNames: Record<
keyof CfWorkerInit["bindings"],
string
> = {
data_blobs: "Data Blobs",
durable_objects: "Durable Objects",
kv_namespaces: "KV Namespaces",
send_email: "Send Email",
queues: "Queues",
d1_databases: "D1 Databases",
vectorize: "Vectorize Indexes",
constellation: "Constellation Projects",
hyperdrive: "Hyperdrive Configs",
r2_buckets: "R2 Buckets",
logfwdr: "logfwdr",
services: "Services",
analytics_engine_datasets: "Analytics Engine Datasets",
text_blobs: "Text Blobs",
browser: "Browser",
ai: "AI",
version_metadata: "Worker Version Metadata",
unsafe: "Unsafe",
vars: "Vars",
wasm_modules: "Wasm Modules",
dispatch_namespaces: "Dispatch Namespaces",
mtls_certificates: "mTLS Certificates",
} as const;

/**
* Print all the bindings a worker using a given config would have access to
*/
Expand All @@ -184,7 +212,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {
};

const output: {
type: string;
name: string;
entries: { key: string; value: string | boolean }[];
}[] = [];

Expand Down Expand Up @@ -215,7 +243,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {

if (data_blobs !== undefined && Object.keys(data_blobs).length > 0) {
output.push({
type: "Data Blobs",
name: friendlyBindingNames.data_blobs,
entries: Object.entries(data_blobs).map(([key, value]) => ({
key,
value: truncate(value),
Expand All @@ -225,7 +253,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {

if (durable_objects !== undefined && durable_objects.bindings.length > 0) {
output.push({
type: "Durable Objects",
name: friendlyBindingNames.durable_objects,
entries: durable_objects.bindings.map(
({ name, class_name, script_name, environment }) => {
let value = class_name;
Expand All @@ -247,7 +275,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {

if (kv_namespaces !== undefined && kv_namespaces.length > 0) {
output.push({
type: "KV Namespaces",
name: friendlyBindingNames.kv_namespaces,
entries: kv_namespaces.map(({ binding, id }) => {
return {
key: binding,
Expand All @@ -259,7 +287,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {

if (send_email !== undefined && send_email.length > 0) {
output.push({
type: "Send Email",
name: friendlyBindingNames.send_email,
entries: send_email.map(
({ name, destination_address, allowed_destination_addresses }) => {
return {
Expand All @@ -276,7 +304,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {

if (queues !== undefined && queues.length > 0) {
output.push({
type: "Queues",
name: friendlyBindingNames.queues,
entries: queues.map(({ binding, queue_name }) => {
return {
key: binding,
Expand All @@ -288,7 +316,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {

if (d1_databases !== undefined && d1_databases.length > 0) {
output.push({
type: "D1 Databases",
name: friendlyBindingNames.d1_databases,
entries: d1_databases.map(
({ binding, database_name, database_id, preview_database_id }) => {
let databaseValue = `${database_id}`;
Expand All @@ -310,7 +338,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {

if (vectorize !== undefined && vectorize.length > 0) {
output.push({
type: "Vectorize Indexes",
name: friendlyBindingNames.vectorize,
entries: vectorize.map(({ binding, index_name }) => {
return {
key: binding,
Expand All @@ -322,7 +350,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {

if (constellation !== undefined && constellation.length > 0) {
output.push({
type: "Constellation Projects",
name: friendlyBindingNames.constellation,
entries: constellation.map(({ binding, project_id }) => {
return {
key: binding,
Expand All @@ -334,7 +362,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {

if (hyperdrive !== undefined && hyperdrive.length > 0) {
output.push({
type: "Hyperdrive Configs",
name: friendlyBindingNames.hyperdrive,
entries: hyperdrive.map(({ binding, id }) => {
return {
key: binding,
Expand All @@ -346,7 +374,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {

if (r2_buckets !== undefined && r2_buckets.length > 0) {
output.push({
type: "R2 Buckets",
name: friendlyBindingNames.r2_buckets,
entries: r2_buckets.map(({ binding, bucket_name, jurisdiction }) => {
if (jurisdiction !== undefined) {
bucket_name += ` (${jurisdiction})`;
Expand All @@ -361,7 +389,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {

if (logfwdr !== undefined && logfwdr.bindings.length > 0) {
output.push({
type: "logfwdr",
name: friendlyBindingNames.logfwdr,
entries: logfwdr.bindings.map((binding) => {
return {
key: binding.name,
Expand All @@ -373,7 +401,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {

if (services !== undefined && services.length > 0) {
output.push({
type: "Services",
name: friendlyBindingNames.services,
entries: services.map(({ binding, service, environment, entrypoint }) => {
let value = service;
if (environment) {
Expand All @@ -393,7 +421,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {
analytics_engine_datasets.length > 0
) {
output.push({
type: "Analytics Engine Datasets",
name: friendlyBindingNames.analytics_engine_datasets,
entries: analytics_engine_datasets.map(({ binding, dataset }) => {
return {
key: binding,
Expand All @@ -405,7 +433,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {

if (text_blobs !== undefined && Object.keys(text_blobs).length > 0) {
output.push({
type: "Text Blobs",
name: friendlyBindingNames.text_blobs,
entries: Object.entries(text_blobs).map(([key, value]) => ({
key,
value: truncate(value),
Expand All @@ -415,7 +443,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {

if (browser !== undefined) {
output.push({
type: "Browser",
name: friendlyBindingNames.browser,
entries: [{ key: "Name", value: browser.binding }],
});
}
Expand All @@ -427,21 +455,21 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {
if (ai.staging) entries.push({ key: "Staging", value: ai.staging });

output.push({
type: "AI",
name: friendlyBindingNames.ai,
entries: entries,
});
}

if (version_metadata !== undefined) {
output.push({
type: "Worker Version Metadata",
name: friendlyBindingNames.version_metadata,
entries: [{ key: "Name", value: version_metadata.binding }],
});
}

if (unsafe?.bindings !== undefined && unsafe.bindings.length > 0) {
output.push({
type: "Unsafe",
name: friendlyBindingNames.unsafe,
entries: unsafe.bindings.map(({ name, type }) => ({
key: type,
value: name,
Expand All @@ -451,7 +479,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {

if (vars !== undefined && Object.keys(vars).length > 0) {
output.push({
type: "Vars",
name: friendlyBindingNames.vars,
entries: Object.entries(vars).map(([key, value]) => {
let parsedValue;
if (typeof value === "string") {
Expand All @@ -471,7 +499,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {

if (wasm_modules !== undefined && Object.keys(wasm_modules).length > 0) {
output.push({
type: "Wasm Modules",
name: friendlyBindingNames.wasm_modules,
entries: Object.entries(wasm_modules).map(([key, value]) => ({
key,
value: truncate(value),
Expand All @@ -481,7 +509,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {

if (dispatch_namespaces !== undefined && dispatch_namespaces.length > 0) {
output.push({
type: "dispatch namespaces",
name: friendlyBindingNames.dispatch_namespaces,
entries: dispatch_namespaces.map(({ binding, namespace, outbound }) => {
return {
key: binding,
Expand All @@ -495,7 +523,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {

if (mtls_certificates !== undefined && mtls_certificates.length > 0) {
output.push({
type: "mTLS Certificates",
name: friendlyBindingNames.mtls_certificates,
entries: mtls_certificates.map(({ binding, certificate_id }) => {
return {
key: binding,
Expand All @@ -507,7 +535,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {

if (unsafe?.metadata !== undefined) {
output.push({
type: "Unsafe Metadata",
name: friendlyBindingNames.unsafe,
entries: Object.entries(unsafe.metadata).map(([key, value]) => ({
key,
value: JSON.stringify(value),
Expand All @@ -524,7 +552,7 @@ export function printBindings(bindings: CfWorkerInit["bindings"]) {
...output
.map((bindingGroup) => {
return [
`- ${bindingGroup.type}:`,
`- ${bindingGroup.name}:`,
bindingGroup.entries.map(({ key, value }) => ` - ${key}: ${value}`),
];
})
Expand Down
2 changes: 0 additions & 2 deletions packages/wrangler/src/config/validation-helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,6 @@ export const getBindingNames = (value: unknown): string[] => {
if (typeof value !== "object" || value === null) {
return [];
}

if (isBindingList(value)) {
return value.bindings.map(({ name }) => name);
} else if (isNamespaceList(value)) {
Expand All @@ -555,7 +554,6 @@ export const getBindingNames = (value: unknown): string[] => {
if (value["binding"] !== undefined) {
return [value["binding"] as string];
}

return Object.keys(value).filter((k) => value[k] !== undefined);
} else {
return [];
Expand Down
48 changes: 20 additions & 28 deletions packages/wrangler/src/config/validation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ import {
validateRequiredProperty,
validateTypedArray,
} from "./validation-helpers";
import { friendlyBindingNames } from ".";
import type { CfWorkerInit } from "../deployment-bundle/worker";
import type { Config, DevConfig, RawConfig, RawDevConfig } from "./config";
import type {
DeprecatedUpload,
Expand Down Expand Up @@ -2597,37 +2599,27 @@ const validateHyperdriveBinding: ValidatorFn = (diagnostics, field, value) => {
*/
const validateBindingsHaveUniqueNames = (
diagnostics: Diagnostics,
{
durable_objects,
kv_namespaces,
r2_buckets,
analytics_engine_datasets,
text_blobs,
browser,
ai,
unsafe,
vars,
define,
wasm_modules,
data_blobs,
}: Partial<Config>
config: Partial<Config>
): boolean => {
let hasDuplicates = false;

const bindingsGroupedByType = {
"Durable Object": getBindingNames(durable_objects),
"KV Namespace": getBindingNames(kv_namespaces),
"R2 Bucket": getBindingNames(r2_buckets),
"Analytics Engine Dataset": getBindingNames(analytics_engine_datasets),
"Text Blob": getBindingNames(text_blobs),
Browser: getBindingNames(browser),
AI: getBindingNames(ai),
Unsafe: getBindingNames(unsafe),
"Environment Variable": getBindingNames(vars),
Definition: getBindingNames(define),
"WASM Module": getBindingNames(wasm_modules),
"Data Blob": getBindingNames(data_blobs),
} as Record<string, string[]>;
const bindingNamesArray = Object.entries(friendlyBindingNames) as [
keyof CfWorkerInit["bindings"],
string
][];

const bindingsGroupedByType = Object.fromEntries(
bindingNamesArray.map(([bindingType, binding]) => [
binding,
getBindingNames(
bindingType === "queues"
? config[bindingType]?.producers
: config[bindingType]
),
])
);

console.log(bindingsGroupedByType);

const bindingsGroupedByName: Record<string, string[]> = {};

Expand Down

0 comments on commit cd5eb7a

Please sign in to comment.