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 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/templates/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import type { ProjectInfo } from "./detect-project.js";
|
|
2
|
+
export declare function checkPeerDependencies(cwd: string): string[];
|
|
3
|
+
export declare function installDependencies(deps: string[], projectInfo: ProjectInfo, cwd: string): void;
|
|
4
|
+
export declare function getShadcnInstallHint(pm: ProjectInfo["packageManager"]): string;
|
|
5
|
+
//# sourceMappingURL=dependencies.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../../src/utils/dependencies.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAcvD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAW3D;AAED,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EAAE,EACd,WAAW,EAAE,WAAW,EACxB,GAAG,EAAE,MAAM,GACV,IAAI,CAaN;AAgBD,wBAAgB,oBAAoB,CAAC,EAAE,EAAE,WAAW,CAAC,gBAAgB,CAAC,GAAG,MAAM,CAG9E"}
|
|
@@ -0,0 +1,57 @@
|
|
|
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
|
+
const PEER_DEPENDENCIES = ["lucide-react", "date-fns"];
|
|
6
|
+
const SHADCN_COMPONENTS = [
|
|
7
|
+
"button",
|
|
8
|
+
"input",
|
|
9
|
+
"select",
|
|
10
|
+
"popover",
|
|
11
|
+
"calendar",
|
|
12
|
+
"command",
|
|
13
|
+
"badge",
|
|
14
|
+
];
|
|
15
|
+
export function checkPeerDependencies(cwd) {
|
|
16
|
+
const pkgPath = path.join(cwd, "package.json");
|
|
17
|
+
if (!fs.existsSync(pkgPath))
|
|
18
|
+
return PEER_DEPENDENCIES;
|
|
19
|
+
const pkg = fs.readJsonSync(pkgPath);
|
|
20
|
+
const allDeps = {
|
|
21
|
+
...pkg.dependencies,
|
|
22
|
+
...pkg.devDependencies,
|
|
23
|
+
};
|
|
24
|
+
return PEER_DEPENDENCIES.filter((dep) => !allDeps[dep]);
|
|
25
|
+
}
|
|
26
|
+
export function installDependencies(deps, projectInfo, cwd) {
|
|
27
|
+
if (deps.length === 0)
|
|
28
|
+
return;
|
|
29
|
+
const installCmd = getInstallCommand(projectInfo.packageManager, deps);
|
|
30
|
+
logger.info(`Installing: ${deps.join(", ")}...`);
|
|
31
|
+
try {
|
|
32
|
+
execSync(installCmd, { cwd, stdio: "pipe" });
|
|
33
|
+
logger.success("Dependencies installed.");
|
|
34
|
+
}
|
|
35
|
+
catch (error) {
|
|
36
|
+
logger.error(`Failed to install dependencies. Run manually:`);
|
|
37
|
+
logger.info(` ${installCmd}`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function getInstallCommand(pm, deps) {
|
|
41
|
+
const depStr = deps.join(" ");
|
|
42
|
+
switch (pm) {
|
|
43
|
+
case "pnpm":
|
|
44
|
+
return `pnpm add ${depStr}`;
|
|
45
|
+
case "yarn":
|
|
46
|
+
return `yarn add ${depStr}`;
|
|
47
|
+
case "bun":
|
|
48
|
+
return `bun add ${depStr}`;
|
|
49
|
+
default:
|
|
50
|
+
return `npm install ${depStr}`;
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
export function getShadcnInstallHint(pm) {
|
|
54
|
+
const runner = pm === "npm" ? "npx" : pm === "pnpm" ? "pnpm dlx" : pm === "yarn" ? "npx" : "bunx";
|
|
55
|
+
return `${runner} shadcn@latest add ${SHADCN_COMPONENTS.join(" ")}`;
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=dependencies.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"dependencies.js","sourceRoot":"","sources":["../../src/utils/dependencies.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,MAAM,iBAAiB,GAAG,CAAC,cAAc,EAAE,UAAU,CAAC,CAAC;AAEvD,MAAM,iBAAiB,GAAG;IACxB,QAAQ;IACR,OAAO;IACP,QAAQ;IACR,SAAS;IACT,UAAU;IACV,SAAS;IACT,OAAO;CACR,CAAC;AAEF,MAAM,UAAU,qBAAqB,CAAC,GAAW;IAC/C,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,cAAc,CAAC,CAAC;IAC/C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,OAAO,CAAC;QAAE,OAAO,iBAAiB,CAAC;IAEtD,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,OAAO,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG;QACd,GAAG,GAAG,CAAC,YAAY;QACnB,GAAG,GAAG,CAAC,eAAe;KACvB,CAAC;IAEF,OAAO,iBAAiB,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC;AAC1D,CAAC;AAED,MAAM,UAAU,mBAAmB,CACjC,IAAc,EACd,WAAwB,EACxB,GAAW;IAEX,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAE9B,MAAM,UAAU,GAAG,iBAAiB,CAAC,WAAW,CAAC,cAAc,EAAE,IAAI,CAAC,CAAC;IACvE,MAAM,CAAC,IAAI,CAAC,eAAe,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAEjD,IAAI,CAAC;QACH,QAAQ,CAAC,UAAU,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,CAAC;QAC7C,MAAM,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAC5C,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,CAAC,KAAK,CAAC,+CAA+C,CAAC,CAAC;QAC9D,MAAM,CAAC,IAAI,CAAC,KAAK,UAAU,EAAE,CAAC,CAAC;IACjC,CAAC;AACH,CAAC;AAED,SAAS,iBAAiB,CAAC,EAAiC,EAAE,IAAc;IAC1E,MAAM,MAAM,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC9B,QAAQ,EAAE,EAAE,CAAC;QACX,KAAK,MAAM;YACT,OAAO,YAAY,MAAM,EAAE,CAAC;QAC9B,KAAK,MAAM;YACT,OAAO,YAAY,MAAM,EAAE,CAAC;QAC9B,KAAK,KAAK;YACR,OAAO,WAAW,MAAM,EAAE,CAAC;QAC7B;YACE,OAAO,eAAe,MAAM,EAAE,CAAC;IACnC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,oBAAoB,CAAC,EAAiC;IACpE,MAAM,MAAM,GAAG,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;IAClG,OAAO,GAAG,MAAM,sBAAsB,iBAAiB,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AACtE,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface ProjectInfo {
|
|
2
|
+
/** Whether the project has a src/ directory */
|
|
3
|
+
hasSrc: boolean;
|
|
4
|
+
/** The components directory path (e.g. "src/components" or "components") */
|
|
5
|
+
componentsDir: string;
|
|
6
|
+
/** The detected package manager */
|
|
7
|
+
packageManager: "npm" | "pnpm" | "yarn" | "bun";
|
|
8
|
+
/** The import alias (e.g. "@/") */
|
|
9
|
+
alias: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function detectProject(cwd: string): ProjectInfo;
|
|
12
|
+
//# sourceMappingURL=detect-project.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-project.d.ts","sourceRoot":"","sources":["../../src/utils/detect-project.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,WAAW;IAC1B,+CAA+C;IAC/C,MAAM,EAAE,OAAO,CAAC;IAChB,4EAA4E;IAC5E,aAAa,EAAE,MAAM,CAAC;IACtB,mCAAmC;IACnC,cAAc,EAAE,KAAK,GAAG,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC;IAChD,mCAAmC;IACnC,KAAK,EAAE,MAAM,CAAC;CACf;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAgBtD"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export function detectProject(cwd) {
|
|
4
|
+
const hasSrc = fs.existsSync(path.join(cwd, "src"));
|
|
5
|
+
// Detect components directory
|
|
6
|
+
let componentsDir = "components";
|
|
7
|
+
if (hasSrc) {
|
|
8
|
+
componentsDir = path.join("src", "components");
|
|
9
|
+
}
|
|
10
|
+
// Detect package manager from lockfiles
|
|
11
|
+
const packageManager = detectPackageManager(cwd);
|
|
12
|
+
// Detect alias from tsconfig
|
|
13
|
+
const alias = detectAlias(cwd);
|
|
14
|
+
return { hasSrc, componentsDir, packageManager, alias };
|
|
15
|
+
}
|
|
16
|
+
function detectPackageManager(cwd) {
|
|
17
|
+
if (fs.existsSync(path.join(cwd, "bun.lockb")) || fs.existsSync(path.join(cwd, "bun.lock"))) {
|
|
18
|
+
return "bun";
|
|
19
|
+
}
|
|
20
|
+
if (fs.existsSync(path.join(cwd, "pnpm-lock.yaml"))) {
|
|
21
|
+
return "pnpm";
|
|
22
|
+
}
|
|
23
|
+
if (fs.existsSync(path.join(cwd, "yarn.lock"))) {
|
|
24
|
+
return "yarn";
|
|
25
|
+
}
|
|
26
|
+
return "npm";
|
|
27
|
+
}
|
|
28
|
+
function detectAlias(cwd) {
|
|
29
|
+
const tsconfigPath = path.join(cwd, "tsconfig.json");
|
|
30
|
+
if (!fs.existsSync(tsconfigPath))
|
|
31
|
+
return "@/";
|
|
32
|
+
try {
|
|
33
|
+
const raw = fs.readFileSync(tsconfigPath, "utf-8");
|
|
34
|
+
// Strip comments (basic) then parse
|
|
35
|
+
const cleaned = raw.replace(/\/\/.*$/gm, "").replace(/\/\*[\s\S]*?\*\//g, "");
|
|
36
|
+
const tsconfig = JSON.parse(cleaned);
|
|
37
|
+
const paths = tsconfig?.compilerOptions?.paths;
|
|
38
|
+
if (paths) {
|
|
39
|
+
// Look for alias patterns like "@/*"
|
|
40
|
+
for (const key of Object.keys(paths)) {
|
|
41
|
+
if (key.endsWith("/*")) {
|
|
42
|
+
return key.replace("/*", "/");
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// Fallback
|
|
49
|
+
}
|
|
50
|
+
return "@/";
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=detect-project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"detect-project.js","sourceRoot":"","sources":["../../src/utils/detect-project.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,WAAW,CAAC;AAa7B,MAAM,UAAU,aAAa,CAAC,GAAW;IACvC,MAAM,MAAM,GAAG,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IAEpD,8BAA8B;IAC9B,IAAI,aAAa,GAAG,YAAY,CAAC;IACjC,IAAI,MAAM,EAAE,CAAC;QACX,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,KAAK,EAAE,YAAY,CAAC,CAAC;IACjD,CAAC;IAED,wCAAwC;IACxC,MAAM,cAAc,GAAG,oBAAoB,CAAC,GAAG,CAAC,CAAC;IAEjD,6BAA6B;IAC7B,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC;IAE/B,OAAO,EAAE,MAAM,EAAE,aAAa,EAAE,cAAc,EAAE,KAAK,EAAE,CAAC;AAC1D,CAAC;AAED,SAAS,oBAAoB,CAAC,GAAW;IACvC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,UAAU,CAAC,CAAC,EAAE,CAAC;QAC5F,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,gBAAgB,CAAC,CAAC,EAAE,CAAC;QACpD,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,IAAI,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC,EAAE,CAAC;QAC/C,OAAO,MAAM,CAAC;IAChB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,WAAW,CAAC,GAAW;IAC9B,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,CAAC;IACrD,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC;QAAE,OAAO,IAAI,CAAC;IAE9C,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;QACnD,oCAAoC;QACpC,MAAM,OAAO,GAAG,GAAG,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,mBAAmB,EAAE,EAAE,CAAC,CAAC;QAC9E,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;QACrC,MAAM,KAAK,GAAG,QAAQ,EAAE,eAAe,EAAE,KAAK,CAAC;QAC/C,IAAI,KAAK,EAAE,CAAC;YACV,qCAAqC;YACrC,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;gBACrC,IAAI,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;oBACvB,OAAO,GAAG,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;gBAChC,CAAC;YACH,CAAC;QACH,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,WAAW;IACb,CAAC;IAED,OAAO,IAAI,CAAC;AACd,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export interface WriteFileOptions {
|
|
2
|
+
/** Base directory (cwd) */
|
|
3
|
+
cwd: string;
|
|
4
|
+
/** Force overwrite existing files */
|
|
5
|
+
force: boolean;
|
|
6
|
+
}
|
|
7
|
+
export declare function writeTemplateFile(relativePath: string, content: string, options: WriteFileOptions): Promise<boolean>;
|
|
8
|
+
export declare function writeAllTemplates(files: Record<string, string>, options: WriteFileOptions): Promise<number>;
|
|
9
|
+
//# sourceMappingURL=file-writer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-writer.d.ts","sourceRoot":"","sources":["../../src/utils/file-writer.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,gBAAgB;IAC/B,2BAA2B;IAC3B,GAAG,EAAE,MAAM,CAAC;IACZ,qCAAqC;IACrC,KAAK,EAAE,OAAO,CAAC;CAChB;AAED,wBAAsB,iBAAiB,CACrC,YAAY,EAAE,MAAM,EACpB,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,OAAO,CAAC,CAYlB;AAED,wBAAsB,iBAAiB,CACrC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC7B,OAAO,EAAE,gBAAgB,GACxB,OAAO,CAAC,MAAM,CAAC,CAOjB"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import fs from "fs-extra";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { logger } from "./logger.js";
|
|
4
|
+
export async function writeTemplateFile(relativePath, content, options) {
|
|
5
|
+
const fullPath = path.join(options.cwd, relativePath);
|
|
6
|
+
if (fs.existsSync(fullPath) && !options.force) {
|
|
7
|
+
logger.warn(`Skipped (already exists): ${relativePath}`);
|
|
8
|
+
return false;
|
|
9
|
+
}
|
|
10
|
+
await fs.ensureDir(path.dirname(fullPath));
|
|
11
|
+
await fs.writeFile(fullPath, content, "utf-8");
|
|
12
|
+
logger.success(`Created: ${relativePath}`);
|
|
13
|
+
return true;
|
|
14
|
+
}
|
|
15
|
+
export async function writeAllTemplates(files, options) {
|
|
16
|
+
let count = 0;
|
|
17
|
+
for (const [relativePath, content] of Object.entries(files)) {
|
|
18
|
+
const written = await writeTemplateFile(relativePath, content, options);
|
|
19
|
+
if (written)
|
|
20
|
+
count++;
|
|
21
|
+
}
|
|
22
|
+
return count;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=file-writer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-writer.js","sourceRoot":"","sources":["../../src/utils/file-writer.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,UAAU,CAAC;AAC1B,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AASrC,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,YAAoB,EACpB,OAAe,EACf,OAAyB;IAEzB,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,YAAY,CAAC,CAAC;IAEtD,IAAI,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAC;QAC9C,MAAM,CAAC,IAAI,CAAC,6BAA6B,YAAY,EAAE,CAAC,CAAC;QACzD,OAAO,KAAK,CAAC;IACf,CAAC;IAED,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC3C,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;IAC/C,MAAM,CAAC,OAAO,CAAC,YAAY,YAAY,EAAE,CAAC,CAAC;IAC3C,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,KAA6B,EAC7B,OAAyB;IAEzB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,KAAK,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;QAC5D,MAAM,OAAO,GAAG,MAAM,iBAAiB,CAAC,YAAY,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC;QACxE,IAAI,OAAO;YAAE,KAAK,EAAE,CAAC;IACvB,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM;gBACL,MAAM;mBACH,MAAM;gBACT,MAAM;iBACL,MAAM;;iBAEN,MAAM;CAKpB,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import chalk from "chalk";
|
|
2
|
+
export const logger = {
|
|
3
|
+
info: (msg) => console.log(chalk.cyan("ℹ"), msg),
|
|
4
|
+
success: (msg) => console.log(chalk.green("✔"), msg),
|
|
5
|
+
warn: (msg) => console.log(chalk.yellow("⚠"), msg),
|
|
6
|
+
error: (msg) => console.log(chalk.red("✖"), msg),
|
|
7
|
+
break: () => console.log(""),
|
|
8
|
+
title: (msg) => {
|
|
9
|
+
console.log("");
|
|
10
|
+
console.log(chalk.bold.blue(` ${msg}`));
|
|
11
|
+
console.log("");
|
|
12
|
+
},
|
|
13
|
+
};
|
|
14
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../../src/utils/logger.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC;IACxD,OAAO,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC;IAC5D,IAAI,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC;IAC1D,KAAK,EAAE,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,GAAG,CAAC;IACxD,KAAK,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC;IAC5B,KAAK,EAAE,CAAC,GAAW,EAAE,EAAE;QACrB,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,GAAG,EAAE,CAAC,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAClB,CAAC;CACF,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "filtercn",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "CLI to scaffold the FilterCN conditional filter component into your Next.js + shadcn/ui project",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"filtercn": "./dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"build": "tsc",
|
|
11
|
+
"dev": "tsc --watch",
|
|
12
|
+
"start": "node dist/index.js"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"chalk": "^5.4.1",
|
|
16
|
+
"commander": "^13.1.0",
|
|
17
|
+
"fs-extra": "^11.3.0",
|
|
18
|
+
"ora": "^8.2.0",
|
|
19
|
+
"prompts": "^2.4.2"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@types/fs-extra": "^11.0.4",
|
|
23
|
+
"@types/node": "^20.17.50",
|
|
24
|
+
"@types/prompts": "^2.4.9",
|
|
25
|
+
"typescript": "^5.8.3"
|
|
26
|
+
},
|
|
27
|
+
"keywords": ["filter", "shadcn", "nextjs", "cli", "component"],
|
|
28
|
+
"license": "MIT"
|
|
29
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import path from "node:path";
|
|
2
|
+
import chalk from "chalk";
|
|
3
|
+
import ora from "ora";
|
|
4
|
+
import prompts from "prompts";
|
|
5
|
+
import { detectProject } from "../utils/detect-project.js";
|
|
6
|
+
import { writeAllTemplates } from "../utils/file-writer.js";
|
|
7
|
+
import {
|
|
8
|
+
checkPeerDependencies,
|
|
9
|
+
installDependencies,
|
|
10
|
+
getShadcnInstallHint,
|
|
11
|
+
} from "../utils/dependencies.js";
|
|
12
|
+
import { getTemplateFiles } from "../templates/index.js";
|
|
13
|
+
import { logger } from "../utils/logger.js";
|
|
14
|
+
|
|
15
|
+
interface InitOptions {
|
|
16
|
+
force: boolean;
|
|
17
|
+
cwd: string;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function initCommand(options: InitOptions) {
|
|
21
|
+
const cwd = path.resolve(options.cwd);
|
|
22
|
+
|
|
23
|
+
logger.title("🎛️ FilterCN — Component Installer");
|
|
24
|
+
|
|
25
|
+
// Step 1: Detect project
|
|
26
|
+
const spinner = ora("Detecting project structure...").start();
|
|
27
|
+
const projectInfo = detectProject(cwd);
|
|
28
|
+
spinner.succeed("Project detected");
|
|
29
|
+
|
|
30
|
+
console.log("");
|
|
31
|
+
console.log(
|
|
32
|
+
chalk.dim(" Project root: ") + cwd
|
|
33
|
+
);
|
|
34
|
+
console.log(
|
|
35
|
+
chalk.dim(" Components dir: ") + projectInfo.componentsDir
|
|
36
|
+
);
|
|
37
|
+
console.log(
|
|
38
|
+
chalk.dim(" Package manager: ") + projectInfo.packageManager
|
|
39
|
+
);
|
|
40
|
+
console.log(
|
|
41
|
+
chalk.dim(" Import alias: ") + projectInfo.alias
|
|
42
|
+
);
|
|
43
|
+
console.log("");
|
|
44
|
+
|
|
45
|
+
// Step 2: Confirm
|
|
46
|
+
const targetDir = path.join(
|
|
47
|
+
projectInfo.componentsDir,
|
|
48
|
+
"conditional-filter"
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
const { proceed } = await prompts({
|
|
52
|
+
type: "confirm",
|
|
53
|
+
name: "proceed",
|
|
54
|
+
message: `This will create files in ${chalk.cyan(targetDir)}. Continue?`,
|
|
55
|
+
initial: true,
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
if (!proceed) {
|
|
59
|
+
logger.info("Cancelled.");
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// Step 3: Write template files
|
|
64
|
+
logger.break();
|
|
65
|
+
const writeSpinner = ora("Scaffolding component files...").start();
|
|
66
|
+
const templates = getTemplateFiles(projectInfo.alias);
|
|
67
|
+
|
|
68
|
+
// Prefix each template path with the target directory
|
|
69
|
+
const prefixedTemplates: Record<string, string> = {};
|
|
70
|
+
for (const [relativePath, content] of Object.entries(templates)) {
|
|
71
|
+
prefixedTemplates[path.join(targetDir, relativePath)] = content;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
writeSpinner.stop();
|
|
75
|
+
|
|
76
|
+
const fileCount = await writeAllTemplates(prefixedTemplates, {
|
|
77
|
+
cwd,
|
|
78
|
+
force: options.force,
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
logger.break();
|
|
82
|
+
logger.success(`${fileCount} files created.`);
|
|
83
|
+
|
|
84
|
+
// Step 4: Install peer dependencies
|
|
85
|
+
logger.break();
|
|
86
|
+
const missingDeps = checkPeerDependencies(cwd);
|
|
87
|
+
|
|
88
|
+
if (missingDeps.length > 0) {
|
|
89
|
+
const { installDeps } = await prompts({
|
|
90
|
+
type: "confirm",
|
|
91
|
+
name: "installDeps",
|
|
92
|
+
message: `Install missing dependencies (${missingDeps.join(", ")})?`,
|
|
93
|
+
initial: true,
|
|
94
|
+
});
|
|
95
|
+
|
|
96
|
+
if (installDeps) {
|
|
97
|
+
installDependencies(missingDeps, projectInfo, cwd);
|
|
98
|
+
} else {
|
|
99
|
+
logger.warn("Skipped dependency installation. Install manually:");
|
|
100
|
+
logger.info(` ${missingDeps.join(" ")}`);
|
|
101
|
+
}
|
|
102
|
+
} else {
|
|
103
|
+
logger.success("All peer dependencies already installed.");
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Step 5: Remind about shadcn/ui components
|
|
107
|
+
logger.break();
|
|
108
|
+
logger.info(
|
|
109
|
+
chalk.yellow("Don't forget to install the required shadcn/ui components:")
|
|
110
|
+
);
|
|
111
|
+
console.log("");
|
|
112
|
+
console.log(chalk.dim(" ") + chalk.cyan(getShadcnInstallHint(projectInfo.packageManager)));
|
|
113
|
+
console.log("");
|
|
114
|
+
|
|
115
|
+
// Done!
|
|
116
|
+
logger.break();
|
|
117
|
+
console.log(chalk.bold.green(" ✨ FilterCN installed successfully!"));
|
|
118
|
+
console.log("");
|
|
119
|
+
console.log(chalk.dim(" Quick start:"));
|
|
120
|
+
console.log("");
|
|
121
|
+
console.log(
|
|
122
|
+
chalk.dim(" ") +
|
|
123
|
+
chalk.white(`import { FilterProvider, FilterRoot } from "${projectInfo.alias}components/conditional-filter";`)
|
|
124
|
+
);
|
|
125
|
+
console.log("");
|
|
126
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { Command } from "commander";
|
|
4
|
+
import { initCommand } from "./commands/init.js";
|
|
5
|
+
|
|
6
|
+
const program = new Command();
|
|
7
|
+
|
|
8
|
+
program
|
|
9
|
+
.name("filtercn")
|
|
10
|
+
.description("CLI to scaffold the FilterCN conditional filter component into your project")
|
|
11
|
+
.version("0.1.0");
|
|
12
|
+
|
|
13
|
+
program
|
|
14
|
+
.command("init")
|
|
15
|
+
.description("Initialize the conditional-filter component in your project")
|
|
16
|
+
.option("-f, --force", "Overwrite existing files", false)
|
|
17
|
+
.option(
|
|
18
|
+
"-c, --cwd <path>",
|
|
19
|
+
"The working directory (defaults to current directory)",
|
|
20
|
+
process.cwd()
|
|
21
|
+
)
|
|
22
|
+
.action(async (opts) => {
|
|
23
|
+
await initCommand({
|
|
24
|
+
force: opts.force,
|
|
25
|
+
cwd: opts.cwd,
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
program.parse();
|