Skip to content

Commit 7fa690d

Browse files
authored
Merge pull request #43 from atk/tauri-integration
feat: tauri integration
2 parents e00dd59 + bd3e725 commit 7fa690d

3 files changed

Lines changed: 159 additions & 94 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ A custom-built CLI for creating and managing SolidJS apps and projects.
2929
- [x] UnoCSS
3030
- [ ] Vanilla Extract
3131
- [x] Vitest
32-
- [ ] Tauri
32+
- [x] Tauri
3333
- [ ] Playwright
3434
- [ ] Utilities
3535
- [ ] eslint-plugin-solid

packages/commands/src/lib/integrations.ts

Lines changed: 67 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { insertAfter, insertAtBeginning } from "@solid-cli/utils/fs";
2-
import { readFile, writeFile } from "fs/promises";
3-
import { fileExists, validateFilePath } from "./utils/helpers";
2+
import { writeFile } from "fs/promises";
3+
import { fileExists, manipulateJsonFile, validateFilePath } from "./utils/helpers";
44
import { $ } from "execa";
55
import { getRunnerCommand, detectPackageManager } from "@solid-cli/utils/package-manager";
66
import { createSignal } from "@solid-cli/reactivity";
@@ -123,27 +123,30 @@ export const integrations: Record<string, IntegrationsValue> = {
123123
additionalConfig: async () => {
124124
try {
125125
p.log.info("Adding test script to package.json");
126-
const packageJsonString = await readFile("package.json", "utf8");
127-
const packageJson = JSON.parse(packageJsonString);
128-
if (!/\bvitest\b/.test(packageJson.scripts.test || "")) {
129-
packageJson.scripts.test = "vitest";
130-
await writeFile("package.json", JSON.stringify(packageJson, null, 2) + "\n", "utf8");
131-
}
126+
let hasStart = false;
127+
manipulateJsonFile("package.json", (packageJson) => {
128+
if (!packageJson.scripts) { packageJson.scripts = {}; }
129+
if (!/\bvitest\b/.test(packageJson.scripts.test || "")) {
130+
packageJson.scripts.test = "vitest";
131+
}
132+
hasStart = packageJson.dependencies["@solidjs/start"]
133+
return packageJson;
134+
});
132135
const hasTs = fileExists("tsconfig.json");
133-
if (hasTs) {
136+
if (hasTs) {
134137
p.log.info("Adding testing types to tsconfig.json");
135-
const tsConfigString = await readFile("tsconfig.json", "utf8");
136-
const tsConfig = JSON.parse(tsConfigString);
137-
if (!tsConfig.compilerOptions) {
138-
tsConfig.compilerOptions = {};
139-
}
140-
tsConfig.compilerOptions.types = [
141-
...new Set([...(tsConfig.compilerOptions.types || []), "vite/client", "@testing-library/jest-dom"]),
142-
];
143-
await writeFile("tsconfig.json", JSON.stringify(tsConfig, null, 2) + "\n", "utf8");
138+
manipulateJsonFile("tsconfig.json", (tsConfig) => {
139+
if (!tsConfig.compilerOptions) {
140+
tsConfig.compilerOptions = {};
141+
}
142+
tsConfig.compilerOptions.types = [
143+
...new Set([...(tsConfig.compilerOptions.types || []), "vite/client", "@testing-library/jest-dom"]),
144+
];
145+
return tsConfig;
146+
});
144147
}
145148
if (
146-
packageJson.dependencies["@solidjs/start"] &&
149+
hasStart &&
147150
["ts", "mjs", "cjs", "js"].every(
148151
(suffix) => !fileExists(`vite.config.${suffix}`) && !fileExists(`vitest.config.${suffix}`),
149152
)
@@ -170,4 +173,49 @@ export default defineConfig({
170173
}
171174
},
172175
},
176+
"tauri-v1.x": {
177+
installs: ["@tauri-apps/cli"],
178+
postInstall: async () => {
179+
try {
180+
let name = "";
181+
manipulateJsonFile("package.json", (packageJson) => {
182+
if (!packageJson.scripts) { packageJson.scripts = {}; }
183+
packageJson.scripts.tauri = "tauri";
184+
name = packageJson.name;
185+
return packageJson;
186+
});
187+
await flushQueue();
188+
const pM = detectPackageManager();
189+
await $`${getRunnerCommand(pM)} tauri init --ci -A ${name} -W ${name} -D ../dist -P http://localhost:3000`;
190+
p.note(`Make sure you have installed all prerequisites: https://tauri.app/v1/guides/getting-started/prerequisites
191+
192+
Start tauri development with ${color.bold(pM.name)} ${color.bold(pM.runScriptCommand("tauri dev"))}`);
193+
} catch (err) {
194+
console.error(err);
195+
}
196+
},
197+
},
198+
"tauri-v2.x": {
199+
installs: ["@tauri-apps/cli@next"],
200+
postInstall: async () => {
201+
try {
202+
let name = "";
203+
manipulateJsonFile("package.json", (packageJson) => {
204+
if (!packageJson.scripts) { packageJson.scripts = {}; }
205+
packageJson.scripts.tauri = "tauri";
206+
name = packageJson.name;
207+
return packageJson;
208+
})
209+
await flushQueue();
210+
const pM = detectPackageManager();
211+
await $`${getRunnerCommand(pM)} tauri init --ci -A ${name} -W ${name} -D ../dist -P http://localhost:3000`;
212+
p.note(`Make sure you have installed all prerequisites: https://v2.tauri.app/start/prerequisites/
213+
214+
Start tauri development with ${color.bold(pM.name)} ${color.bold(pM.runScriptCommand("tauri dev"))}`);
215+
} catch (err) {
216+
console.error(err);
217+
}
218+
},
219+
},
173220
};
221+
Lines changed: 91 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { existsSync, lstatSync, readdirSync } from "fs";
2+
import { readFile, writeFile } from "fs/promises";
23
import { isSolidStart } from "@solid-cli/utils";
34
import { join, resolve } from "path";
45
import { $ } from "execa";
@@ -7,96 +8,98 @@ import * as p from "@clack/prompts";
78
import color from "picocolors";
89

910
export const getProjectRoot = async () => {
10-
const { stdout } = await $`npm root`;
11+
const { stdout } = await $`npm root`;
1112

12-
return stdout.slice(0, stdout.lastIndexOf("/"));
13+
return stdout.slice(0, stdout.lastIndexOf("/"));
1314
};
1415

1516
export const getRootFile = async () => {
16-
if (await isSolidStart()) {
17-
return "src/app.tsx";
18-
}
19-
return "src/index.tsx";
17+
if (await isSolidStart()) {
18+
return "src/app.tsx";
19+
}
20+
return "src/index.tsx";
2021
};
2122

2223
export const fileExists = (path: string) => {
23-
return existsSync(path);
24+
return existsSync(path);
2425
};
2526

2627
export function validateFilePath(path: string, lookingFor: string): string | undefined;
2728
export function validateFilePath(path: string, lookingFor: string[]): string | undefined;
2829
export function validateFilePath(path: string, lookingFor: string | string[]): string | undefined {
29-
path = resolve(path);
30-
let isDir: boolean;
31-
try {
32-
console.log(path)
33-
isDir = lstatSync(path).isDirectory();
34-
}
35-
catch (e) { return undefined }
36-
if (isDir) {
37-
const files = readdirSync(path, { withFileTypes: true });
38-
39-
const config = files.find((file) => {
40-
if (Array.isArray(lookingFor)) {
41-
return lookingFor.some((s) => file.name.startsWith(s));
42-
}
43-
44-
return file.name.startsWith(lookingFor);
45-
});
46-
return config ? join(path, config.name) : undefined;
47-
}
48-
49-
const pathIsValid = Array.isArray(lookingFor)
50-
? lookingFor.some((s) => path.startsWith(s))
51-
: path.startsWith(lookingFor);
52-
53-
const exists = fileExists(path) && pathIsValid;
54-
55-
return exists ? path : undefined;
30+
path = resolve(path);
31+
let isDir: boolean;
32+
try {
33+
console.log(path);
34+
isDir = lstatSync(path).isDirectory();
35+
} catch (e) {
36+
return undefined;
37+
}
38+
if (isDir) {
39+
const files = readdirSync(path, { withFileTypes: true });
40+
41+
const config = files.find((file) => {
42+
if (Array.isArray(lookingFor)) {
43+
return lookingFor.some((s) => file.name.startsWith(s));
44+
}
45+
46+
return file.name.startsWith(lookingFor);
47+
});
48+
return config ? join(path, config.name) : undefined;
49+
}
50+
51+
const pathIsValid = Array.isArray(lookingFor)
52+
? lookingFor.some((s) => path.startsWith(s))
53+
: path.startsWith(lookingFor);
54+
55+
const exists = fileExists(path) && pathIsValid;
56+
57+
return exists ? path : undefined;
5658
}
5759

5860
export async function findFiles(
59-
startPath: string,
60-
lookingFor: string | string[],
61-
opts: { depth?: number; ignoreDirs?: string[]; startsWith?: boolean },
61+
startPath: string,
62+
lookingFor: string | string[],
63+
opts: { depth?: number; ignoreDirs?: string[]; startsWith?: boolean },
6264
): Promise<string[]> {
63-
let { depth = Infinity, ignoreDirs = ["node_modules", "."], startsWith = true } = opts;
64-
65-
startPath = resolve(startPath);
66-
let isDir: boolean;
67-
try {
68-
isDir = lstatSync(startPath).isDirectory();
69-
}
70-
catch (e) { return [] };
71-
if (!isDir) {
72-
startPath = resolve(startPath.slice(0, startPath.lastIndexOf("/")));
73-
}
74-
75-
let filePaths: string[] = [];
76-
77-
const files = readdirSync(startPath, { withFileTypes: true });
78-
79-
for (const file of files) {
80-
if (file.isDirectory() && !ignoreDirs.some((s) => file.name.includes(s))) {
81-
if (Number.isFinite(depth) && depth-- <= 0) continue;
82-
filePaths = filePaths.concat(await findFiles(resolve(startPath, file.name), lookingFor, opts));
83-
continue;
84-
}
85-
86-
if (file.isFile()) {
87-
const fileMatch = Array.isArray(lookingFor)
88-
? lookingFor.some((s) => (startsWith ? file.name.startsWith(s) : file.name.endsWith(s)))
89-
: startsWith
90-
? file.name.startsWith(lookingFor)
91-
: file.name.endsWith(lookingFor);
92-
93-
if (fileMatch) {
94-
filePaths.push(resolve(startPath, file.name));
95-
}
96-
}
97-
}
98-
99-
return filePaths;
65+
let { depth = Infinity, ignoreDirs = ["node_modules", "."], startsWith = true } = opts;
66+
67+
startPath = resolve(startPath);
68+
let isDir: boolean;
69+
try {
70+
isDir = lstatSync(startPath).isDirectory();
71+
} catch (e) {
72+
return [];
73+
}
74+
if (!isDir) {
75+
startPath = resolve(startPath.slice(0, startPath.lastIndexOf("/")));
76+
}
77+
78+
let filePaths: string[] = [];
79+
80+
const files = readdirSync(startPath, { withFileTypes: true });
81+
82+
for (const file of files) {
83+
if (file.isDirectory() && !ignoreDirs.some((s) => file.name.includes(s))) {
84+
if (Number.isFinite(depth) && depth-- <= 0) continue;
85+
filePaths = filePaths.concat(await findFiles(resolve(startPath, file.name), lookingFor, opts));
86+
continue;
87+
}
88+
89+
if (file.isFile()) {
90+
const fileMatch = Array.isArray(lookingFor)
91+
? lookingFor.some((s) => (startsWith ? file.name.startsWith(s) : file.name.endsWith(s)))
92+
: startsWith
93+
? file.name.startsWith(lookingFor)
94+
: file.name.endsWith(lookingFor);
95+
96+
if (fileMatch) {
97+
filePaths.push(resolve(startPath, file.name));
98+
}
99+
}
100+
}
101+
102+
return filePaths;
100103
}
101104

102105
export const getConfigFile = async (file: "app" | "vite" = "app") => {
@@ -133,3 +136,17 @@ export const getConfigFile = async (file: "app" | "vite" = "app") => {
133136

134137
return configFile;
135138
};
139+
140+
export async function manipulateJsonFile(name: string, manipulate: (obj: Record<string, any>) => Record<string, any>) {
141+
try {
142+
const jsonString = await readFile(name, "utf8");
143+
const jsonObj = JSON.parse(jsonString);
144+
await writeFile(
145+
name,
146+
JSON.stringify(manipulate(jsonObj), null, /^(\t|\s+)/m.exec(jsonString)?.[0] || 2) + "\n",
147+
"utf8",
148+
);
149+
} catch (error) {
150+
p.log.error(color.red(error ? error.toString() : `unknown error when manipulating ${name}`));
151+
}
152+
}

0 commit comments

Comments
 (0)