@docyrus/cli 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -0
- package/dist/cli.js +854 -18
- package/dist/cli.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
package/dist/cli.js
CHANGED
|
@@ -1,25 +1,478 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { join, resolve, dirname } from 'path';
|
|
3
|
+
import { URL as URL$1, fileURLToPath } from 'url';
|
|
2
4
|
import { Command } from 'commander';
|
|
3
5
|
import { RestApiClient, AuthenticationError as AuthenticationError$1 } from '@docyrus/api-client';
|
|
4
6
|
import { createServer } from 'http';
|
|
5
|
-
import { URL, fileURLToPath } from 'url';
|
|
6
7
|
import { randomBytes, createDecipheriv, createCipheriv, scryptSync, createHash } from 'crypto';
|
|
7
8
|
import open from 'open';
|
|
8
9
|
import { existsSync, readFileSync, mkdirSync, writeFileSync, unlinkSync, constants as constants$1 } from 'fs';
|
|
9
|
-
import { join, resolve, dirname } from 'path';
|
|
10
10
|
import { homedir, arch, release, platform, hostname, userInfo } from 'os';
|
|
11
11
|
import Conf from 'conf';
|
|
12
12
|
import chalk4 from 'chalk';
|
|
13
13
|
import ora from 'ora';
|
|
14
14
|
import { select, input, password, confirm } from '@inquirer/prompts';
|
|
15
|
-
import { exec } from 'child_process';
|
|
15
|
+
import { exec, execFileSync } from 'child_process';
|
|
16
16
|
import { promisify } from 'util';
|
|
17
17
|
import { access, constants, writeFile, readFile, mkdir, cp, rm, readdir } from 'fs/promises';
|
|
18
18
|
import { downloadTemplate } from 'giget';
|
|
19
19
|
import { generateFromOpenAPI } from '@docyrus/tanstack-db-generator';
|
|
20
20
|
|
|
21
|
+
var __create = Object.create;
|
|
22
|
+
var __defProp = Object.defineProperty;
|
|
23
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
24
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
25
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
26
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
27
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
28
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
29
|
+
}) : x)(function(x) {
|
|
30
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
31
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
32
|
+
});
|
|
33
|
+
var __esm = (fn, res) => function __init() {
|
|
34
|
+
return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
|
|
35
|
+
};
|
|
36
|
+
var __commonJS = (cb, mod) => function __require2() {
|
|
37
|
+
return mod || (0, cb[__getOwnPropNames(cb)[0]])((mod = { exports: {} }).exports, mod), mod.exports;
|
|
38
|
+
};
|
|
39
|
+
var __copyProps = (to, from, except, desc) => {
|
|
40
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
41
|
+
for (let key of __getOwnPropNames(from))
|
|
42
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
43
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
44
|
+
}
|
|
45
|
+
return to;
|
|
46
|
+
};
|
|
47
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
48
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
49
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
50
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
51
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
52
|
+
__defProp(target, "default", { value: mod, enumerable: true }) ,
|
|
53
|
+
mod
|
|
54
|
+
));
|
|
55
|
+
var init_esm_shims = __esm({
|
|
56
|
+
"../../node_modules/.pnpm/tsup@8.5.1_jiti@2.6.1_postcss@8.5.6_tsx@4.21.0_typescript@5.9.3_yaml@2.8.2/node_modules/tsup/assets/esm_shims.js"() {
|
|
57
|
+
}
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
// ../../node_modules/.pnpm/dotenv@17.2.4/node_modules/dotenv/package.json
|
|
61
|
+
var require_package = __commonJS({
|
|
62
|
+
"../../node_modules/.pnpm/dotenv@17.2.4/node_modules/dotenv/package.json"(exports$1, module) {
|
|
63
|
+
module.exports = {
|
|
64
|
+
name: "dotenv",
|
|
65
|
+
version: "17.2.4",
|
|
66
|
+
description: "Loads environment variables from .env file",
|
|
67
|
+
main: "lib/main.js",
|
|
68
|
+
types: "lib/main.d.ts",
|
|
69
|
+
exports: {
|
|
70
|
+
".": {
|
|
71
|
+
types: "./lib/main.d.ts",
|
|
72
|
+
require: "./lib/main.js",
|
|
73
|
+
default: "./lib/main.js"
|
|
74
|
+
},
|
|
75
|
+
"./config": "./config.js",
|
|
76
|
+
"./config.js": "./config.js",
|
|
77
|
+
"./lib/env-options": "./lib/env-options.js",
|
|
78
|
+
"./lib/env-options.js": "./lib/env-options.js",
|
|
79
|
+
"./lib/cli-options": "./lib/cli-options.js",
|
|
80
|
+
"./lib/cli-options.js": "./lib/cli-options.js",
|
|
81
|
+
"./package.json": "./package.json"
|
|
82
|
+
},
|
|
83
|
+
scripts: {
|
|
84
|
+
"dts-check": "tsc --project tests/types/tsconfig.json",
|
|
85
|
+
lint: "standard",
|
|
86
|
+
pretest: "npm run lint && npm run dts-check",
|
|
87
|
+
test: "tap run tests/**/*.js --allow-empty-coverage --disable-coverage --timeout=60000",
|
|
88
|
+
"test:coverage": "tap run tests/**/*.js --show-full-coverage --timeout=60000 --coverage-report=text --coverage-report=lcov",
|
|
89
|
+
prerelease: "npm test",
|
|
90
|
+
release: "standard-version"
|
|
91
|
+
},
|
|
92
|
+
repository: {
|
|
93
|
+
type: "git",
|
|
94
|
+
url: "git://github.com/motdotla/dotenv.git"
|
|
95
|
+
},
|
|
96
|
+
homepage: "https://github.com/motdotla/dotenv#readme",
|
|
97
|
+
funding: "https://dotenvx.com",
|
|
98
|
+
keywords: [
|
|
99
|
+
"dotenv",
|
|
100
|
+
"env",
|
|
101
|
+
".env",
|
|
102
|
+
"environment",
|
|
103
|
+
"variables",
|
|
104
|
+
"config",
|
|
105
|
+
"settings"
|
|
106
|
+
],
|
|
107
|
+
readmeFilename: "README.md",
|
|
108
|
+
license: "BSD-2-Clause",
|
|
109
|
+
devDependencies: {
|
|
110
|
+
"@types/node": "^18.11.3",
|
|
111
|
+
decache: "^4.6.2",
|
|
112
|
+
sinon: "^14.0.1",
|
|
113
|
+
standard: "^17.0.0",
|
|
114
|
+
"standard-version": "^9.5.0",
|
|
115
|
+
tap: "^19.2.0",
|
|
116
|
+
typescript: "^4.8.4"
|
|
117
|
+
},
|
|
118
|
+
engines: {
|
|
119
|
+
node: ">=12"
|
|
120
|
+
},
|
|
121
|
+
browser: {
|
|
122
|
+
fs: false
|
|
123
|
+
}
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
// ../../node_modules/.pnpm/dotenv@17.2.4/node_modules/dotenv/lib/main.js
|
|
129
|
+
var require_main = __commonJS({
|
|
130
|
+
"../../node_modules/.pnpm/dotenv@17.2.4/node_modules/dotenv/lib/main.js"(exports$1, module) {
|
|
131
|
+
init_esm_shims();
|
|
132
|
+
var fs = __require("fs");
|
|
133
|
+
var path2 = __require("path");
|
|
134
|
+
var os = __require("os");
|
|
135
|
+
var crypto2 = __require("crypto");
|
|
136
|
+
var packageJson = require_package();
|
|
137
|
+
var version = packageJson.version;
|
|
138
|
+
var TIPS = [
|
|
139
|
+
"\u{1F510} encrypt with Dotenvx: https://dotenvx.com",
|
|
140
|
+
"\u{1F510} prevent committing .env to code: https://dotenvx.com/precommit",
|
|
141
|
+
"\u{1F510} prevent building .env in docker: https://dotenvx.com/prebuild",
|
|
142
|
+
"\u{1F4E1} add observability to secrets: https://dotenvx.com/ops",
|
|
143
|
+
"\u{1F465} sync secrets across teammates & machines: https://dotenvx.com/ops",
|
|
144
|
+
"\u{1F5C2}\uFE0F backup and recover secrets: https://dotenvx.com/ops",
|
|
145
|
+
"\u2705 audit secrets and track compliance: https://dotenvx.com/ops",
|
|
146
|
+
"\u{1F504} add secrets lifecycle management: https://dotenvx.com/ops",
|
|
147
|
+
"\u{1F511} add access controls to secrets: https://dotenvx.com/ops",
|
|
148
|
+
"\u{1F6E0}\uFE0F run anywhere with `dotenvx run -- yourcommand`",
|
|
149
|
+
"\u2699\uFE0F specify custom .env file path with { path: '/custom/path/.env' }",
|
|
150
|
+
"\u2699\uFE0F enable debug logging with { debug: true }",
|
|
151
|
+
"\u2699\uFE0F override existing env vars with { override: true }",
|
|
152
|
+
"\u2699\uFE0F suppress all logs with { quiet: true }",
|
|
153
|
+
"\u2699\uFE0F write to custom object with { processEnv: myObject }",
|
|
154
|
+
"\u2699\uFE0F load multiple .env files with { path: ['.env.local', '.env'] }"
|
|
155
|
+
];
|
|
156
|
+
function _getRandomTip() {
|
|
157
|
+
return TIPS[Math.floor(Math.random() * TIPS.length)];
|
|
158
|
+
}
|
|
159
|
+
function parseBoolean(value) {
|
|
160
|
+
if (typeof value === "string") {
|
|
161
|
+
return !["false", "0", "no", "off", ""].includes(value.toLowerCase());
|
|
162
|
+
}
|
|
163
|
+
return Boolean(value);
|
|
164
|
+
}
|
|
165
|
+
function supportsAnsi() {
|
|
166
|
+
return process.stdout.isTTY;
|
|
167
|
+
}
|
|
168
|
+
function dim(text) {
|
|
169
|
+
return supportsAnsi() ? `\x1B[2m${text}\x1B[0m` : text;
|
|
170
|
+
}
|
|
171
|
+
var LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
|
|
172
|
+
function parse(src) {
|
|
173
|
+
const obj = {};
|
|
174
|
+
let lines = src.toString();
|
|
175
|
+
lines = lines.replace(/\r\n?/mg, "\n");
|
|
176
|
+
let match;
|
|
177
|
+
while ((match = LINE.exec(lines)) != null) {
|
|
178
|
+
const key = match[1];
|
|
179
|
+
let value = match[2] || "";
|
|
180
|
+
value = value.trim();
|
|
181
|
+
const maybeQuote = value[0];
|
|
182
|
+
value = value.replace(/^(['"`])([\s\S]*)\1$/mg, "$2");
|
|
183
|
+
if (maybeQuote === '"') {
|
|
184
|
+
value = value.replace(/\\n/g, "\n");
|
|
185
|
+
value = value.replace(/\\r/g, "\r");
|
|
186
|
+
}
|
|
187
|
+
obj[key] = value;
|
|
188
|
+
}
|
|
189
|
+
return obj;
|
|
190
|
+
}
|
|
191
|
+
function _parseVault(options) {
|
|
192
|
+
options = options || {};
|
|
193
|
+
const vaultPath = _vaultPath(options);
|
|
194
|
+
options.path = vaultPath;
|
|
195
|
+
const result = DotenvModule.configDotenv(options);
|
|
196
|
+
if (!result.parsed) {
|
|
197
|
+
const err = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`);
|
|
198
|
+
err.code = "MISSING_DATA";
|
|
199
|
+
throw err;
|
|
200
|
+
}
|
|
201
|
+
const keys = _dotenvKey(options).split(",");
|
|
202
|
+
const length = keys.length;
|
|
203
|
+
let decrypted;
|
|
204
|
+
for (let i = 0; i < length; i++) {
|
|
205
|
+
try {
|
|
206
|
+
const key = keys[i].trim();
|
|
207
|
+
const attrs = _instructions(result, key);
|
|
208
|
+
decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key);
|
|
209
|
+
break;
|
|
210
|
+
} catch (error) {
|
|
211
|
+
if (i + 1 >= length) {
|
|
212
|
+
throw error;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
return DotenvModule.parse(decrypted);
|
|
217
|
+
}
|
|
218
|
+
function _warn(message) {
|
|
219
|
+
console.error(`[dotenv@${version}][WARN] ${message}`);
|
|
220
|
+
}
|
|
221
|
+
function _debug(message) {
|
|
222
|
+
console.log(`[dotenv@${version}][DEBUG] ${message}`);
|
|
223
|
+
}
|
|
224
|
+
function _log(message) {
|
|
225
|
+
console.log(`[dotenv@${version}] ${message}`);
|
|
226
|
+
}
|
|
227
|
+
function _dotenvKey(options) {
|
|
228
|
+
if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {
|
|
229
|
+
return options.DOTENV_KEY;
|
|
230
|
+
}
|
|
231
|
+
if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {
|
|
232
|
+
return process.env.DOTENV_KEY;
|
|
233
|
+
}
|
|
234
|
+
return "";
|
|
235
|
+
}
|
|
236
|
+
function _instructions(result, dotenvKey) {
|
|
237
|
+
let uri;
|
|
238
|
+
try {
|
|
239
|
+
uri = new URL(dotenvKey);
|
|
240
|
+
} catch (error) {
|
|
241
|
+
if (error.code === "ERR_INVALID_URL") {
|
|
242
|
+
const err = new Error("INVALID_DOTENV_KEY: Wrong format. Must be in valid uri format like dotenv://:key_1234@dotenvx.com/vault/.env.vault?environment=development");
|
|
243
|
+
err.code = "INVALID_DOTENV_KEY";
|
|
244
|
+
throw err;
|
|
245
|
+
}
|
|
246
|
+
throw error;
|
|
247
|
+
}
|
|
248
|
+
const key = uri.password;
|
|
249
|
+
if (!key) {
|
|
250
|
+
const err = new Error("INVALID_DOTENV_KEY: Missing key part");
|
|
251
|
+
err.code = "INVALID_DOTENV_KEY";
|
|
252
|
+
throw err;
|
|
253
|
+
}
|
|
254
|
+
const environment = uri.searchParams.get("environment");
|
|
255
|
+
if (!environment) {
|
|
256
|
+
const err = new Error("INVALID_DOTENV_KEY: Missing environment part");
|
|
257
|
+
err.code = "INVALID_DOTENV_KEY";
|
|
258
|
+
throw err;
|
|
259
|
+
}
|
|
260
|
+
const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`;
|
|
261
|
+
const ciphertext = result.parsed[environmentKey];
|
|
262
|
+
if (!ciphertext) {
|
|
263
|
+
const err = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`);
|
|
264
|
+
err.code = "NOT_FOUND_DOTENV_ENVIRONMENT";
|
|
265
|
+
throw err;
|
|
266
|
+
}
|
|
267
|
+
return { ciphertext, key };
|
|
268
|
+
}
|
|
269
|
+
function _vaultPath(options) {
|
|
270
|
+
let possibleVaultPath = null;
|
|
271
|
+
if (options && options.path && options.path.length > 0) {
|
|
272
|
+
if (Array.isArray(options.path)) {
|
|
273
|
+
for (const filepath of options.path) {
|
|
274
|
+
if (fs.existsSync(filepath)) {
|
|
275
|
+
possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
} else {
|
|
279
|
+
possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
|
|
280
|
+
}
|
|
281
|
+
} else {
|
|
282
|
+
possibleVaultPath = path2.resolve(process.cwd(), ".env.vault");
|
|
283
|
+
}
|
|
284
|
+
if (fs.existsSync(possibleVaultPath)) {
|
|
285
|
+
return possibleVaultPath;
|
|
286
|
+
}
|
|
287
|
+
return null;
|
|
288
|
+
}
|
|
289
|
+
function _resolveHome(envPath) {
|
|
290
|
+
return envPath[0] === "~" ? path2.join(os.homedir(), envPath.slice(1)) : envPath;
|
|
291
|
+
}
|
|
292
|
+
function _configVault(options) {
|
|
293
|
+
const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || options && options.debug);
|
|
294
|
+
const quiet = parseBoolean(process.env.DOTENV_CONFIG_QUIET || options && options.quiet);
|
|
295
|
+
if (debug || !quiet) {
|
|
296
|
+
_log("Loading env from encrypted .env.vault");
|
|
297
|
+
}
|
|
298
|
+
const parsed = DotenvModule._parseVault(options);
|
|
299
|
+
let processEnv = process.env;
|
|
300
|
+
if (options && options.processEnv != null) {
|
|
301
|
+
processEnv = options.processEnv;
|
|
302
|
+
}
|
|
303
|
+
DotenvModule.populate(processEnv, parsed, options);
|
|
304
|
+
return { parsed };
|
|
305
|
+
}
|
|
306
|
+
function configDotenv(options) {
|
|
307
|
+
const dotenvPath = path2.resolve(process.cwd(), ".env");
|
|
308
|
+
let encoding = "utf8";
|
|
309
|
+
let processEnv = process.env;
|
|
310
|
+
if (options && options.processEnv != null) {
|
|
311
|
+
processEnv = options.processEnv;
|
|
312
|
+
}
|
|
313
|
+
let debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || options && options.debug);
|
|
314
|
+
let quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || options && options.quiet);
|
|
315
|
+
if (options && options.encoding) {
|
|
316
|
+
encoding = options.encoding;
|
|
317
|
+
} else {
|
|
318
|
+
if (debug) {
|
|
319
|
+
_debug("No encoding is specified. UTF-8 is used by default");
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
let optionPaths = [dotenvPath];
|
|
323
|
+
if (options && options.path) {
|
|
324
|
+
if (!Array.isArray(options.path)) {
|
|
325
|
+
optionPaths = [_resolveHome(options.path)];
|
|
326
|
+
} else {
|
|
327
|
+
optionPaths = [];
|
|
328
|
+
for (const filepath of options.path) {
|
|
329
|
+
optionPaths.push(_resolveHome(filepath));
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
let lastError;
|
|
334
|
+
const parsedAll = {};
|
|
335
|
+
for (const path3 of optionPaths) {
|
|
336
|
+
try {
|
|
337
|
+
const parsed = DotenvModule.parse(fs.readFileSync(path3, { encoding }));
|
|
338
|
+
DotenvModule.populate(parsedAll, parsed, options);
|
|
339
|
+
} catch (e) {
|
|
340
|
+
if (debug) {
|
|
341
|
+
_debug(`Failed to load ${path3} ${e.message}`);
|
|
342
|
+
}
|
|
343
|
+
lastError = e;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
const populated = DotenvModule.populate(processEnv, parsedAll, options);
|
|
347
|
+
debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || debug);
|
|
348
|
+
quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || quiet);
|
|
349
|
+
if (debug || !quiet) {
|
|
350
|
+
const keysCount = Object.keys(populated).length;
|
|
351
|
+
const shortPaths = [];
|
|
352
|
+
for (const filePath of optionPaths) {
|
|
353
|
+
try {
|
|
354
|
+
const relative = path2.relative(process.cwd(), filePath);
|
|
355
|
+
shortPaths.push(relative);
|
|
356
|
+
} catch (e) {
|
|
357
|
+
if (debug) {
|
|
358
|
+
_debug(`Failed to load ${filePath} ${e.message}`);
|
|
359
|
+
}
|
|
360
|
+
lastError = e;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
_log(`injecting env (${keysCount}) from ${shortPaths.join(",")} ${dim(`-- tip: ${_getRandomTip()}`)}`);
|
|
364
|
+
}
|
|
365
|
+
if (lastError) {
|
|
366
|
+
return { parsed: parsedAll, error: lastError };
|
|
367
|
+
} else {
|
|
368
|
+
return { parsed: parsedAll };
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
function config(options) {
|
|
372
|
+
if (_dotenvKey(options).length === 0) {
|
|
373
|
+
return DotenvModule.configDotenv(options);
|
|
374
|
+
}
|
|
375
|
+
const vaultPath = _vaultPath(options);
|
|
376
|
+
if (!vaultPath) {
|
|
377
|
+
_warn(`You set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}. Did you forget to build it?`);
|
|
378
|
+
return DotenvModule.configDotenv(options);
|
|
379
|
+
}
|
|
380
|
+
return DotenvModule._configVault(options);
|
|
381
|
+
}
|
|
382
|
+
function decrypt2(encrypted, keyStr) {
|
|
383
|
+
const key = Buffer.from(keyStr.slice(-64), "hex");
|
|
384
|
+
let ciphertext = Buffer.from(encrypted, "base64");
|
|
385
|
+
const nonce = ciphertext.subarray(0, 12);
|
|
386
|
+
const authTag = ciphertext.subarray(-16);
|
|
387
|
+
ciphertext = ciphertext.subarray(12, -16);
|
|
388
|
+
try {
|
|
389
|
+
const aesgcm = crypto2.createDecipheriv("aes-256-gcm", key, nonce);
|
|
390
|
+
aesgcm.setAuthTag(authTag);
|
|
391
|
+
return `${aesgcm.update(ciphertext)}${aesgcm.final()}`;
|
|
392
|
+
} catch (error) {
|
|
393
|
+
const isRange = error instanceof RangeError;
|
|
394
|
+
const invalidKeyLength = error.message === "Invalid key length";
|
|
395
|
+
const decryptionFailed = error.message === "Unsupported state or unable to authenticate data";
|
|
396
|
+
if (isRange || invalidKeyLength) {
|
|
397
|
+
const err = new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)");
|
|
398
|
+
err.code = "INVALID_DOTENV_KEY";
|
|
399
|
+
throw err;
|
|
400
|
+
} else if (decryptionFailed) {
|
|
401
|
+
const err = new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY");
|
|
402
|
+
err.code = "DECRYPTION_FAILED";
|
|
403
|
+
throw err;
|
|
404
|
+
} else {
|
|
405
|
+
throw error;
|
|
406
|
+
}
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
function populate(processEnv, parsed, options = {}) {
|
|
410
|
+
const debug = Boolean(options && options.debug);
|
|
411
|
+
const override = Boolean(options && options.override);
|
|
412
|
+
const populated = {};
|
|
413
|
+
if (typeof parsed !== "object") {
|
|
414
|
+
const err = new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");
|
|
415
|
+
err.code = "OBJECT_REQUIRED";
|
|
416
|
+
throw err;
|
|
417
|
+
}
|
|
418
|
+
for (const key of Object.keys(parsed)) {
|
|
419
|
+
if (Object.prototype.hasOwnProperty.call(processEnv, key)) {
|
|
420
|
+
if (override === true) {
|
|
421
|
+
processEnv[key] = parsed[key];
|
|
422
|
+
populated[key] = parsed[key];
|
|
423
|
+
}
|
|
424
|
+
if (debug) {
|
|
425
|
+
if (override === true) {
|
|
426
|
+
_debug(`"${key}" is already defined and WAS overwritten`);
|
|
427
|
+
} else {
|
|
428
|
+
_debug(`"${key}" is already defined and was NOT overwritten`);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
} else {
|
|
432
|
+
processEnv[key] = parsed[key];
|
|
433
|
+
populated[key] = parsed[key];
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
return populated;
|
|
437
|
+
}
|
|
438
|
+
var DotenvModule = {
|
|
439
|
+
configDotenv,
|
|
440
|
+
_configVault,
|
|
441
|
+
_parseVault,
|
|
442
|
+
config,
|
|
443
|
+
decrypt: decrypt2,
|
|
444
|
+
parse,
|
|
445
|
+
populate
|
|
446
|
+
};
|
|
447
|
+
module.exports.configDotenv = DotenvModule.configDotenv;
|
|
448
|
+
module.exports._configVault = DotenvModule._configVault;
|
|
449
|
+
module.exports._parseVault = DotenvModule._parseVault;
|
|
450
|
+
module.exports.config = DotenvModule.config;
|
|
451
|
+
module.exports.decrypt = DotenvModule.decrypt;
|
|
452
|
+
module.exports.parse = DotenvModule.parse;
|
|
453
|
+
module.exports.populate = DotenvModule.populate;
|
|
454
|
+
module.exports = DotenvModule;
|
|
455
|
+
}
|
|
456
|
+
});
|
|
457
|
+
|
|
458
|
+
// src/cli.ts
|
|
459
|
+
init_esm_shims();
|
|
460
|
+
|
|
461
|
+
// src/commands/index.ts
|
|
462
|
+
init_esm_shims();
|
|
463
|
+
|
|
464
|
+
// src/commands/login.ts
|
|
465
|
+
init_esm_shims();
|
|
466
|
+
|
|
467
|
+
// src/auth/index.ts
|
|
468
|
+
init_esm_shims();
|
|
469
|
+
|
|
470
|
+
// src/auth/credential-auth.ts
|
|
471
|
+
init_esm_shims();
|
|
472
|
+
|
|
21
473
|
// src/config/constants.ts
|
|
22
|
-
|
|
474
|
+
init_esm_shims();
|
|
475
|
+
var DOCYRUS_API_URL = "https://alpha-api.docyrus.com";
|
|
23
476
|
var OAUTH_CLIENT_ID = "90565525-8283-4881-82a9-8613eb82ae27";
|
|
24
477
|
var OAUTH_SCOPES = "offline_access Read.All Users.Read Users.Read.All DS.Read.All".split(" ");
|
|
25
478
|
var OAUTH_CALLBACK_PORT_MIN = 9876;
|
|
@@ -36,11 +489,13 @@ var TOKEN_KEYS = {
|
|
|
36
489
|
GITHUB_TOKEN: "githubToken"
|
|
37
490
|
// For private template access - persists after logout
|
|
38
491
|
};
|
|
492
|
+
var REGISTRY_BASE_URL = "https://ui.docy.app/r";
|
|
39
493
|
var CLI_NAME = "docyrus";
|
|
40
494
|
var CLI_VERSION = "0.0.1";
|
|
41
495
|
var NPM_PACKAGE_NAME = "docyrus";
|
|
42
496
|
|
|
43
497
|
// src/utils/errors.ts
|
|
498
|
+
init_esm_shims();
|
|
44
499
|
var CliError = class extends Error {
|
|
45
500
|
exitCode;
|
|
46
501
|
suggestion;
|
|
@@ -107,6 +562,36 @@ var ConflictingFlagsError = class extends CliError {
|
|
|
107
562
|
this.name = "ConflictingFlagsError";
|
|
108
563
|
}
|
|
109
564
|
};
|
|
565
|
+
var ComponentNotFoundError = class extends CliError {
|
|
566
|
+
constructor(name) {
|
|
567
|
+
super(
|
|
568
|
+
`"${name}" not found in the registry.`,
|
|
569
|
+
1,
|
|
570
|
+
"Check the name and try again. Run `docyrus add --help` for usage."
|
|
571
|
+
);
|
|
572
|
+
this.name = "ComponentNotFoundError";
|
|
573
|
+
}
|
|
574
|
+
};
|
|
575
|
+
var PremiumAuthError = class extends CliError {
|
|
576
|
+
constructor(name) {
|
|
577
|
+
super(
|
|
578
|
+
`"${name}" is a premium component. Authentication required.`,
|
|
579
|
+
1,
|
|
580
|
+
"Run `docyrus login` to authenticate, then try again."
|
|
581
|
+
);
|
|
582
|
+
this.name = "PremiumAuthError";
|
|
583
|
+
}
|
|
584
|
+
};
|
|
585
|
+
var MissingConfigError = class extends CliError {
|
|
586
|
+
constructor() {
|
|
587
|
+
super(
|
|
588
|
+
"components.json not found.",
|
|
589
|
+
1,
|
|
590
|
+
"Run `npx shadcn@latest init` first to initialize your project."
|
|
591
|
+
);
|
|
592
|
+
this.name = "MissingConfigError";
|
|
593
|
+
}
|
|
594
|
+
};
|
|
110
595
|
|
|
111
596
|
// src/auth/credential-auth.ts
|
|
112
597
|
function getApiClient() {
|
|
@@ -195,6 +680,12 @@ async function refreshAccessToken(refreshToken) {
|
|
|
195
680
|
throw new AuthenticationError("Session expired. Please log in again.");
|
|
196
681
|
}
|
|
197
682
|
}
|
|
683
|
+
|
|
684
|
+
// src/auth/oauth-auth.ts
|
|
685
|
+
init_esm_shims();
|
|
686
|
+
|
|
687
|
+
// src/auth/oauth-server.ts
|
|
688
|
+
init_esm_shims();
|
|
198
689
|
var SUCCESS_HTML = `
|
|
199
690
|
<!DOCTYPE html>
|
|
200
691
|
<html>
|
|
@@ -377,7 +868,7 @@ async function startCallbackServer(expectedState) {
|
|
|
377
868
|
rejectResult(new TimeoutError("OAuth authentication timed out."));
|
|
378
869
|
}, OAUTH_TIMEOUT_MS);
|
|
379
870
|
const server = createServer((req, res) => {
|
|
380
|
-
const url = new URL(req.url || "/", `http://127.0.0.1:${port}`);
|
|
871
|
+
const url = new URL$1(req.url || "/", `http://127.0.0.1:${port}`);
|
|
381
872
|
if (url.pathname === "/callback") {
|
|
382
873
|
const code = url.searchParams.get("code");
|
|
383
874
|
const state2 = url.searchParams.get("state");
|
|
@@ -421,6 +912,9 @@ async function startCallbackServer(expectedState) {
|
|
|
421
912
|
cleanup
|
|
422
913
|
};
|
|
423
914
|
}
|
|
915
|
+
|
|
916
|
+
// src/utils/browser.ts
|
|
917
|
+
init_esm_shims();
|
|
424
918
|
async function openBrowser(url) {
|
|
425
919
|
await open(url);
|
|
426
920
|
}
|
|
@@ -505,12 +999,24 @@ async function loginWithOAuth(options = {}) {
|
|
|
505
999
|
cleanup();
|
|
506
1000
|
}
|
|
507
1001
|
}
|
|
1002
|
+
|
|
1003
|
+
// src/storage/index.ts
|
|
1004
|
+
init_esm_shims();
|
|
1005
|
+
|
|
1006
|
+
// src/storage/file-storage.ts
|
|
1007
|
+
init_esm_shims();
|
|
1008
|
+
|
|
1009
|
+
// src/utils/platform.ts
|
|
1010
|
+
init_esm_shims();
|
|
508
1011
|
function getHomeDir() {
|
|
509
1012
|
return homedir();
|
|
510
1013
|
}
|
|
511
1014
|
function getConfigDir() {
|
|
512
1015
|
return join(getHomeDir(), CONFIG_DIR);
|
|
513
1016
|
}
|
|
1017
|
+
|
|
1018
|
+
// src/storage/encryption.ts
|
|
1019
|
+
init_esm_shims();
|
|
514
1020
|
var ALGORITHM = "aes-256-gcm";
|
|
515
1021
|
var KEY_LENGTH = 32;
|
|
516
1022
|
var IV_LENGTH = 16;
|
|
@@ -626,6 +1132,7 @@ var FileStorage = class {
|
|
|
626
1132
|
};
|
|
627
1133
|
|
|
628
1134
|
// src/storage/keychain-storage.ts
|
|
1135
|
+
init_esm_shims();
|
|
629
1136
|
var keytar = null;
|
|
630
1137
|
async function getKeytar() {
|
|
631
1138
|
if (keytar !== null) {
|
|
@@ -696,6 +1203,7 @@ var KeychainStorage = class {
|
|
|
696
1203
|
};
|
|
697
1204
|
|
|
698
1205
|
// src/storage/cli-token-manager.ts
|
|
1206
|
+
init_esm_shims();
|
|
699
1207
|
var CliTokenManager = class {
|
|
700
1208
|
keychain;
|
|
701
1209
|
fileStorage;
|
|
@@ -795,6 +1303,12 @@ function getTokenManager() {
|
|
|
795
1303
|
}
|
|
796
1304
|
return instance;
|
|
797
1305
|
}
|
|
1306
|
+
|
|
1307
|
+
// src/config/index.ts
|
|
1308
|
+
init_esm_shims();
|
|
1309
|
+
|
|
1310
|
+
// src/config/config-manager.ts
|
|
1311
|
+
init_esm_shims();
|
|
798
1312
|
var defaults = {
|
|
799
1313
|
telemetryEnabled: true
|
|
800
1314
|
};
|
|
@@ -826,6 +1340,12 @@ var ConfigManager = class {
|
|
|
826
1340
|
}
|
|
827
1341
|
};
|
|
828
1342
|
var configManager = new ConfigManager();
|
|
1343
|
+
|
|
1344
|
+
// src/ui/index.ts
|
|
1345
|
+
init_esm_shims();
|
|
1346
|
+
|
|
1347
|
+
// src/ui/logger.ts
|
|
1348
|
+
init_esm_shims();
|
|
829
1349
|
var logger = {
|
|
830
1350
|
success(message) {
|
|
831
1351
|
console.info(chalk4.green("\u2713"), message);
|
|
@@ -860,6 +1380,9 @@ var logger = {
|
|
|
860
1380
|
return chalk4.cyan.underline(url);
|
|
861
1381
|
}
|
|
862
1382
|
};
|
|
1383
|
+
|
|
1384
|
+
// src/ui/output.ts
|
|
1385
|
+
init_esm_shims();
|
|
863
1386
|
var state = {
|
|
864
1387
|
format: "text",
|
|
865
1388
|
data: {}
|
|
@@ -944,6 +1467,7 @@ var output = {
|
|
|
944
1467
|
};
|
|
945
1468
|
|
|
946
1469
|
// src/ui/messages.ts
|
|
1470
|
+
init_esm_shims();
|
|
947
1471
|
var MESSAGES = {
|
|
948
1472
|
// Login
|
|
949
1473
|
LOGIN_SUCCESS: (email) => `Successfully logged in as ${email}`,
|
|
@@ -990,7 +1514,7 @@ var MESSAGES = {
|
|
|
990
1514
|
CREATE_SUCCESS: "Project created successfully!",
|
|
991
1515
|
CREATE_DOWNLOAD_OPENAPI: "Download OpenAPI spec for code generation?",
|
|
992
1516
|
CREATE_DOWNLOADING_OPENAPI: "Downloading OpenAPI specification...",
|
|
993
|
-
CREATE_OPENAPI_SUCCESS: (
|
|
1517
|
+
CREATE_OPENAPI_SUCCESS: (path2) => `OpenAPI spec saved to ${path2}`,
|
|
994
1518
|
// TanStack DB Generator
|
|
995
1519
|
TANSTACK_GENERATOR_PROMPT: "Generate TanStack Query collections from OpenAPI spec?",
|
|
996
1520
|
TANSTACK_GENERATOR_RUNNING: "Generating TanStack Query collections...",
|
|
@@ -1012,8 +1536,26 @@ var MESSAGES = {
|
|
|
1012
1536
|
DOCYRUS_TOKEN_REQUIRED: "Docyrus token required for template download",
|
|
1013
1537
|
DOCYRUS_TOKEN_PROMPT: "Enter Docyrus token:",
|
|
1014
1538
|
DOCYRUS_TOKEN_SAVED: "Docyrus token saved successfully",
|
|
1015
|
-
DOCYRUS_TOKEN_INVALID: "Invalid Docyrus token. Please check and try again."
|
|
1539
|
+
DOCYRUS_TOKEN_INVALID: "Invalid Docyrus token. Please check and try again.",
|
|
1540
|
+
// Add command
|
|
1541
|
+
ADD_RESOLVING: "Resolving components and dependencies...",
|
|
1542
|
+
ADD_INSTALLING_ITEM: (name) => `Installing ${name}...`,
|
|
1543
|
+
ADD_INSTALLING_DEPS: (count) => `Installing ${count} dependenc${count === 1 ? "y" : "ies"}...`,
|
|
1544
|
+
ADD_SUCCESS: (items, files) => `Done! Added ${items} item(s), ${files} file(s).`,
|
|
1545
|
+
ADD_NO_ITEMS: "Please specify at least one item to add.",
|
|
1546
|
+
ADD_NOT_FOUND: (name) => `"${name}" not found in the registry.`,
|
|
1547
|
+
ADD_PREMIUM_AUTH: (name) => `"${name}" is a premium component. Authentication required.`,
|
|
1548
|
+
ADD_FILE_EXISTS: (path2) => `File ${path2} already exists. Overwrite?`,
|
|
1549
|
+
ADD_FILE_SKIPPED: (path2) => `Skipped: ${path2}`,
|
|
1550
|
+
ADD_DRY_RUN_HEADER: "Dry run \u2014 the following changes would be made:",
|
|
1551
|
+
ADD_MISSING_CONFIG: "components.json not found.",
|
|
1552
|
+
ADD_MISSING_CONFIG_HINT: "Run `npx shadcn@latest init` first to initialize your project.",
|
|
1553
|
+
ADD_DETECTED_STYLE: (style) => `Detected style: ${style}`,
|
|
1554
|
+
ADD_DEPRECATED_BASE_STYLE: 'Your components.json uses a deprecated "base-*" style. The radix/base variant distinction has been removed. All components now use the unified registry (@docyrus/ui-*).'
|
|
1016
1555
|
};
|
|
1556
|
+
|
|
1557
|
+
// src/ui/spinner.ts
|
|
1558
|
+
init_esm_shims();
|
|
1017
1559
|
function createSpinner(text) {
|
|
1018
1560
|
return ora({
|
|
1019
1561
|
text,
|
|
@@ -1042,6 +1584,9 @@ async function withSpinner(text, fn, options) {
|
|
|
1042
1584
|
throw error;
|
|
1043
1585
|
}
|
|
1044
1586
|
}
|
|
1587
|
+
|
|
1588
|
+
// src/ui/prompts.ts
|
|
1589
|
+
init_esm_shims();
|
|
1045
1590
|
async function promptEmail(defaultValue) {
|
|
1046
1591
|
return input({
|
|
1047
1592
|
message: MESSAGES.LOGIN_PROMPT_EMAIL,
|
|
@@ -1066,6 +1611,9 @@ async function promptPassword() {
|
|
|
1066
1611
|
}
|
|
1067
1612
|
});
|
|
1068
1613
|
}
|
|
1614
|
+
|
|
1615
|
+
// src/ui/progress.ts
|
|
1616
|
+
init_esm_shims();
|
|
1069
1617
|
({
|
|
1070
1618
|
pending: chalk4.dim("\u25CB"),
|
|
1071
1619
|
in_progress: chalk4.cyan("\u25D0"),
|
|
@@ -1170,6 +1718,7 @@ function registerLoginCommand(program2) {
|
|
|
1170
1718
|
}
|
|
1171
1719
|
|
|
1172
1720
|
// src/commands/logout.ts
|
|
1721
|
+
init_esm_shims();
|
|
1173
1722
|
function registerLogoutCommand(program2) {
|
|
1174
1723
|
program2.command("logout").description("Log out from Docyrus").action(async () => {
|
|
1175
1724
|
const tokenManager = getTokenManager();
|
|
@@ -1192,7 +1741,11 @@ function registerLogoutCommand(program2) {
|
|
|
1192
1741
|
});
|
|
1193
1742
|
}
|
|
1194
1743
|
|
|
1744
|
+
// src/commands/whoami.ts
|
|
1745
|
+
init_esm_shims();
|
|
1746
|
+
|
|
1195
1747
|
// src/utils/auth-guard.ts
|
|
1748
|
+
init_esm_shims();
|
|
1196
1749
|
function decodeJwtPayload(token) {
|
|
1197
1750
|
try {
|
|
1198
1751
|
const parts = token.split(".");
|
|
@@ -1286,6 +1839,12 @@ function registerWhoamiCommand(program2) {
|
|
|
1286
1839
|
}
|
|
1287
1840
|
});
|
|
1288
1841
|
}
|
|
1842
|
+
|
|
1843
|
+
// src/commands/create.ts
|
|
1844
|
+
init_esm_shims();
|
|
1845
|
+
|
|
1846
|
+
// src/utils/linter-config.ts
|
|
1847
|
+
init_esm_shims();
|
|
1289
1848
|
var ESLINT_CONFIGS = {
|
|
1290
1849
|
react: {
|
|
1291
1850
|
imports: ["baseConfig", "reactConfig"],
|
|
@@ -1354,6 +1913,9 @@ async function applyLinterConfig(targetDir, framework, linter, onProgress) {
|
|
|
1354
1913
|
};
|
|
1355
1914
|
await writeFile(targetPkgPath, JSON.stringify(targetPkg, null, 2));
|
|
1356
1915
|
}
|
|
1916
|
+
|
|
1917
|
+
// src/utils/alias-config.ts
|
|
1918
|
+
init_esm_shims();
|
|
1357
1919
|
async function applyAliasConfig(targetDir, framework, aliasPrefix) {
|
|
1358
1920
|
if (aliasPrefix === "@" || aliasPrefix === "@/") return;
|
|
1359
1921
|
const config = {
|
|
@@ -1426,6 +1988,9 @@ async function updateImportsRecursive(dir, newPrefix, framework) {
|
|
|
1426
1988
|
}
|
|
1427
1989
|
}
|
|
1428
1990
|
}
|
|
1991
|
+
|
|
1992
|
+
// src/utils/api-client.ts
|
|
1993
|
+
init_esm_shims();
|
|
1429
1994
|
function createAuthenticatedClient(accessToken) {
|
|
1430
1995
|
const apiUrl = configManager.get("apiUrl") || DOCYRUS_API_URL;
|
|
1431
1996
|
const client = new RestApiClient({ baseURL: apiUrl });
|
|
@@ -1441,6 +2006,9 @@ async function downloadOpenApiSpec(accessToken, targetDir, filename = "openapi.j
|
|
|
1441
2006
|
await writeFile(targetPath, JSON.stringify(spec, null, 2));
|
|
1442
2007
|
return targetPath;
|
|
1443
2008
|
}
|
|
2009
|
+
|
|
2010
|
+
// src/utils/ui-variant-swap.ts
|
|
2011
|
+
init_esm_shims();
|
|
1444
2012
|
async function applyUIVariants(targetDir, uiLibrary) {
|
|
1445
2013
|
const variantsDir = join(targetDir, "__ui-variants__");
|
|
1446
2014
|
try {
|
|
@@ -1458,6 +2026,9 @@ async function applyUIVariants(targetDir, uiLibrary) {
|
|
|
1458
2026
|
}
|
|
1459
2027
|
await rm(variantsDir, { recursive: true, force: true });
|
|
1460
2028
|
}
|
|
2029
|
+
|
|
2030
|
+
// src/utils/ui-library-setup.ts
|
|
2031
|
+
init_esm_shims();
|
|
1461
2032
|
var execAsync = promisify(exec);
|
|
1462
2033
|
var DICEUI_COMPONENTS = "action-bar,avatar-group,badge-overflow,checkbox-group,circular-progress,color-picker,color-swatch,combobox,compare-slider,cropper,editable,file-upload,gauge,kanban,key-value,listbox,mask-input,media-player,mention,phone-input,qr-code,rating,relative-time-card,responsive-dialog,scroll-spy,scroller,segmented-input,sortable,speed-dial,stack,stat,status,stepper,swap,tags-input,time-picker,timeline,tour".split(",");
|
|
1463
2034
|
var UI_LIBRARY_COMPATIBILITY = {
|
|
@@ -1707,6 +2278,9 @@ async function addHeroUIProviderReact(targetDir) {
|
|
|
1707
2278
|
} catch {
|
|
1708
2279
|
}
|
|
1709
2280
|
}
|
|
2281
|
+
|
|
2282
|
+
// src/utils/state-management-setup.ts
|
|
2283
|
+
init_esm_shims();
|
|
1710
2284
|
var STATE_MANAGEMENT_VERSIONS = {
|
|
1711
2285
|
zustand: { name: "zustand", version: "5.0.11" },
|
|
1712
2286
|
"tanstack-query": { name: "@tanstack/react-query", version: "5.90.20" },
|
|
@@ -1901,7 +2475,7 @@ import { vueQueryOptions } from './lib/query-client';
|
|
|
1901
2475
|
|
|
1902
2476
|
// src/commands/create.ts
|
|
1903
2477
|
var execAsync2 = promisify(exec);
|
|
1904
|
-
var SHADCN_BASE_COLORS = "zinc,
|
|
2478
|
+
var SHADCN_BASE_COLORS = "slate,gray,zinc,neutral,stone,red,orange,amber,yellow,lime,green,emerald,teal,cyan,sky".split(",");
|
|
1905
2479
|
function validateConflictingFlags(options) {
|
|
1906
2480
|
const frameworkFlags = [
|
|
1907
2481
|
options.nextjs,
|
|
@@ -2069,13 +2643,13 @@ var PACKAGE_MANAGERS = [
|
|
|
2069
2643
|
{ name: "yarn", label: "yarn", description: "Fast, reliable, and secure" },
|
|
2070
2644
|
{ name: "bun", label: "bun", description: "All-in-one JavaScript runtime" }
|
|
2071
2645
|
];
|
|
2072
|
-
var TEMPLATE_REPO_BASE = "Docyrus/docyrus-
|
|
2646
|
+
var TEMPLATE_REPO_BASE = "Docyrus/docyrus-ui/templates";
|
|
2073
2647
|
function getTemplateRepo(framework) {
|
|
2074
2648
|
return `${TEMPLATE_REPO_BASE}/${framework}`;
|
|
2075
2649
|
}
|
|
2076
|
-
async function directoryExists(
|
|
2650
|
+
async function directoryExists(path2) {
|
|
2077
2651
|
try {
|
|
2078
|
-
await access(
|
|
2652
|
+
await access(path2, constants.F_OK);
|
|
2079
2653
|
return true;
|
|
2080
2654
|
} catch {
|
|
2081
2655
|
return false;
|
|
@@ -2265,20 +2839,36 @@ Examples:
|
|
|
2265
2839
|
);
|
|
2266
2840
|
}
|
|
2267
2841
|
await cp(localTemplateDir, targetDir, { recursive: true });
|
|
2842
|
+
if (!process.env.DOCYRUS_DEVKIT_PATH) {
|
|
2843
|
+
const { config } = await Promise.resolve().then(() => __toESM(require_main(), 1));
|
|
2844
|
+
config({ path: resolve(cliPackageDir, "..", "..", ".env") });
|
|
2845
|
+
}
|
|
2268
2846
|
const pkgJsonPath = join(targetDir, "package.json");
|
|
2269
2847
|
const pkgJson = JSON.parse(await readFile(pkgJsonPath, "utf-8"));
|
|
2270
|
-
const
|
|
2848
|
+
const monorepoRoot = resolve(cliPackageDir, "..", "..");
|
|
2849
|
+
const devkitPath = process.env.DOCYRUS_DEVKIT_PATH;
|
|
2850
|
+
const packagesDirs = [
|
|
2851
|
+
resolve(monorepoRoot, "packages"),
|
|
2852
|
+
...devkitPath ? [resolve(devkitPath, "packages")] : [resolve(monorepoRoot, "..", "docyrus-devkit", "packages")]
|
|
2853
|
+
];
|
|
2271
2854
|
for (const depType of ["dependencies", "devDependencies"]) {
|
|
2272
2855
|
const deps = pkgJson[depType];
|
|
2273
2856
|
if (!deps) continue;
|
|
2274
2857
|
for (const [name2, version] of Object.entries(deps)) {
|
|
2275
2858
|
if (name2.startsWith("@docyrus/") && version === "latest") {
|
|
2276
2859
|
const pkgName = name2.replace("@docyrus/", "");
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2860
|
+
let found = false;
|
|
2861
|
+
for (const packagesDir of packagesDirs) {
|
|
2862
|
+
const localPkgDir = resolve(packagesDir, pkgName);
|
|
2863
|
+
try {
|
|
2864
|
+
await access(localPkgDir, constants.F_OK);
|
|
2865
|
+
deps[name2] = `file:${localPkgDir}`;
|
|
2866
|
+
found = true;
|
|
2867
|
+
break;
|
|
2868
|
+
} catch {
|
|
2869
|
+
}
|
|
2870
|
+
}
|
|
2871
|
+
if (!found) {
|
|
2282
2872
|
logger.warn(`Local package not found for ${name2}, keeping "latest"`);
|
|
2283
2873
|
}
|
|
2284
2874
|
}
|
|
@@ -2303,7 +2893,7 @@ Examples:
|
|
|
2303
2893
|
await withSpinner(
|
|
2304
2894
|
MESSAGES.CREATE_DOWNLOADING,
|
|
2305
2895
|
async () => {
|
|
2306
|
-
const gigetCachePath = resolve(homedir(), ".cache/giget/gh/Docyrus-docyrus-
|
|
2896
|
+
const gigetCachePath = resolve(homedir(), ".cache/giget/gh/Docyrus-docyrus-ui");
|
|
2307
2897
|
if (existsSync(gigetCachePath)) {
|
|
2308
2898
|
await rm(gigetCachePath, { recursive: true, force: true });
|
|
2309
2899
|
}
|
|
@@ -2455,6 +3045,9 @@ ${errorMessage}`
|
|
|
2455
3045
|
logger.dim(MESSAGES.API_CLIENT_DOCS);
|
|
2456
3046
|
});
|
|
2457
3047
|
}
|
|
3048
|
+
|
|
3049
|
+
// src/commands/generate.ts
|
|
3050
|
+
init_esm_shims();
|
|
2458
3051
|
function registerGenerateCommand(program2) {
|
|
2459
3052
|
const generate = program2.command("generate").description("Code generation commands");
|
|
2460
3053
|
generate.command("api-spec").description("Download OpenAPI specification from Docyrus API").option("-o, --output <path>", "Output file path", "openapi.json").action(async (options) => {
|
|
@@ -2539,6 +3132,9 @@ function findSpecFile(specPath) {
|
|
|
2539
3132
|
}
|
|
2540
3133
|
return null;
|
|
2541
3134
|
}
|
|
3135
|
+
|
|
3136
|
+
// src/commands/upgrade.ts
|
|
3137
|
+
init_esm_shims();
|
|
2542
3138
|
var execAsync3 = promisify(exec);
|
|
2543
3139
|
async function getLatestVersion() {
|
|
2544
3140
|
try {
|
|
@@ -2633,6 +3229,7 @@ function registerUpgradeCommand(program2) {
|
|
|
2633
3229
|
}
|
|
2634
3230
|
|
|
2635
3231
|
// src/commands/completion.ts
|
|
3232
|
+
init_esm_shims();
|
|
2636
3233
|
var BASH_COMPLETION = `
|
|
2637
3234
|
###-begin-${CLI_NAME}-completions-###
|
|
2638
3235
|
_${CLI_NAME}_completions() {
|
|
@@ -2752,6 +3349,9 @@ function registerCompletionCommand(program2) {
|
|
|
2752
3349
|
}
|
|
2753
3350
|
});
|
|
2754
3351
|
}
|
|
3352
|
+
|
|
3353
|
+
// src/commands/info.ts
|
|
3354
|
+
init_esm_shims();
|
|
2755
3355
|
function registerInfoCommand(program2) {
|
|
2756
3356
|
program2.command("info").description("Display CLI and environment information").action(async () => {
|
|
2757
3357
|
const tokenManager = getTokenManager();
|
|
@@ -2804,6 +3404,9 @@ function registerInfoCommand(program2) {
|
|
|
2804
3404
|
}
|
|
2805
3405
|
});
|
|
2806
3406
|
}
|
|
3407
|
+
|
|
3408
|
+
// src/commands/config.ts
|
|
3409
|
+
init_esm_shims();
|
|
2807
3410
|
function registerConfigCommand(program2) {
|
|
2808
3411
|
program2.command("config").description("Manage CLI configuration").option("--token", "Update Docyrus token for private template access").option("--show", "Show current configuration").action(async (options) => {
|
|
2809
3412
|
const tokenManager = getTokenManager();
|
|
@@ -2847,18 +3450,251 @@ function registerConfigCommand(program2) {
|
|
|
2847
3450
|
});
|
|
2848
3451
|
}
|
|
2849
3452
|
|
|
3453
|
+
// src/commands/add.ts
|
|
3454
|
+
init_esm_shims();
|
|
3455
|
+
function findProjectRoot() {
|
|
3456
|
+
let dir = process.cwd();
|
|
3457
|
+
while (dir !== dirname(dir)) {
|
|
3458
|
+
if (existsSync(join(dir, "package.json"))) {
|
|
3459
|
+
return dir;
|
|
3460
|
+
}
|
|
3461
|
+
dir = dirname(dir);
|
|
3462
|
+
}
|
|
3463
|
+
throw new CliError(
|
|
3464
|
+
"Could not find a package.json in the current directory or any parent directory.",
|
|
3465
|
+
1,
|
|
3466
|
+
"Run this command from within a JavaScript/TypeScript project."
|
|
3467
|
+
);
|
|
3468
|
+
}
|
|
3469
|
+
async function readComponentsJson(projectRoot) {
|
|
3470
|
+
const configPath = join(projectRoot, "components.json");
|
|
3471
|
+
if (!existsSync(configPath)) {
|
|
3472
|
+
throw new MissingConfigError();
|
|
3473
|
+
}
|
|
3474
|
+
const raw = await readFile(configPath, "utf-8");
|
|
3475
|
+
return JSON.parse(raw);
|
|
3476
|
+
}
|
|
3477
|
+
function detectPackageManager2(projectRoot) {
|
|
3478
|
+
if (existsSync(join(projectRoot, "pnpm-lock.yaml"))) return "pnpm";
|
|
3479
|
+
if (existsSync(join(projectRoot, "yarn.lock"))) return "yarn";
|
|
3480
|
+
if (existsSync(join(projectRoot, "bun.lockb")) || existsSync(join(projectRoot, "bun.lock"))) return "bun";
|
|
3481
|
+
return "npm";
|
|
3482
|
+
}
|
|
3483
|
+
function normalizeRegistryName(input3) {
|
|
3484
|
+
if (input3.startsWith("@docyrus/")) return input3;
|
|
3485
|
+
if (input3.startsWith("hooks-")) return `@docyrus/${input3}`;
|
|
3486
|
+
if (input3.startsWith("utils-")) return `@docyrus/${input3}`;
|
|
3487
|
+
return `@docyrus/ui-${input3}`;
|
|
3488
|
+
}
|
|
3489
|
+
async function fetchRegistryItem(name, token) {
|
|
3490
|
+
const url = `${REGISTRY_BASE_URL}/${encodeURIComponent(name)}.json`;
|
|
3491
|
+
const headers = {
|
|
3492
|
+
Accept: "application/json"
|
|
3493
|
+
};
|
|
3494
|
+
if (token) {
|
|
3495
|
+
headers.Authorization = `Bearer ${token}`;
|
|
3496
|
+
}
|
|
3497
|
+
let response;
|
|
3498
|
+
try {
|
|
3499
|
+
response = await fetch(url, { headers });
|
|
3500
|
+
} catch {
|
|
3501
|
+
throw new NetworkError();
|
|
3502
|
+
}
|
|
3503
|
+
if (response.status === 401 || response.status === 403) {
|
|
3504
|
+
throw new PremiumAuthError(name);
|
|
3505
|
+
}
|
|
3506
|
+
if (response.status === 404) {
|
|
3507
|
+
throw new ComponentNotFoundError(name);
|
|
3508
|
+
}
|
|
3509
|
+
if (!response.ok) {
|
|
3510
|
+
throw new NetworkError(`Failed to fetch "${name}" from registry (HTTP ${response.status})`);
|
|
3511
|
+
}
|
|
3512
|
+
return response.json();
|
|
3513
|
+
}
|
|
3514
|
+
async function resolveAllDependencies(names, token) {
|
|
3515
|
+
const resolved = /* @__PURE__ */ new Map();
|
|
3516
|
+
const queue = [...names];
|
|
3517
|
+
while (queue.length > 0) {
|
|
3518
|
+
const name = queue.shift();
|
|
3519
|
+
if (resolved.has(name)) continue;
|
|
3520
|
+
const item = await fetchRegistryItem(name, token);
|
|
3521
|
+
resolved.set(name, item);
|
|
3522
|
+
if (item.registryDependencies?.length > 0) {
|
|
3523
|
+
for (const dep of item.registryDependencies) {
|
|
3524
|
+
if (!resolved.has(dep)) {
|
|
3525
|
+
queue.push(dep);
|
|
3526
|
+
}
|
|
3527
|
+
}
|
|
3528
|
+
}
|
|
3529
|
+
}
|
|
3530
|
+
return resolved;
|
|
3531
|
+
}
|
|
3532
|
+
function resolveTargetDir(projectRoot) {
|
|
3533
|
+
if (existsSync(join(projectRoot, "src"))) {
|
|
3534
|
+
return join(projectRoot, "src");
|
|
3535
|
+
}
|
|
3536
|
+
return projectRoot;
|
|
3537
|
+
}
|
|
3538
|
+
async function writeItemFiles(item, baseDir, overwrite) {
|
|
3539
|
+
const written = [];
|
|
3540
|
+
for (const file of item.files) {
|
|
3541
|
+
const targetPath = join(baseDir, file.path);
|
|
3542
|
+
const targetDir = dirname(targetPath);
|
|
3543
|
+
if (!existsSync(targetDir)) {
|
|
3544
|
+
await mkdir(targetDir, { recursive: true });
|
|
3545
|
+
}
|
|
3546
|
+
if (existsSync(targetPath) && !overwrite) {
|
|
3547
|
+
const shouldOverwrite = await confirm({
|
|
3548
|
+
message: MESSAGES.ADD_FILE_EXISTS(file.path),
|
|
3549
|
+
default: false
|
|
3550
|
+
});
|
|
3551
|
+
if (!shouldOverwrite) {
|
|
3552
|
+
logger.dim(` ${MESSAGES.ADD_FILE_SKIPPED(file.path)}`);
|
|
3553
|
+
continue;
|
|
3554
|
+
}
|
|
3555
|
+
}
|
|
3556
|
+
await writeFile(targetPath, file.content, "utf-8");
|
|
3557
|
+
written.push(file.path);
|
|
3558
|
+
}
|
|
3559
|
+
return written;
|
|
3560
|
+
}
|
|
3561
|
+
async function getExistingDependencies(projectRoot) {
|
|
3562
|
+
const pkgPath = join(projectRoot, "package.json");
|
|
3563
|
+
try {
|
|
3564
|
+
const raw = await readFile(pkgPath, "utf-8");
|
|
3565
|
+
const pkg = JSON.parse(raw);
|
|
3566
|
+
const deps = /* @__PURE__ */ new Set();
|
|
3567
|
+
for (const key of Object.keys(pkg.dependencies || {})) {
|
|
3568
|
+
deps.add(key);
|
|
3569
|
+
}
|
|
3570
|
+
for (const key of Object.keys(pkg.devDependencies || {})) {
|
|
3571
|
+
deps.add(key);
|
|
3572
|
+
}
|
|
3573
|
+
return deps;
|
|
3574
|
+
} catch {
|
|
3575
|
+
return /* @__PURE__ */ new Set();
|
|
3576
|
+
}
|
|
3577
|
+
}
|
|
3578
|
+
function installNpmDependencies(deps, projectRoot) {
|
|
3579
|
+
if (deps.length === 0) return;
|
|
3580
|
+
const pm = detectPackageManager2(projectRoot);
|
|
3581
|
+
const pmArgs = {
|
|
3582
|
+
npm: ["install", ...deps],
|
|
3583
|
+
pnpm: ["add", ...deps],
|
|
3584
|
+
yarn: ["add", ...deps],
|
|
3585
|
+
bun: ["add", ...deps]
|
|
3586
|
+
};
|
|
3587
|
+
execFileSync(pm, pmArgs[pm], { cwd: projectRoot, stdio: "pipe" });
|
|
3588
|
+
}
|
|
3589
|
+
function handleDryRun(items, baseDir, allNewDeps) {
|
|
3590
|
+
logger.newline();
|
|
3591
|
+
logger.bold(MESSAGES.ADD_DRY_RUN_HEADER);
|
|
3592
|
+
logger.newline();
|
|
3593
|
+
for (const [name, item] of items) {
|
|
3594
|
+
logger.info(`${item.title || name}`);
|
|
3595
|
+
for (const file of item.files) {
|
|
3596
|
+
const targetPath = join(baseDir, file.path);
|
|
3597
|
+
const exists = existsSync(targetPath);
|
|
3598
|
+
logger.dim(` ${exists ? "(overwrite)" : "(create)"} ${file.path}`);
|
|
3599
|
+
}
|
|
3600
|
+
}
|
|
3601
|
+
if (allNewDeps.length > 0) {
|
|
3602
|
+
logger.newline();
|
|
3603
|
+
logger.info("Dependencies to install:");
|
|
3604
|
+
logger.dim(` ${allNewDeps.join(", ")}`);
|
|
3605
|
+
}
|
|
3606
|
+
logger.newline();
|
|
3607
|
+
}
|
|
3608
|
+
function registerAddCommand(program2) {
|
|
3609
|
+
program2.command("add [items...]").description("Add Docyrus UI components, hooks, or utilities to your project").option("-o, --overwrite", "Overwrite existing files without prompting").option("-d, --dry-run", "Show what would be installed without making changes").option("-p, --path <path>", "Custom target path for files").addHelpText("after", `
|
|
3610
|
+
Examples:
|
|
3611
|
+
$ docyrus add button Add a component
|
|
3612
|
+
$ docyrus add button dialog Add multiple components
|
|
3613
|
+
$ docyrus add hooks-debounce Add a hook
|
|
3614
|
+
$ docyrus add utils-cn Add a utility
|
|
3615
|
+
$ docyrus add button --dry-run Preview installation
|
|
3616
|
+
$ docyrus add button -o Overwrite existing files
|
|
3617
|
+
`).action(async (items, options) => {
|
|
3618
|
+
if (!items || items.length === 0) {
|
|
3619
|
+
throw new CliError(
|
|
3620
|
+
MESSAGES.ADD_NO_ITEMS,
|
|
3621
|
+
1,
|
|
3622
|
+
"Usage: docyrus add <item...>\nExample: docyrus add button dialog hooks-debounce"
|
|
3623
|
+
);
|
|
3624
|
+
}
|
|
3625
|
+
const projectRoot = findProjectRoot();
|
|
3626
|
+
const config = await readComponentsJson(projectRoot);
|
|
3627
|
+
const baseDir = options.path ? join(projectRoot, options.path) : resolveTargetDir(projectRoot);
|
|
3628
|
+
logger.newline();
|
|
3629
|
+
logger.dim(MESSAGES.ADD_DETECTED_STYLE(config.style));
|
|
3630
|
+
if (config.style.startsWith("base")) {
|
|
3631
|
+
logger.warn(MESSAGES.ADD_DEPRECATED_BASE_STYLE);
|
|
3632
|
+
}
|
|
3633
|
+
let token;
|
|
3634
|
+
try {
|
|
3635
|
+
token = await requireAuth();
|
|
3636
|
+
} catch {
|
|
3637
|
+
}
|
|
3638
|
+
const registryNames = items.map((item) => normalizeRegistryName(item));
|
|
3639
|
+
const allItems = await withSpinner(
|
|
3640
|
+
MESSAGES.ADD_RESOLVING,
|
|
3641
|
+
() => resolveAllDependencies(registryNames, token),
|
|
3642
|
+
{ successText: `Resolved ${registryNames.length} item(s)` }
|
|
3643
|
+
);
|
|
3644
|
+
const existingDeps = await getExistingDependencies(projectRoot);
|
|
3645
|
+
const allNewDeps = [];
|
|
3646
|
+
for (const item of allItems.values()) {
|
|
3647
|
+
for (const dep of item.dependencies) {
|
|
3648
|
+
if (!existingDeps.has(dep) && !allNewDeps.includes(dep)) {
|
|
3649
|
+
allNewDeps.push(dep);
|
|
3650
|
+
}
|
|
3651
|
+
}
|
|
3652
|
+
}
|
|
3653
|
+
if (options.dryRun) {
|
|
3654
|
+
handleDryRun(allItems, baseDir, allNewDeps);
|
|
3655
|
+
return;
|
|
3656
|
+
}
|
|
3657
|
+
let totalFiles = 0;
|
|
3658
|
+
for (const [name, item] of allItems) {
|
|
3659
|
+
const written = await withSpinner(
|
|
3660
|
+
MESSAGES.ADD_INSTALLING_ITEM(item.title || name),
|
|
3661
|
+
() => writeItemFiles(item, baseDir, !!options.overwrite),
|
|
3662
|
+
{ successText: `${item.title || name}` }
|
|
3663
|
+
);
|
|
3664
|
+
totalFiles += written.length;
|
|
3665
|
+
}
|
|
3666
|
+
if (allNewDeps.length > 0) {
|
|
3667
|
+
await withSpinner(
|
|
3668
|
+
MESSAGES.ADD_INSTALLING_DEPS(allNewDeps.length),
|
|
3669
|
+
async () => installNpmDependencies(allNewDeps, projectRoot),
|
|
3670
|
+
{ successText: `${allNewDeps.length} dependenc${allNewDeps.length === 1 ? "y" : "ies"} installed` }
|
|
3671
|
+
);
|
|
3672
|
+
}
|
|
3673
|
+
logger.newline();
|
|
3674
|
+
logger.success(MESSAGES.ADD_SUCCESS(allItems.size, totalFiles));
|
|
3675
|
+
if (allNewDeps.length > 0) {
|
|
3676
|
+
logger.dim(` Dependencies: ${allNewDeps.join(", ")}`);
|
|
3677
|
+
}
|
|
3678
|
+
logger.newline();
|
|
3679
|
+
});
|
|
3680
|
+
}
|
|
3681
|
+
|
|
2850
3682
|
// src/commands/index.ts
|
|
2851
3683
|
function registerCommands(program2) {
|
|
2852
3684
|
registerLoginCommand(program2);
|
|
2853
3685
|
registerLogoutCommand(program2);
|
|
2854
3686
|
registerWhoamiCommand(program2);
|
|
2855
3687
|
registerCreateCommand(program2);
|
|
3688
|
+
registerAddCommand(program2);
|
|
2856
3689
|
registerGenerateCommand(program2);
|
|
2857
3690
|
registerUpgradeCommand(program2);
|
|
2858
3691
|
registerCompletionCommand(program2);
|
|
2859
3692
|
registerInfoCommand(program2);
|
|
2860
3693
|
registerConfigCommand(program2);
|
|
2861
3694
|
}
|
|
3695
|
+
|
|
3696
|
+
// src/utils/update-checker.ts
|
|
3697
|
+
init_esm_shims();
|
|
2862
3698
|
function isNewerVersion2(current, latest) {
|
|
2863
3699
|
const currentParts = current.replace(/^v/, "").split(".").map(Number);
|
|
2864
3700
|
const latestParts = latest.replace(/^v/, "").split(".").map(Number);
|