@nexical/cli 0.10.0 → 0.11.1
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/.github/workflows/deploy.yml +1 -1
- package/.husky/pre-commit +1 -0
- package/.prettierignore +8 -0
- package/.prettierrc +7 -0
- package/GEMINI.md +199 -0
- package/README.md +85 -56
- package/dist/chunk-AC4B3HPJ.js +93 -0
- package/dist/chunk-AC4B3HPJ.js.map +1 -0
- package/dist/{chunk-JYASTIIW.js → chunk-PJIOCW2A.js} +1 -1
- package/dist/chunk-PJIOCW2A.js.map +1 -0
- package/dist/{chunk-WKERTCM6.js → chunk-Q7YLW5HJ.js} +5 -2
- package/dist/chunk-Q7YLW5HJ.js.map +1 -0
- package/dist/index.js +41 -12
- package/dist/index.js.map +1 -1
- package/dist/src/commands/init.d.ts +4 -1
- package/dist/src/commands/init.js +15 -10
- package/dist/src/commands/init.js.map +1 -1
- package/dist/src/commands/module/add.d.ts +3 -1
- package/dist/src/commands/module/add.js +27 -16
- package/dist/src/commands/module/add.js.map +1 -1
- package/dist/src/commands/module/list.js +9 -5
- package/dist/src/commands/module/list.js.map +1 -1
- package/dist/src/commands/module/remove.d.ts +3 -1
- package/dist/src/commands/module/remove.js +13 -7
- package/dist/src/commands/module/remove.js.map +1 -1
- package/dist/src/commands/module/update.d.ts +3 -1
- package/dist/src/commands/module/update.js +7 -5
- package/dist/src/commands/module/update.js.map +1 -1
- package/dist/src/commands/run.d.ts +4 -1
- package/dist/src/commands/run.js +10 -2
- package/dist/src/commands/run.js.map +1 -1
- package/dist/src/commands/setup.d.ts +8 -0
- package/dist/src/commands/setup.js +75 -0
- package/dist/src/commands/setup.js.map +1 -0
- package/dist/src/utils/discovery.js +1 -1
- package/dist/src/utils/git.js +1 -1
- package/dist/src/utils/url-resolver.js +1 -1
- package/eslint.config.mjs +67 -0
- package/index.ts +34 -20
- package/package.json +57 -33
- package/src/commands/init.ts +79 -75
- package/src/commands/module/add.ts +158 -148
- package/src/commands/module/list.ts +61 -50
- package/src/commands/module/remove.ts +59 -54
- package/src/commands/module/update.ts +44 -42
- package/src/commands/run.ts +89 -81
- package/src/commands/setup.ts +92 -0
- package/src/utils/discovery.ts +98 -113
- package/src/utils/git.ts +35 -28
- package/src/utils/url-resolver.ts +50 -45
- package/test/e2e/lifecycle.e2e.test.ts +139 -130
- package/test/integration/commands/init.integration.test.ts +64 -61
- package/test/integration/commands/module.integration.test.ts +122 -122
- package/test/integration/commands/run.integration.test.ts +70 -63
- package/test/integration/utils/command-loading.integration.test.ts +40 -53
- package/test/unit/commands/init.test.ts +163 -128
- package/test/unit/commands/module/add.test.ts +312 -245
- package/test/unit/commands/module/list.test.ts +108 -91
- package/test/unit/commands/module/remove.test.ts +74 -67
- package/test/unit/commands/module/update.test.ts +74 -70
- package/test/unit/commands/run.test.ts +253 -201
- package/test/unit/commands/setup.test.ts +187 -0
- package/test/unit/utils/command-discovery.test.ts +138 -125
- package/test/unit/utils/git.test.ts +135 -117
- package/test/unit/utils/integration-helpers.test.ts +59 -49
- package/test/unit/utils/url-resolver.test.ts +46 -34
- package/test/utils/integration-helpers.ts +36 -29
- package/tsconfig.json +15 -25
- package/tsup.config.ts +14 -14
- package/vitest.config.ts +10 -10
- package/vitest.e2e.config.ts +6 -6
- package/vitest.integration.config.ts +17 -17
- package/dist/chunk-JYASTIIW.js.map +0 -1
- package/dist/chunk-OKXOCNXP.js +0 -105
- package/dist/chunk-OKXOCNXP.js.map +0 -1
- package/dist/chunk-WKERTCM6.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/discovery.ts"],"sourcesContent":["import { logger } from '@nexical/cli-core';\nimport path from 'node:path';\nimport fs from 'node:fs';\n\n/**\n * Discovers command directories to load into the CLI.\n *\n * Scans for:\n * 1. Core commands (projectRoot/src/commands)\n * 2. Module commands (projectRoot/src/modules/ * /src/commands)\n *\n * @param projectRoot - The root directory of the project\n * @returns Array of absolute paths to command directories\n */\nexport function discoverCommandDirectories(projectRoot: string): string[] {\n const directories: string[] = [];\n const visited = new Set<string>();\n\n const isTsEnvironment =\n process.argv[1]?.endsWith('.ts') ||\n process.argv[1]?.endsWith('.mts') ||\n process.execArgv.some(\n (arg) => arg.includes('tsx') || arg.includes('ts-node') || arg.includes('vitest'),\n ) ||\n process.env.VITEST === 'true' ||\n process.env.NODE_ENV === 'test';\n\n const addDir = (dir: string) => {\n const resolved = path.resolve(dir);\n if (!fs.existsSync(resolved)) {\n logger.debug(`Command directory not found (skipping): ${resolved}`);\n return;\n }\n\n if (visited.has(resolved)) return;\n\n // Detect if this is a source command directory\n const srcPattern = path.join(path.sep, 'src', 'commands');\n const distPattern = path.join(path.sep, 'dist');\n const isSrcDir = resolved.endsWith(srcPattern) && !resolved.includes(distPattern);\n\n // Strict check: if we are adding a 'src' directory...\n if (isSrcDir) {\n // 1. Check if an equivalent 'dist' exists in the same package\n const distPath1 = resolved.replace(\n srcPattern,\n path.join(path.sep, 'dist', 'src', 'commands'),\n );\n const distPath2 = resolved.replace(srcPattern, path.join(path.sep, 'dist', 'commands'));\n\n if (fs.existsSync(distPath1) || fs.existsSync(distPath2)) {\n logger.debug(`Skipping src commands at ${resolved} because dist exists`);\n return;\n }\n\n // 2. If no TS loader, skip src/commands entirely IF it's likely to contain .ts\n if (!isTsEnvironment) {\n logger.debug(`Skipping src commands at ${resolved}: no TS loader detected`);\n return;\n }\n }\n\n logger.debug(`Found command directory: ${resolved}`);\n directories.push(resolved);\n visited.add(resolved);\n };\n\n // 1. Core commands\n const possibleCorePaths = [path.join(projectRoot, 'src/commands')];\n possibleCorePaths.forEach(addDir);\n\n // 2. Module & Package commands\n const searchRoots = [\n path.join(projectRoot, 'modules'),\n path.join(projectRoot, 'src', 'modules'),\n path.join(projectRoot, 'packages'),\n ];\n\n searchRoots.forEach((root) => {\n if (!fs.existsSync(root)) return;\n try {\n const entries = fs.readdirSync(root);\n for (const entry of entries) {\n if (entry.startsWith('.')) continue;\n const entryPath = path.join(root, entry);\n if (!fs.statSync(entryPath).isDirectory()) continue;\n\n // Preference: dist/src/commands > dist/commands > src/commands\n const possiblePaths = [\n path.join(entryPath, 'dist/src/commands'),\n path.join(entryPath, 'dist/commands'),\n path.join(entryPath, 'src/commands'),\n ];\n\n let foundDist = false;\n for (const p of possiblePaths) {\n if (fs.existsSync(p) && fs.statSync(p).isDirectory()) {\n if (p.includes(path.sep + 'dist' + path.sep)) {\n addDir(p);\n foundDist = true;\n break; // Found a dist version, skip others for this entry\n }\n }\n }\n\n if (!foundDist) {\n const srcPath = path.join(entryPath, 'src/commands');\n if (fs.existsSync(srcPath) && fs.statSync(srcPath).isDirectory()) {\n addDir(srcPath);\n }\n }\n }\n } catch (e: unknown) {\n logger.debug(`Error scanning root ${root}: ${e instanceof Error ? e.message : String(e)}`);\n }\n });\n\n return directories;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/url-resolver.ts"],"sourcesContent":["/**\n * Resolves a git URL from various shorthand formats.\n *\n * Supported formats:\n * - gh@org/repo -> https://github.com/org/repo.git\n * - gh@org/repo//path -> https://github.com/org/repo.git//path\n * - https://github.com/org/repo -> https://github.com/org/repo.git\n * - https://github.com/org/repo.git -> https://github.com/org/repo.git\n *\n * @param url The URL string to resolve\n * @returns The fully qualified git URL with .git extension\n */\nexport function resolveGitUrl(url: string): string {\n if (!url) {\n throw new Error('URL cannot be empty');\n }\n\n let resolved = url;\n\n // Handle gh@ syntax\n if (resolved.startsWith('gh@')) {\n resolved = resolved.replace(/^gh@/, 'https://github.com/');\n }\n\n // Handle subpaths (split by //)\n // We must be careful not to split the protocol (e.g. https://)\n const protocolMatch = resolved.match(/^[a-z0-9]+:\\/\\//i);\n let splitIndex = -1;\n\n if (protocolMatch) {\n splitIndex = resolved.indexOf('//', protocolMatch[0].length);\n } else {\n splitIndex = resolved.indexOf('//');\n }\n\n let repoUrl = resolved;\n let subPath = '';\n\n if (splitIndex !== -1) {\n repoUrl = resolved.substring(0, splitIndex);\n subPath = resolved.substring(splitIndex + 2);\n }\n\n // Ensure .git extension, but ONLY for remote URLs (not local paths)\n const isLocal =\n repoUrl.startsWith('/') ||\n repoUrl.startsWith('./') ||\n repoUrl.startsWith('../') ||\n repoUrl.startsWith('file:') ||\n repoUrl.startsWith('~');\n\n if (!isLocal && !repoUrl.endsWith('.git')) {\n repoUrl += '.git';\n }\n\n // Reconstruction\n if (subPath) {\n return `${repoUrl}//${subPath}`;\n }\n\n return repoUrl;\n}\n"],"mappings":";;;;;;AAAA;AAYO,SAAS,cAAc,KAAqB;AACjD,MAAI,CAAC,KAAK;AACR,UAAM,IAAI,MAAM,qBAAqB;AAAA,EACvC;AAEA,MAAI,WAAW;AAGf,MAAI,SAAS,WAAW,KAAK,GAAG;AAC9B,eAAW,SAAS,QAAQ,QAAQ,qBAAqB;AAAA,EAC3D;AAIA,QAAM,gBAAgB,SAAS,MAAM,kBAAkB;AACvD,MAAI,aAAa;AAEjB,MAAI,eAAe;AACjB,iBAAa,SAAS,QAAQ,MAAM,cAAc,CAAC,EAAE,MAAM;AAAA,EAC7D,OAAO;AACL,iBAAa,SAAS,QAAQ,IAAI;AAAA,EACpC;AAEA,MAAI,UAAU;AACd,MAAI,UAAU;AAEd,MAAI,eAAe,IAAI;AACrB,cAAU,SAAS,UAAU,GAAG,UAAU;AAC1C,cAAU,SAAS,UAAU,aAAa,CAAC;AAAA,EAC7C;AAGA,QAAM,UACJ,QAAQ,WAAW,GAAG,KACtB,QAAQ,WAAW,IAAI,KACvB,QAAQ,WAAW,KAAK,KACxB,QAAQ,WAAW,OAAO,KAC1B,QAAQ,WAAW,GAAG;AAExB,MAAI,CAAC,WAAW,CAAC,QAAQ,SAAS,MAAM,GAAG;AACzC,eAAW;AAAA,EACb;AAGA,MAAI,SAAS;AACX,WAAO,GAAG,OAAO,KAAK,OAAO;AAAA,EAC/B;AAEA,SAAO;AACT;","names":[]}
|
|
@@ -26,7 +26,10 @@ async function getRemoteUrl(cwd, remote = "origin") {
|
|
|
26
26
|
}
|
|
27
27
|
async function updateSubmodules(cwd) {
|
|
28
28
|
logger.debug(`Updating submodules in ${cwd}`);
|
|
29
|
-
await runCommand(
|
|
29
|
+
await runCommand(
|
|
30
|
+
'git submodule foreach --recursive "git checkout main && git pull origin main"',
|
|
31
|
+
cwd
|
|
32
|
+
);
|
|
30
33
|
}
|
|
31
34
|
async function checkoutOrphan(branch, cwd) {
|
|
32
35
|
await runCommand(`git checkout --orphan ${branch}`, cwd);
|
|
@@ -71,4 +74,4 @@ export {
|
|
|
71
74
|
renameRemote,
|
|
72
75
|
branchExists
|
|
73
76
|
};
|
|
74
|
-
//# sourceMappingURL=chunk-
|
|
77
|
+
//# sourceMappingURL=chunk-Q7YLW5HJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/git.ts"],"sourcesContent":["import { logger, runCommand } from '@nexical/cli-core';\nimport { exec } from 'node:child_process';\nimport { promisify } from 'node:util';\n\nconst execAsync = promisify(exec);\n\nexport async function clone(\n url: string,\n destination: string,\n options: { recursive?: boolean; depth?: number } = {},\n): Promise<void> {\n const { recursive = false, depth } = options;\n const cmd = `git clone ${recursive ? '--recursive ' : ''}${depth ? `--depth ${depth} ` : ''}${url} .`;\n logger.debug(`Git clone: ${url} to ${destination}`);\n await runCommand(cmd, destination);\n}\n\nexport async function getRemoteUrl(cwd: string, remote = 'origin'): Promise<string> {\n try {\n const { stdout } = await execAsync(`git remote get-url ${remote}`, { cwd });\n return stdout.trim();\n } catch (e) {\n console.error('getRemoteUrl failed:', e);\n return '';\n }\n}\n\nexport async function updateSubmodules(cwd: string): Promise<void> {\n logger.debug(`Updating submodules in ${cwd}`);\n await runCommand(\n 'git submodule foreach --recursive \"git checkout main && git pull origin main\"',\n cwd,\n );\n}\n\nexport async function checkoutOrphan(branch: string, cwd: string): Promise<void> {\n await runCommand(`git checkout --orphan ${branch}`, cwd);\n}\n\nexport async function addAll(cwd: string): Promise<void> {\n await runCommand('git add -A', cwd);\n}\n\nexport async function commit(message: string, cwd: string): Promise<void> {\n // Escape quotes in message if needed, for now assuming simple messages\n await runCommand(`git commit -m \"${message}\"`, cwd);\n}\n\nexport async function deleteBranch(branch: string, cwd: string): Promise<void> {\n await runCommand(`git branch -D ${branch}`, cwd);\n}\n\nexport async function renameBranch(branch: string, cwd: string): Promise<void> {\n await runCommand(`git branch -m ${branch}`, cwd);\n}\n\nexport async function removeRemote(remote: string, cwd: string): Promise<void> {\n await runCommand(`git remote remove ${remote}`, cwd);\n}\n\nexport async function renameRemote(oldName: string, newName: string, cwd: string): Promise<void> {\n await runCommand(`git remote rename ${oldName} ${newName}`, cwd);\n}\n\nexport async function branchExists(branch: string, cwd: string): Promise<boolean> {\n try {\n await execAsync(`git show-ref --verify --quiet refs/heads/${branch}`, { cwd });\n return true;\n } catch {\n return false;\n }\n}\n"],"mappings":";;;;;;AAAA;AAAA,SAAS,QAAQ,kBAAkB;AACnC,SAAS,YAAY;AACrB,SAAS,iBAAiB;AAE1B,IAAM,YAAY,UAAU,IAAI;AAEhC,eAAsB,MACpB,KACA,aACA,UAAmD,CAAC,GACrC;AACf,QAAM,EAAE,YAAY,OAAO,MAAM,IAAI;AACrC,QAAM,MAAM,aAAa,YAAY,iBAAiB,EAAE,GAAG,QAAQ,WAAW,KAAK,MAAM,EAAE,GAAG,GAAG;AACjG,SAAO,MAAM,cAAc,GAAG,OAAO,WAAW,EAAE;AAClD,QAAM,WAAW,KAAK,WAAW;AACnC;AAEA,eAAsB,aAAa,KAAa,SAAS,UAA2B;AAClF,MAAI;AACF,UAAM,EAAE,OAAO,IAAI,MAAM,UAAU,sBAAsB,MAAM,IAAI,EAAE,IAAI,CAAC;AAC1E,WAAO,OAAO,KAAK;AAAA,EACrB,SAAS,GAAG;AACV,YAAQ,MAAM,wBAAwB,CAAC;AACvC,WAAO;AAAA,EACT;AACF;AAEA,eAAsB,iBAAiB,KAA4B;AACjE,SAAO,MAAM,0BAA0B,GAAG,EAAE;AAC5C,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,EACF;AACF;AAEA,eAAsB,eAAe,QAAgB,KAA4B;AAC/E,QAAM,WAAW,yBAAyB,MAAM,IAAI,GAAG;AACzD;AAEA,eAAsB,OAAO,KAA4B;AACvD,QAAM,WAAW,cAAc,GAAG;AACpC;AAEA,eAAsB,OAAO,SAAiB,KAA4B;AAExE,QAAM,WAAW,kBAAkB,OAAO,KAAK,GAAG;AACpD;AAEA,eAAsB,aAAa,QAAgB,KAA4B;AAC7E,QAAM,WAAW,iBAAiB,MAAM,IAAI,GAAG;AACjD;AAEA,eAAsB,aAAa,QAAgB,KAA4B;AAC7E,QAAM,WAAW,iBAAiB,MAAM,IAAI,GAAG;AACjD;AAEA,eAAsB,aAAa,QAAgB,KAA4B;AAC7E,QAAM,WAAW,qBAAqB,MAAM,IAAI,GAAG;AACrD;AAEA,eAAsB,aAAa,SAAiB,SAAiB,KAA4B;AAC/F,QAAM,WAAW,qBAAqB,OAAO,IAAI,OAAO,IAAI,GAAG;AACjE;AAEA,eAAsB,aAAa,QAAgB,KAA+B;AAChF,MAAI;AACF,UAAM,UAAU,4CAA4C,MAAM,IAAI,EAAE,IAAI,CAAC;AAC7E,WAAO;AAAA,EACT,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
|
package/dist/index.js
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
3
3
|
import {
|
|
4
4
|
discoverCommandDirectories
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-AC4B3HPJ.js";
|
|
6
6
|
import {
|
|
7
7
|
init_esm_shims
|
|
8
8
|
} from "./chunk-OYFWMYPG.js";
|
|
@@ -15,7 +15,7 @@ import { fileURLToPath } from "url";
|
|
|
15
15
|
// package.json
|
|
16
16
|
var package_default = {
|
|
17
17
|
name: "@nexical/cli",
|
|
18
|
-
version: "0.
|
|
18
|
+
version: "0.11.1",
|
|
19
19
|
type: "module",
|
|
20
20
|
bin: {
|
|
21
21
|
nexical: "./dist/index.js"
|
|
@@ -28,7 +28,19 @@ var package_default = {
|
|
|
28
28
|
"test:unit": "vitest run --config vitest.config.ts --coverage",
|
|
29
29
|
"test:integration": "vitest run --config vitest.integration.config.ts",
|
|
30
30
|
"test:e2e": "npm run build && vitest run --config vitest.e2e.config.ts",
|
|
31
|
-
"test:watch": "vitest"
|
|
31
|
+
"test:watch": "vitest",
|
|
32
|
+
format: "prettier --write .",
|
|
33
|
+
lint: "eslint .",
|
|
34
|
+
"lint:fix": "eslint . --fix",
|
|
35
|
+
prepare: "husky"
|
|
36
|
+
},
|
|
37
|
+
"lint-staged": {
|
|
38
|
+
"**/*": [
|
|
39
|
+
"prettier --write --ignore-unknown"
|
|
40
|
+
],
|
|
41
|
+
"**/*.{js,jsx,ts,tsx,astro}": [
|
|
42
|
+
"eslint --fix"
|
|
43
|
+
]
|
|
32
44
|
},
|
|
33
45
|
dependencies: {
|
|
34
46
|
"@nexical/cli-core": "^0.1.12",
|
|
@@ -44,7 +56,19 @@ var package_default = {
|
|
|
44
56
|
tsup: "^8.0.1",
|
|
45
57
|
tsx: "^4.21.0",
|
|
46
58
|
typescript: "^5.3.3",
|
|
47
|
-
vitest: "^4.0.15"
|
|
59
|
+
vitest: "^4.0.15",
|
|
60
|
+
"@eslint/js": "^9.39.2",
|
|
61
|
+
eslint: "^9.39.2",
|
|
62
|
+
"eslint-config-prettier": "^10.1.8",
|
|
63
|
+
"eslint-plugin-astro": "^1.5.0",
|
|
64
|
+
"eslint-plugin-jsx-a11y": "^6.10.2",
|
|
65
|
+
"eslint-plugin-react": "^7.37.5",
|
|
66
|
+
"eslint-plugin-react-hooks": "^7.0.1",
|
|
67
|
+
globals: "^17.2.0",
|
|
68
|
+
husky: "^9.1.7",
|
|
69
|
+
"lint-staged": "^16.2.7",
|
|
70
|
+
prettier: "^3.8.1",
|
|
71
|
+
"typescript-eslint": "^8.54.0"
|
|
48
72
|
}
|
|
49
73
|
};
|
|
50
74
|
|
|
@@ -56,23 +80,28 @@ var projectRoot = await findProjectRoot(commandName, process.cwd()) || process.c
|
|
|
56
80
|
var coreCommandsDir = path.resolve(__dirname, "./src/commands");
|
|
57
81
|
var additionalCommands = discoverCommandDirectories(projectRoot);
|
|
58
82
|
var filteredAdditional = additionalCommands.filter((dir) => {
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
83
|
+
const resolvedDir = path.resolve(dir);
|
|
84
|
+
const resolvedCore = path.resolve(coreCommandsDir);
|
|
85
|
+
if (resolvedDir === resolvedCore) return false;
|
|
86
|
+
const coreSuffix = path.join("@nexical", "cli", "dist", "src", "commands");
|
|
87
|
+
const coreSuffixSrc = path.join("packages", "cli", "dist", "src", "commands");
|
|
88
|
+
const coreSuffixRawSrc = path.join("packages", "cli", "src", "commands");
|
|
89
|
+
if (resolvedDir.endsWith(coreSuffix) || resolvedDir.endsWith(coreSuffixSrc) || resolvedDir.endsWith(coreSuffixRawSrc)) {
|
|
90
|
+
return false;
|
|
91
|
+
}
|
|
92
|
+
if (resolvedCore.includes(path.join(path.sep, "dist", "src", "commands"))) {
|
|
93
|
+
const srcVersion = resolvedCore.replace(
|
|
62
94
|
path.join(path.sep, "dist", "src", "commands"),
|
|
63
95
|
path.join(path.sep, "src", "commands")
|
|
64
96
|
);
|
|
65
|
-
if (
|
|
97
|
+
if (resolvedDir === srcVersion) return false;
|
|
66
98
|
}
|
|
67
99
|
return true;
|
|
68
100
|
});
|
|
69
101
|
var app = new CLI({
|
|
70
102
|
version: package_default.version,
|
|
71
103
|
commandName,
|
|
72
|
-
searchDirectories: [.../* @__PURE__ */ new Set([
|
|
73
|
-
coreCommandsDir,
|
|
74
|
-
...filteredAdditional
|
|
75
|
-
])]
|
|
104
|
+
searchDirectories: [.../* @__PURE__ */ new Set([coreCommandsDir, ...filteredAdditional])]
|
|
76
105
|
});
|
|
77
106
|
app.start();
|
|
78
107
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../index.ts","../package.json"],"sourcesContent":["#!/usr/bin/env node\nimport { CLI, findProjectRoot } from '@nexical/cli-core';\nimport { fileURLToPath } from 'node:url';\nimport { discoverCommandDirectories } from './src/utils/discovery.js';\nimport pkg from './package.json';\nimport path from 'node:path';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nconst commandName = 'nexical';\nconst projectRoot = await findProjectRoot(commandName, process.cwd()) || process.cwd();\nconst coreCommandsDir = path.resolve(__dirname, './src/commands');\nconst additionalCommands = discoverCommandDirectories(projectRoot);\n\n// Filter out
|
|
1
|
+
{"version":3,"sources":["../index.ts","../package.json"],"sourcesContent":["#!/usr/bin/env node\nimport { CLI, findProjectRoot } from '@nexical/cli-core';\nimport { fileURLToPath } from 'node:url';\nimport { discoverCommandDirectories } from './src/utils/discovery.js';\nimport pkg from './package.json';\nimport path from 'node:path';\n\nconst __dirname = path.dirname(fileURLToPath(import.meta.url));\n\nconst commandName = 'nexical';\nconst projectRoot = (await findProjectRoot(commandName, process.cwd())) || process.cwd();\nconst coreCommandsDir = path.resolve(__dirname, './src/commands');\nconst additionalCommands = discoverCommandDirectories(projectRoot);\n\n// Filter out duplicate core commands and source versions\nconst filteredAdditional = additionalCommands.filter((dir) => {\n const resolvedDir = path.resolve(dir);\n const resolvedCore = path.resolve(coreCommandsDir);\n\n if (resolvedDir === resolvedCore) return false;\n\n // Check if this is another instance of the core CLI commands (by checking path suffix)\n const coreSuffix = path.join('@nexical', 'cli', 'dist', 'src', 'commands');\n const coreSuffixSrc = path.join('packages', 'cli', 'dist', 'src', 'commands');\n const coreSuffixRawSrc = path.join('packages', 'cli', 'src', 'commands');\n\n if (\n resolvedDir.endsWith(coreSuffix) ||\n resolvedDir.endsWith(coreSuffixSrc) ||\n resolvedDir.endsWith(coreSuffixRawSrc)\n ) {\n return false;\n }\n\n // Handle mismatch between dist/src and src/\n if (resolvedCore.includes(path.join(path.sep, 'dist', 'src', 'commands'))) {\n const srcVersion = resolvedCore.replace(\n path.join(path.sep, 'dist', 'src', 'commands'),\n path.join(path.sep, 'src', 'commands'),\n );\n if (resolvedDir === srcVersion) return false;\n }\n\n return true;\n});\n\nconst app = new CLI({\n version: pkg.version,\n commandName: commandName,\n searchDirectories: [...new Set([coreCommandsDir, ...filteredAdditional])],\n});\napp.start();\n","{\n \"name\": \"@nexical/cli\",\n \"version\": \"0.11.1\",\n \"type\": \"module\",\n \"bin\": {\n \"nexical\": \"./dist/index.js\"\n },\n \"scripts\": {\n \"build\": \"tsup\",\n \"dev\": \"tsup --watch\",\n \"start\": \"node dist/index.js\",\n \"test\": \"npm run test:unit && npm run test:integration && npm run test:e2e\",\n \"test:unit\": \"vitest run --config vitest.config.ts --coverage\",\n \"test:integration\": \"vitest run --config vitest.integration.config.ts\",\n \"test:e2e\": \"npm run build && vitest run --config vitest.e2e.config.ts\",\n \"test:watch\": \"vitest\",\n \"format\": \"prettier --write .\",\n \"lint\": \"eslint .\",\n \"lint:fix\": \"eslint . --fix\",\n \"prepare\": \"husky\"\n },\n \"lint-staged\": {\n \"**/*\": [\n \"prettier --write --ignore-unknown\"\n ],\n \"**/*.{js,jsx,ts,tsx,astro}\": [\n \"eslint --fix\"\n ]\n },\n \"dependencies\": {\n \"@nexical/cli-core\": \"^0.1.12\",\n \"yaml\": \"^2.3.4\",\n \"fast-glob\": \"^3.3.3\"\n },\n \"devDependencies\": {\n \"@types/fs-extra\": \"^11.0.4\",\n \"@types/node\": \"^20.10.0\",\n \"@vitest/coverage-v8\": \"^4.0.15\",\n \"execa\": \"^9.6.1\",\n \"fs-extra\": \"^11.3.2\",\n \"tsup\": \"^8.0.1\",\n \"tsx\": \"^4.21.0\",\n \"typescript\": \"^5.3.3\",\n \"vitest\": \"^4.0.15\",\n \"@eslint/js\": \"^9.39.2\",\n \"eslint\": \"^9.39.2\",\n \"eslint-config-prettier\": \"^10.1.8\",\n \"eslint-plugin-astro\": \"^1.5.0\",\n \"eslint-plugin-jsx-a11y\": \"^6.10.2\",\n \"eslint-plugin-react\": \"^7.37.5\",\n \"eslint-plugin-react-hooks\": \"^7.0.1\",\n \"globals\": \"^17.2.0\",\n \"husky\": \"^9.1.7\",\n \"lint-staged\": \"^16.2.7\",\n \"prettier\": \"^3.8.1\",\n \"typescript-eslint\": \"^8.54.0\"\n }\n}\n"],"mappings":";;;;;;;;;;AAAA;AACA,SAAS,KAAK,uBAAuB;AACrC,SAAS,qBAAqB;;;ACF9B;AAAA,EACE,MAAQ;AAAA,EACR,SAAW;AAAA,EACX,MAAQ;AAAA,EACR,KAAO;AAAA,IACL,SAAW;AAAA,EACb;AAAA,EACA,SAAW;AAAA,IACT,OAAS;AAAA,IACT,KAAO;AAAA,IACP,OAAS;AAAA,IACT,MAAQ;AAAA,IACR,aAAa;AAAA,IACb,oBAAoB;AAAA,IACpB,YAAY;AAAA,IACZ,cAAc;AAAA,IACd,QAAU;AAAA,IACV,MAAQ;AAAA,IACR,YAAY;AAAA,IACZ,SAAW;AAAA,EACb;AAAA,EACA,eAAe;AAAA,IACb,QAAQ;AAAA,MACN;AAAA,IACF;AAAA,IACA,8BAA8B;AAAA,MAC5B;AAAA,IACF;AAAA,EACF;AAAA,EACA,cAAgB;AAAA,IACd,qBAAqB;AAAA,IACrB,MAAQ;AAAA,IACR,aAAa;AAAA,EACf;AAAA,EACA,iBAAmB;AAAA,IACjB,mBAAmB;AAAA,IACnB,eAAe;AAAA,IACf,uBAAuB;AAAA,IACvB,OAAS;AAAA,IACT,YAAY;AAAA,IACZ,MAAQ;AAAA,IACR,KAAO;AAAA,IACP,YAAc;AAAA,IACd,QAAU;AAAA,IACV,cAAc;AAAA,IACd,QAAU;AAAA,IACV,0BAA0B;AAAA,IAC1B,uBAAuB;AAAA,IACvB,0BAA0B;AAAA,IAC1B,uBAAuB;AAAA,IACvB,6BAA6B;AAAA,IAC7B,SAAW;AAAA,IACX,OAAS;AAAA,IACT,eAAe;AAAA,IACf,UAAY;AAAA,IACZ,qBAAqB;AAAA,EACvB;AACF;;;ADpDA,OAAO,UAAU;AAEjB,IAAM,YAAY,KAAK,QAAQ,cAAc,YAAY,GAAG,CAAC;AAE7D,IAAM,cAAc;AACpB,IAAM,cAAe,MAAM,gBAAgB,aAAa,QAAQ,IAAI,CAAC,KAAM,QAAQ,IAAI;AACvF,IAAM,kBAAkB,KAAK,QAAQ,WAAW,gBAAgB;AAChE,IAAM,qBAAqB,2BAA2B,WAAW;AAGjE,IAAM,qBAAqB,mBAAmB,OAAO,CAAC,QAAQ;AAC5D,QAAM,cAAc,KAAK,QAAQ,GAAG;AACpC,QAAM,eAAe,KAAK,QAAQ,eAAe;AAEjD,MAAI,gBAAgB,aAAc,QAAO;AAGzC,QAAM,aAAa,KAAK,KAAK,YAAY,OAAO,QAAQ,OAAO,UAAU;AACzE,QAAM,gBAAgB,KAAK,KAAK,YAAY,OAAO,QAAQ,OAAO,UAAU;AAC5E,QAAM,mBAAmB,KAAK,KAAK,YAAY,OAAO,OAAO,UAAU;AAEvE,MACE,YAAY,SAAS,UAAU,KAC/B,YAAY,SAAS,aAAa,KAClC,YAAY,SAAS,gBAAgB,GACrC;AACA,WAAO;AAAA,EACT;AAGA,MAAI,aAAa,SAAS,KAAK,KAAK,KAAK,KAAK,QAAQ,OAAO,UAAU,CAAC,GAAG;AACzE,UAAM,aAAa,aAAa;AAAA,MAC9B,KAAK,KAAK,KAAK,KAAK,QAAQ,OAAO,UAAU;AAAA,MAC7C,KAAK,KAAK,KAAK,KAAK,OAAO,UAAU;AAAA,IACvC;AACA,QAAI,gBAAgB,WAAY,QAAO;AAAA,EACzC;AAEA,SAAO;AACT,CAAC;AAED,IAAM,MAAM,IAAI,IAAI;AAAA,EAClB,SAAS,gBAAI;AAAA,EACb;AAAA,EACA,mBAAmB,CAAC,GAAG,oBAAI,IAAI,CAAC,iBAAiB,GAAG,kBAAkB,CAAC,CAAC;AAC1E,CAAC;AACD,IAAI,MAAM;","names":[]}
|
|
@@ -5,7 +5,10 @@ declare class InitCommand extends BaseCommand {
|
|
|
5
5
|
static description: string;
|
|
6
6
|
static requiresProject: boolean;
|
|
7
7
|
static args: CommandDefinition;
|
|
8
|
-
run(options:
|
|
8
|
+
run(options: {
|
|
9
|
+
directory: string;
|
|
10
|
+
repo: string;
|
|
11
|
+
}): Promise<void>;
|
|
9
12
|
}
|
|
10
13
|
|
|
11
14
|
export { InitCommand as default };
|
|
@@ -1,17 +1,17 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
require_lib
|
|
4
|
+
} from "../../chunk-LZ3YQWAR.js";
|
|
2
5
|
import {
|
|
3
6
|
addAll,
|
|
4
7
|
clone,
|
|
5
8
|
commit,
|
|
6
9
|
renameRemote,
|
|
7
10
|
updateSubmodules
|
|
8
|
-
} from "../../chunk-
|
|
11
|
+
} from "../../chunk-Q7YLW5HJ.js";
|
|
9
12
|
import {
|
|
10
13
|
resolveGitUrl
|
|
11
|
-
} from "../../chunk-
|
|
12
|
-
import {
|
|
13
|
-
require_lib
|
|
14
|
-
} from "../../chunk-LZ3YQWAR.js";
|
|
14
|
+
} from "../../chunk-PJIOCW2A.js";
|
|
15
15
|
import {
|
|
16
16
|
__toESM,
|
|
17
17
|
init_esm_shims
|
|
@@ -34,14 +34,14 @@ var InitCommand = class extends BaseCommand {
|
|
|
34
34
|
{
|
|
35
35
|
name: "--repo <url>",
|
|
36
36
|
description: "Starter repository URL (supports gh@owner/repo syntax)",
|
|
37
|
-
default: "gh@nexical/app-
|
|
37
|
+
default: "gh@nexical/app-starter"
|
|
38
38
|
}
|
|
39
39
|
]
|
|
40
40
|
};
|
|
41
41
|
async run(options) {
|
|
42
42
|
const directory = options.directory;
|
|
43
43
|
const targetPath = path.resolve(process.cwd(), directory);
|
|
44
|
-
|
|
44
|
+
const repoUrl = resolveGitUrl(options.repo);
|
|
45
45
|
logger.debug("Init options:", { directory, targetPath, repoUrl });
|
|
46
46
|
this.info(`Initializing project in: ${targetPath}`);
|
|
47
47
|
this.info(`Using starter repository: ${repoUrl}`);
|
|
@@ -54,7 +54,7 @@ var InitCommand = class extends BaseCommand {
|
|
|
54
54
|
await import_fs_extra.default.mkdir(targetPath, { recursive: true });
|
|
55
55
|
}
|
|
56
56
|
try {
|
|
57
|
-
this.info("Cloning
|
|
57
|
+
this.info("Cloning starter repository...");
|
|
58
58
|
await clone(repoUrl, targetPath, { recursive: true });
|
|
59
59
|
this.info("Updating submodules...");
|
|
60
60
|
await updateSubmodules(targetPath);
|
|
@@ -62,7 +62,8 @@ var InitCommand = class extends BaseCommand {
|
|
|
62
62
|
await runCommand("npm install", targetPath);
|
|
63
63
|
this.info("Setting up upstream remote...");
|
|
64
64
|
await renameRemote("origin", "upstream", targetPath);
|
|
65
|
-
|
|
65
|
+
this.info("Running project setup...");
|
|
66
|
+
await runCommand("npm run setup", targetPath);
|
|
66
67
|
const configPath = path.join(targetPath, "nexical.yaml");
|
|
67
68
|
if (!await import_fs_extra.default.pathExists(configPath)) {
|
|
68
69
|
this.info("Creating default nexical.yaml...");
|
|
@@ -77,7 +78,11 @@ var InitCommand = class extends BaseCommand {
|
|
|
77
78
|
await commit("Initial site commit", targetPath);
|
|
78
79
|
this.success(`Project initialized successfully in ${directory}!`);
|
|
79
80
|
} catch (error) {
|
|
80
|
-
|
|
81
|
+
if (error instanceof Error) {
|
|
82
|
+
this.error(`Failed to initialize project: ${error.message}`);
|
|
83
|
+
} else {
|
|
84
|
+
this.error(`Failed to initialize project: ${String(error)}`);
|
|
85
|
+
}
|
|
81
86
|
process.exit(1);
|
|
82
87
|
}
|
|
83
88
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../src/commands/init.ts"],"sourcesContent":["import { type CommandDefinition, BaseCommand, logger, runCommand } from '@nexical/cli-core';\nimport * as git from '../utils/git.js';\nimport { resolveGitUrl } from '../utils/url-resolver.js';\nimport fs from 'fs-extra';\nimport path from 'path';\n\nexport default class InitCommand extends BaseCommand {\n
|
|
1
|
+
{"version":3,"sources":["../../../src/commands/init.ts"],"sourcesContent":["import { type CommandDefinition, BaseCommand, logger, runCommand } from '@nexical/cli-core';\nimport * as git from '../utils/git.js';\nimport { resolveGitUrl } from '../utils/url-resolver.js';\nimport fs from 'fs-extra';\nimport path from 'path';\n\nexport default class InitCommand extends BaseCommand {\n static usage = 'init';\n static description = 'Initialize a new Nexical project.';\n static requiresProject = false;\n\n static args: CommandDefinition = {\n args: [\n { name: 'directory', required: true, description: 'Directory to initialize the project in' },\n ],\n options: [\n {\n name: '--repo <url>',\n description: 'Starter repository URL (supports gh@owner/repo syntax)',\n default: 'gh@nexical/app-starter',\n },\n ],\n };\n\n async run(options: { directory: string; repo: string }) {\n const directory = options.directory;\n const targetPath = path.resolve(process.cwd(), directory);\n const repoUrl = resolveGitUrl(options.repo);\n\n logger.debug('Init options:', { directory, targetPath, repoUrl });\n\n this.info(`Initializing project in: ${targetPath}`);\n this.info(`Using starter repository: ${repoUrl}`);\n\n if (await fs.pathExists(targetPath)) {\n if ((await fs.readdir(targetPath)).length > 0) {\n this.error(`Directory ${directory} is not empty.`);\n process.exit(1);\n }\n } else {\n await fs.mkdir(targetPath, { recursive: true });\n }\n\n try {\n this.info('Cloning starter repository...');\n await git.clone(repoUrl, targetPath, { recursive: true });\n\n this.info('Updating submodules...');\n await git.updateSubmodules(targetPath);\n\n this.info('Installing dependencies...');\n await runCommand('npm install', targetPath);\n\n this.info('Setting up upstream remote...');\n await git.renameRemote('origin', 'upstream', targetPath);\n\n // Run setup script\n this.info('Running project setup...');\n await runCommand('npm run setup', targetPath);\n\n // Check for nexical.yaml, if not present create a default one\n const configPath = path.join(targetPath, 'nexical.yaml');\n if (!(await fs.pathExists(configPath))) {\n this.info('Creating default nexical.yaml...');\n await fs.writeFile(configPath, 'name: ' + path.basename(targetPath) + '\\nmodules: []\\n');\n }\n\n // Create VERSION file\n const versionPath = path.join(targetPath, 'VERSION');\n // Check if version file exists, if not create it\n if (!(await fs.pathExists(versionPath))) {\n this.info('Creating VERSION file with 0.1.0...');\n await fs.writeFile(versionPath, '0.1.0');\n }\n\n await git.addAll(targetPath);\n await git.commit('Initial site commit', targetPath);\n\n this.success(`Project initialized successfully in ${directory}!`);\n } catch (error: unknown) {\n if (error instanceof Error) {\n this.error(`Failed to initialize project: ${error.message}`);\n } else {\n this.error(`Failed to initialize project: ${String(error)}`);\n }\n process.exit(1);\n }\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA,SAAiC,aAAa,QAAQ,kBAAkB;AAGxE,sBAAe;AACf,OAAO,UAAU;AAEjB,IAAqB,cAArB,cAAyC,YAAY;AAAA,EACnD,OAAO,QAAQ;AAAA,EACf,OAAO,cAAc;AAAA,EACrB,OAAO,kBAAkB;AAAA,EAEzB,OAAO,OAA0B;AAAA,IAC/B,MAAM;AAAA,MACJ,EAAE,MAAM,aAAa,UAAU,MAAM,aAAa,yCAAyC;AAAA,IAC7F;AAAA,IACA,SAAS;AAAA,MACP;AAAA,QACE,MAAM;AAAA,QACN,aAAa;AAAA,QACb,SAAS;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAAA,EAEA,MAAM,IAAI,SAA8C;AACtD,UAAM,YAAY,QAAQ;AAC1B,UAAM,aAAa,KAAK,QAAQ,QAAQ,IAAI,GAAG,SAAS;AACxD,UAAM,UAAU,cAAc,QAAQ,IAAI;AAE1C,WAAO,MAAM,iBAAiB,EAAE,WAAW,YAAY,QAAQ,CAAC;AAEhE,SAAK,KAAK,4BAA4B,UAAU,EAAE;AAClD,SAAK,KAAK,6BAA6B,OAAO,EAAE;AAEhD,QAAI,MAAM,gBAAAA,QAAG,WAAW,UAAU,GAAG;AACnC,WAAK,MAAM,gBAAAA,QAAG,QAAQ,UAAU,GAAG,SAAS,GAAG;AAC7C,aAAK,MAAM,aAAa,SAAS,gBAAgB;AACjD,gBAAQ,KAAK,CAAC;AAAA,MAChB;AAAA,IACF,OAAO;AACL,YAAM,gBAAAA,QAAG,MAAM,YAAY,EAAE,WAAW,KAAK,CAAC;AAAA,IAChD;AAEA,QAAI;AACF,WAAK,KAAK,+BAA+B;AACzC,YAAU,MAAM,SAAS,YAAY,EAAE,WAAW,KAAK,CAAC;AAExD,WAAK,KAAK,wBAAwB;AAClC,YAAU,iBAAiB,UAAU;AAErC,WAAK,KAAK,4BAA4B;AACtC,YAAM,WAAW,eAAe,UAAU;AAE1C,WAAK,KAAK,+BAA+B;AACzC,YAAU,aAAa,UAAU,YAAY,UAAU;AAGvD,WAAK,KAAK,0BAA0B;AACpC,YAAM,WAAW,iBAAiB,UAAU;AAG5C,YAAM,aAAa,KAAK,KAAK,YAAY,cAAc;AACvD,UAAI,CAAE,MAAM,gBAAAA,QAAG,WAAW,UAAU,GAAI;AACtC,aAAK,KAAK,kCAAkC;AAC5C,cAAM,gBAAAA,QAAG,UAAU,YAAY,WAAW,KAAK,SAAS,UAAU,IAAI,iBAAiB;AAAA,MACzF;AAGA,YAAM,cAAc,KAAK,KAAK,YAAY,SAAS;AAEnD,UAAI,CAAE,MAAM,gBAAAA,QAAG,WAAW,WAAW,GAAI;AACvC,aAAK,KAAK,qCAAqC;AAC/C,cAAM,gBAAAA,QAAG,UAAU,aAAa,OAAO;AAAA,MACzC;AAEA,YAAU,OAAO,UAAU;AAC3B,YAAU,OAAO,uBAAuB,UAAU;AAElD,WAAK,QAAQ,uCAAuC,SAAS,GAAG;AAAA,IAClE,SAAS,OAAgB;AACvB,UAAI,iBAAiB,OAAO;AAC1B,aAAK,MAAM,iCAAiC,MAAM,OAAO,EAAE;AAAA,MAC7D,OAAO;AACL,aAAK,MAAM,iCAAiC,OAAO,KAAK,CAAC,EAAE;AAAA,MAC7D;AACA,cAAQ,KAAK,CAAC;AAAA,IAChB;AAAA,EACF;AACF;","names":["fs"]}
|
|
@@ -6,7 +6,9 @@ declare class ModuleAddCommand extends BaseCommand {
|
|
|
6
6
|
static requiresProject: boolean;
|
|
7
7
|
static args: CommandDefinition;
|
|
8
8
|
private visited;
|
|
9
|
-
run(options:
|
|
9
|
+
run(options: {
|
|
10
|
+
url: string;
|
|
11
|
+
}): Promise<void>;
|
|
10
12
|
private installModule;
|
|
11
13
|
private addToConfig;
|
|
12
14
|
}
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { createRequire } from "module"; const require = createRequire(import.meta.url);
|
|
2
|
+
import {
|
|
3
|
+
require_lib
|
|
4
|
+
} from "../../../chunk-LZ3YQWAR.js";
|
|
2
5
|
import {
|
|
3
6
|
clone,
|
|
4
7
|
getRemoteUrl
|
|
5
|
-
} from "../../../chunk-
|
|
8
|
+
} from "../../../chunk-Q7YLW5HJ.js";
|
|
6
9
|
import {
|
|
7
10
|
resolveGitUrl
|
|
8
|
-
} from "../../../chunk-
|
|
9
|
-
import {
|
|
10
|
-
require_lib
|
|
11
|
-
} from "../../../chunk-LZ3YQWAR.js";
|
|
11
|
+
} from "../../../chunk-PJIOCW2A.js";
|
|
12
12
|
import {
|
|
13
13
|
__toESM,
|
|
14
14
|
init_esm_shims
|
|
@@ -25,14 +25,12 @@ var ModuleAddCommand = class extends BaseCommand {
|
|
|
25
25
|
static description = "Add a module and its dependencies as git submodules.";
|
|
26
26
|
static requiresProject = true;
|
|
27
27
|
static args = {
|
|
28
|
-
args: [
|
|
29
|
-
{ name: "url", required: true, description: "Git repository URL or gh@org/repo" }
|
|
30
|
-
]
|
|
28
|
+
args: [{ name: "url", required: true, description: "Git repository URL or gh@org/repo" }]
|
|
31
29
|
};
|
|
32
30
|
visited = /* @__PURE__ */ new Set();
|
|
33
31
|
async run(options) {
|
|
34
32
|
const projectRoot = this.projectRoot;
|
|
35
|
-
|
|
33
|
+
const { url } = options;
|
|
36
34
|
if (!url) {
|
|
37
35
|
this.error("Please specify a repository URL.");
|
|
38
36
|
return;
|
|
@@ -43,7 +41,11 @@ var ModuleAddCommand = class extends BaseCommand {
|
|
|
43
41
|
await runCommand("npm install", projectRoot);
|
|
44
42
|
this.success("All modules installed successfully.");
|
|
45
43
|
} catch (e) {
|
|
46
|
-
|
|
44
|
+
if (e instanceof Error) {
|
|
45
|
+
this.error(`Failed to add module: ${e.message}`);
|
|
46
|
+
} else {
|
|
47
|
+
this.error(`Failed to add module: ${String(e)}`);
|
|
48
|
+
}
|
|
47
49
|
}
|
|
48
50
|
}
|
|
49
51
|
async installModule(url) {
|
|
@@ -57,7 +59,12 @@ var ModuleAddCommand = class extends BaseCommand {
|
|
|
57
59
|
}
|
|
58
60
|
this.visited.add(cleanUrl);
|
|
59
61
|
this.info(`Inspecting ${cleanUrl}...`);
|
|
60
|
-
const stagingDir = path.resolve(
|
|
62
|
+
const stagingDir = path.resolve(
|
|
63
|
+
projectRoot,
|
|
64
|
+
".nexical",
|
|
65
|
+
"cache",
|
|
66
|
+
`staging-${Date.now()}-${Math.random().toString(36).substring(7)}`
|
|
67
|
+
);
|
|
61
68
|
let moduleName = "";
|
|
62
69
|
let dependencies = [];
|
|
63
70
|
try {
|
|
@@ -82,8 +89,6 @@ var ModuleAddCommand = class extends BaseCommand {
|
|
|
82
89
|
if (dependencies && !Array.isArray(dependencies)) {
|
|
83
90
|
dependencies = Object.keys(dependencies);
|
|
84
91
|
}
|
|
85
|
-
} catch (e) {
|
|
86
|
-
throw e;
|
|
87
92
|
} finally {
|
|
88
93
|
await import_fs_extra.default.remove(stagingDir);
|
|
89
94
|
}
|
|
@@ -94,7 +99,9 @@ var ModuleAddCommand = class extends BaseCommand {
|
|
|
94
99
|
const normExisting = existingRemote.replace(/\.git$/, "");
|
|
95
100
|
const normNew = cleanUrl.replace(/\.git$/, "");
|
|
96
101
|
if (normExisting !== normNew && existingRemote !== "") {
|
|
97
|
-
throw new Error(
|
|
102
|
+
throw new Error(
|
|
103
|
+
`Dependency Conflict! Module '${moduleName}' exists but remote '${existingRemote}' does not match '${cleanUrl}'.`
|
|
104
|
+
);
|
|
98
105
|
}
|
|
99
106
|
this.info(`Module ${moduleName} already installed.`);
|
|
100
107
|
} else {
|
|
@@ -118,7 +125,7 @@ var ModuleAddCommand = class extends BaseCommand {
|
|
|
118
125
|
}
|
|
119
126
|
try {
|
|
120
127
|
const content = await import_fs_extra.default.readFile(configPath, "utf8");
|
|
121
|
-
|
|
128
|
+
const config = YAML.parse(content) || {};
|
|
122
129
|
if (!config.modules) config.modules = [];
|
|
123
130
|
if (!config.modules.includes(moduleName)) {
|
|
124
131
|
config.modules.push(moduleName);
|
|
@@ -126,7 +133,11 @@ var ModuleAddCommand = class extends BaseCommand {
|
|
|
126
133
|
logger.debug(`Added ${moduleName} to nexical.yaml modules list.`);
|
|
127
134
|
}
|
|
128
135
|
} catch (e) {
|
|
129
|
-
|
|
136
|
+
if (e instanceof Error) {
|
|
137
|
+
logger.warn(`Failed to update nexical.yaml: ${e.message}`);
|
|
138
|
+
} else {
|
|
139
|
+
logger.warn(`Failed to update nexical.yaml: ${String(e)}`);
|
|
140
|
+
}
|
|
130
141
|
}
|
|
131
142
|
}
|
|
132
143
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/commands/module/add.ts"],"sourcesContent":["import { type CommandDefinition, BaseCommand, logger, runCommand } from '@nexical/cli-core';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { clone, getRemoteUrl } from '../../utils/git.js';\nimport { resolveGitUrl } from '../../utils/url-resolver.js';\nimport YAML from 'yaml';\n\nexport default class ModuleAddCommand extends BaseCommand {\n
|
|
1
|
+
{"version":3,"sources":["../../../../src/commands/module/add.ts"],"sourcesContent":["import { type CommandDefinition, BaseCommand, logger, runCommand } from '@nexical/cli-core';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport { clone, getRemoteUrl } from '../../utils/git.js';\nimport { resolveGitUrl } from '../../utils/url-resolver.js';\nimport YAML from 'yaml';\n\nexport default class ModuleAddCommand extends BaseCommand {\n static usage = 'module add <url>';\n static description = 'Add a module and its dependencies as git submodules.';\n static requiresProject = true;\n\n static args: CommandDefinition = {\n args: [{ name: 'url', required: true, description: 'Git repository URL or gh@org/repo' }],\n };\n\n private visited = new Set<string>();\n\n async run(options: { url: string }) {\n const projectRoot = this.projectRoot as string;\n const { url } = options;\n\n if (!url) {\n this.error('Please specify a repository URL.');\n return;\n }\n\n try {\n await this.installModule(url);\n\n this.info('Syncing workspace dependencies...');\n await runCommand('npm install', projectRoot);\n\n this.success('All modules installed successfully.');\n } catch (e: unknown) {\n if (e instanceof Error) {\n this.error(`Failed to add module: ${e.message}`);\n } else {\n this.error(`Failed to add module: ${String(e)}`);\n }\n }\n }\n\n private async installModule(url: string) {\n const projectRoot = this.projectRoot as string;\n\n // Resolve URL using utility\n url = resolveGitUrl(url);\n\n const [repoUrl, subPath] = url.split('.git//');\n const cleanUrl = subPath ? repoUrl + '.git' : url;\n\n if (this.visited.has(cleanUrl)) {\n logger.debug(`Already visited ${cleanUrl}, skipping.`);\n return;\n }\n this.visited.add(cleanUrl);\n\n this.info(`Inspecting ${cleanUrl}...`);\n\n // Stage 1: Inspect (Temp Clone)\n const stagingDir = path.resolve(\n projectRoot!,\n '.nexical',\n 'cache',\n `staging-${Date.now()}-${Math.random().toString(36).substring(7)}`,\n );\n let moduleName = '';\n let dependencies: string[] = [];\n\n try {\n await fs.ensureDir(stagingDir);\n\n // Shallow clone to inspect\n await clone(cleanUrl, stagingDir, { depth: 1 });\n\n // Read module.yaml\n const searchPath = subPath ? path.join(stagingDir, subPath) : stagingDir;\n const moduleYamlPath = path.join(searchPath, 'module.yaml');\n const moduleYmlPath = path.join(searchPath, 'module.yml');\n\n let configPath = '';\n if (await fs.pathExists(moduleYamlPath)) configPath = moduleYamlPath;\n else if (await fs.pathExists(moduleYmlPath)) configPath = moduleYmlPath;\n else {\n throw new Error(`No module.yaml found in ${cleanUrl}${subPath ? '//' + subPath : ''}`);\n }\n\n const configContent = await fs.readFile(configPath, 'utf8');\n const config = YAML.parse(configContent);\n\n if (!config.name) {\n throw new Error(`Module at ${url} is missing 'name' in module.yaml`);\n }\n moduleName = config.name;\n dependencies = config.dependencies || [];\n\n // Normalize dependencies to array if object (though spec says list of strings, defensiveness is good)\n if (dependencies && !Array.isArray(dependencies)) {\n dependencies = Object.keys(dependencies);\n }\n } finally {\n // Cleanup staging always\n await fs.remove(stagingDir);\n }\n\n // Stage 2: Conflict Detection\n const targetDir = path.join(projectRoot!, 'modules', moduleName);\n const relativeTargetDir = path.relative(projectRoot!, targetDir);\n\n if (await fs.pathExists(targetDir)) {\n // Check origin\n const existingRemote = await getRemoteUrl(targetDir);\n // We compare cleanUrl (the repo root).\n // normalize both\n const normExisting = existingRemote.replace(/\\.git$/, '');\n const normNew = cleanUrl.replace(/\\.git$/, '');\n\n if (normExisting !== normNew && existingRemote !== '') {\n throw new Error(\n `Dependency Conflict! Module '${moduleName}' exists but remote '${existingRemote}' does not match '${cleanUrl}'.`,\n );\n }\n\n this.info(`Module ${moduleName} already installed.`);\n // Proceed to recurse, but skip add\n } else {\n // Stage 3: Submodule Add\n this.info(`Installing ${moduleName} to ${relativeTargetDir}...`);\n // We install the ROOT repo.\n // IMPORTANT: If subPath exists, \"Identity is Internal\" means we name the folder `moduleName`.\n // But the CONTENT will be the whole repo.\n // If the user meant to only have the subdir, we can't do that with submodule add easily without manual git plumbing.\n // Given instructions, I will proceed with submodule add of root repo to target dir.\n await runCommand(`git submodule add ${cleanUrl} ${relativeTargetDir}`, projectRoot!);\n }\n\n // Update nexical.yaml\n await this.addToConfig(moduleName);\n\n // Stage 4: Recurse\n if (dependencies.length > 0) {\n this.info(`Resolving ${dependencies.length} dependencies for ${moduleName}...`);\n for (const depUrl of dependencies) {\n await this.installModule(depUrl);\n }\n }\n }\n\n private async addToConfig(moduleName: string) {\n const projectRoot = this.projectRoot as string;\n const configPath = path.join(projectRoot, 'nexical.yaml');\n\n if (!(await fs.pathExists(configPath))) {\n // Not strictly required to exist for all operations, but good to have if we are tracking modules.\n logger.warn('nexical.yaml not found, skipping module list update.');\n return;\n }\n\n try {\n const content = await fs.readFile(configPath, 'utf8');\n const config = YAML.parse(content) || {};\n\n if (!config.modules) config.modules = [];\n\n if (!config.modules.includes(moduleName)) {\n config.modules.push(moduleName);\n await fs.writeFile(configPath, YAML.stringify(config));\n logger.debug(`Added ${moduleName} to nexical.yaml modules list.`);\n }\n } catch (e: unknown) {\n if (e instanceof Error) {\n logger.warn(`Failed to update nexical.yaml: ${e.message}`);\n } else {\n logger.warn(`Failed to update nexical.yaml: ${String(e)}`);\n }\n }\n }\n}\n"],"mappings":"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","names":["fs"]}
|
|
@@ -41,7 +41,7 @@ var ModuleListCommand = class extends BaseCommand {
|
|
|
41
41
|
if (await import_fs_extra.default.pathExists(pkgJsonPath)) {
|
|
42
42
|
try {
|
|
43
43
|
pkg = await import_fs_extra.default.readJson(pkgJsonPath);
|
|
44
|
-
} catch
|
|
44
|
+
} catch {
|
|
45
45
|
}
|
|
46
46
|
}
|
|
47
47
|
if (await import_fs_extra.default.pathExists(moduleYamlPath) || await import_fs_extra.default.pathExists(moduleYmlPath)) {
|
|
@@ -49,11 +49,11 @@ var ModuleListCommand = class extends BaseCommand {
|
|
|
49
49
|
const configPath = await import_fs_extra.default.pathExists(moduleYamlPath) ? moduleYamlPath : moduleYmlPath;
|
|
50
50
|
const content = await import_fs_extra.default.readFile(configPath, "utf8");
|
|
51
51
|
modConfig = YAML.parse(content) || {};
|
|
52
|
-
} catch
|
|
52
|
+
} catch {
|
|
53
53
|
}
|
|
54
54
|
}
|
|
55
|
-
version = pkg.version || "unknown";
|
|
56
|
-
description =
|
|
55
|
+
version = pkg.version || modConfig.version || "unknown";
|
|
56
|
+
description = pkg.description || modConfig.description || "";
|
|
57
57
|
validModules.push({ name: moduleName, version, description });
|
|
58
58
|
}
|
|
59
59
|
}
|
|
@@ -63,7 +63,11 @@ var ModuleListCommand = class extends BaseCommand {
|
|
|
63
63
|
console.table(validModules);
|
|
64
64
|
}
|
|
65
65
|
} catch (error) {
|
|
66
|
-
|
|
66
|
+
if (error instanceof Error) {
|
|
67
|
+
this.error(`Failed to list modules: ${error.message}`);
|
|
68
|
+
} else {
|
|
69
|
+
this.error(`Failed to list modules: ${String(error)}`);
|
|
70
|
+
}
|
|
67
71
|
}
|
|
68
72
|
}
|
|
69
73
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../../../src/commands/module/list.ts"],"sourcesContent":["import { BaseCommand, logger } from '@nexical/cli-core';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport YAML from 'yaml';\n\nexport default class ModuleListCommand extends BaseCommand {\n
|
|
1
|
+
{"version":3,"sources":["../../../../src/commands/module/list.ts"],"sourcesContent":["import { BaseCommand, logger } from '@nexical/cli-core';\nimport fs from 'fs-extra';\nimport path from 'path';\nimport YAML from 'yaml';\n\nexport default class ModuleListCommand extends BaseCommand {\n static usage = 'module list';\n static description = 'List installed modules.';\n static requiresProject = true;\n\n async run() {\n const projectRoot = this.projectRoot as string;\n const modulesDir = path.resolve(projectRoot, 'modules');\n logger.debug(`Scanning for modules in: ${modulesDir}`);\n\n if (!(await fs.pathExists(modulesDir))) {\n this.info('No modules installed (modules directory missing).');\n return;\n }\n\n try {\n const modules = await fs.readdir(modulesDir);\n const validModules: { name: string; version: string; description: string }[] = [];\n\n for (const moduleName of modules) {\n const modulePath = path.join(modulesDir, moduleName);\n if ((await fs.stat(modulePath)).isDirectory()) {\n let version = 'unknown';\n let description = '';\n\n const pkgJsonPath = path.join(modulePath, 'package.json');\n const moduleYamlPath = path.join(modulePath, 'module.yaml');\n const moduleYmlPath = path.join(modulePath, 'module.yml');\n\n let pkg: Record<string, unknown> = {};\n let modConfig: Record<string, unknown> = {};\n\n if (await fs.pathExists(pkgJsonPath)) {\n try {\n pkg = await fs.readJson(pkgJsonPath);\n } catch {\n /* ignore */\n }\n }\n\n if ((await fs.pathExists(moduleYamlPath)) || (await fs.pathExists(moduleYmlPath))) {\n try {\n const configPath = (await fs.pathExists(moduleYamlPath))\n ? moduleYamlPath\n : moduleYmlPath;\n const content = await fs.readFile(configPath, 'utf8');\n modConfig = YAML.parse(content) || {};\n } catch {\n /* ignore */\n }\n }\n\n version = (pkg.version as string) || (modConfig.version as string) || 'unknown';\n description = (pkg.description as string) || (modConfig.description as string) || '';\n // Optionally use display name from module.yaml if present, but strictly list is usually dir name.\n // Let's stick to dir name for \"name\" column, but description from module.yaml is good.\n validModules.push({ name: moduleName, version, description });\n }\n }\n\n if (validModules.length === 0) {\n this.info('No modules installed.');\n } else {\n // eslint-disable-next-line no-console\n console.table(validModules);\n }\n } catch (error: unknown) {\n if (error instanceof Error) {\n this.error(`Failed to list modules: ${error.message}`);\n } else {\n this.error(`Failed to list modules: ${String(error)}`);\n }\n }\n }\n}\n"],"mappings":";;;;;;;;;;AAAA;AACA,sBAAe;AADf,SAAS,aAAa,cAAc;AAEpC,OAAO,UAAU;AACjB,OAAO,UAAU;AAEjB,IAAqB,oBAArB,cAA+C,YAAY;AAAA,EACzD,OAAO,QAAQ;AAAA,EACf,OAAO,cAAc;AAAA,EACrB,OAAO,kBAAkB;AAAA,EAEzB,MAAM,MAAM;AACV,UAAM,cAAc,KAAK;AACzB,UAAM,aAAa,KAAK,QAAQ,aAAa,SAAS;AACtD,WAAO,MAAM,4BAA4B,UAAU,EAAE;AAErD,QAAI,CAAE,MAAM,gBAAAA,QAAG,WAAW,UAAU,GAAI;AACtC,WAAK,KAAK,mDAAmD;AAC7D;AAAA,IACF;AAEA,QAAI;AACF,YAAM,UAAU,MAAM,gBAAAA,QAAG,QAAQ,UAAU;AAC3C,YAAM,eAAyE,CAAC;AAEhF,iBAAW,cAAc,SAAS;AAChC,cAAM,aAAa,KAAK,KAAK,YAAY,UAAU;AACnD,aAAK,MAAM,gBAAAA,QAAG,KAAK,UAAU,GAAG,YAAY,GAAG;AAC7C,cAAI,UAAU;AACd,cAAI,cAAc;AAElB,gBAAM,cAAc,KAAK,KAAK,YAAY,cAAc;AACxD,gBAAM,iBAAiB,KAAK,KAAK,YAAY,aAAa;AAC1D,gBAAM,gBAAgB,KAAK,KAAK,YAAY,YAAY;AAExD,cAAI,MAA+B,CAAC;AACpC,cAAI,YAAqC,CAAC;AAE1C,cAAI,MAAM,gBAAAA,QAAG,WAAW,WAAW,GAAG;AACpC,gBAAI;AACF,oBAAM,MAAM,gBAAAA,QAAG,SAAS,WAAW;AAAA,YACrC,QAAQ;AAAA,YAER;AAAA,UACF;AAEA,cAAK,MAAM,gBAAAA,QAAG,WAAW,cAAc,KAAO,MAAM,gBAAAA,QAAG,WAAW,aAAa,GAAI;AACjF,gBAAI;AACF,oBAAM,aAAc,MAAM,gBAAAA,QAAG,WAAW,cAAc,IAClD,iBACA;AACJ,oBAAM,UAAU,MAAM,gBAAAA,QAAG,SAAS,YAAY,MAAM;AACpD,0BAAY,KAAK,MAAM,OAAO,KAAK,CAAC;AAAA,YACtC,QAAQ;AAAA,YAER;AAAA,UACF;AAEA,oBAAW,IAAI,WAAuB,UAAU,WAAsB;AACtE,wBAAe,IAAI,eAA2B,UAAU,eAA0B;AAGlF,uBAAa,KAAK,EAAE,MAAM,YAAY,SAAS,YAAY,CAAC;AAAA,QAC9D;AAAA,MACF;AAEA,UAAI,aAAa,WAAW,GAAG;AAC7B,aAAK,KAAK,uBAAuB;AAAA,MACnC,OAAO;AAEL,gBAAQ,MAAM,YAAY;AAAA,MAC5B;AAAA,IACF,SAAS,OAAgB;AACvB,UAAI,iBAAiB,OAAO;AAC1B,aAAK,MAAM,2BAA2B,MAAM,OAAO,EAAE;AAAA,MACvD,OAAO;AACL,aAAK,MAAM,2BAA2B,OAAO,KAAK,CAAC,EAAE;AAAA,MACvD;AAAA,IACF;AAAA,EACF;AACF;","names":["fs"]}
|
|
@@ -5,7 +5,9 @@ declare class ModuleRemoveCommand extends BaseCommand {
|
|
|
5
5
|
static description: string;
|
|
6
6
|
static requiresProject: boolean;
|
|
7
7
|
static args: CommandDefinition;
|
|
8
|
-
run(options:
|
|
8
|
+
run(options: {
|
|
9
|
+
name: string;
|
|
10
|
+
}): Promise<void>;
|
|
9
11
|
private removeFromConfig;
|
|
10
12
|
}
|
|
11
13
|
|
|
@@ -18,13 +18,11 @@ var ModuleRemoveCommand = class extends BaseCommand {
|
|
|
18
18
|
static description = "Remove an installed module.";
|
|
19
19
|
static requiresProject = true;
|
|
20
20
|
static args = {
|
|
21
|
-
args: [
|
|
22
|
-
{ name: "name", required: true, description: "Name of the module to remove" }
|
|
23
|
-
]
|
|
21
|
+
args: [{ name: "name", required: true, description: "Name of the module to remove" }]
|
|
24
22
|
};
|
|
25
23
|
async run(options) {
|
|
26
24
|
const projectRoot = this.projectRoot;
|
|
27
|
-
|
|
25
|
+
const { name } = options;
|
|
28
26
|
const relativePath = `modules/${name}`;
|
|
29
27
|
const fullPath = path.resolve(projectRoot, relativePath);
|
|
30
28
|
logger.debug("Removing module at:", fullPath);
|
|
@@ -45,7 +43,11 @@ var ModuleRemoveCommand = class extends BaseCommand {
|
|
|
45
43
|
await this.removeFromConfig(name);
|
|
46
44
|
this.success(`Module ${name} removed successfully.`);
|
|
47
45
|
} catch (e) {
|
|
48
|
-
|
|
46
|
+
if (e instanceof Error) {
|
|
47
|
+
this.error(`Failed to remove module: ${e.message}`);
|
|
48
|
+
} else {
|
|
49
|
+
this.error(`Failed to remove module: ${String(e)}`);
|
|
50
|
+
}
|
|
49
51
|
}
|
|
50
52
|
}
|
|
51
53
|
async removeFromConfig(moduleName) {
|
|
@@ -54,14 +56,18 @@ var ModuleRemoveCommand = class extends BaseCommand {
|
|
|
54
56
|
if (!await import_fs_extra.default.pathExists(configPath)) return;
|
|
55
57
|
try {
|
|
56
58
|
const content = await import_fs_extra.default.readFile(configPath, "utf8");
|
|
57
|
-
|
|
59
|
+
const config = YAML.parse(content) || {};
|
|
58
60
|
if (config.modules && config.modules.includes(moduleName)) {
|
|
59
61
|
config.modules = config.modules.filter((m) => m !== moduleName);
|
|
60
62
|
await import_fs_extra.default.writeFile(configPath, YAML.stringify(config));
|
|
61
63
|
logger.debug(`Removed ${moduleName} from nexical.yaml modules list.`);
|
|
62
64
|
}
|
|
63
65
|
} catch (e) {
|
|
64
|
-
|
|
66
|
+
if (e instanceof Error) {
|
|
67
|
+
logger.warn(`Failed to update nexical.yaml: ${e.message}`);
|
|
68
|
+
} else {
|
|
69
|
+
logger.warn(`Failed to update nexical.yaml: ${String(e)}`);
|
|
70
|
+
}
|
|
65
71
|
}
|
|
66
72
|
}
|
|
67
73
|
};
|