Skip to content

Commit

Permalink
Merge pull request #43 from atk/tauri-integration
Browse files Browse the repository at this point in the history
feat: tauri integration
  • Loading branch information
Tommypop2 authored May 19, 2024
2 parents e00dd59 + bd3e725 commit 7fa690d
Show file tree
Hide file tree
Showing 3 changed files with 159 additions and 94 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ A custom-built CLI for creating and managing SolidJS apps and projects.
- [x] UnoCSS
- [ ] Vanilla Extract
- [x] Vitest
- [ ] Tauri
- [x] Tauri
- [ ] Playwright
- [ ] Utilities
- [ ] eslint-plugin-solid
Expand Down
86 changes: 67 additions & 19 deletions packages/commands/src/lib/integrations.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { insertAfter, insertAtBeginning } from "@solid-cli/utils/fs";
import { readFile, writeFile } from "fs/promises";
import { fileExists, validateFilePath } from "./utils/helpers";
import { writeFile } from "fs/promises";
import { fileExists, manipulateJsonFile, validateFilePath } from "./utils/helpers";
import { $ } from "execa";
import { getRunnerCommand, detectPackageManager } from "@solid-cli/utils/package-manager";
import { createSignal } from "@solid-cli/reactivity";
Expand Down Expand Up @@ -123,27 +123,30 @@ export const integrations: Record<string, IntegrationsValue> = {
additionalConfig: async () => {
try {
p.log.info("Adding test script to package.json");
const packageJsonString = await readFile("package.json", "utf8");
const packageJson = JSON.parse(packageJsonString);
if (!/\bvitest\b/.test(packageJson.scripts.test || "")) {
packageJson.scripts.test = "vitest";
await writeFile("package.json", JSON.stringify(packageJson, null, 2) + "\n", "utf8");
}
let hasStart = false;
manipulateJsonFile("package.json", (packageJson) => {
if (!packageJson.scripts) { packageJson.scripts = {}; }
if (!/\bvitest\b/.test(packageJson.scripts.test || "")) {
packageJson.scripts.test = "vitest";
}
hasStart = packageJson.dependencies["@solidjs/start"]
return packageJson;
});
const hasTs = fileExists("tsconfig.json");
if (hasTs) {
if (hasTs) {
p.log.info("Adding testing types to tsconfig.json");
const tsConfigString = await readFile("tsconfig.json", "utf8");
const tsConfig = JSON.parse(tsConfigString);
if (!tsConfig.compilerOptions) {
tsConfig.compilerOptions = {};
}
tsConfig.compilerOptions.types = [
...new Set([...(tsConfig.compilerOptions.types || []), "vite/client", "@testing-library/jest-dom"]),
];
await writeFile("tsconfig.json", JSON.stringify(tsConfig, null, 2) + "\n", "utf8");
manipulateJsonFile("tsconfig.json", (tsConfig) => {
if (!tsConfig.compilerOptions) {
tsConfig.compilerOptions = {};
}
tsConfig.compilerOptions.types = [
...new Set([...(tsConfig.compilerOptions.types || []), "vite/client", "@testing-library/jest-dom"]),
];
return tsConfig;
});
}
if (
packageJson.dependencies["@solidjs/start"] &&
hasStart &&
["ts", "mjs", "cjs", "js"].every(
(suffix) => !fileExists(`vite.config.${suffix}`) && !fileExists(`vitest.config.${suffix}`),
)
Expand All @@ -170,4 +173,49 @@ export default defineConfig({
}
},
},
"tauri-v1.x": {
installs: ["@tauri-apps/cli"],
postInstall: async () => {
try {
let name = "";
manipulateJsonFile("package.json", (packageJson) => {
if (!packageJson.scripts) { packageJson.scripts = {}; }
packageJson.scripts.tauri = "tauri";
name = packageJson.name;
return packageJson;
});
await flushQueue();
const pM = detectPackageManager();
await $`${getRunnerCommand(pM)} tauri init --ci -A ${name} -W ${name} -D ../dist -P http://localhost:3000`;
p.note(`Make sure you have installed all prerequisites: https://tauri.app/v1/guides/getting-started/prerequisites
Start tauri development with ${color.bold(pM.name)} ${color.bold(pM.runScriptCommand("tauri dev"))}`);
} catch (err) {
console.error(err);
}
},
},
"tauri-v2.x": {
installs: ["@tauri-apps/cli@next"],
postInstall: async () => {
try {
let name = "";
manipulateJsonFile("package.json", (packageJson) => {
if (!packageJson.scripts) { packageJson.scripts = {}; }
packageJson.scripts.tauri = "tauri";
name = packageJson.name;
return packageJson;
})
await flushQueue();
const pM = detectPackageManager();
await $`${getRunnerCommand(pM)} tauri init --ci -A ${name} -W ${name} -D ../dist -P http://localhost:3000`;
p.note(`Make sure you have installed all prerequisites: https://v2.tauri.app/start/prerequisites/
Start tauri development with ${color.bold(pM.name)} ${color.bold(pM.runScriptCommand("tauri dev"))}`);
} catch (err) {
console.error(err);
}
},
},
};

165 changes: 91 additions & 74 deletions packages/commands/src/lib/utils/helpers.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { existsSync, lstatSync, readdirSync } from "fs";
import { readFile, writeFile } from "fs/promises";
import { isSolidStart } from "@solid-cli/utils";
import { join, resolve } from "path";
import { $ } from "execa";
Expand All @@ -7,96 +8,98 @@ import * as p from "@clack/prompts";
import color from "picocolors";

export const getProjectRoot = async () => {
const { stdout } = await $`npm root`;
const { stdout } = await $`npm root`;

return stdout.slice(0, stdout.lastIndexOf("/"));
return stdout.slice(0, stdout.lastIndexOf("/"));
};

export const getRootFile = async () => {
if (await isSolidStart()) {
return "src/app.tsx";
}
return "src/index.tsx";
if (await isSolidStart()) {
return "src/app.tsx";
}
return "src/index.tsx";
};

export const fileExists = (path: string) => {
return existsSync(path);
return existsSync(path);
};

export function validateFilePath(path: string, lookingFor: string): string | undefined;
export function validateFilePath(path: string, lookingFor: string[]): string | undefined;
export function validateFilePath(path: string, lookingFor: string | string[]): string | undefined {
path = resolve(path);
let isDir: boolean;
try {
console.log(path)
isDir = lstatSync(path).isDirectory();
}
catch (e) { return undefined }
if (isDir) {
const files = readdirSync(path, { withFileTypes: true });

const config = files.find((file) => {
if (Array.isArray(lookingFor)) {
return lookingFor.some((s) => file.name.startsWith(s));
}

return file.name.startsWith(lookingFor);
});
return config ? join(path, config.name) : undefined;
}

const pathIsValid = Array.isArray(lookingFor)
? lookingFor.some((s) => path.startsWith(s))
: path.startsWith(lookingFor);

const exists = fileExists(path) && pathIsValid;

return exists ? path : undefined;
path = resolve(path);
let isDir: boolean;
try {
console.log(path);
isDir = lstatSync(path).isDirectory();
} catch (e) {
return undefined;
}
if (isDir) {
const files = readdirSync(path, { withFileTypes: true });

const config = files.find((file) => {
if (Array.isArray(lookingFor)) {
return lookingFor.some((s) => file.name.startsWith(s));
}

return file.name.startsWith(lookingFor);
});
return config ? join(path, config.name) : undefined;
}

const pathIsValid = Array.isArray(lookingFor)
? lookingFor.some((s) => path.startsWith(s))
: path.startsWith(lookingFor);

const exists = fileExists(path) && pathIsValid;

return exists ? path : undefined;
}

export async function findFiles(
startPath: string,
lookingFor: string | string[],
opts: { depth?: number; ignoreDirs?: string[]; startsWith?: boolean },
startPath: string,
lookingFor: string | string[],
opts: { depth?: number; ignoreDirs?: string[]; startsWith?: boolean },
): Promise<string[]> {
let { depth = Infinity, ignoreDirs = ["node_modules", "."], startsWith = true } = opts;

startPath = resolve(startPath);
let isDir: boolean;
try {
isDir = lstatSync(startPath).isDirectory();
}
catch (e) { return [] };
if (!isDir) {
startPath = resolve(startPath.slice(0, startPath.lastIndexOf("/")));
}

let filePaths: string[] = [];

const files = readdirSync(startPath, { withFileTypes: true });

for (const file of files) {
if (file.isDirectory() && !ignoreDirs.some((s) => file.name.includes(s))) {
if (Number.isFinite(depth) && depth-- <= 0) continue;
filePaths = filePaths.concat(await findFiles(resolve(startPath, file.name), lookingFor, opts));
continue;
}

if (file.isFile()) {
const fileMatch = Array.isArray(lookingFor)
? lookingFor.some((s) => (startsWith ? file.name.startsWith(s) : file.name.endsWith(s)))
: startsWith
? file.name.startsWith(lookingFor)
: file.name.endsWith(lookingFor);

if (fileMatch) {
filePaths.push(resolve(startPath, file.name));
}
}
}

return filePaths;
let { depth = Infinity, ignoreDirs = ["node_modules", "."], startsWith = true } = opts;

startPath = resolve(startPath);
let isDir: boolean;
try {
isDir = lstatSync(startPath).isDirectory();
} catch (e) {
return [];
}
if (!isDir) {
startPath = resolve(startPath.slice(0, startPath.lastIndexOf("/")));
}

let filePaths: string[] = [];

const files = readdirSync(startPath, { withFileTypes: true });

for (const file of files) {
if (file.isDirectory() && !ignoreDirs.some((s) => file.name.includes(s))) {
if (Number.isFinite(depth) && depth-- <= 0) continue;
filePaths = filePaths.concat(await findFiles(resolve(startPath, file.name), lookingFor, opts));
continue;
}

if (file.isFile()) {
const fileMatch = Array.isArray(lookingFor)
? lookingFor.some((s) => (startsWith ? file.name.startsWith(s) : file.name.endsWith(s)))
: startsWith
? file.name.startsWith(lookingFor)
: file.name.endsWith(lookingFor);

if (fileMatch) {
filePaths.push(resolve(startPath, file.name));
}
}
}

return filePaths;
}

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

return configFile;
};

export async function manipulateJsonFile(name: string, manipulate: (obj: Record<string, any>) => Record<string, any>) {
try {
const jsonString = await readFile(name, "utf8");
const jsonObj = JSON.parse(jsonString);
await writeFile(
name,
JSON.stringify(manipulate(jsonObj), null, /^(\t|\s+)/m.exec(jsonString)?.[0] || 2) + "\n",
"utf8",
);
} catch (error) {
p.log.error(color.red(error ? error.toString() : `unknown error when manipulating ${name}`));
}
}

0 comments on commit 7fa690d

Please sign in to comment.