Skip to content

Commit 17cdba5

Browse files
committed
Add vite config handling for SPAs.
1 parent 263396e commit 17cdba5

7 files changed

Lines changed: 78 additions & 30 deletions

File tree

packages/commands/src/handlers/add.ts

Lines changed: 20 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ import { Integrations, Supported, integrations, setRootFile } from "../lib/integ
44
import * as p from "@clack/prompts";
55
import color from "picocolors";
66
import { primitives, loadPrimitives } from "@solid-cli/utils/primitives";
7-
import { t } from "@solid-cli/utils";
8-
import { fileExists, getRootFile, getAppConfig, validateFilePath } from "../lib/utils/helpers";
7+
import { isSolidStart, t } from "@solid-cli/utils";
8+
import { fileExists, getRootFile, getConfigFile, validateFilePath } from "../lib/utils/helpers";
99
import { writeFile, readFile } from "@solid-cli/utils/fs";
1010
import { transformPlugins, type PluginOptions } from "@solid-cli/utils/transform";
1111
import {
@@ -43,8 +43,9 @@ const handleAutocompleteAdd = async () => {
4343
{ label: t.NO, value: false },
4444
{ label: t.YES_FORCE, value: [true, "force"] },
4545
],
46-
message: `${t.CONFIRM_INSTALL(a.length)} \n${color.red(S_BAR)} \n${color.red(S_BAR)} ${" " + color.yellow(a.map((opt) => opt.label).join(" ")) + " "
47-
} \n${color.red(S_BAR)} `,
46+
message: `${t.CONFIRM_INSTALL(a.length)} \n${color.red(S_BAR)} \n${color.red(S_BAR)} ${
47+
" " + color.yellow(a.map((opt) => opt.label).join(" ")) + " "
48+
} \n${color.red(S_BAR)} `,
4849
}),
4950
);
5051

@@ -109,7 +110,9 @@ export const handleAdd = async (packages?: string[], forceTransform: boolean = f
109110
})
110111
.filter((p) => p) as Configs;
111112

112-
const appConfig = await getAppConfig();
113+
const configType = (await isSolidStart()) ? "app" : "vite";
114+
115+
const configFile = await getConfigFile(configType);
113116

114117
for (let i = 0; i < configs.length; i++) {
115118
const config = configs[i];
@@ -124,20 +127,19 @@ export const handleAdd = async (packages?: string[], forceTransform: boolean = f
124127
if (!configs.length) return;
125128
const pluginOptions = configs.map((c) => c.pluginOptions).filter(Boolean) as PluginOptions[];
126129
if (pluginOptions.length) {
127-
const appConfig = await getAppConfig();
128130
await spinnerify({
129-
startText: "Processing config",
130-
finishText: "Config processed",
131-
fn: async () => {
132-
const code = await transformPlugins(
133-
configs.map((c) => c.pluginOptions).filter(Boolean) as PluginOptions[],
134-
{ name: appConfig, contents: (await readFile(appConfig)).toString() },
135-
forceTransform,
136-
undefined,
137-
);
138-
await writeFile(appConfig, code);
139-
},
140-
});
131+
startText: "Processing config",
132+
finishText: "Config processed",
133+
fn: async () => {
134+
const code = await transformPlugins(
135+
configs.map((c) => c.pluginOptions).filter(Boolean) as PluginOptions[],
136+
{ type: configType, name: configFile, contents: (await readFile(configFile)).toString() },
137+
forceTransform,
138+
undefined,
139+
);
140+
await writeFile(configFile, code);
141+
},
142+
});
141143
}
142144

143145
p.log.info("Preparing post install steps for integrations");

