filtercn 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/init.d.ts +7 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +88 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/templates/index.d.ts +14 -0
- package/dist/templates/index.d.ts.map +1 -0
- package/dist/templates/index.js +1174 -0
- package/dist/templates/index.js.map +1 -0
- package/dist/utils/dependencies.d.ts +5 -0
- package/dist/utils/dependencies.d.ts.map +1 -0
- package/dist/utils/dependencies.js +57 -0
- package/dist/utils/dependencies.js.map +1 -0
- package/dist/utils/detect-project.d.ts +12 -0
- package/dist/utils/detect-project.d.ts.map +1 -0
- package/dist/utils/detect-project.js +52 -0
- package/dist/utils/detect-project.js.map +1 -0
- package/dist/utils/file-writer.d.ts +9 -0
- package/dist/utils/file-writer.d.ts.map +1 -0
- package/dist/utils/file-writer.js +24 -0
- package/dist/utils/file-writer.js.map +1 -0
- package/dist/utils/logger.d.ts +9 -0
- package/dist/utils/logger.d.ts.map +1 -0
- package/dist/utils/logger.js +14 -0
- package/dist/utils/logger.js.map +1 -0
- package/package.json +29 -0
- package/src/commands/init.ts +126 -0
- package/src/index.ts +29 -0
- package/src/templates/index.ts +1196 -0
- package/src/utils/dependencies.ts +68 -0
- package/src/utils/detect-project.ts +69 -0
- package/src/utils/file-writer.ts +40 -0
- package/src/utils/logger.ts +14 -0
- package/tsconfig.json +19 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { execSync } from "node:child_process";
|
|
4
|
+
import { logger } from "./logger.js";
|
|
5
|
+
import type { ProjectInfo } from "./detect-project.js";
|
|
6
|
+
|
|
7
|
+
const PEER_DEPENDENCIES = ["lucide-react", "date-fns"];
|
|
8
|
+
|
|
9
|
+
const SHADCN_COMPONENTS = [
|
|
10
|
+
"button",
|
|
11
|
+
"input",
|
|
12
|
+
"select",
|
|
13
|
+
"popover",
|
|
14
|
+
"calendar",
|
|
15
|
+
"command",
|
|
16
|
+
"badge",
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
export function checkPeerDependencies(cwd: string): string[] {
|
|
20
|
+
const pkgPath = path.join(cwd, "package.json");
|
|
21
|
+
if (!fs.existsSync(pkgPath)) return PEER_DEPENDENCIES;
|
|
22
|
+
|
|
23
|
+
const pkg = fs.readJsonSync(pkgPath);
|
|
24
|
+
const allDeps = {
|
|
25
|
+
...pkg.dependencies,
|
|
26
|
+
...pkg.devDependencies,
|
|
27
|
+
};
|
|
28
|
+
|
|
29
|
+
return PEER_DEPENDENCIES.filter((dep) => !allDeps[dep]);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function installDependencies(
|
|
33
|
+
deps: string[],
|
|
34
|
+
projectInfo: ProjectInfo,
|
|
35
|
+
cwd: string,
|
|
36
|
+
): void {
|
|
37
|
+
if (deps.length === 0) return;
|
|
38
|
+
|
|
39
|
+
const installCmd = getInstallCommand(projectInfo.packageManager, deps);
|
|
40
|
+
logger.info(`Installing: ${deps.join(", ")}...`);
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
execSync(installCmd, { cwd, stdio: "pipe" });
|
|
44
|
+
logger.success("Dependencies installed.");
|
|
45
|
+
} catch (error) {
|
|
46
|
+
logger.error(`Failed to install dependencies. Run manually:`);
|
|
47
|
+
logger.info(` ${installCmd}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
function getInstallCommand(pm: ProjectInfo["packageManager"], deps: string[]): string {
|
|
52
|
+
const depStr = deps.join(" ");
|
|
53
|
+
switch (pm) {
|
|
54
|
+
case "pnpm":
|
|
55
|
+
return `pnpm add ${depStr}`;
|
|
56
|
+
case "yarn":
|
|
57
|
+
return `yarn add ${depStr}`;
|
|
58
|
+
case "bun":
|
|
59
|
+
return `bun add ${depStr}`;
|
|
60
|
+
default:
|
|
61
|
+
return `npm install ${depStr}`;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export function getShadcnInstallHint(pm: ProjectInfo["packageManager"]): string {
|
|
66
|
+
const runner = pm === "npm" ? "npx" : pm === "pnpm" ? "pnpm dlx" : pm === "yarn" ? "npx" : "bunx";
|
|
67
|
+
return `${runner} shadcn@latest add ${SHADCN_COMPONENTS.join(" ")}`;
|
|
68
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
|
|
4
|
+
export interface ProjectInfo {
|
|
5
|
+
/** Whether the project has a src/ directory */
|
|
6
|
+
hasSrc: boolean;
|
|
7
|
+
/** The components directory path (e.g. "src/components" or "components") */
|
|
8
|
+
componentsDir: string;
|
|
9
|
+
/** The detected package manager */
|
|
10
|
+
packageManager: "npm" | "pnpm" | "yarn" | "bun";
|
|
11
|
+
/** The import alias (e.g. "@/") */
|
|
12
|
+
alias: string;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function detectProject(cwd: string): ProjectInfo {
|
|
16
|
+
const hasSrc = fs.existsSync(path.join(cwd, "src"));
|
|
17
|
+
|
|
18
|
+
// Detect components directory
|
|
19
|
+
let componentsDir = "components";
|
|
20
|
+
if (hasSrc) {
|
|
21
|
+
componentsDir = path.join("src", "components");
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Detect package manager from lockfiles
|
|
25
|
+
const packageManager = detectPackageManager(cwd);
|
|
26
|
+
|
|
27
|
+
// Detect alias from tsconfig
|
|
28
|
+
const alias = detectAlias(cwd);
|
|
29
|
+
|
|
30
|
+
return { hasSrc, componentsDir, packageManager, alias };
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
function detectPackageManager(cwd: string): ProjectInfo["packageManager"] {
|
|
34
|
+
if (fs.existsSync(path.join(cwd, "bun.lockb")) || fs.existsSync(path.join(cwd, "bun.lock"))) {
|
|
35
|
+
return "bun";
|
|
36
|
+
}
|
|
37
|
+
if (fs.existsSync(path.join(cwd, "pnpm-lock.yaml"))) {
|
|
38
|
+
return "pnpm";
|
|
39
|
+
}
|
|
40
|
+
if (fs.existsSync(path.join(cwd, "yarn.lock"))) {
|
|
41
|
+
return "yarn";
|
|
42
|
+
}
|
|
43
|
+
return "npm";
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function detectAlias(cwd: string): string {
|
|
47
|
+
const tsconfigPath = path.join(cwd, "tsconfig.json");
|
|
48
|
+
if (!fs.existsSync(tsconfigPath)) return "@/";
|
|
49
|
+
|
|
50
|
+
try {
|
|
51
|
+
const raw = fs.readFileSync(tsconfigPath, "utf-8");
|
|
52
|
+
// Strip comments (basic) then parse
|
|
53
|
+
const cleaned = raw.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
54
|
+
const tsconfig = JSON.parse(cleaned);
|
|
55
|
+
const paths = tsconfig?.compilerOptions?.paths;
|
|
56
|
+
if (paths) {
|
|
57
|
+
// Look for alias patterns like "@/*"
|
|
58
|
+
for (const key of Object.keys(paths)) {
|
|
59
|
+
if (key.endsWith("/*")) {
|
|
60
|
+
return key.replace("/*", "/");
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
} catch {
|
|
65
|
+
// Fallback
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
return "@/";
|
|
69
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { logger } from "./logger.js";
|
|
4
|
+
|
|
5
|
+
export interface WriteFileOptions {
|
|
6
|
+
/** Base directory (cwd) */
|
|
7
|
+
cwd: string;
|
|
8
|
+
/** Force overwrite existing files */
|
|
9
|
+
force: boolean;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export async function writeTemplateFile(
|
|
13
|
+
relativePath: string,
|
|
14
|
+
content: string,
|
|
15
|
+
options: WriteFileOptions,
|
|
16
|
+
): Promise<boolean> {
|
|
17
|
+
const fullPath = path.join(options.cwd, relativePath);
|
|
18
|
+
|
|
19
|
+
if (fs.existsSync(fullPath) && !options.force) {
|
|
20
|
+
logger.warn(`Skipped (already exists): ${relativePath}`);
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
await fs.ensureDir(path.dirname(fullPath));
|
|
25
|
+
await fs.writeFile(fullPath, content, "utf-8");
|
|
26
|
+
logger.success(`Created: ${relativePath}`);
|
|
27
|
+
return true;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export async function writeAllTemplates(
|
|
31
|
+
files: Record<string, string>,
|
|
32
|
+
options: WriteFileOptions,
|
|
33
|
+
): Promise<number> {
|
|
34
|
+
let count = 0;
|
|
35
|
+
for (const [relativePath, content] of Object.entries(files)) {
|
|
36
|
+
const written = await writeTemplateFile(relativePath, content, options);
|
|
37
|
+
if (written) count++;
|
|
38
|
+
}
|
|
39
|
+
return count;
|
|
40
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
|
|
3
|
+
export const logger = {
|
|
4
|
+
info: (msg: string) => console.log(chalk.cyan("ℹ"), msg),
|
|
5
|
+
success: (msg: string) => console.log(chalk.green("✔"), msg),
|
|
6
|
+
warn: (msg: string) => console.log(chalk.yellow("⚠"), msg),
|
|
7
|
+
error: (msg: string) => console.log(chalk.red("✖"), msg),
|
|
8
|
+
break: () => console.log(""),
|
|
9
|
+
title: (msg: string) => {
|
|
10
|
+
console.log("");
|
|
11
|
+
console.log(chalk.bold.blue(` ${msg}`));
|
|
12
|
+
console.log("");
|
|
13
|
+
},
|
|
14
|
+
};
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "ES2022",
|
|
4
|
+
"module": "NodeNext",
|
|
5
|
+
"moduleResolution": "NodeNext",
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"rootDir": "./src",
|
|
8
|
+
"strict": true,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"resolveJsonModule": true,
|
|
13
|
+
"declaration": true,
|
|
14
|
+
"declarationMap": true,
|
|
15
|
+
"sourceMap": true
|
|
16
|
+
},
|
|
17
|
+
"include": ["src/**/*"],
|
|
18
|
+
"exclude": ["node_modules", "dist"]
|
|
19
|
+
}
|