kigumi 0.4.2 → 0.4.4

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.
@@ -0,0 +1,52 @@
1
+ // src/utils/tier.ts
2
+ import fs from "fs-extra";
3
+ import path from "path";
4
+ async function detectTier(cwd) {
5
+ const envPath = path.join(cwd, ".env");
6
+ if (!await fs.pathExists(envPath)) {
7
+ return "free";
8
+ }
9
+ const envContent = await fs.readFile(envPath, "utf-8");
10
+ const tokenMatch = envContent.match(
11
+ /^\s*WEBAWESOME_NPM_TOKEN\s*=\s*(.+?)\s*$/m
12
+ );
13
+ if (tokenMatch && tokenMatch[1] && tokenMatch[1].length >= 10) {
14
+ return "pro";
15
+ }
16
+ return "free";
17
+ }
18
+ function detectTierSync(cwd) {
19
+ const envPath = path.join(cwd, ".env");
20
+ if (!fs.existsSync(envPath)) {
21
+ return "free";
22
+ }
23
+ const envContent = fs.readFileSync(envPath, "utf-8");
24
+ const tokenMatch = envContent.match(
25
+ /^\s*WEBAWESOME_NPM_TOKEN\s*=\s*(.+?)\s*$/m
26
+ );
27
+ if (tokenMatch && tokenMatch[1] && tokenMatch[1].length >= 10) {
28
+ return "pro";
29
+ }
30
+ return "free";
31
+ }
32
+ async function getProToken(cwd) {
33
+ const envPath = path.join(cwd, ".env");
34
+ if (!await fs.pathExists(envPath)) {
35
+ return null;
36
+ }
37
+ const envContent = await fs.readFile(envPath, "utf-8");
38
+ const tokenMatch = envContent.match(
39
+ /^\s*WEBAWESOME_NPM_TOKEN\s*=\s*(.+?)\s*$/m
40
+ );
41
+ return tokenMatch && tokenMatch[1] ? tokenMatch[1].trim() : null;
42
+ }
43
+ function getWebAwesomePackage(tier) {
44
+ return tier === "pro" ? "@awesome.me/webawesome-pro" : "@awesome.me/webawesome";
45
+ }
46
+
47
+ export {
48
+ detectTier,
49
+ detectTierSync,
50
+ getProToken,
51
+ getWebAwesomePackage
52
+ };
@@ -0,0 +1,72 @@
1
+ // src/utils/tier.ts
2
+ import fs from "fs-extra";
3
+ import path from "path";
4
+
5
+ // src/constants.ts
6
+ var WEB_AWESOME_FREE_PACKAGE = "@awesome.me/webawesome";
7
+ var WEB_AWESOME_PRO_PACKAGE = "@awesome.me/webawesome-pro";
8
+ var WEB_AWESOME_SCOPE = "@awesome.me";
9
+ var ENV_TOKEN_KEY = "WEBAWESOME_NPM_TOKEN";
10
+ var MIN_TOKEN_LENGTH = 10;
11
+ var ENV_FILE_NAME = ".env";
12
+ var NPM_PUBLIC_REGISTRY = "https://registry.npmjs.org/";
13
+ var NPM_PRO_REGISTRY = "https://npm.cloudsmith.io/fortawesome/webawesome-pro";
14
+ var FREE_PACKAGE_REGEX = /@awesome\.me\/webawesome(?!-pro)/g;
15
+ var PRO_PACKAGE_REGEX = /@awesome\.me\/webawesome-pro/g;
16
+ var ENV_TOKEN_REGEX = /^\s*WEBAWESOME_NPM_TOKEN\s*=\s*(.+?)\s*$/m;
17
+
18
+ // src/utils/tier.ts
19
+ async function detectTier(cwd) {
20
+ const envPath = path.join(cwd, ENV_FILE_NAME);
21
+ if (!await fs.pathExists(envPath)) {
22
+ return "free";
23
+ }
24
+ const envContent = await fs.readFile(envPath, "utf-8");
25
+ const tokenMatch = envContent.match(ENV_TOKEN_REGEX);
26
+ if (tokenMatch && tokenMatch[1] && tokenMatch[1].length >= MIN_TOKEN_LENGTH) {
27
+ return "pro";
28
+ }
29
+ return "free";
30
+ }
31
+ function detectTierSync(cwd) {
32
+ const envPath = path.join(cwd, ENV_FILE_NAME);
33
+ if (!fs.existsSync(envPath)) {
34
+ return "free";
35
+ }
36
+ const envContent = fs.readFileSync(envPath, "utf-8");
37
+ const tokenMatch = envContent.match(ENV_TOKEN_REGEX);
38
+ if (tokenMatch && tokenMatch[1] && tokenMatch[1].length >= MIN_TOKEN_LENGTH) {
39
+ return "pro";
40
+ }
41
+ return "free";
42
+ }
43
+ async function getProToken(cwd) {
44
+ const envPath = path.join(cwd, ENV_FILE_NAME);
45
+ if (!await fs.pathExists(envPath)) {
46
+ return null;
47
+ }
48
+ const envContent = await fs.readFile(envPath, "utf-8");
49
+ const tokenMatch = envContent.match(ENV_TOKEN_REGEX);
50
+ return tokenMatch && tokenMatch[1] ? tokenMatch[1].trim() : null;
51
+ }
52
+ function getWebAwesomePackage(tier) {
53
+ return tier === "pro" ? WEB_AWESOME_PRO_PACKAGE : WEB_AWESOME_FREE_PACKAGE;
54
+ }
55
+
56
+ export {
57
+ WEB_AWESOME_FREE_PACKAGE,
58
+ WEB_AWESOME_PRO_PACKAGE,
59
+ WEB_AWESOME_SCOPE,
60
+ ENV_TOKEN_KEY,
61
+ MIN_TOKEN_LENGTH,
62
+ ENV_FILE_NAME,
63
+ NPM_PUBLIC_REGISTRY,
64
+ NPM_PRO_REGISTRY,
65
+ FREE_PACKAGE_REGEX,
66
+ PRO_PACKAGE_REGEX,
67
+ ENV_TOKEN_REGEX,
68
+ detectTier,
69
+ detectTierSync,
70
+ getProToken,
71
+ getWebAwesomePackage
72
+ };
package/dist/index.js CHANGED
@@ -1371,8 +1371,85 @@ async function buildConfigInteractive(options, projectInfo, cwd, output, existin
1371
1371
  import { execa } from "execa";
1372
1372
  import fs5 from "fs-extra";
1373
1373
  import path4 from "path";
1374
+ async function checkLockfileCompatibility(cwd, packageManager) {
1375
+ const lockfiles = {
1376
+ npm: "package-lock.json",
1377
+ pnpm: "pnpm-lock.yaml",
1378
+ yarn: "yarn.lock"
1379
+ };
1380
+ const lockfileName = lockfiles[packageManager];
1381
+ if (!lockfileName) {
1382
+ return { compatible: true, lockfilePath: null };
1383
+ }
1384
+ const lockfilePath = path4.join(cwd, lockfileName);
1385
+ if (!await fs5.pathExists(lockfilePath)) {
1386
+ return { compatible: true, lockfilePath: null };
1387
+ }
1388
+ try {
1389
+ const result = await execa(
1390
+ packageManager,
1391
+ ["install", "--frozen-lockfile"],
1392
+ { cwd, reject: false, timeout: 5e3, stdio: "pipe" }
1393
+ );
1394
+ const incompatiblePatterns = [
1395
+ /not compatible with current/i,
1396
+ /ignoring broken lockfile/i,
1397
+ /lockfile .* version/i
1398
+ ];
1399
+ const output = (result.stderr || "") + (result.stdout || "");
1400
+ const hasIncompatibility = incompatiblePatterns.some(
1401
+ (pattern) => pattern.test(output)
1402
+ );
1403
+ return {
1404
+ compatible: !hasIncompatibility,
1405
+ lockfilePath: hasIncompatibility ? lockfilePath : null
1406
+ };
1407
+ } catch {
1408
+ return { compatible: true, lockfilePath: null };
1409
+ }
1410
+ }
1411
+ function createLockfileErrorMessage(packageManager, lockfilePath) {
1412
+ const commands = {
1413
+ npm: "rm package-lock.json && npm install",
1414
+ pnpm: "rm pnpm-lock.yaml && pnpm install",
1415
+ yarn: "rm yarn.lock && yarn install"
1416
+ };
1417
+ const command = commands[packageManager] || "reinstall";
1418
+ return `Your ${packageManager} lockfile is incompatible with the current ${packageManager} version.
1419
+
1420
+ This can cause authentication failures during installation.
1421
+
1422
+ Quick fix:
1423
+ cd ${path4.dirname(lockfilePath)}
1424
+ ${command}
1425
+
1426
+ Then run kigumi init again.`;
1427
+ }
1428
+ function createStoreErrorMessage(cwd) {
1429
+ return `Your node_modules were installed with a different pnpm version.
1430
+
1431
+ The pnpm store version has changed, causing installation failures.
1432
+
1433
+ Quick fix:
1434
+ cd ${cwd}
1435
+ rm -rf node_modules pnpm-lock.yaml
1436
+ pnpm install
1437
+
1438
+ Then run kigumi init again.`;
1439
+ }
1374
1440
  async function installDependencies(options) {
1375
1441
  const { cwd, config, tier, packageManager, output } = options;
1442
+ const lockfileCheck = await checkLockfileCompatibility(cwd, packageManager);
1443
+ if (!lockfileCheck.compatible && lockfileCheck.lockfilePath) {
1444
+ output.warn("Incompatible lockfile detected");
1445
+ output.note(
1446
+ "Lockfile compatibility issue",
1447
+ createLockfileErrorMessage(packageManager, lockfileCheck.lockfilePath)
1448
+ );
1449
+ throw new Error(
1450
+ `Incompatible ${packageManager} lockfile - please delete and reinstall`
1451
+ );
1452
+ }
1376
1453
  const spinner2 = output.spinner("Installing dependencies...");
1377
1454
  const waPackage = getWebAwesomePackage(tier);
1378
1455
  const dependencies = [waPackage];
@@ -1416,6 +1493,42 @@ async function installDependencies(options) {
1416
1493
  if (error && typeof error === "object" && "exitCode" in error && "stderr" in error) {
1417
1494
  const execaError = error;
1418
1495
  const stderr = execaError.stderr || "";
1496
+ const stdout = execaError.stdout || "";
1497
+ const errorOutput = stderr + stdout;
1498
+ const isStoreIssue = /ERR_PNPM_UNEXPECTED_STORE/i.test(errorOutput) || /Unexpected store location/i.test(errorOutput) || /currently linked from the store/i.test(errorOutput);
1499
+ if (isStoreIssue && packageManager === "pnpm") {
1500
+ output.error("Installation failed due to pnpm store version mismatch");
1501
+ output.note("Store compatibility issue", createStoreErrorMessage(cwd));
1502
+ throw new DependencyInstallError(
1503
+ dependencies.join(" "),
1504
+ packageManager,
1505
+ execaError,
1506
+ execaError.exitCode
1507
+ );
1508
+ }
1509
+ const isLockfileIssue = /not compatible with current/i.test(errorOutput) || /ignoring broken lockfile/i.test(errorOutput) || /lockfile .* version/i.test(errorOutput);
1510
+ if (isLockfileIssue) {
1511
+ output.error("Installation failed due to incompatible lockfile");
1512
+ const lockfiles = {
1513
+ npm: "package-lock.json",
1514
+ pnpm: "pnpm-lock.yaml",
1515
+ yarn: "yarn.lock"
1516
+ };
1517
+ const lockfileName = lockfiles[packageManager];
1518
+ const lockfilePath = lockfileName ? path4.join(cwd, lockfileName) : null;
1519
+ if (lockfilePath) {
1520
+ output.note(
1521
+ "Lockfile compatibility issue",
1522
+ createLockfileErrorMessage(packageManager, lockfilePath)
1523
+ );
1524
+ }
1525
+ throw new DependencyInstallError(
1526
+ dependencies.join(" "),
1527
+ packageManager,
1528
+ execaError,
1529
+ execaError.exitCode
1530
+ );
1531
+ }
1419
1532
  const is401Error = stderr.includes("401") || stderr.includes("Unauthorized");
1420
1533
  if (is401Error && tier === "pro") {
1421
1534
  output.error("Authentication failed for Pro package");
@@ -0,0 +1,95 @@
1
+ // src/utils/path-aliases.ts
2
+ import fs2 from "fs-extra";
3
+ import path from "path";
4
+
5
+ // src/utils/json.ts
6
+ import fs from "fs-extra";
7
+ async function readJSONWithComments(filePath) {
8
+ const content = await fs.readFile(filePath, "utf-8");
9
+ const stripped = stripJSONComments(content);
10
+ return JSON.parse(stripped);
11
+ }
12
+ function stripJSONComments(content) {
13
+ return content.replace(/\/\/.*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
14
+ }
15
+
16
+ // src/utils/path-aliases.ts
17
+ async function configureVitePathAliases(cwd, output) {
18
+ const viteConfigTs = path.join(cwd, "vite.config.ts");
19
+ const viteConfigJs = path.join(cwd, "vite.config.js");
20
+ let configPath = null;
21
+ if (await fs2.pathExists(viteConfigTs)) {
22
+ configPath = viteConfigTs;
23
+ } else if (await fs2.pathExists(viteConfigJs)) {
24
+ configPath = viteConfigJs;
25
+ }
26
+ if (!configPath) {
27
+ output.log("[DEBUG] No vite.config found, skipping");
28
+ return false;
29
+ }
30
+ let content = await fs2.readFile(configPath, "utf-8");
31
+ if (content.includes("alias:") && content.includes("'@'")) {
32
+ output.log("[DEBUG] Path aliases already configured in vite.config");
33
+ return false;
34
+ }
35
+ if (!content.includes("import path from 'path'") && !content.includes('import path from "path"')) {
36
+ const lastImportMatch = content.match(/(import .+;)\n*(?!import)/s);
37
+ if (lastImportMatch) {
38
+ content = content.replace(
39
+ lastImportMatch[1],
40
+ `${lastImportMatch[1]}
41
+ import path from 'path';`
42
+ );
43
+ }
44
+ }
45
+ const configMatch = content.match(
46
+ /export default defineConfig\(\{([^}]*?)\}\)/s
47
+ );
48
+ if (!configMatch) {
49
+ output.warn("Could not parse vite.config, skipping path alias config");
50
+ return false;
51
+ }
52
+ const configContent = configMatch[1];
53
+ const hasResolve = configContent.includes("resolve:");
54
+ if (hasResolve) {
55
+ output.log("[DEBUG] resolve config exists, skipping");
56
+ return false;
57
+ }
58
+ const resolveConfig = `
59
+ resolve: {
60
+ alias: {
61
+ '@': path.resolve(__dirname, './src'),
62
+ },
63
+ },`;
64
+ content = content.replace(
65
+ /export default defineConfig\(\{/,
66
+ `export default defineConfig({${resolveConfig}`
67
+ );
68
+ await fs2.writeFile(configPath, content);
69
+ output.log("[DEBUG] \u2713 vite.config updated with path aliases");
70
+ return true;
71
+ }
72
+ async function configureTSConfigPathAliases(cwd, output) {
73
+ const tsconfigAppPath = path.join(cwd, "tsconfig.app.json");
74
+ if (!await fs2.pathExists(tsconfigAppPath)) {
75
+ output.log("[DEBUG] No tsconfig.app.json found, skipping");
76
+ return false;
77
+ }
78
+ const tsconfig = await readJSONWithComments(tsconfigAppPath);
79
+ if (tsconfig.compilerOptions?.paths?.["@/*"]) {
80
+ output.log("[DEBUG] Path aliases already in tsconfig.app.json");
81
+ return false;
82
+ }
83
+ tsconfig.compilerOptions = tsconfig.compilerOptions || {};
84
+ tsconfig.compilerOptions.baseUrl = ".";
85
+ tsconfig.compilerOptions.paths = {
86
+ "@/*": ["./src/*"]
87
+ };
88
+ await fs2.writeJSON(tsconfigAppPath, tsconfig, { spaces: 2 });
89
+ output.log("[DEBUG] \u2713 tsconfig.app.json updated with path aliases");
90
+ return true;
91
+ }
92
+ export {
93
+ configureTSConfigPathAliases,
94
+ configureVitePathAliases
95
+ };
@@ -0,0 +1,89 @@
1
+ // src/utils/path-aliases.ts
2
+ import fs2 from "fs-extra";
3
+ import path from "path";
4
+
5
+ // src/utils/json.ts
6
+ import fs from "fs-extra";
7
+ async function readJSONWithComments(filePath) {
8
+ const content = await fs.readFile(filePath, "utf-8");
9
+ const stripped = stripJSONComments(content);
10
+ return JSON.parse(stripped);
11
+ }
12
+ function stripJSONComments(content) {
13
+ return content.replace(/\/\/.*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
14
+ }
15
+
16
+ // src/utils/path-aliases.ts
17
+ async function configureVitePathAliases(cwd, output) {
18
+ const viteConfigTs = path.join(cwd, "vite.config.ts");
19
+ const viteConfigJs = path.join(cwd, "vite.config.js");
20
+ let configPath = null;
21
+ if (await fs2.pathExists(viteConfigTs)) {
22
+ configPath = viteConfigTs;
23
+ } else if (await fs2.pathExists(viteConfigJs)) {
24
+ configPath = viteConfigJs;
25
+ }
26
+ if (!configPath) {
27
+ return false;
28
+ }
29
+ let content = await fs2.readFile(configPath, "utf-8");
30
+ if (content.includes("alias:") && content.includes("'@'")) {
31
+ return false;
32
+ }
33
+ if (!content.includes("import path from 'path'") && !content.includes('import path from "path"')) {
34
+ const lines = content.split("\n");
35
+ let lastImportIndex = -1;
36
+ for (let i = 0; i < lines.length; i++) {
37
+ if (lines[i].trim().startsWith("import ")) {
38
+ lastImportIndex = i;
39
+ }
40
+ }
41
+ if (lastImportIndex >= 0) {
42
+ lines.splice(lastImportIndex + 1, 0, "import path from 'path';");
43
+ content = lines.join("\n");
44
+ }
45
+ }
46
+ if (content.includes("resolve:")) {
47
+ return false;
48
+ }
49
+ const resolveConfig = `
50
+ resolve: {
51
+ alias: {
52
+ '@': path.resolve(__dirname, './src'),
53
+ },
54
+ },`;
55
+ const defineConfigMatch = content.match(/export default defineConfig\(\{/);
56
+ if (!defineConfigMatch) {
57
+ output.warn("Could not parse vite.config, skipping path alias config");
58
+ return false;
59
+ }
60
+ content = content.replace(
61
+ /export default defineConfig\(\{/,
62
+ `export default defineConfig({${resolveConfig}`
63
+ );
64
+ await fs2.writeFile(configPath, content);
65
+ return true;
66
+ }
67
+ async function configureTSConfigPathAliases(cwd, _output) {
68
+ const tsconfigAppPath = path.join(cwd, "tsconfig.app.json");
69
+ if (!await fs2.pathExists(tsconfigAppPath)) {
70
+ return false;
71
+ }
72
+ const tsconfig = await readJSONWithComments(tsconfigAppPath);
73
+ if (tsconfig.compilerOptions?.paths?.["@/*"]) {
74
+ return false;
75
+ }
76
+ tsconfig.compilerOptions = tsconfig.compilerOptions || {};
77
+ tsconfig.compilerOptions.baseUrl = tsconfig.compilerOptions.baseUrl || ".";
78
+ tsconfig.compilerOptions.paths = {
79
+ ...tsconfig.compilerOptions.paths,
80
+ // Preserve existing paths
81
+ "@/*": ["./src/*"]
82
+ };
83
+ await fs2.writeJSON(tsconfigAppPath, tsconfig, { spaces: 2 });
84
+ return true;
85
+ }
86
+ export {
87
+ configureTSConfigPathAliases,
88
+ configureVitePathAliases
89
+ };
@@ -0,0 +1,98 @@
1
+ // src/utils/path-aliases.ts
2
+ import fs2 from "fs-extra";
3
+ import path from "path";
4
+
5
+ // src/utils/json.ts
6
+ import fs from "fs-extra";
7
+ async function readJSONWithComments(filePath) {
8
+ const content = await fs.readFile(filePath, "utf-8");
9
+ const stripped = stripJSONComments(content);
10
+ return JSON.parse(stripped);
11
+ }
12
+ function stripJSONComments(content) {
13
+ return content.replace(/\/\/.*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
14
+ }
15
+
16
+ // src/utils/path-aliases.ts
17
+ async function configureVitePathAliases(cwd, output) {
18
+ const viteConfigTs = path.join(cwd, "vite.config.ts");
19
+ const viteConfigJs = path.join(cwd, "vite.config.js");
20
+ let configPath = null;
21
+ if (await fs2.pathExists(viteConfigTs)) {
22
+ configPath = viteConfigTs;
23
+ } else if (await fs2.pathExists(viteConfigJs)) {
24
+ configPath = viteConfigJs;
25
+ }
26
+ if (!configPath) {
27
+ output.log("[DEBUG] No vite.config found, skipping");
28
+ return false;
29
+ }
30
+ let content = await fs2.readFile(configPath, "utf-8");
31
+ if (content.includes("alias:") && content.includes("'@'")) {
32
+ output.log("[DEBUG] Path aliases already configured in vite.config");
33
+ return false;
34
+ }
35
+ if (!content.includes("import path from 'path'") && !content.includes('import path from "path"')) {
36
+ const lines = content.split("\n");
37
+ let lastImportIndex = -1;
38
+ for (let i = 0; i < lines.length; i++) {
39
+ if (lines[i].trim().startsWith("import ")) {
40
+ lastImportIndex = i;
41
+ }
42
+ }
43
+ if (lastImportIndex >= 0) {
44
+ lines.splice(lastImportIndex + 1, 0, "import path from 'path';");
45
+ content = lines.join("\n");
46
+ }
47
+ }
48
+ const configMatch = content.match(
49
+ /export default defineConfig\(\{([^}]*?)\}\)/s
50
+ );
51
+ if (!configMatch) {
52
+ output.warn("Could not parse vite.config, skipping path alias config");
53
+ return false;
54
+ }
55
+ const configContent = configMatch[1];
56
+ const hasResolve = configContent.includes("resolve:");
57
+ if (hasResolve) {
58
+ output.log("[DEBUG] resolve config exists, skipping");
59
+ return false;
60
+ }
61
+ const resolveConfig = `
62
+ resolve: {
63
+ alias: {
64
+ '@': path.resolve(__dirname, './src'),
65
+ },
66
+ },`;
67
+ content = content.replace(
68
+ /export default defineConfig\(\{/,
69
+ `export default defineConfig({${resolveConfig}`
70
+ );
71
+ await fs2.writeFile(configPath, content);
72
+ output.log("[DEBUG] \u2713 vite.config updated with path aliases");
73
+ return true;
74
+ }
75
+ async function configureTSConfigPathAliases(cwd, output) {
76
+ const tsconfigAppPath = path.join(cwd, "tsconfig.app.json");
77
+ if (!await fs2.pathExists(tsconfigAppPath)) {
78
+ output.log("[DEBUG] No tsconfig.app.json found, skipping");
79
+ return false;
80
+ }
81
+ const tsconfig = await readJSONWithComments(tsconfigAppPath);
82
+ if (tsconfig.compilerOptions?.paths?.["@/*"]) {
83
+ output.log("[DEBUG] Path aliases already in tsconfig.app.json");
84
+ return false;
85
+ }
86
+ tsconfig.compilerOptions = tsconfig.compilerOptions || {};
87
+ tsconfig.compilerOptions.baseUrl = ".";
88
+ tsconfig.compilerOptions.paths = {
89
+ "@/*": ["./src/*"]
90
+ };
91
+ await fs2.writeJSON(tsconfigAppPath, tsconfig, { spaces: 2 });
92
+ output.log("[DEBUG] \u2713 tsconfig.app.json updated with path aliases");
93
+ return true;
94
+ }
95
+ export {
96
+ configureTSConfigPathAliases,
97
+ configureVitePathAliases
98
+ };
@@ -0,0 +1,91 @@
1
+ // src/utils/path-aliases.ts
2
+ import fs2 from "fs-extra";
3
+ import path from "path";
4
+
5
+ // src/utils/json.ts
6
+ import fs from "fs-extra";
7
+ async function readJSONWithComments(filePath) {
8
+ const content = await fs.readFile(filePath, "utf-8");
9
+ const stripped = stripJSONComments(content);
10
+ return JSON.parse(stripped);
11
+ }
12
+ function stripJSONComments(content) {
13
+ return content.replace(/\/\/.*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
14
+ }
15
+
16
+ // src/utils/path-aliases.ts
17
+ async function configureVitePathAliases(cwd, output) {
18
+ const viteConfigTs = path.join(cwd, "vite.config.ts");
19
+ const viteConfigJs = path.join(cwd, "vite.config.js");
20
+ let configPath = null;
21
+ if (await fs2.pathExists(viteConfigTs)) {
22
+ configPath = viteConfigTs;
23
+ } else if (await fs2.pathExists(viteConfigJs)) {
24
+ configPath = viteConfigJs;
25
+ }
26
+ if (!configPath) {
27
+ output.log("[DEBUG] No vite.config found, skipping");
28
+ return false;
29
+ }
30
+ let content = await fs2.readFile(configPath, "utf-8");
31
+ if (content.includes("alias:") && content.includes("'@'")) {
32
+ output.log("[DEBUG] Path aliases already configured in vite.config");
33
+ return false;
34
+ }
35
+ if (!content.includes("import path from 'path'") && !content.includes('import path from "path"')) {
36
+ content = content.replace(
37
+ /(import .+ from ['"]vite['"][^;]*;)/,
38
+ "$1\nimport path from 'path';"
39
+ );
40
+ }
41
+ const configMatch = content.match(
42
+ /export default defineConfig\(\{([^}]*?)\}\)/s
43
+ );
44
+ if (!configMatch) {
45
+ output.warn("Could not parse vite.config, skipping path alias config");
46
+ return false;
47
+ }
48
+ const configContent = configMatch[1];
49
+ const hasResolve = configContent.includes("resolve:");
50
+ if (hasResolve) {
51
+ output.log("[DEBUG] resolve config exists, skipping");
52
+ return false;
53
+ }
54
+ const resolveConfig = `
55
+ resolve: {
56
+ alias: {
57
+ '@': path.resolve(__dirname, './src'),
58
+ },
59
+ },`;
60
+ content = content.replace(
61
+ /export default defineConfig\(\{/,
62
+ `export default defineConfig({${resolveConfig}`
63
+ );
64
+ await fs2.writeFile(configPath, content);
65
+ output.log("[DEBUG] \u2713 vite.config updated with path aliases");
66
+ return true;
67
+ }
68
+ async function configureTSConfigPathAliases(cwd, output) {
69
+ const tsconfigAppPath = path.join(cwd, "tsconfig.app.json");
70
+ if (!await fs2.pathExists(tsconfigAppPath)) {
71
+ output.log("[DEBUG] No tsconfig.app.json found, skipping");
72
+ return false;
73
+ }
74
+ const tsconfig = await readJSONWithComments(tsconfigAppPath);
75
+ if (tsconfig.compilerOptions?.paths?.["@/*"]) {
76
+ output.log("[DEBUG] Path aliases already in tsconfig.app.json");
77
+ return false;
78
+ }
79
+ tsconfig.compilerOptions = tsconfig.compilerOptions || {};
80
+ tsconfig.compilerOptions.baseUrl = ".";
81
+ tsconfig.compilerOptions.paths = {
82
+ "@/*": ["./src/*"]
83
+ };
84
+ await fs2.writeJSON(tsconfigAppPath, tsconfig, { spaces: 2 });
85
+ output.log("[DEBUG] \u2713 tsconfig.app.json updated with path aliases");
86
+ return true;
87
+ }
88
+ export {
89
+ configureTSConfigPathAliases,
90
+ configureVitePathAliases
91
+ };
@@ -0,0 +1,92 @@
1
+ // src/utils/path-aliases.ts
2
+ import fs2 from "fs-extra";
3
+ import path from "path";
4
+
5
+ // src/utils/json.ts
6
+ import fs from "fs-extra";
7
+ async function readJSONWithComments(filePath) {
8
+ const content = await fs.readFile(filePath, "utf-8");
9
+ const stripped = stripJSONComments(content);
10
+ return JSON.parse(stripped);
11
+ }
12
+ function stripJSONComments(content) {
13
+ return content.replace(/\/\/.*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
14
+ }
15
+
16
+ // src/utils/path-aliases.ts
17
+ async function configureVitePathAliases(cwd, output) {
18
+ const viteConfigTs = path.join(cwd, "vite.config.ts");
19
+ const viteConfigJs = path.join(cwd, "vite.config.js");
20
+ let configPath = null;
21
+ if (await fs2.pathExists(viteConfigTs)) {
22
+ configPath = viteConfigTs;
23
+ } else if (await fs2.pathExists(viteConfigJs)) {
24
+ configPath = viteConfigJs;
25
+ }
26
+ if (!configPath) {
27
+ return false;
28
+ }
29
+ let content = await fs2.readFile(configPath, "utf-8");
30
+ if (content.includes("alias:") && content.includes("'@'")) {
31
+ return false;
32
+ }
33
+ if (!content.includes("import path from 'path'") && !content.includes('import path from "path"')) {
34
+ const lines = content.split("\n");
35
+ let lastImportIndex = -1;
36
+ for (let i = 0; i < lines.length; i++) {
37
+ if (lines[i].trim().startsWith("import ")) {
38
+ lastImportIndex = i;
39
+ }
40
+ }
41
+ if (lastImportIndex >= 0) {
42
+ lines.splice(lastImportIndex + 1, 0, "import path from 'path';");
43
+ content = lines.join("\n");
44
+ }
45
+ }
46
+ if (content.includes("resolve:")) {
47
+ return false;
48
+ }
49
+ const resolveConfig = `
50
+ resolve: {
51
+ alias: {
52
+ '@': path.resolve(__dirname, './src'),
53
+ },
54
+ },`;
55
+ const defineConfigMatch = content.match(/export default defineConfig\(\{/);
56
+ if (!defineConfigMatch) {
57
+ output.warn("Could not parse vite.config, skipping path alias config");
58
+ return false;
59
+ }
60
+ content = content.replace(
61
+ /export default defineConfig\(\{/,
62
+ `export default defineConfig({${resolveConfig}`
63
+ );
64
+ await fs2.writeFile(configPath, content);
65
+ return true;
66
+ }
67
+ async function configureTSConfigPathAliases(cwd, _output) {
68
+ const tsconfigAppPath = path.join(cwd, "tsconfig.app.json");
69
+ if (!await fs2.pathExists(tsconfigAppPath)) {
70
+ return false;
71
+ }
72
+ const tsconfig = await readJSONWithComments(tsconfigAppPath);
73
+ if (tsconfig.compilerOptions?.paths?.["@/*"]) {
74
+ return false;
75
+ }
76
+ tsconfig.compilerOptions = tsconfig.compilerOptions || {};
77
+ tsconfig.compilerOptions.baseUrl = tsconfig.compilerOptions.baseUrl || ".";
78
+ tsconfig.compilerOptions.paths = {
79
+ ...tsconfig.compilerOptions.paths,
80
+ // Preserve existing paths
81
+ "@/*": ["./src/*"]
82
+ };
83
+ if (Array.isArray(tsconfig.compilerOptions.types) && tsconfig.compilerOptions.types.length === 1 && tsconfig.compilerOptions.types[0] === "vite/client") {
84
+ delete tsconfig.compilerOptions.types;
85
+ }
86
+ await fs2.writeJSON(tsconfigAppPath, tsconfig, { spaces: 2 });
87
+ return true;
88
+ }
89
+ export {
90
+ configureTSConfigPathAliases,
91
+ configureVitePathAliases
92
+ };
@@ -0,0 +1,94 @@
1
+ // src/utils/path-aliases.ts
2
+ import fs2 from "fs-extra";
3
+ import path from "path";
4
+
5
+ // src/utils/json.ts
6
+ import fs from "fs-extra";
7
+ async function readJSONWithComments(filePath) {
8
+ const content = await fs.readFile(filePath, "utf-8");
9
+ const stripped = stripJSONComments(content);
10
+ return JSON.parse(stripped);
11
+ }
12
+ function stripJSONComments(content) {
13
+ return content.replace(/\/\/.*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
14
+ }
15
+
16
+ // src/utils/path-aliases.ts
17
+ async function configureVitePathAliases(cwd, output) {
18
+ const viteConfigTs = path.join(cwd, "vite.config.ts");
19
+ const viteConfigJs = path.join(cwd, "vite.config.js");
20
+ let configPath = null;
21
+ if (await fs2.pathExists(viteConfigTs)) {
22
+ configPath = viteConfigTs;
23
+ } else if (await fs2.pathExists(viteConfigJs)) {
24
+ configPath = viteConfigJs;
25
+ }
26
+ if (!configPath) {
27
+ output.log("[DEBUG] No vite.config found, skipping");
28
+ return false;
29
+ }
30
+ let content = await fs2.readFile(configPath, "utf-8");
31
+ if (content.includes("alias:") && content.includes("'@'")) {
32
+ output.log("[DEBUG] Path aliases already configured in vite.config");
33
+ return false;
34
+ }
35
+ if (!content.includes("import path from 'path'") && !content.includes('import path from "path"')) {
36
+ const lines = content.split("\n");
37
+ let lastImportIndex = -1;
38
+ for (let i = 0; i < lines.length; i++) {
39
+ if (lines[i].trim().startsWith("import ")) {
40
+ lastImportIndex = i;
41
+ }
42
+ }
43
+ if (lastImportIndex >= 0) {
44
+ lines.splice(lastImportIndex + 1, 0, "import path from 'path';");
45
+ content = lines.join("\n");
46
+ }
47
+ }
48
+ if (content.includes("resolve:")) {
49
+ output.log("[DEBUG] resolve config exists, skipping");
50
+ return false;
51
+ }
52
+ const resolveConfig = `
53
+ resolve: {
54
+ alias: {
55
+ '@': path.resolve(__dirname, './src'),
56
+ },
57
+ },`;
58
+ const defineConfigMatch = content.match(/export default defineConfig\(\{/);
59
+ if (!defineConfigMatch) {
60
+ output.warn("Could not parse vite.config, skipping path alias config");
61
+ return false;
62
+ }
63
+ content = content.replace(
64
+ /export default defineConfig\(\{/,
65
+ `export default defineConfig({${resolveConfig}`
66
+ );
67
+ await fs2.writeFile(configPath, content);
68
+ output.log("[DEBUG] \u2713 vite.config updated with path aliases");
69
+ return true;
70
+ }
71
+ async function configureTSConfigPathAliases(cwd, output) {
72
+ const tsconfigAppPath = path.join(cwd, "tsconfig.app.json");
73
+ if (!await fs2.pathExists(tsconfigAppPath)) {
74
+ output.log("[DEBUG] No tsconfig.app.json found, skipping");
75
+ return false;
76
+ }
77
+ const tsconfig = await readJSONWithComments(tsconfigAppPath);
78
+ if (tsconfig.compilerOptions?.paths?.["@/*"]) {
79
+ output.log("[DEBUG] Path aliases already in tsconfig.app.json");
80
+ return false;
81
+ }
82
+ tsconfig.compilerOptions = tsconfig.compilerOptions || {};
83
+ tsconfig.compilerOptions.baseUrl = ".";
84
+ tsconfig.compilerOptions.paths = {
85
+ "@/*": ["./src/*"]
86
+ };
87
+ await fs2.writeJSON(tsconfigAppPath, tsconfig, { spaces: 2 });
88
+ output.log("[DEBUG] \u2713 tsconfig.app.json updated with path aliases");
89
+ return true;
90
+ }
91
+ export {
92
+ configureTSConfigPathAliases,
93
+ configureVitePathAliases
94
+ };
@@ -0,0 +1,115 @@
1
+ // src/utils/project-config.ts
2
+ import fs2 from "fs-extra";
3
+ import path from "path";
4
+
5
+ // src/utils/json.ts
6
+ import fs from "fs-extra";
7
+ async function readJSONWithComments(filePath) {
8
+ const content = await fs.readFile(filePath, "utf-8");
9
+ const stripped = stripJSONComments(content);
10
+ return JSON.parse(stripped);
11
+ }
12
+ function stripJSONComments(content) {
13
+ return content.replace(/\/\/.*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
14
+ }
15
+
16
+ // src/utils/project-config.ts
17
+ async function configureVitePathAliases(cwd, output) {
18
+ const viteConfigTs = path.join(cwd, "vite.config.ts");
19
+ const viteConfigJs = path.join(cwd, "vite.config.js");
20
+ let configPath = null;
21
+ if (await fs2.pathExists(viteConfigTs)) {
22
+ configPath = viteConfigTs;
23
+ } else if (await fs2.pathExists(viteConfigJs)) {
24
+ configPath = viteConfigJs;
25
+ }
26
+ if (!configPath) {
27
+ return false;
28
+ }
29
+ let content = await fs2.readFile(configPath, "utf-8");
30
+ if (content.includes("alias:") && content.includes("'@'")) {
31
+ return false;
32
+ }
33
+ if (!content.includes("import path from 'path'") && !content.includes('import path from "path"')) {
34
+ const lines = content.split("\n");
35
+ let lastImportIndex = -1;
36
+ for (let i = 0; i < lines.length; i++) {
37
+ if (lines[i].trim().startsWith("import ")) {
38
+ lastImportIndex = i;
39
+ }
40
+ }
41
+ if (lastImportIndex >= 0) {
42
+ lines.splice(lastImportIndex + 1, 0, "import path from 'path';");
43
+ content = lines.join("\n");
44
+ }
45
+ }
46
+ if (content.includes("resolve:")) {
47
+ return false;
48
+ }
49
+ const resolveConfig = `
50
+ resolve: {
51
+ alias: {
52
+ '@': path.resolve(__dirname, './src'),
53
+ },
54
+ },`;
55
+ const defineConfigMatch = content.match(/export default defineConfig\(\{/);
56
+ if (!defineConfigMatch) {
57
+ output.warn("Could not parse vite.config, skipping path alias config");
58
+ return false;
59
+ }
60
+ content = content.replace(
61
+ /export default defineConfig\(\{/,
62
+ `export default defineConfig({${resolveConfig}`
63
+ );
64
+ await fs2.writeFile(configPath, content);
65
+ return true;
66
+ }
67
+ async function configureTSConfig(cwd, _output) {
68
+ const tsconfigAppPath = path.join(cwd, "tsconfig.app.json");
69
+ if (!await fs2.pathExists(tsconfigAppPath)) {
70
+ return false;
71
+ }
72
+ const tsconfig = await readJSONWithComments(tsconfigAppPath);
73
+ let modified = false;
74
+ tsconfig.compilerOptions = tsconfig.compilerOptions || {};
75
+ if (!tsconfig.compilerOptions.paths?.["@/*"]) {
76
+ tsconfig.compilerOptions.baseUrl = tsconfig.compilerOptions.baseUrl || ".";
77
+ tsconfig.compilerOptions.paths = {
78
+ ...tsconfig.compilerOptions.paths,
79
+ "@/*": ["./src/*"]
80
+ };
81
+ modified = true;
82
+ }
83
+ if (tsconfig.compilerOptions.esModuleInterop !== true) {
84
+ tsconfig.compilerOptions.esModuleInterop = true;
85
+ modified = true;
86
+ }
87
+ if (tsconfig.compilerOptions.allowSyntheticDefaultImports !== true) {
88
+ tsconfig.compilerOptions.allowSyntheticDefaultImports = true;
89
+ modified = true;
90
+ }
91
+ if (tsconfig.compilerOptions.verbatimModuleSyntax === true) {
92
+ delete tsconfig.compilerOptions.verbatimModuleSyntax;
93
+ modified = true;
94
+ }
95
+ if (Array.isArray(tsconfig.compilerOptions.types)) {
96
+ if (tsconfig.compilerOptions.types.length === 1 && tsconfig.compilerOptions.types[0] === "vite/client") {
97
+ delete tsconfig.compilerOptions.types;
98
+ modified = true;
99
+ }
100
+ }
101
+ if (tsconfig.compilerOptions.moduleResolution === "bundler" || tsconfig.compilerOptions.moduleResolution === "Bundler") {
102
+ } else if (!tsconfig.compilerOptions.moduleResolution) {
103
+ tsconfig.compilerOptions.moduleResolution = "bundler";
104
+ modified = true;
105
+ }
106
+ if (modified) {
107
+ await fs2.writeJSON(tsconfigAppPath, tsconfig, { spaces: 2 });
108
+ }
109
+ return modified;
110
+ }
111
+ export {
112
+ configureTSConfig,
113
+ configureTSConfig as configureTSConfigPathAliases,
114
+ configureVitePathAliases
115
+ };
@@ -0,0 +1,108 @@
1
+ // src/utils/project-config.ts
2
+ import fs2 from "fs-extra";
3
+ import path from "path";
4
+
5
+ // src/utils/json.ts
6
+ import fs from "fs-extra";
7
+ async function readJSONWithComments(filePath) {
8
+ const content = await fs.readFile(filePath, "utf-8");
9
+ const stripped = stripJSONComments(content);
10
+ return JSON.parse(stripped);
11
+ }
12
+ function stripJSONComments(content) {
13
+ return content.replace(/\/\/.*/g, "").replace(/\/\*[\s\S]*?\*\//g, "");
14
+ }
15
+
16
+ // src/utils/project-config.ts
17
+ async function configureVitePathAliases(cwd, output) {
18
+ const viteConfigTs = path.join(cwd, "vite.config.ts");
19
+ const viteConfigJs = path.join(cwd, "vite.config.js");
20
+ let configPath = null;
21
+ if (await fs2.pathExists(viteConfigTs)) {
22
+ configPath = viteConfigTs;
23
+ } else if (await fs2.pathExists(viteConfigJs)) {
24
+ configPath = viteConfigJs;
25
+ }
26
+ if (!configPath) {
27
+ return false;
28
+ }
29
+ let content = await fs2.readFile(configPath, "utf-8");
30
+ if (content.includes("alias:") && content.includes("'@'")) {
31
+ return false;
32
+ }
33
+ if (!content.includes("import path from 'path'") && !content.includes('import path from "path"')) {
34
+ const lines = content.split("\n");
35
+ let lastImportIndex = -1;
36
+ for (let i = 0; i < lines.length; i++) {
37
+ if (lines[i].trim().startsWith("import ")) {
38
+ lastImportIndex = i;
39
+ }
40
+ }
41
+ if (lastImportIndex >= 0) {
42
+ lines.splice(lastImportIndex + 1, 0, "import path from 'path';");
43
+ content = lines.join("\n");
44
+ }
45
+ }
46
+ if (content.includes("resolve:")) {
47
+ return false;
48
+ }
49
+ const resolveConfig = `
50
+ resolve: {
51
+ alias: {
52
+ '@': path.resolve(__dirname, './src'),
53
+ },
54
+ },`;
55
+ const defineConfigMatch = content.match(/export default defineConfig\(\{/);
56
+ if (!defineConfigMatch) {
57
+ output.warn("Could not parse vite.config, skipping path alias config");
58
+ return false;
59
+ }
60
+ content = content.replace(
61
+ /export default defineConfig\(\{/,
62
+ `export default defineConfig({${resolveConfig}`
63
+ );
64
+ await fs2.writeFile(configPath, content);
65
+ return true;
66
+ }
67
+ async function configureTSConfig(cwd, _output) {
68
+ const tsconfigAppPath = path.join(cwd, "tsconfig.app.json");
69
+ if (!await fs2.pathExists(tsconfigAppPath)) {
70
+ return false;
71
+ }
72
+ const tsconfig = await readJSONWithComments(tsconfigAppPath);
73
+ let modified = false;
74
+ tsconfig.compilerOptions = tsconfig.compilerOptions || {};
75
+ if (!tsconfig.compilerOptions.paths?.["@/*"]) {
76
+ tsconfig.compilerOptions.baseUrl = tsconfig.compilerOptions.baseUrl || ".";
77
+ tsconfig.compilerOptions.paths = {
78
+ ...tsconfig.compilerOptions.paths,
79
+ "@/*": ["./src/*"]
80
+ };
81
+ modified = true;
82
+ }
83
+ if (tsconfig.compilerOptions.esModuleInterop !== true) {
84
+ tsconfig.compilerOptions.esModuleInterop = true;
85
+ modified = true;
86
+ }
87
+ if (tsconfig.compilerOptions.allowSyntheticDefaultImports !== true) {
88
+ tsconfig.compilerOptions.allowSyntheticDefaultImports = true;
89
+ modified = true;
90
+ }
91
+ if (tsconfig.compilerOptions.verbatimModuleSyntax === true) {
92
+ delete tsconfig.compilerOptions.verbatimModuleSyntax;
93
+ modified = true;
94
+ }
95
+ if (Array.isArray(tsconfig.compilerOptions.types) && tsconfig.compilerOptions.types.length === 1 && tsconfig.compilerOptions.types[0] === "vite/client") {
96
+ delete tsconfig.compilerOptions.types;
97
+ modified = true;
98
+ }
99
+ if (modified) {
100
+ await fs2.writeJSON(tsconfigAppPath, tsconfig, { spaces: 2 });
101
+ }
102
+ return modified;
103
+ }
104
+ export {
105
+ configureTSConfig,
106
+ configureTSConfig as configureTSConfigPathAliases,
107
+ configureVitePathAliases
108
+ };
@@ -0,0 +1,52 @@
1
+ # Kigumi Setup Instructions
2
+
3
+ Welcome to Kigumi! Your setup is complete.
4
+
5
+ ## ✅ Completed by CLI
6
+
7
+ - ✓ Installed `{{{waPackage}}}` and dependencies
8
+ - ✓ Created `kigumi.config.json` (theme: {{theme}})
9
+ - ✓ Generated `src/lib/webawesome.ts` (Web Awesome imports)
10
+ - ✓ Generated `src/styles/theme.css` ({{theme}} theme)
11
+ - ✓ Configured path aliases (`@/*` → `./src/*`)
12
+ - ✓ Created `src/vite-env.d.ts` for TypeScript support
13
+ {{#if componentsDir}}
14
+ - ✓ Created components directory: `{{componentsDir}}`
15
+ {{/if}}
16
+
17
+ ## 📦 Adding Components
18
+
19
+ Add components with:
20
+
21
+ ```bash
22
+ npx kigumi add button card dialog input
23
+ ```
24
+
25
+ The CLI will:
26
+ - Generate React component wrappers
27
+ - Update `src/lib/webawesome.ts` with imports
28
+ - Update `src/vite-env.d.ts` with TypeScript types
29
+
30
+ ## 🎨 Changing Themes
31
+
32
+ Available themes: `awesome`, `brutal`, `brutalist`, `camp`, `glossy`, `hacker`, `retro`, `tech`, `terminal`, `tropical`, `vintage`
33
+
34
+ ```bash
35
+ npx kigumi theme set brutalist
36
+ ```
37
+
38
+ ## 🚀 Development
39
+
40
+ ```bash
41
+ npm run dev
42
+ ```
43
+
44
+ ## 📚 Need Help?
45
+
46
+ - **Documentation**: https://kigumi.dev/docs
47
+ - **Web Awesome Docs**: https://webawesome.com/docs
48
+ - **GitHub Issues**: https://github.com/kigumi/cli/issues
49
+
50
+ ---
51
+
52
+ Generated by Kigumi CLI v{{version}}
@@ -0,0 +1,12 @@
1
+ import {
2
+ detectTier,
3
+ detectTierSync,
4
+ getProToken,
5
+ getWebAwesomePackage
6
+ } from "./chunk-IRCCX2A2.js";
7
+ export {
8
+ detectTier,
9
+ detectTierSync,
10
+ getProToken,
11
+ getWebAwesomePackage
12
+ };
@@ -0,0 +1,12 @@
1
+ import {
2
+ detectTier,
3
+ detectTierSync,
4
+ getProToken,
5
+ getWebAwesomePackage
6
+ } from "./chunk-FG4CIVPT.js";
7
+ export {
8
+ detectTier,
9
+ detectTierSync,
10
+ getProToken,
11
+ getWebAwesomePackage
12
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "kigumi",
3
- "version": "0.4.2",
3
+ "version": "0.4.4",
4
4
  "description": "CLI tool to add Web Awesome components to your project",
5
5
  "type": "module",
6
6
  "bin": {