Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Output .json by default in C3 #7676

Merged
merged 14 commits into from
Jan 10, 2025
5 changes: 5 additions & 0 deletions .changeset/young-apes-battle.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"create-cloudflare": patch
---

Output the `wrangler.json` config format when running `create-cloudflare`
6 changes: 3 additions & 3 deletions packages/create-cloudflare/src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ import {
} from "./templates";
import { validateProjectDirectory } from "./validators";
import { installWorkersTypes } from "./workers";
import { updateWranglerToml } from "./wrangler/config";
import { updateWranglerConfig } from "./wrangler/config";
import type { C3Args, C3Context } from "types";

const { npm } = detectPackageManager();
Expand Down Expand Up @@ -156,9 +156,9 @@ const configure = async (ctx: C3Context) => {
await installWrangler();
await installWorkersTypes(ctx);

// Note: updateWranglerToml _must_ be called before the configure phase since
// Note: This _must_ be called before the configure phase since
// pre-existing workers assume its presence in their configure phase
await updateWranglerToml(ctx);
await updateWranglerConfig(ctx);

const { template } = ctx;
if (template.configure) {
Expand Down
2 changes: 1 addition & 1 deletion packages/create-cloudflare/src/deploy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ const isDeployable = async (ctx: C3Context) => {
const readWranglerConfig = (ctx: C3Context) => {
if (wranglerJsonExists(ctx)) {
const wranglerJsonStr = readWranglerJson(ctx);
return jsoncParse(wranglerJsonStr);
return jsoncParse(wranglerJsonStr, undefined, { allowTrailingComma: true });
}
const wranglerTomlStr = readWranglerToml(ctx);
return TOML.parse(wranglerTomlStr.replace(/\r\n/g, "\n"));
Expand Down
2 changes: 1 addition & 1 deletion packages/create-cloudflare/src/helpers/compatDate.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import type { C3Context } from "types";

/**
* Look up the latest release of workerd and use its date as the compatibility_date
* configuration value for wrangler.toml.
* configuration value for a wrangler config file.
*
* If the look up fails then we fall back to a well known date.
*
Expand Down
285 changes: 246 additions & 39 deletions packages/create-cloudflare/src/wrangler/__tests__/config.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,22 +4,24 @@ import { getWorkerdCompatibilityDate } from "helpers/compatDate";
import { readFile, writeFile } from "helpers/files";
import { beforeEach, describe, expect, test, vi } from "vitest";
import { createTestContext } from "../../__tests__/helpers";
import { updateWranglerToml } from "../config";
import { updateWranglerConfig } from "../config";

vi.mock("helpers/files");
vi.mock("helpers/compatDate");
vi.mock("fs");

const mockCompatDate = "2024-01-17";

describe("updateWranglerToml", () => {
describe("update wrangler config", () => {
const ctx = createTestContext();

beforeEach(() => {
vi.mocked(getWorkerdCompatibilityDate).mockReturnValue(
Promise.resolve(mockCompatDate),
);
vi.mocked(existsSync).mockImplementation(() => true);
vi.mocked(existsSync).mockImplementation((f) =>
(f as string).endsWith(".toml"),
);
mockWorkersTypesDirectory();

// Mock the read of tsconfig.json
Expand All @@ -36,32 +38,119 @@ describe("updateWranglerToml", () => {
].join("\n");
vi.mocked(readFile).mockReturnValue(toml);

await updateWranglerToml(ctx);
await updateWranglerConfig(ctx);

const newToml = vi.mocked(writeFile).mock.calls[0][1];
expect(newToml).toBe(
`name = "${ctx.project.name}"\n` +
`main = "src/index.ts"\n` +
`compatibility_date = "${mockCompatDate}"`,
);
});
expect(newToml).toMatchInlineSnapshot(`
"#:schema node_modules/wrangler/config-schema.json
# For more details on how to configure Wrangler, refer to:
# https://developers.cloudflare.com/workers/wrangler/configuration/
name = "test"
main = "src/index.ts"
compatibility_date = "2024-01-17"

test("empty replacement", async () => {
const toml = [
`name = `,
`main = "src/index.ts"`,
`compatibility_date = `,
].join("\n");
vi.mocked(readFile).mockReturnValue(toml);
[observability]
enabled = true

await updateWranglerToml(ctx);
# Smart Placement
# Docs: https://developers.cloudflare.com/workers/configuration/smart-placement/#smart-placement
# [placement]
# mode = "smart"

const newToml = vi.mocked(writeFile).mock.calls[0][1];
expect(newToml).toBe(
`name = "${ctx.project.name}"\n` +
`main = "src/index.ts"\n` +
`compatibility_date = "${mockCompatDate}"`,
###
# Bindings
# Bindings allow your Worker to interact with resources on the Cloudflare Developer Platform, including
# databases, object storage, AI inference, real-time communication and more.
# https://developers.cloudflare.com/workers/runtime-apis/bindings/
###

# Environment Variables
# https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables
# [vars]
# MY_VARIABLE = "production_value"

# Note: Use secrets to store sensitive data.
# https://developers.cloudflare.com/workers/configuration/secrets/

# Static Assets
# https://developers.cloudflare.com/workers/static-assets/binding/
# [assets]
# directory = "./public/"
# binding = "ASSETS"

# Service Bindings (communicate between multiple Workers)
# https://developers.cloudflare.com/workers/wrangler/configuration/#service-bindings
# [[services]]
# binding = "MY_SERVICE"
# service = "my-service"
"
`);
});

test("placeholder replacement (json)", async () => {
vi.mocked(existsSync).mockImplementationOnce((f) =>
(f as string).endsWith(".json"),
);
const json = JSON.stringify({
name: "<TBD>",
main: "src/index.ts",
compatibility_date: "<TBD>",
});
vi.mocked(readFile).mockReturnValueOnce(json);

await updateWranglerConfig(ctx);

const newConfig = vi.mocked(writeFile).mock.calls[0][1];
expect(newConfig).toMatchInlineSnapshot(`
"/**
* For more details on how to configure Wrangler, refer to:
* https://developers.cloudflare.com/workers/wrangler/configuration/
*/
{
"$schema": "node_modules/wrangler/config-schema.json",
"name": "test",
"main": "src/index.ts",
"compatibility_date": "2024-01-17",
"observability": {
"enabled": true
},
/**
* Smart Placement
* Docs: https://developers.cloudflare.com/workers/configuration/smart-placement/#smart-placement
*/
// "placement": { "mode": "smart" },

/**
* Bindings
* Bindings allow your Worker to interact with resources on the Cloudflare Developer Platform, including
* databases, object storage, AI inference, real-time communication and more.
* https://developers.cloudflare.com/workers/runtime-apis/bindings/
*/

/**
* Environment Variables
* https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables
*/
// "vars": { "MY_VARIABLE": "production_value" },
/**
* Note: Use secrets to store sensitive data.
* https://developers.cloudflare.com/workers/configuration/secrets/
*/

/**
* Static Assets
* https://developers.cloudflare.com/workers/static-assets/binding/
*/
// "assets": { "directory": "./public/", "binding": "ASSETS" },

/**
* Service Bindings (communicate between multiple Workers)
* https://developers.cloudflare.com/workers/wrangler/configuration/#service-bindings
*/
// "services": [{ "binding": "MY_SERVICE", "service": "my-service" }]
}
"
`);
});

test("string literal replacement", async () => {
Expand All @@ -70,28 +159,106 @@ describe("updateWranglerToml", () => {
);
vi.mocked(readFile).mockReturnValue(toml);

await updateWranglerToml(ctx);
await updateWranglerConfig(ctx);

const newToml = vi.mocked(writeFile).mock.calls[0][1];
expect(newToml).toBe(
`compatibility_date = "${mockCompatDate}"\n` +
`name = "${ctx.project.name}"\n` +
`main = "src/index.ts"`,
);
expect(newToml).toMatchInlineSnapshot(`
"#:schema node_modules/wrangler/config-schema.json
# For more details on how to configure Wrangler, refer to:
# https://developers.cloudflare.com/workers/wrangler/configuration/
name = "test"
main = "src/index.ts"
compatibility_date = "2024-01-17"

[observability]
enabled = true

# Smart Placement
# Docs: https://developers.cloudflare.com/workers/configuration/smart-placement/#smart-placement
# [placement]
# mode = "smart"

###
# Bindings
# Bindings allow your Worker to interact with resources on the Cloudflare Developer Platform, including
# databases, object storage, AI inference, real-time communication and more.
# https://developers.cloudflare.com/workers/runtime-apis/bindings/
###

# Environment Variables
# https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables
# [vars]
# MY_VARIABLE = "production_value"

# Note: Use secrets to store sensitive data.
# https://developers.cloudflare.com/workers/configuration/secrets/

# Static Assets
# https://developers.cloudflare.com/workers/static-assets/binding/
# [assets]
# directory = "./public/"
# binding = "ASSETS"

# Service Bindings (communicate between multiple Workers)
# https://developers.cloudflare.com/workers/wrangler/configuration/#service-bindings
# [[services]]
# binding = "MY_SERVICE"
# service = "my-service"
"
`);
});

test("missing name and compat date", async () => {
const toml = `main = "src/index.ts"`;
vi.mocked(readFile).mockReturnValue(toml);

await updateWranglerToml(ctx);
await updateWranglerConfig(ctx);

const newToml = vi.mocked(writeFile).mock.calls[0][1];
expect(newToml).toBe(
`name = "${ctx.project.name}"\n` +
`compatibility_date = "${mockCompatDate}"\n` +
`main = "src/index.ts"`,
);
expect(newToml).toMatchInlineSnapshot(`
"#:schema node_modules/wrangler/config-schema.json
# For more details on how to configure Wrangler, refer to:
# https://developers.cloudflare.com/workers/wrangler/configuration/
main = "src/index.ts"
name = "test"
compatibility_date = "2024-01-17"

[observability]
enabled = true

# Smart Placement
# Docs: https://developers.cloudflare.com/workers/configuration/smart-placement/#smart-placement
# [placement]
# mode = "smart"

###
# Bindings
# Bindings allow your Worker to interact with resources on the Cloudflare Developer Platform, including
# databases, object storage, AI inference, real-time communication and more.
# https://developers.cloudflare.com/workers/runtime-apis/bindings/
###

# Environment Variables
# https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables
# [vars]
# MY_VARIABLE = "production_value"

# Note: Use secrets to store sensitive data.
# https://developers.cloudflare.com/workers/configuration/secrets/

# Static Assets
# https://developers.cloudflare.com/workers/static-assets/binding/
# [assets]
# directory = "./public/"
# binding = "ASSETS"

# Service Bindings (communicate between multiple Workers)
# https://developers.cloudflare.com/workers/wrangler/configuration/#service-bindings
# [[services]]
# binding = "MY_SERVICE"
# service = "my-service"
"
`);
});

test("dont replace valid existing compatibility date", async () => {
Expand All @@ -101,11 +268,51 @@ describe("updateWranglerToml", () => {
].join("\n");
vi.mocked(readFile).mockReturnValue(toml);

await updateWranglerToml(ctx);
await updateWranglerConfig(ctx);

const newToml = vi.mocked(writeFile).mock.calls[0][1];
expect(newToml).toBe(
`name = "test"\n` + `compatibility_date = "2001-10-12"`,
);
expect(newToml).toMatchInlineSnapshot(`
"#:schema node_modules/wrangler/config-schema.json
# For more details on how to configure Wrangler, refer to:
# https://developers.cloudflare.com/workers/wrangler/configuration/
name = "test"
compatibility_date = "2001-10-12"

[observability]
enabled = true

# Smart Placement
# Docs: https://developers.cloudflare.com/workers/configuration/smart-placement/#smart-placement
# [placement]
# mode = "smart"

###
# Bindings
# Bindings allow your Worker to interact with resources on the Cloudflare Developer Platform, including
# databases, object storage, AI inference, real-time communication and more.
# https://developers.cloudflare.com/workers/runtime-apis/bindings/
###

# Environment Variables
# https://developers.cloudflare.com/workers/wrangler/configuration/#environment-variables
# [vars]
# MY_VARIABLE = "production_value"

# Note: Use secrets to store sensitive data.
# https://developers.cloudflare.com/workers/configuration/secrets/

# Static Assets
# https://developers.cloudflare.com/workers/static-assets/binding/
# [assets]
# directory = "./public/"
# binding = "ASSETS"

# Service Bindings (communicate between multiple Workers)
# https://developers.cloudflare.com/workers/wrangler/configuration/#service-bindings
# [[services]]
# binding = "MY_SERVICE"
# service = "my-service"
"
`);
});
});
Loading
Loading