Skip to content

Commit bb47e20

Browse files
Support Analog in autoconfig (#11576)
1 parent c15e99e commit bb47e20

File tree

7 files changed

+152
-1
lines changed

7 files changed

+152
-1
lines changed

.changeset/sour-tables-jump.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"wrangler": minor
3+
---
4+
5+
Support Analog projects in autoconfig

.changeset/wicked-oranges-fix.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"create-cloudflare": minor
3+
---
4+
5+
Support Analog in `--experimental` mode

packages/create-cloudflare/e2e/tests/cli/cli.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -555,7 +555,7 @@ describe("Create Cloudflare CLI", () => {
555555
npm create cloudflare -- --framework svelte -- --types=ts
556556
pnpm create cloudflare --framework svelte -- --types=ts
557557
Allowed Values:
558-
angular, astro, docusaurus, gatsby, nuxt, qwik, react, react-router, redwood, solid, svelte, tanstack-start, vue
558+
analog, angular, astro, docusaurus, gatsby, nuxt, qwik, react, react-router, redwood, solid, svelte, tanstack-start, vue
559559
--platform=<value>
560560
Whether the application should be deployed to Pages or Workers. This is only applicable for Frameworks templates that support both Pages and Workers.
561561
Allowed Values:

packages/create-cloudflare/e2e/tests/frameworks/test-config.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -956,6 +956,24 @@ function getExperimentalFrameworkTestConfig(
956956
GITHUB_API_TOKEN: process.env.GITHUB_TOKEN,
957957
},
958958
},
959+
{
960+
name: "analog",
961+
testCommitMessage: true,
962+
timeout: LONG_TIMEOUT,
963+
unsupportedOSs: ["win32"],
964+
verifyDeploy: {
965+
route: "/",
966+
expectedText: "The fullstack Angular meta-framework",
967+
},
968+
verifyPreview: {
969+
previewArgs: ["--inspector-port=0"],
970+
route: "/api/v1/hello",
971+
expectedText: "Hello World",
972+
},
973+
nodeCompat: false,
974+
flags: ["--skipTailwind"],
975+
verifyTypes: false,
976+
},
959977
];
960978
}
961979

packages/create-cloudflare/src/templates.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -237,6 +237,7 @@ export type TemplateMap = Record<
237237
export function getFrameworkMap({ experimental = false }): TemplateMap {
238238
if (experimental) {
239239
return {
240+
analog: analogTemplate,
240241
angular: angularTemplate,
241242
astro: astroTemplate,
242243
docusaurus: docusaurusTemplate,
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
import assert from "node:assert";
2+
import { existsSync } from "node:fs";
3+
import { join } from "node:path";
4+
import { updateStatus } from "@cloudflare/cli";
5+
import { blue } from "@cloudflare/cli/colors";
6+
import * as recast from "recast";
7+
import semiver from "semiver";
8+
import { getDevCompatibilityDate } from "../../utils/compatibility-date";
9+
import { mergeObjectProperties, transformFile } from "../c3-vendor/codemod";
10+
import { Framework, getInstalledPackageVersion } from ".";
11+
import type { ConfigurationOptions, ConfigurationResults } from ".";
12+
13+
export class Analog extends Framework {
14+
async configure({
15+
dryRun,
16+
projectPath,
17+
}: ConfigurationOptions): Promise<ConfigurationResults> {
18+
checkMinimumAnalogVersion(projectPath);
19+
20+
if (!dryRun) {
21+
await updateViteConfig(projectPath);
22+
}
23+
return {
24+
wranglerConfig: {
25+
main: "./dist/analog/server/index.mjs",
26+
assets: {
27+
binding: "ASSETS",
28+
directory: "./dist/analog/public",
29+
},
30+
},
31+
};
32+
}
33+
}
34+
35+
async function updateViteConfig(projectPath: string) {
36+
const viteConfigTsPAth = join(projectPath, "vite.config.ts");
37+
const viteConfigJsPath = join(projectPath, "vite.config.js");
38+
39+
let viteConfigPath: string;
40+
41+
if (existsSync(viteConfigTsPAth)) {
42+
viteConfigPath = viteConfigTsPAth;
43+
} else if (existsSync(viteConfigJsPath)) {
44+
viteConfigPath = viteConfigJsPath;
45+
} else {
46+
throw new Error("Could not find Vite config file to modify");
47+
}
48+
49+
const compatDate = getDevCompatibilityDate(undefined);
50+
51+
updateStatus(`Updating configuration in ${blue(viteConfigPath)}`);
52+
53+
transformFile(viteConfigPath, {
54+
visitCallExpression: function (n) {
55+
const callee = n.node.callee as recast.types.namedTypes.Identifier;
56+
if (callee.name !== "analog") {
57+
return this.traverse(n);
58+
}
59+
60+
const b = recast.types.builders;
61+
const presetDef = [
62+
b.objectProperty(
63+
b.identifier("nitro"),
64+
b.objectExpression([
65+
// preset: "cloudflare_module"
66+
b.objectProperty(
67+
b.identifier("preset"),
68+
b.stringLiteral("cloudflare_module")
69+
),
70+
b.objectProperty(
71+
b.identifier("compatibilityDate"),
72+
b.stringLiteral(compatDate)
73+
),
74+
])
75+
),
76+
];
77+
78+
if (n.node.arguments.length === 0) {
79+
n.node.arguments.push(b.objectExpression(presetDef));
80+
} else {
81+
mergeObjectProperties(
82+
n.node.arguments[0] as recast.types.namedTypes.ObjectExpression,
83+
presetDef
84+
);
85+
}
86+
87+
return false;
88+
},
89+
});
90+
}
91+
92+
/**
93+
* Checks that the project's analog version to ensure that it is greater than 2.0.0, an error is thrown if it isn't.
94+
*
95+
* We preform this check because, prior to v2 Analog had a different implementation, so the autoconfig configuration steps
96+
* would be significantly different for such versions, also some of those versions had some incompatibility with what was
97+
* at the time our integration solution with Analog (and we didn't get to the bottom of those issues), for these two reasons
98+
* we just say what analog pre-v2 is not supported (of course we can always revisit this in the future is needed).
99+
*
100+
* @param projectPath The path of the project
101+
*/
102+
function checkMinimumAnalogVersion(projectPath: string): void {
103+
const analogJsVersion = getInstalledPackageVersion(
104+
"@analogjs/platform",
105+
projectPath
106+
);
107+
108+
assert(
109+
analogJsVersion,
110+
"Unable to discern the version of the `@analogjs/platform` package"
111+
);
112+
113+
if (semiver(analogJsVersion, "2.0.0") < 0) {
114+
// Note: analog, prior to v2 had a different implementation so the configuration steps here would be significantly different,
115+
// also some of those analog versions had some incompatibility with what was at the time our integration solution with analog,
116+
// for these two reasons we just say what analog pre-v2 is not supported
117+
throw new Error("Analog versions earlier than 2.0.0 are not supported");
118+
}
119+
}

packages/wrangler/src/autoconfig/frameworks/get-framework.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { Analog } from "./analog";
12
import { Angular } from "./angular";
23
import { Astro } from "./astro";
34
import { Nuxt } from "./nuxt";
@@ -33,6 +34,8 @@ export function getFramework(detectedFramework?: {
3334
return new Qwik(detectedFramework.name);
3435
case "vite":
3536
return new Vite(detectedFramework.name);
37+
case "analog":
38+
return new Analog(detectedFramework.name);
3639
default:
3740
return new Static(detectedFramework?.name);
3841
}

0 commit comments

Comments
 (0)