Skip to content

Commit e00dd59

Browse files
authored
Merge pull request #47 from solidjs-community/fix/spa-vite-config
Add vite config handling for SPAs
2 parents 0c4ffb3 + 36b0d4e commit e00dd59

11 files changed

Lines changed: 135 additions & 46 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
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import { defineConfig } from "@solidjs/start/config";
2+
// Simulates an app config
3+
export default defineConfig({
4+
vite: {
5+
plugins: [solid()]
6+
}
7+
});

packages/commands/tests/assets/sample_unocss_result.txt renamed to packages/commands/tests/assets/sample_unocss_app_result.txt

File renamed without changes.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import UnoCss from "unocss/vite";
2+
import { defineConfig } from "vite";
3+
// Simulates an app config
4+
export default defineConfig({
5+
plugins: [
6+
solid(),
7+
UnoCss({})
8+
]
9+
});
Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
import { defineConfig } from "@solidjs/start/config";
1+
import { defineConfig } from "vite";
22
// Simulates an app config
33
export default defineConfig({
4-
vite: {
5-
plugins: [solid()]
6-
}
4+
plugins: [solid()]
75
});

packages/commands/tests/config_manipulation.test.ts

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,21 @@ const readFile = async (path: string): Promise<string> => {
99
readFile1(path, (_, data) => res(data.toString())),
1010
);
1111
};
12+
1213
const removeWhitespace = (str: string) => str.replace(/\s/g, "");
14+
1315
vi.mock("fs/promises", () => {
1416
return {
1517
readFile: async (name: string) => {
1618
if (name === "app.config.ts") {
19+
const sampleConfig: string = await readFile("./packages/commands/tests/assets/sample_app_config.txt");
20+
return sampleConfig;
21+
}
22+
if (name === "vite.config.ts") {
1723
const sampleConfig: string = await readFile("./packages/commands/tests/assets/sample_vite_config.txt");
1824
return sampleConfig;
1925
}
26+
2027
return "{}";
2128
},
2229
writeFile: async (_, contents: string) => {
@@ -46,22 +53,41 @@ vi.mock("@solid-cli/utils/updates", async () => {
4653

4754
vi.mock("../src/lib/utils/helpers.ts", async () => {
4855
return {
49-
getAppConfig: async (): Promise<string> => new Promise((r) => r("app.config.ts")),
50-
fileExists: (path: string) => path.includes("app_config") || path.includes("app.tsx") || path.includes("index.tsx"),
56+
getConfigFile: async (file: string): Promise<string> => new Promise((r) => r(`${file}.config.ts`)),
57+
fileExists: (path: string) =>
58+
path.includes("vite_config") ||
59+
path.includes("app_config") ||
60+
path.includes("app.tsx") ||
61+
path.includes("index.tsx"),
5162
getRootFile: async (): Promise<string> => new Promise((r) => r("./src/app.tsx")),
5263
};
5364
});
65+
66+
let testingSolidStart = false;
67+
68+
vi.mock("@solid-cli/utils", async () => {
69+
return {
70+
isSolidStart: async () => new Promise((r) => r(testingSolidStart)),
71+
};
72+
});
73+
5474
describe("Update config", () => {
55-
it(
56-
"Adds a plugin properly to the config",
57-
async () => {
58-
await handleAdd(["unocss"]);
75+
it("Adds a plugin properly to the app config", { timeout: 50000 }, async () => {
76+
testingSolidStart = true;
77+
await handleAdd(["unocss"]);
5978

60-
const expected = await readFile("./packages/commands/tests/assets/sample_unocss_result.txt");
61-
// @ts-ignore
62-
const newConfig = UPDATESQUEUE.find((u) => u.name === "app.config.ts")?.contents;
63-
expect(removeWhitespace(expected)).toBe(removeWhitespace(newConfig));
64-
},
65-
{ timeout: 50000 },
66-
);
79+
const expected = await readFile("./packages/commands/tests/assets/sample_unocss_app_result.txt");
80+
// @ts-ignore
81+
const newConfig = UPDATESQUEUE.find((u) => u.name === "app.config.ts")?.contents;
82+
expect(removeWhitespace(newConfig)).toBe(removeWhitespace(expected));
83+
});
84+
it("Adds a plugin properly to the vite config", { timeout: 50000 }, async () => {
85+
testingSolidStart = false;
86+
await handleAdd(["unocss"]);
87+
88+
const expected = await readFile("./packages/commands/tests/assets/sample_unocss_vite_result.txt");
89+
// @ts-ignore
90+
const newConfig = UPDATESQUEUE.find((u) => u.name === "vite.config.ts")?.contents;
91+
expect(removeWhitespace(newConfig)).toBe(removeWhitespace(expected));
92+
});
6793
});

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

0 commit comments

Comments
 (0)