Skip to content

Commit d2447c6

Browse files
GregBrimbleCarmenPopoviciu
andauthoredDec 9, 2024··
fix(wrangler): Add more helpful error messages when validating compatibility date (#7002)
* Add more helpful error messages when validating compatibility date * PR feedback --------- Co-authored-by: Carmen Popoviciu <cpopoviciu@cloudflare.com>
1 parent 0920d13 commit d2447c6

File tree

4 files changed

+163
-1
lines changed

4 files changed

+163
-1
lines changed
 

‎.changeset/fifty-dots-end.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"wrangler": patch
3+
---
4+
5+
fix: More helpful error messages when validating compatibility date

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

+100
Original file line numberDiff line numberDiff line change
@@ -283,6 +283,106 @@ describe("normalizeAndValidateConfig()", () => {
283283
`);
284284
});
285285

286+
describe("compatibility_date", () => {
287+
it("should allow valid values", () => {
288+
const expectedConfig: RawConfig = {
289+
compatibility_date: "2024-10-01",
290+
};
291+
292+
const { config, diagnostics } = normalizeAndValidateConfig(
293+
expectedConfig,
294+
undefined,
295+
{ env: undefined }
296+
);
297+
298+
expect(config).toEqual(expect.objectContaining(expectedConfig));
299+
expect(diagnostics.hasWarnings()).toBe(false);
300+
expect(diagnostics.hasErrors()).toBe(false);
301+
});
302+
303+
it("should error for en-dashes", () => {
304+
const expectedConfig: RawConfig = {
305+
compatibility_date: "2024–10–01", // en-dash
306+
};
307+
308+
const result = normalizeAndValidateConfig(expectedConfig, undefined, {
309+
env: undefined,
310+
});
311+
312+
expect(result.config).toEqual(expect.objectContaining(expectedConfig));
313+
expect(result.diagnostics.hasWarnings()).toBe(false);
314+
expect(result.diagnostics.hasErrors()).toBe(true);
315+
316+
expect(normalizeString(result.diagnostics.renderErrors()))
317+
.toMatchInlineSnapshot(`
318+
"Processing wrangler configuration:
319+
- \\"compatibility_date\\" field should use ISO-8601 accepted hyphens (-) rather than en-dashes (–) or em-dashes (—)."
320+
`);
321+
});
322+
323+
it("should error for em-dashes", () => {
324+
const expectedConfig = {
325+
compatibility_date: "2024—10—01", // em-dash
326+
};
327+
328+
const result = normalizeAndValidateConfig(expectedConfig, undefined, {
329+
env: undefined,
330+
});
331+
332+
expect(result.config).toEqual(expect.objectContaining(expectedConfig));
333+
expect(result.diagnostics.hasWarnings()).toBe(false);
334+
expect(result.diagnostics.hasErrors()).toBe(true);
335+
336+
expect(normalizeString(result.diagnostics.renderErrors()))
337+
.toMatchInlineSnapshot(`
338+
"Processing wrangler configuration:
339+
- \\"compatibility_date\\" field should use ISO-8601 accepted hyphens (-) rather than en-dashes (–) or em-dashes (—)."
340+
`);
341+
});
342+
343+
it("should error for invalid date values", () => {
344+
const expectedConfig: RawConfig = {
345+
compatibility_date: "abc",
346+
};
347+
348+
const { config, diagnostics } = normalizeAndValidateConfig(
349+
expectedConfig,
350+
undefined,
351+
{ env: undefined }
352+
);
353+
354+
expect(config).toEqual(expect.objectContaining(expectedConfig));
355+
expect(diagnostics.hasErrors()).toBe(true);
356+
357+
expect(normalizeString(diagnostics.renderErrors()))
358+
.toMatchInlineSnapshot(`
359+
"Processing wrangler configuration:
360+
- \\"compatibility_date\\" field should be a valid ISO-8601 date (YYYY-MM-DD), but got \\"abc\\"."
361+
`);
362+
});
363+
364+
it("should error for dates that are both invalid and include en/em dashes", () => {
365+
const expectedConfig = {
366+
compatibility_date: "2024—100—01", // invalid date + em-dash
367+
};
368+
369+
const result = normalizeAndValidateConfig(expectedConfig, undefined, {
370+
env: undefined,
371+
});
372+
373+
expect(result.config).toEqual(expect.objectContaining(expectedConfig));
374+
expect(result.diagnostics.hasWarnings()).toBe(false);
375+
expect(result.diagnostics.hasErrors()).toBe(true);
376+
377+
expect(normalizeString(result.diagnostics.renderErrors()))
378+
.toMatchInlineSnapshot(`
379+
"Processing wrangler configuration:
380+
- \\"compatibility_date\\" field should use ISO-8601 accepted hyphens (-) rather than en-dashes (–) or em-dashes (—).
381+
- \\"compatibility_date\\" field should be a valid ISO-8601 date (YYYY-MM-DD), but got \\"2024—100—01\\"."
382+
`);
383+
});
384+
});
385+
286386
describe("[site]", () => {
287387
it("should override `site` config defaults with provided values", () => {
288388
const expectedConfig: RawConfig = {

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

+41
Original file line numberDiff line numberDiff line change
@@ -250,6 +250,47 @@ export const isValidName: ValidatorFn = (diagnostics, field, value) => {
250250
}
251251
};
252252

253+
/**
254+
* Validate that the field is a valid ISO-8601 date time string
255+
* see https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#date_time_string_format
256+
* or https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-date-time-string-format
257+
*/
258+
export const isValidDateTimeStringFormat = (
259+
diagnostics: Diagnostics,
260+
field: string,
261+
value: string
262+
): boolean => {
263+
let isValid = true;
264+
265+
// en/em dashes are not valid characters in the JS date time string format.
266+
// While they would be caught by the `isNaN(data.getTime())` check below,
267+
// we want to single these use cases out, and throw a more specific error
268+
if (
269+
value.includes("–") || // en-dash
270+
value.includes("—") // em-dash
271+
) {
272+
diagnostics.errors.push(
273+
`"${field}" field should use ISO-8601 accepted hyphens (-) rather than en-dashes (–) or em-dashes (—).`
274+
);
275+
isValid = false;
276+
}
277+
278+
// en/em dashes were already handled above. Let's replace them with hyphens,
279+
// which is a valid date time string format character, and evaluate the
280+
// resulting date time string further. This ensures we validate for hyphens
281+
// only once!
282+
const data = new Date(value.replaceAll(/|/g, "-"));
283+
284+
if (isNaN(data.getTime())) {
285+
diagnostics.errors.push(
286+
`"${field}" field should be a valid ISO-8601 date (YYYY-MM-DD), but got ${JSON.stringify(value)}.`
287+
);
288+
isValid = false;
289+
}
290+
291+
return isValid;
292+
};
293+
253294
/**
254295
* Validate that the field is an array of strings.
255296
*/

‎packages/wrangler/src/config/validation.ts

+17-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import {
2222
isRequiredProperty,
2323
isString,
2424
isStringArray,
25+
isValidDateTimeStringFormat,
2526
isValidName,
2627
notInheritable,
2728
validateAdditionalProperties,
@@ -1173,7 +1174,7 @@ function normalizeAndValidateEnvironment(
11731174
topLevelEnv,
11741175
rawEnv,
11751176
"compatibility_date",
1176-
isString,
1177+
validateCompatibilityDate,
11771178
undefined
11781179
),
11791180
compatibility_flags: inheritable(
@@ -3216,6 +3217,21 @@ const validateConsumer: ValidatorFn = (diagnostics, field, value, _config) => {
32163217
return isValid;
32173218
};
32183219

3220+
const validateCompatibilityDate: ValidatorFn = (diagnostics, field, value) => {
3221+
if (value === undefined) {
3222+
return true;
3223+
}
3224+
3225+
if (typeof value !== "string") {
3226+
diagnostics.errors.push(
3227+
`Expected "${field}" to be of type string but got ${JSON.stringify(value)}.`
3228+
);
3229+
return false;
3230+
}
3231+
3232+
return isValidDateTimeStringFormat(diagnostics, field, value);
3233+
};
3234+
32193235
const validatePipelineBinding: ValidatorFn = (diagnostics, field, value) => {
32203236
if (typeof value !== "object" || value === null) {
32213237
diagnostics.errors.push(

0 commit comments

Comments
 (0)
Please sign in to comment.