Skip to content

Commit b40d0ab

Browse files
fix: allow the asset directory to be omitted in Wrangler config for commands that don't need it (#7426)
1 parent a3d5aad commit b40d0ab

File tree

12 files changed

+96
-71
lines changed

12 files changed

+96
-71
lines changed

.changeset/forty-gifts-grab.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"wrangler": patch
3+
---
4+
5+
fix: allow the asset directory to be omitted in Wrangler config for commands that don't need it

packages/wrangler/src/__tests__/configuration.test.ts

Lines changed: 0 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1792,7 +1792,6 @@ describe("normalizeAndValidateConfig()", () => {
17921792
`);
17931793
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
17941794
"Processing wrangler configuration:
1795-
- \\"assets.directory\\" is a required field.
17961795
- Expected \\"assets.binding\\" to be of type string but got 2."
17971796
`);
17981797
});
@@ -1845,27 +1844,6 @@ describe("normalizeAndValidateConfig()", () => {
18451844
expect(diagnostics.hasErrors()).toBe(false);
18461845
});
18471846

1848-
it("should error if `directory` is an empty string", () => {
1849-
const expectedConfig = {
1850-
assets: {
1851-
directory: "",
1852-
},
1853-
};
1854-
1855-
const { config, diagnostics } = normalizeAndValidateConfig(
1856-
expectedConfig as unknown as RawConfig,
1857-
undefined,
1858-
{ env: undefined }
1859-
);
1860-
1861-
expect(config).toEqual(expect.objectContaining(expectedConfig));
1862-
expect(diagnostics.hasWarnings()).toBeFalsy();
1863-
expect(diagnostics.renderErrors()).toMatchInlineSnapshot(`
1864-
"Processing wrangler configuration:
1865-
- Expected \\"assets.directory\\" to be a non-empty string."
1866-
`);
1867-
});
1868-
18691847
it("should error on invalid additional fields", () => {
18701848
const expectedConfig = {
18711849
assets: {

packages/wrangler/src/__tests__/deploy.test.ts

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4291,7 +4291,7 @@ addEventListener('fetch', event => {});`
42914291
});
42924292
});
42934293

4294-
describe("--assets", () => {
4294+
describe("assets", () => {
42954295
it("should use the directory specified in the CLI over wrangler.toml", async () => {
42964296
const cliAssets = [
42974297
{ filePath: "cliAsset.txt", content: "Content of file-1" },
@@ -4326,6 +4326,36 @@ addEventListener('fetch', event => {});`
43264326
});
43274327
});
43284328