packages/commands/src/handlers/start/adapter.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ export const handleAdapter = async (name?: string, forceTransform = false) => {
3434
const sym = Symbol(name).toString();
3535
let code = await transformPlugins(
3636
[],
37-
{ name: "app.config.ts", contents: (await readFile("app.config.ts")).toString() },
37+
{ type: "app", name: "app.config.ts", contents: (await readFile("app.config.ts")).toString() },
3838
forceTransform,
3939
);
4040
code = `import ${name} from "solid-start-${name}";\n` + code;

packages/commands/src/handlers/start/mode.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export const handleMode = async (mode?: SupportedModes) => {
3030
if (mode != "ssg") {
3131
const newConfig = await transformPlugins(
3232
[],
33-
{ name: "app.config.ts", contents: (await readFile("app.config.ts")).toString() },
33+
{ type: "app", name: "app.config.ts", contents: (await readFile("app.config.ts")).toString() },
3434
true,
3535
true,
3636
);

packages/commands/src/lib/utils/helpers.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -99,30 +99,30 @@ export async function findFiles(
9999
return filePaths;
100100
}
101101

102-
export const getAppConfig = async () => {
103-
let configFile = "app.config.ts";
102+
export const getConfigFile = async (file: "app" | "vite" = "app") => {
103+
let configFile = `${file}.config.ts`;
104104

105105
const existsHere = fileExists(configFile);
106106

107107
if (!existsHere) {
108108
const root = await getProjectRoot();
109-
const existsInRoot = validateFilePath(root, "app.config");
109+
const existsInRoot = validateFilePath(root, `${file}.config`);
110110
if (existsInRoot) {
111111
const correctConfig = await cancelable(
112112
p.confirm({
113-
message: `Could not find app config in current directory, but found app config in \`${root}\`. Is this the correct vite config?`,
113+
message: `Could not find ${file} config in current directory, but found ${file} config in \`${root}\`. Is this the correct ${file} config?`,
114114
}),
115115
);
116116
if (correctConfig) return existsInRoot;
117117
}
118118

119-
p.log.error(color.red(`Can't find app.config file`));
119+
p.log.error(color.red(`Can't find ${file}.config file`));
120120
await cancelable(
121121
p.text({
122-
message: "Type path to app config: ",
122+
message: `Type path to ${file} config: `,
123123
validate(value) {
124-
const path = validateFilePath(value, "app.config");
125-
if (!path) return `App config not found. Please try again`;
124+
const path = validateFilePath(value, `${file}.config`);
125+
if (!path) return `${file} config not found. Please try again`;
126126
else {
127127
configFile = path;
128128
}

packages/commands/tests/config_manipulation.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ vi.mock("@solid-cli/utils/updates", async () => {
4646

4747
vi.mock("../src/lib/utils/helpers.ts", async () => {
4848
return {
49-
getAppConfig: async (): Promise<string> => new Promise((r) => r("app.config.ts")),
49+
getConfigFile: async (file): Promise<string> => new Promise((r) => r(`${file}.config.ts`)),
5050
fileExists: (path: string) => path.includes("app_config") || path.includes("app.tsx") || path.includes("index.tsx"),
5151
getRootFile: async (): Promise<string> => new Promise((r) => r("./src/app.tsx")),
5252
};

packages/utils/src/transform/index.ts

Lines changed: 17 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
import { parseModule } from "magicast";
1+
import { generateCode, parseModule } from "magicast";
2+
import { addVitePlugin } from "magicast/helpers";
23
import { addPlugins } from "./parse";
34

45
export type Config = {
6+
type: "app" | "vite";
57
name: string;
68
contents: string;
79
};
@@ -15,6 +17,20 @@ export const transformPlugins = async (
1517
_merge_configs = false,
1618
) => {
1719
const mod = parseModule(config.contents, { trailingComma: false, flowObjectCommas: false });
20+
21+
if (config.type === "vite") {
22+
for (const plugin of new_plugins) {
23+
addVitePlugin(mod, {
24+
imported: plugin.isDefault ? "default" : plugin.importName,
25+
from: plugin.importSource,
26+
constructor: plugin.importName,
27+
options: plugin.options,
28+
});
29+
}
30+
31+
return generateCode(mod).code;
32+
}
33+
1834
return addPlugins(mod, new_plugins).code;
1935
};
2036
// All the integrations/packages that we support

packages/utils/tests/plugin_transforms.test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,36 @@ const examplePlugin: PluginOptions = {
4949
options: {},
5050
};
5151
describe("transformPlugins", () => {
52+
test("SPA config is updated properly", async () => {
53+
const config: Config = {
54+
type: "vite",
55+
name: "vite.config.ts",
56+
contents: `
57+
import { defineConfig } from "vite";
58+
59+
// Simulates a vite config
60+
export default defineConfig({
61+
plugins: []
62+
});
63+
`,
64+
};
65+
const expected = `
66+
import examplePlugin from "example";
67+
import { defineConfig } from "vite";
68+
69+
// Simulates a vite config
70+
export default defineConfig({
71+
plugins: [examplePlugin({})]
72+
});
73+
`;
74+
75+
const result = await transformPlugins([examplePlugin], config);
76+
77+
expect(removeWhitespace(result)).toBe(removeWhitespace(expected));
78+
});
5279
test("No vite property defined config is updated properly", async () => {
5380
const config: Config = {
81+
type: "app",
5482
name: "app.config.ts",
5583
contents: `
5684
import { defineConfig } from "@solidjs/start/config";
@@ -67,6 +95,7 @@ describe("transformPlugins", () => {
6795
});
6896
test("Object config is updated properly", async () => {
6997
const config: Config = {
98+
type: "app",
7099
name: "app.config.ts",
71100
contents: makeExampleConfig(["solid()"]),
72101
};
@@ -77,6 +106,7 @@ describe("transformPlugins", () => {
77106
});
78107
test("Arrow-function config is updated properly", async () => {
79108
const config: Config = {
109+
type: "app",
80110
name: "app.config.ts",
81111
contents: makeExampleConfig(["solid()"], [], "arrow"),
82112
};

0 commit comments

Comments
 (0)