@decantr/cli 1.7.25 → 1.7.26
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.js +1 -1
- package/dist/{chunk-7FXMRAC3.js → chunk-RAAUNHXD.js} +130 -34
- package/dist/index.js +1 -1
- package/package.json +12 -8
- package/LICENSE +0 -21
package/dist/bin.js
CHANGED
|
@@ -40,29 +40,63 @@ import {
|
|
|
40
40
|
} from "@decantr/verifier";
|
|
41
41
|
|
|
42
42
|
// src/auth.ts
|
|
43
|
-
import {
|
|
43
|
+
import {
|
|
44
|
+
chmodSync,
|
|
45
|
+
existsSync,
|
|
46
|
+
mkdirSync,
|
|
47
|
+
readFileSync,
|
|
48
|
+
rmSync,
|
|
49
|
+
statSync,
|
|
50
|
+
writeFileSync
|
|
51
|
+
} from "fs";
|
|
44
52
|
import { homedir } from "os";
|
|
45
53
|
import { join } from "path";
|
|
46
|
-
var
|
|
47
|
-
var
|
|
54
|
+
var CONFIG_DIR_MODE = 448;
|
|
55
|
+
var AUTH_FILE_MODE = 384;
|
|
56
|
+
function getConfigDir() {
|
|
57
|
+
return process.env.DECANTR_CONFIG_DIR || join(homedir(), ".config", "decantr");
|
|
58
|
+
}
|
|
59
|
+
function getAuthFile() {
|
|
60
|
+
return join(getConfigDir(), "auth.json");
|
|
61
|
+
}
|
|
62
|
+
function chmodIfNeeded(path, mode) {
|
|
63
|
+
try {
|
|
64
|
+
if ((statSync(path).mode & 511) !== mode) {
|
|
65
|
+
chmodSync(path, mode);
|
|
66
|
+
}
|
|
67
|
+
} catch {
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function ensureConfigDir() {
|
|
71
|
+
const configDir = getConfigDir();
|
|
72
|
+
mkdirSync(configDir, { recursive: true, mode: CONFIG_DIR_MODE });
|
|
73
|
+
chmodIfNeeded(configDir, CONFIG_DIR_MODE);
|
|
74
|
+
}
|
|
48
75
|
function getCredentials() {
|
|
49
|
-
|
|
76
|
+
const authFile = getAuthFile();
|
|
77
|
+
if (!existsSync(authFile)) return null;
|
|
50
78
|
try {
|
|
51
|
-
|
|
79
|
+
chmodIfNeeded(authFile, AUTH_FILE_MODE);
|
|
80
|
+
return JSON.parse(readFileSync(authFile, "utf-8"));
|
|
52
81
|
} catch {
|
|
53
82
|
return null;
|
|
54
83
|
}
|
|
55
84
|
}
|
|
56
85
|
function saveCredentials(creds) {
|
|
57
|
-
|
|
58
|
-
|
|
86
|
+
ensureConfigDir();
|
|
87
|
+
const authFile = getAuthFile();
|
|
88
|
+
writeFileSync(authFile, JSON.stringify(creds, null, 2), { mode: AUTH_FILE_MODE });
|
|
89
|
+
chmodIfNeeded(authFile, AUTH_FILE_MODE);
|
|
59
90
|
}
|
|
60
91
|
function clearCredentials() {
|
|
61
|
-
|
|
62
|
-
|
|
92
|
+
const authFile = getAuthFile();
|
|
93
|
+
if (existsSync(authFile)) {
|
|
94
|
+
rmSync(authFile);
|
|
63
95
|
}
|
|
64
96
|
}
|
|
65
97
|
function getApiKeyOrToken() {
|
|
98
|
+
const envKey = process.env.DECANTR_API_KEY?.trim();
|
|
99
|
+
if (envKey) return envKey;
|
|
66
100
|
const creds = getCredentials();
|
|
67
101
|
if (!creds) return null;
|
|
68
102
|
return creds.api_key || creds.access_token || null;
|
|
@@ -341,7 +375,7 @@ import { existsSync as existsSync12, mkdirSync as mkdirSync3, writeFileSync as w
|
|
|
341
375
|
import { join as join12 } from "path";
|
|
342
376
|
|
|
343
377
|
// src/analyzers/components.ts
|
|
344
|
-
import { existsSync as existsSync4, readdirSync, statSync } from "fs";
|
|
378
|
+
import { existsSync as existsSync4, readdirSync, statSync as statSync2 } from "fs";
|
|
345
379
|
import { join as join4 } from "path";
|
|
346
380
|
var PAGE_EXTENSIONS = /* @__PURE__ */ new Set([".tsx", ".ts", ".jsx", ".js"]);
|
|
347
381
|
var ROOT_COMPONENT_CANDIDATES = [
|
|
@@ -366,7 +400,7 @@ function countFilesRecursive(dir, extensions) {
|
|
|
366
400
|
if (entry.startsWith(".") || entry === "node_modules") continue;
|
|
367
401
|
const fullPath = join4(dir, entry);
|
|
368
402
|
try {
|
|
369
|
-
const stat =
|
|
403
|
+
const stat = statSync2(fullPath);
|
|
370
404
|
if (stat.isDirectory()) {
|
|
371
405
|
count += countFilesRecursive(fullPath, extensions);
|
|
372
406
|
} else if (stat.isFile()) {
|
|
@@ -392,7 +426,7 @@ function countPageFiles(dir) {
|
|
|
392
426
|
if (entry.startsWith(".") || entry === "node_modules") continue;
|
|
393
427
|
const fullPath = join4(dir, entry);
|
|
394
428
|
try {
|
|
395
|
-
const stat =
|
|
429
|
+
const stat = statSync2(fullPath);
|
|
396
430
|
if (stat.isDirectory()) {
|
|
397
431
|
count += countPageFiles(fullPath);
|
|
398
432
|
} else if (stat.isFile()) {
|
|
@@ -632,7 +666,7 @@ function scanDependencies(projectRoot) {
|
|
|
632
666
|
}
|
|
633
667
|
|
|
634
668
|
// src/analyzers/features.ts
|
|
635
|
-
import { existsSync as existsSync6, readdirSync as readdirSync2, statSync as
|
|
669
|
+
import { existsSync as existsSync6, readdirSync as readdirSync2, statSync as statSync3 } from "fs";
|
|
636
670
|
import { join as join6 } from "path";
|
|
637
671
|
var FEATURE_PATTERNS = {
|
|
638
672
|
auth: [
|
|
@@ -690,7 +724,7 @@ function collectPaths(dir, baseDir, depth = 0) {
|
|
|
690
724
|
const relPath = fullPath.slice(baseDir.length + 1);
|
|
691
725
|
paths.push(relPath);
|
|
692
726
|
try {
|
|
693
|
-
if (
|
|
727
|
+
if (statSync3(fullPath).isDirectory()) {
|
|
694
728
|
paths.push(...collectPaths(fullPath, baseDir, depth + 1));
|
|
695
729
|
}
|
|
696
730
|
} catch {
|
|
@@ -861,7 +895,7 @@ function scanLayout(projectRoot) {
|
|
|
861
895
|
}
|
|
862
896
|
|
|
863
897
|
// src/analyzers/routes.ts
|
|
864
|
-
import { existsSync as existsSync8, readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as
|
|
898
|
+
import { existsSync as existsSync8, readdirSync as readdirSync4, readFileSync as readFileSync6, statSync as statSync4 } from "fs";
|
|
865
899
|
import { join as join8, relative } from "path";
|
|
866
900
|
var SKIP_DIRS = /* @__PURE__ */ new Set(["node_modules", ".next", ".git", "api", "_app", "_document"]);
|
|
867
901
|
function shouldSkipDir(name) {
|
|
@@ -910,7 +944,7 @@ function walkAppDir(dir, baseDir, segments) {
|
|
|
910
944
|
if (shouldSkipDir(entry)) continue;
|
|
911
945
|
const fullPath = join8(dir, entry);
|
|
912
946
|
try {
|
|
913
|
-
if (!
|
|
947
|
+
if (!statSync4(fullPath).isDirectory()) continue;
|
|
914
948
|
} catch {
|
|
915
949
|
continue;
|
|
916
950
|
}
|
|
@@ -932,7 +966,7 @@ function walkPagesDir(dir, baseDir, segments) {
|
|
|
932
966
|
if (shouldSkipDir(entry)) continue;
|
|
933
967
|
const fullPath = join8(dir, entry);
|
|
934
968
|
try {
|
|
935
|
-
const stat =
|
|
969
|
+
const stat = statSync4(fullPath);
|
|
936
970
|
if (stat.isDirectory()) {
|
|
937
971
|
const routeSegment = segmentToRoute(entry);
|
|
938
972
|
const nextSegments = routeSegment === null ? [...segments] : [...segments, routeSegment];
|
|
@@ -968,7 +1002,7 @@ function collectRouteCandidateFiles(dir, files, depth = 0) {
|
|
|
968
1002
|
if (entry.startsWith(".") || entry === "node_modules") continue;
|
|
969
1003
|
const fullPath = join8(dir, entry);
|
|
970
1004
|
try {
|
|
971
|
-
const stat =
|
|
1005
|
+
const stat = statSync4(fullPath);
|
|
972
1006
|
if (stat.isDirectory()) {
|
|
973
1007
|
collectRouteCandidateFiles(fullPath, files, depth + 1);
|
|
974
1008
|
} else if (stat.isFile()) {
|
|
@@ -2668,7 +2702,7 @@ async function cmdMigrate(projectRoot = process.cwd()) {
|
|
|
2668
2702
|
}
|
|
2669
2703
|
|
|
2670
2704
|
// src/commands/new-project.ts
|
|
2671
|
-
import {
|
|
2705
|
+
import { spawnSync } from "child_process";
|
|
2672
2706
|
import { existsSync as existsSync18, mkdirSync as mkdirSync8 } from "fs";
|
|
2673
2707
|
import { join as join19, resolve as resolve2 } from "path";
|
|
2674
2708
|
import { fileURLToPath } from "url";
|
|
@@ -3118,6 +3152,72 @@ function dim2(text) {
|
|
|
3118
3152
|
function cyan2(text) {
|
|
3119
3153
|
return `${CYAN3}${text}${RESET6}`;
|
|
3120
3154
|
}
|
|
3155
|
+
function validatePassThroughFlagValue(flag, value) {
|
|
3156
|
+
if (value.length === 0) {
|
|
3157
|
+
throw new Error(`--${flag} cannot be empty.`);
|
|
3158
|
+
}
|
|
3159
|
+
if (value.length > 512) {
|
|
3160
|
+
throw new Error(`--${flag} is too long.`);
|
|
3161
|
+
}
|
|
3162
|
+
if (/[\u0000-\u001f\u007f]/.test(value)) {
|
|
3163
|
+
throw new Error(`--${flag} contains unsupported control characters.`);
|
|
3164
|
+
}
|
|
3165
|
+
return value;
|
|
3166
|
+
}
|
|
3167
|
+
function pushPassThroughFlag(flags, flag, value) {
|
|
3168
|
+
if (value == null) return;
|
|
3169
|
+
flags.push(`--${flag}=${validatePassThroughFlagValue(flag, value)}`);
|
|
3170
|
+
}
|
|
3171
|
+
function buildNewProjectInitArgs(options, inferredAdoption) {
|
|
3172
|
+
const initFlags = [
|
|
3173
|
+
"--yes",
|
|
3174
|
+
"--workflow=greenfield",
|
|
3175
|
+
`--adoption=${validatePassThroughFlagValue("mode", inferredAdoption)}`
|
|
3176
|
+
];
|
|
3177
|
+
pushPassThroughFlag(initFlags, "blueprint", options.blueprint);
|
|
3178
|
+
pushPassThroughFlag(initFlags, "archetype", options.archetype);
|
|
3179
|
+
pushPassThroughFlag(initFlags, "theme", options.theme);
|
|
3180
|
+
pushPassThroughFlag(initFlags, "mode", options.mode);
|
|
3181
|
+
pushPassThroughFlag(initFlags, "shape", options.shape);
|
|
3182
|
+
pushPassThroughFlag(initFlags, "target", options.target);
|
|
3183
|
+
if (options.offline) initFlags.push("--offline");
|
|
3184
|
+
pushPassThroughFlag(initFlags, "registry", options.registry);
|
|
3185
|
+
pushPassThroughFlag(initFlags, "assistant-bridge", options.assistantBridge);
|
|
3186
|
+
return initFlags;
|
|
3187
|
+
}
|
|
3188
|
+
function commandForPlatform(command) {
|
|
3189
|
+
if (process.platform !== "win32") {
|
|
3190
|
+
return command;
|
|
3191
|
+
}
|
|
3192
|
+
return /^(?:npm|pnpm|yarn|bun|npx)$/.test(command) ? `${command}.cmd` : command;
|
|
3193
|
+
}
|
|
3194
|
+
function runArgvCommand(command, args, cwd) {
|
|
3195
|
+
const result = spawnSync(commandForPlatform(command), args, {
|
|
3196
|
+
cwd,
|
|
3197
|
+
stdio: "inherit",
|
|
3198
|
+
shell: false
|
|
3199
|
+
});
|
|
3200
|
+
if (result.error) {
|
|
3201
|
+
throw result.error;
|
|
3202
|
+
}
|
|
3203
|
+
if (result.status !== 0) {
|
|
3204
|
+
throw new Error(`Command failed: ${command} ${args.join(" ")}`);
|
|
3205
|
+
}
|
|
3206
|
+
}
|
|
3207
|
+
function resolveInitCommand(initFlags) {
|
|
3208
|
+
const bundledCliEntrypoint = fileURLToPath(new URL("./bin.js", import.meta.url));
|
|
3209
|
+
const cliEntrypoint = existsSync18(bundledCliEntrypoint) ? bundledCliEntrypoint : process.argv[1] && existsSync18(process.argv[1]) ? process.argv[1] : null;
|
|
3210
|
+
if (cliEntrypoint) {
|
|
3211
|
+
return {
|
|
3212
|
+
command: process.execPath,
|
|
3213
|
+
args: [cliEntrypoint, "init", ...initFlags]
|
|
3214
|
+
};
|
|
3215
|
+
}
|
|
3216
|
+
return {
|
|
3217
|
+
command: "npx",
|
|
3218
|
+
args: ["decantr", "init", ...initFlags]
|
|
3219
|
+
};
|
|
3220
|
+
}
|
|
3121
3221
|
async function cmdNewProject(projectName, options) {
|
|
3122
3222
|
const workspaceRoot = process.cwd();
|
|
3123
3223
|
const projectDir = resolve2(workspaceRoot, projectName);
|
|
@@ -3138,6 +3238,14 @@ async function cmdNewProject(projectName, options) {
|
|
|
3138
3238
|
process.exitCode = 1;
|
|
3139
3239
|
return;
|
|
3140
3240
|
}
|
|
3241
|
+
let initFlags;
|
|
3242
|
+
try {
|
|
3243
|
+
initFlags = buildNewProjectInitArgs(options, inferredAdoption);
|
|
3244
|
+
} catch (err) {
|
|
3245
|
+
console.error(error2(err.message));
|
|
3246
|
+
process.exitCode = 1;
|
|
3247
|
+
return;
|
|
3248
|
+
}
|
|
3141
3249
|
console.log(heading(`Creating ${projectName}...`));
|
|
3142
3250
|
mkdirSync8(projectDir, { recursive: true });
|
|
3143
3251
|
console.log(dim2(` Created ${projectName}/`));
|
|
@@ -3165,7 +3273,7 @@ async function cmdNewProject(projectName, options) {
|
|
|
3165
3273
|
if (shouldBootstrapRuntime) {
|
|
3166
3274
|
console.log(heading("Installing dependencies..."));
|
|
3167
3275
|
try {
|
|
3168
|
-
|
|
3276
|
+
runArgvCommand(packageManager, ["install"], projectDir);
|
|
3169
3277
|
} catch {
|
|
3170
3278
|
console.log(
|
|
3171
3279
|
`
|
|
@@ -3202,21 +3310,9 @@ ${YELLOW4}Dependency install failed. Run \`${packageManager} install\` manually.
|
|
|
3202
3310
|
return;
|
|
3203
3311
|
}
|
|
3204
3312
|
console.log(heading("Initializing Decantr..."));
|
|
3205
|
-
const initFlags = ["--yes", "--workflow=greenfield", `--adoption=${inferredAdoption}`];
|
|
3206
|
-
if (options.blueprint) initFlags.push(`--blueprint=${options.blueprint}`);
|
|
3207
|
-
if (options.archetype) initFlags.push(`--archetype=${options.archetype}`);
|
|
3208
|
-
if (options.theme) initFlags.push(`--theme=${options.theme}`);
|
|
3209
|
-
if (options.mode) initFlags.push(`--mode=${options.mode}`);
|
|
3210
|
-
if (options.shape) initFlags.push(`--shape=${options.shape}`);
|
|
3211
|
-
if (options.target) initFlags.push(`--target=${options.target}`);
|
|
3212
|
-
if (options.offline) initFlags.push("--offline");
|
|
3213
|
-
if (options.registry) initFlags.push(`--registry=${options.registry}`);
|
|
3214
|
-
if (options.assistantBridge) initFlags.push(`--assistant-bridge=${options.assistantBridge}`);
|
|
3215
3313
|
try {
|
|
3216
|
-
const
|
|
3217
|
-
|
|
3218
|
-
const cliPath = cliEntrypoint ? `"${process.execPath}" "${cliEntrypoint}"` : "npx decantr";
|
|
3219
|
-
execSync(`${cliPath} init ${initFlags.join(" ")}`, { cwd: projectDir, stdio: "inherit" });
|
|
3314
|
+
const initCommand = resolveInitCommand(initFlags);
|
|
3315
|
+
runArgvCommand(initCommand.command, initCommand.args, projectDir);
|
|
3220
3316
|
if (shouldBootstrapRuntime && bootstrapAdapter) {
|
|
3221
3317
|
bootstrapAdapter.writeProjectFiles(projectDir, title, detectRoutingMode(projectDir));
|
|
3222
3318
|
}
|
package/dist/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@decantr/cli",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.26",
|
|
4
4
|
"description": "Decantr CLI — scaffold, audit, and maintain Decantr projects from the terminal",
|
|
5
5
|
"author": "Decantr AI",
|
|
6
6
|
"license": "MIT",
|
|
@@ -23,21 +23,25 @@
|
|
|
23
23
|
"src/templates",
|
|
24
24
|
"src/bundled"
|
|
25
25
|
],
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=20"
|
|
28
|
+
},
|
|
26
29
|
"publishConfig": {
|
|
27
30
|
"access": "public"
|
|
28
31
|
},
|
|
29
|
-
"dependencies": {
|
|
30
|
-
"@decantr/core": "1.0.5",
|
|
31
|
-
"@decantr/essence-spec": "1.0.5",
|
|
32
|
-
"@decantr/registry": "1.0.3",
|
|
33
|
-
"@decantr/verifier": "1.0.4"
|
|
34
|
-
},
|
|
35
32
|
"scripts": {
|
|
36
33
|
"build": "tsup",
|
|
37
34
|
"certify:blueprints": "pnpm build && node scripts/certify-blueprints.mjs",
|
|
38
35
|
"certify:workflows": "pnpm build && node scripts/certify-workflows.mjs",
|
|
39
36
|
"test": "vitest run",
|
|
40
37
|
"test:watch": "vitest",
|
|
38
|
+
"prepublishOnly": "pnpm build",
|
|
41
39
|
"preversion": "pnpm build && pnpm test"
|
|
40
|
+
},
|
|
41
|
+
"dependencies": {
|
|
42
|
+
"@decantr/core": "workspace:*",
|
|
43
|
+
"@decantr/essence-spec": "workspace:*",
|
|
44
|
+
"@decantr/registry": "workspace:*",
|
|
45
|
+
"@decantr/verifier": "workspace:*"
|
|
42
46
|
}
|
|
43
|
-
}
|
|
47
|
+
}
|
package/LICENSE
DELETED
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
MIT License
|
|
2
|
-
|
|
3
|
-
Copyright (c) 2026 Decantr AI
|
|
4
|
-
|
|
5
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
-
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
-
in the Software without restriction, including without limitation the rights
|
|
8
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
-
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
-
furnished to do so, subject to the following conditions:
|
|
11
|
-
|
|
12
|
-
The above copyright notice and this permission notice shall be included in all
|
|
13
|
-
copies or substantial portions of the Software.
|
|
14
|
-
|
|
15
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|