4329+
it("should use the directory specified in the CLI and allow the directory to be missing in the configuration", async () => {
4330+
const cliAssets = [
4331+
{ filePath: "cliAsset.txt", content: "Content of file-1" },
4332+
];
4333+
writeAssets(cliAssets, "cli-assets");
4334+
writeWranglerConfig({
4335+
assets: {},
4336+
});
4337+
const bodies: AssetManifest[] = [];
4338+
await mockAUSRequest(bodies);
4339+
mockSubDomainRequest();
4340+
mockUploadWorkerRequest({
4341+
expectedAssets: {
4342+
jwt: "<<aus-completion-token>>",
4343+
config: {},
4344+
},
4345+
expectedType: "none",
4346+
});
4347+
await runWrangler("deploy --assets cli-assets");
4348+
expect(bodies.length).toBe(1);
4349+
expect(bodies[0]).toEqual({
4350+
manifest: {
4351+
"/cliAsset.txt": {
4352+
hash: "0de3dd5df907418e9730fd2bd747bd5e",
4353+
size: 17,
4354+
},
4355+
},
4356+
});
4357+
});
4358+
43294359
it("should error if config.site and config.assets are used together", async () => {
43304360
writeWranglerConfig({
43314361
main: "./index.js",
@@ -4367,6 +4397,28 @@ addEventListener('fetch', event => {});`
43674397
);
43684398
});
43694399

4400+
it("should error if the directory path specified by the assets config is undefined", async () => {
4401+
writeWranglerConfig({
4402+
assets: {},
4403+
});
4404+
await expect(
4405+
runWrangler("deploy")
4406+
).rejects.toThrowErrorMatchingInlineSnapshot(
4407+
`[Error: The \`assets\` property in your configuration is missing the required \`directory\` property.]`
4408+
);
4409+
});
4410+
4411+
it("should error if the directory path specified by the assets config is an empty string", async () => {
4412+
writeWranglerConfig({
4413+
assets: { directory: "" },
4414+
});
4415+
await expect(
4416+
runWrangler("deploy")
4417+
).rejects.toThrowErrorMatchingInlineSnapshot(
4418+
`[Error: \`The assets directory cannot be an empty string.]`
4419+
);
4420+
});
4421+
43704422
it("should error if directory specified by config assets does not exist", async () => {
43714423
writeWranglerConfig({
43724424
assets: { directory: "abc" },

packages/wrangler/src/api/integrations/platform/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { kCurrentWorker, Miniflare } from "miniflare";
2-
import { processAssetsArg } from "../../../assets";
2+
import { getAssetsOptions } from "../../../assets";
33
import { readConfig } from "../../../config";
44
import { DEFAULT_MODULE_RULES } from "../../../deployment-bundle/rules";
55
import { getBindings } from "../../../dev";
@@ -309,7 +309,7 @@ export function unstable_getMiniflareWorkerOptions(
309309
? getLegacyAssetPaths(config, undefined)
310310
: getSiteAssetPaths(config);
311311
const sitesOptions = buildSitesOptions({ legacyAssetPaths });
312-
const processedAssetOptions = processAssetsArg({ assets: undefined }, config);
312+
const processedAssetOptions = getAssetsOptions({ assets: undefined }, config);
313313
const assetOptions = processedAssetOptions
314314
? buildAssetOptions({ assets: processedAssetOptions })
315315
: {};

packages/wrangler/src/api/startDevWorker/ConfigController.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
getScriptName,
1010
isLegacyEnv,
1111
} from "../..";
12-
import { processAssetsArg, validateAssetsArgsAndConfig } from "../../assets";
12+
import { getAssetsOptions, validateAssetsArgsAndConfig } from "../../assets";
1313
import { printBindings, readConfig } from "../../config";
1414
import { getEntry } from "../../deployment-bundle/entry";
1515
import {
@@ -248,7 +248,7 @@ async function resolveConfig(
248248

249249
const { bindings, unsafe } = await resolveBindings(config, input);
250250

251-
const assetsOptions = processAssetsArg(
251+
const assetsOptions = getAssetsOptions(
252252
{
253253
assets: input?.assets,
254254
script: input.entrypoint,

packages/wrangler/src/assets.ts

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import { dedent } from "./utils/dedent";
2424
import { createPatternMatcher } from "./utils/filesystem";
2525
import type { StartDevWorkerOptions } from "./api";
2626
import type { Config } from "./config";
27-
import type { Assets } from "./config/environment";
2827
import type { DeployArgs } from "./deploy";
2928
import type { StartDevOptions } from "./dev";
3029
import type { AssetConfig, RoutingConfig } from "@cloudflare/workers-shared";
@@ -310,12 +309,14 @@ function getAssetsBasePath(
310309
: path.resolve(path.dirname(config.configPath ?? "wrangler.toml"));
311310
}
312311

313-
export type AssetsOptions = Pick<Assets, "directory" | "binding"> & {
312+
export type AssetsOptions = {
313+
directory: string;
314+
binding?: string;
314315
routingConfig: RoutingConfig;
315316
assetConfig: AssetConfig;
316317
};
317318

318-
export function processAssetsArg(
319+
export function getAssetsOptions(
319320
args: { assets: string | undefined; script?: string },
320321
config: Config
321322
): AssetsOptions | undefined {
@@ -325,8 +326,20 @@ export function processAssetsArg(
325326
return;
326327
}
327328

329+
const { directory, binding } = assets;
330+
331+
if (directory === undefined) {
332+
throw new UserError(
333+
"The `assets` property in your configuration is missing the required `directory` property."
334+
);
335+
}
336+
337+
if (directory === "") {
338+
throw new UserError("`The assets directory cannot be an empty string.");
339+
}
340+
328341
const assetsBasePath = getAssetsBasePath(config, args.assets);
329-
const resolvedAssetsPath = path.resolve(assetsBasePath, assets.directory);
342+
const resolvedAssetsPath = path.resolve(assetsBasePath, directory);
330343

331344
if (!existsSync(resolvedAssetsPath)) {
332345
const sourceOfTruthMessage = args.assets
@@ -339,7 +352,6 @@ export function processAssetsArg(
339352
);
340353
}
341354

342-
assets.directory = resolvedAssetsPath;
343355
const routingConfig = {
344356
has_user_worker: Boolean(args.script || config.main),
345357
};
@@ -351,7 +363,8 @@ export function processAssetsArg(
351363
};
352364

353365
return {
354-
...assets,
366+
directory: resolvedAssetsPath,
367+
binding,
355368
routingConfig,
356369
assetConfig,
357370
};

packages/wrangler/src/config/environment.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -940,14 +940,21 @@ export interface UserLimits {
940940

941941
export type Assets = {
942942
/** Absolute path to assets directory */
943-
directory: string;
943+
directory?: string;
944+
/** Name of `env` binding property in the User Worker. */
944945
binding?: string;
946+
/** How to handle HTML requests. */
945947
html_handling?:
946948
| "auto-trailing-slash"
947949
| "force-trailing-slash"
948950
| "drop-trailing-slash"
949951
| "none";
952+
/** How to handle requests that do not match an asset. */
950953
not_found_handling?: "single-page-application" | "404-page" | "none";
954+
/**
955+
* If true, then respond to requests that match an asset with that asset directly.
956+
* If false, route every request to the User Worker, whether or not it matches an asset.
957+
* */
951958
experimental_serve_directly?: boolean;
952959
};
953960

packages/wrangler/src/config/validation-helpers.ts

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -231,27 +231,6 @@ export const isString: ValidatorFn = (diagnostics, field, value) => {
231231
return true;
232232
};
233233

234-
/**
235-
* Validate that the field is a non-empty string.
236-
*/
237-
export const isNonEmptyString: ValidatorFn = (
238-
diagnostics,
239-
field,
240-
value,
241-
topLevelEnv
242-
) => {
243-
if (!isString(diagnostics, field, value, topLevelEnv)) {
244-
return false;
245-
}
246-
247-
if ((value as string)?.trim() === "") {
248-
diagnostics.errors.push(`Expected "${field}" to be a non-empty string.`);
249-
return false;
250-
}
251-
252-
return true;
253-
};
254-
255234
/**
256235
* Validate that the `name` field is compliant with EWC constraints.
257236
*/

packages/wrangler/src/config/validation.ts

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@ import {
1515
inheritableInLegacyEnvironments,
1616
isBoolean,
1717
isMutuallyExclusiveWith,
18-
isNonEmptyString,
1918
isObjectWith,
2019
isOneOf,
2120
isOptionalProperty,
@@ -2122,22 +2121,14 @@ const validateAssetsConfig: ValidatorFn = (diagnostics, field, value) => {
21222121
// ensure we validate all props before we show the validation errors
21232122
// this way users have all the necessary info to fix all errors in one go
21242123
isValid =
2125-
validateRequiredProperty(
2124+
validateOptionalProperty(
21262125
diagnostics,
21272126
field,
21282127
"directory",
21292128
(value as Assets).directory,
21302129
"string"
21312130
) && isValid;
21322131

2133-
isValid =
2134-
isNonEmptyString(
2135-
diagnostics,
2136-
`${field}.directory`,
2137-
(value as Assets).directory,
2138-
undefined
2139-
) && isValid;
2140-
21412132
isValid =
21422133
validateOptionalProperty(
21432134
diagnostics,

packages/wrangler/src/deploy/index.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import assert from "node:assert";
22
import path from "node:path";
3-
import { processAssetsArg, validateAssetsArgsAndConfig } from "../assets";
3+
import { getAssetsOptions, validateAssetsArgsAndConfig } from "../assets";
44
import { configFileName, findWranglerConfig, readConfig } from "../config";
55
import { getEntry } from "../deployment-bundle/entry";
66
import { UserError } from "../errors";
@@ -301,7 +301,7 @@ async function deployWorker(args: DeployArgs) {
301301

302302
validateAssetsArgsAndConfig(args, config);
303303

304-
const assetsOptions = processAssetsArg(args, config);
304+
const assetsOptions = getAssetsOptions(args, config);
305305

306306
if (args.latest) {
307307
logger.warn(

0 commit comments

Comments
 (0)