@nikelyh/metamorph 2.0.1 → 2.0.3
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 +62 -29
- package/bin/metamorph.js +2 -16
- package/dist/{TechDetector-YCDEZ6OR.js → TechDetector-TKTX5YAM.js} +1 -1
- package/dist/chunk-3RG5ZIWI.js +10 -0
- package/dist/{chunk-DJO6FY4K.js → chunk-GNWRSZXT.js} +1 -5
- package/dist/index.js +71 -435
- package/dist/{runtime-WTVS3IND.js → runtime-MOEIRP73.js} +2 -3
- package/package.json +5 -2
- package/dist/chunk-IIEUXZPM.js +0 -4792
- package/dist/chunk-RCULELX2.js +0 -241770
- package/dist/chunk-VS2QQHAK.js +0 -46
- package/dist/chunk-XHQSMB6V.js +0 -73585
- package/dist/dist-63RNBEIQ.js +0 -63
- package/dist/dist-VCTPPAJN.js +0 -1129
- package/dist/multipart-parser-ALMYCQSC.js +0 -371
- package/dist/src-ZMFD37HA.js +0 -1408
- package/dist/ts-morph-LFNGDRSW.js +0 -5
package/dist/index.js
CHANGED
|
@@ -1,7 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import {
|
|
3
|
-
require_ts_morph
|
|
4
|
-
} from "./chunk-RCULELX2.js";
|
|
5
2
|
import {
|
|
6
3
|
detectTechnologies
|
|
7
4
|
} from "./chunk-3QN2Q75J.js";
|
|
@@ -13,403 +10,19 @@ import {
|
|
|
13
10
|
resolveRuntime,
|
|
14
11
|
runLoop,
|
|
15
12
|
sendEvent
|
|
16
|
-
} from "./chunk-
|
|
17
|
-
import {
|
|
18
|
-
SituationSpecification,
|
|
19
|
-
createAgent
|
|
20
|
-
} from "./chunk-XHQSMB6V.js";
|
|
13
|
+
} from "./chunk-GNWRSZXT.js";
|
|
21
14
|
import {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
__toESM
|
|
25
|
-
} from "./chunk-VS2QQHAK.js";
|
|
26
|
-
|
|
27
|
-
// ../../../node_modules/dotenv/lib/main.js
|
|
28
|
-
var require_main = __commonJS({
|
|
29
|
-
"../../../node_modules/dotenv/lib/main.js"(exports, module) {
|
|
30
|
-
"use strict";
|
|
31
|
-
var fs7 = __require("fs");
|
|
32
|
-
var path6 = __require("path");
|
|
33
|
-
var os = __require("os");
|
|
34
|
-
var crypto = __require("crypto");
|
|
35
|
-
var TIPS = [
|
|
36
|
-
"\u25C8 encrypted .env [www.dotenvx.com]",
|
|
37
|
-
"\u25C8 secrets for agents [www.dotenvx.com]",
|
|
38
|
-
"\u2301 auth for agents [www.vestauth.com]",
|
|
39
|
-
"\u2318 custom filepath { path: '/custom/path/.env' }",
|
|
40
|
-
"\u2318 enable debugging { debug: true }",
|
|
41
|
-
"\u2318 override existing { override: true }",
|
|
42
|
-
"\u2318 suppress logs { quiet: true }",
|
|
43
|
-
"\u2318 multiple files { path: ['.env.local', '.env'] }"
|
|
44
|
-
];
|
|
45
|
-
function _getRandomTip() {
|
|
46
|
-
return TIPS[Math.floor(Math.random() * TIPS.length)];
|
|
47
|
-
}
|
|
48
|
-
function parseBoolean(value) {
|
|
49
|
-
if (typeof value === "string") {
|
|
50
|
-
return !["false", "0", "no", "off", ""].includes(value.toLowerCase());
|
|
51
|
-
}
|
|
52
|
-
return Boolean(value);
|
|
53
|
-
}
|
|
54
|
-
function supportsAnsi() {
|
|
55
|
-
return process.stdout.isTTY;
|
|
56
|
-
}
|
|
57
|
-
function dim(text) {
|
|
58
|
-
return supportsAnsi() ? `\x1B[2m${text}\x1B[0m` : text;
|
|
59
|
-
}
|
|
60
|
-
var LINE = /(?:^|^)\s*(?:export\s+)?([\w.-]+)(?:\s*=\s*?|:\s+?)(\s*'(?:\\'|[^'])*'|\s*"(?:\\"|[^"])*"|\s*`(?:\\`|[^`])*`|[^#\r\n]+)?\s*(?:#.*)?(?:$|$)/mg;
|
|
61
|
-
function parse(src) {
|
|
62
|
-
const obj = {};
|
|
63
|
-
let lines = src.toString();
|
|
64
|
-
lines = lines.replace(/\r\n?/mg, "\n");
|
|
65
|
-
let match;
|
|
66
|
-
while ((match = LINE.exec(lines)) != null) {
|
|
67
|
-
const key = match[1];
|
|
68
|
-
let value = match[2] || "";
|
|
69
|
-
value = value.trim();
|
|
70
|
-
const maybeQuote = value[0];
|
|
71
|
-
value = value.replace(/^(['"`])([\s\S]*)\1$/mg, "$2");
|
|
72
|
-
if (maybeQuote === '"') {
|
|
73
|
-
value = value.replace(/\\n/g, "\n");
|
|
74
|
-
value = value.replace(/\\r/g, "\r");
|
|
75
|
-
}
|
|
76
|
-
obj[key] = value;
|
|
77
|
-
}
|
|
78
|
-
return obj;
|
|
79
|
-
}
|
|
80
|
-
function _parseVault(options) {
|
|
81
|
-
options = options || {};
|
|
82
|
-
const vaultPath = _vaultPath(options);
|
|
83
|
-
options.path = vaultPath;
|
|
84
|
-
const result = DotenvModule.configDotenv(options);
|
|
85
|
-
if (!result.parsed) {
|
|
86
|
-
const err = new Error(`MISSING_DATA: Cannot parse ${vaultPath} for an unknown reason`);
|
|
87
|
-
err.code = "MISSING_DATA";
|
|
88
|
-
throw err;
|
|
89
|
-
}
|
|
90
|
-
const keys = _dotenvKey(options).split(",");
|
|
91
|
-
const length = keys.length;
|
|
92
|
-
let decrypted;
|
|
93
|
-
for (let i = 0; i < length; i++) {
|
|
94
|
-
try {
|
|
95
|
-
const key = keys[i].trim();
|
|
96
|
-
const attrs = _instructions(result, key);
|
|
97
|
-
decrypted = DotenvModule.decrypt(attrs.ciphertext, attrs.key);
|
|
98
|
-
break;
|
|
99
|
-
} catch (error) {
|
|
100
|
-
if (i + 1 >= length) {
|
|
101
|
-
throw error;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
return DotenvModule.parse(decrypted);
|
|
106
|
-
}
|
|
107
|
-
function _warn(message) {
|
|
108
|
-
console.error(`\u26A0 ${message}`);
|
|
109
|
-
}
|
|
110
|
-
function _debug(message) {
|
|
111
|
-
console.log(`\u2506 ${message}`);
|
|
112
|
-
}
|
|
113
|
-
function _log(message) {
|
|
114
|
-
console.log(`\u25C7 ${message}`);
|
|
115
|
-
}
|
|
116
|
-
function _dotenvKey(options) {
|
|
117
|
-
if (options && options.DOTENV_KEY && options.DOTENV_KEY.length > 0) {
|
|
118
|
-
return options.DOTENV_KEY;
|
|
119
|
-
}
|
|
120
|
-
if (process.env.DOTENV_KEY && process.env.DOTENV_KEY.length > 0) {
|
|
121
|
-
return process.env.DOTENV_KEY;
|
|
122
|
-
}
|
|
123
|
-
return "";
|
|
124
|
-
}
|
|
125
|
-
function _instructions(result, dotenvKey) {
|
|
126
|
-
let uri;
|
|
127
|
-
try {
|
|
128
|
-
uri = new URL(dotenvKey);
|
|
129
|
-
} catch (error) {
|
|
130
|
-
if (error.code === "ERR_INVALID_URL") {
|
|
131
|
-
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");
|
|
132
|
-
err.code = "INVALID_DOTENV_KEY";
|
|
133
|
-
throw err;
|
|
134
|
-
}
|
|
135
|
-
throw error;
|
|
136
|
-
}
|
|
137
|
-
const key = uri.password;
|
|
138
|
-
if (!key) {
|
|
139
|
-
const err = new Error("INVALID_DOTENV_KEY: Missing key part");
|
|
140
|
-
err.code = "INVALID_DOTENV_KEY";
|
|
141
|
-
throw err;
|
|
142
|
-
}
|
|
143
|
-
const environment = uri.searchParams.get("environment");
|
|
144
|
-
if (!environment) {
|
|
145
|
-
const err = new Error("INVALID_DOTENV_KEY: Missing environment part");
|
|
146
|
-
err.code = "INVALID_DOTENV_KEY";
|
|
147
|
-
throw err;
|
|
148
|
-
}
|
|
149
|
-
const environmentKey = `DOTENV_VAULT_${environment.toUpperCase()}`;
|
|
150
|
-
const ciphertext = result.parsed[environmentKey];
|
|
151
|
-
if (!ciphertext) {
|
|
152
|
-
const err = new Error(`NOT_FOUND_DOTENV_ENVIRONMENT: Cannot locate environment ${environmentKey} in your .env.vault file.`);
|
|
153
|
-
err.code = "NOT_FOUND_DOTENV_ENVIRONMENT";
|
|
154
|
-
throw err;
|
|
155
|
-
}
|
|
156
|
-
return { ciphertext, key };
|
|
157
|
-
}
|
|
158
|
-
function _vaultPath(options) {
|
|
159
|
-
let possibleVaultPath = null;
|
|
160
|
-
if (options && options.path && options.path.length > 0) {
|
|
161
|
-
if (Array.isArray(options.path)) {
|
|
162
|
-
for (const filepath of options.path) {
|
|
163
|
-
if (fs7.existsSync(filepath)) {
|
|
164
|
-
possibleVaultPath = filepath.endsWith(".vault") ? filepath : `${filepath}.vault`;
|
|
165
|
-
}
|
|
166
|
-
}
|
|
167
|
-
} else {
|
|
168
|
-
possibleVaultPath = options.path.endsWith(".vault") ? options.path : `${options.path}.vault`;
|
|
169
|
-
}
|
|
170
|
-
} else {
|
|
171
|
-
possibleVaultPath = path6.resolve(process.cwd(), ".env.vault");
|
|
172
|
-
}
|
|
173
|
-
if (fs7.existsSync(possibleVaultPath)) {
|
|
174
|
-
return possibleVaultPath;
|
|
175
|
-
}
|
|
176
|
-
return null;
|
|
177
|
-
}
|
|
178
|
-
function _resolveHome(envPath) {
|
|
179
|
-
return envPath[0] === "~" ? path6.join(os.homedir(), envPath.slice(1)) : envPath;
|
|
180
|
-
}
|
|
181
|
-
function _configVault(options) {
|
|
182
|
-
const debug = parseBoolean(process.env.DOTENV_CONFIG_DEBUG || options && options.debug);
|
|
183
|
-
const quiet = parseBoolean(process.env.DOTENV_CONFIG_QUIET || options && options.quiet);
|
|
184
|
-
if (debug || !quiet) {
|
|
185
|
-
_log("loading env from encrypted .env.vault");
|
|
186
|
-
}
|
|
187
|
-
const parsed = DotenvModule._parseVault(options);
|
|
188
|
-
let processEnv = process.env;
|
|
189
|
-
if (options && options.processEnv != null) {
|
|
190
|
-
processEnv = options.processEnv;
|
|
191
|
-
}
|
|
192
|
-
DotenvModule.populate(processEnv, parsed, options);
|
|
193
|
-
return { parsed };
|
|
194
|
-
}
|
|
195
|
-
function configDotenv(options) {
|
|
196
|
-
const dotenvPath = path6.resolve(process.cwd(), ".env");
|
|
197
|
-
let encoding = "utf8";
|
|
198
|
-
let processEnv = process.env;
|
|
199
|
-
if (options && options.processEnv != null) {
|
|
200
|
-
processEnv = options.processEnv;
|
|
201
|
-
}
|
|
202
|
-
let debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || options && options.debug);
|
|
203
|
-
let quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || options && options.quiet);
|
|
204
|
-
if (options && options.encoding) {
|
|
205
|
-
encoding = options.encoding;
|
|
206
|
-
} else {
|
|
207
|
-
if (debug) {
|
|
208
|
-
_debug("no encoding is specified (UTF-8 is used by default)");
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
let optionPaths = [dotenvPath];
|
|
212
|
-
if (options && options.path) {
|
|
213
|
-
if (!Array.isArray(options.path)) {
|
|
214
|
-
optionPaths = [_resolveHome(options.path)];
|
|
215
|
-
} else {
|
|
216
|
-
optionPaths = [];
|
|
217
|
-
for (const filepath of options.path) {
|
|
218
|
-
optionPaths.push(_resolveHome(filepath));
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
let lastError;
|
|
223
|
-
const parsedAll = {};
|
|
224
|
-
for (const path7 of optionPaths) {
|
|
225
|
-
try {
|
|
226
|
-
const parsed = DotenvModule.parse(fs7.readFileSync(path7, { encoding }));
|
|
227
|
-
DotenvModule.populate(parsedAll, parsed, options);
|
|
228
|
-
} catch (e) {
|
|
229
|
-
if (debug) {
|
|
230
|
-
_debug(`failed to load ${path7} ${e.message}`);
|
|
231
|
-
}
|
|
232
|
-
lastError = e;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
const populated = DotenvModule.populate(processEnv, parsedAll, options);
|
|
236
|
-
debug = parseBoolean(processEnv.DOTENV_CONFIG_DEBUG || debug);
|
|
237
|
-
quiet = parseBoolean(processEnv.DOTENV_CONFIG_QUIET || quiet);
|
|
238
|
-
if (debug || !quiet) {
|
|
239
|
-
const keysCount = Object.keys(populated).length;
|
|
240
|
-
const shortPaths = [];
|
|
241
|
-
for (const filePath of optionPaths) {
|
|
242
|
-
try {
|
|
243
|
-
const relative2 = path6.relative(process.cwd(), filePath);
|
|
244
|
-
shortPaths.push(relative2);
|
|
245
|
-
} catch (e) {
|
|
246
|
-
if (debug) {
|
|
247
|
-
_debug(`failed to load ${filePath} ${e.message}`);
|
|
248
|
-
}
|
|
249
|
-
lastError = e;
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
_log(`injected env (${keysCount}) from ${shortPaths.join(",")} ${dim(`// tip: ${_getRandomTip()}`)}`);
|
|
253
|
-
}
|
|
254
|
-
if (lastError) {
|
|
255
|
-
return { parsed: parsedAll, error: lastError };
|
|
256
|
-
} else {
|
|
257
|
-
return { parsed: parsedAll };
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
function config(options) {
|
|
261
|
-
if (_dotenvKey(options).length === 0) {
|
|
262
|
-
return DotenvModule.configDotenv(options);
|
|
263
|
-
}
|
|
264
|
-
const vaultPath = _vaultPath(options);
|
|
265
|
-
if (!vaultPath) {
|
|
266
|
-
_warn(`you set DOTENV_KEY but you are missing a .env.vault file at ${vaultPath}`);
|
|
267
|
-
return DotenvModule.configDotenv(options);
|
|
268
|
-
}
|
|
269
|
-
return DotenvModule._configVault(options);
|
|
270
|
-
}
|
|
271
|
-
function decrypt(encrypted, keyStr) {
|
|
272
|
-
const key = Buffer.from(keyStr.slice(-64), "hex");
|
|
273
|
-
let ciphertext = Buffer.from(encrypted, "base64");
|
|
274
|
-
const nonce = ciphertext.subarray(0, 12);
|
|
275
|
-
const authTag = ciphertext.subarray(-16);
|
|
276
|
-
ciphertext = ciphertext.subarray(12, -16);
|
|
277
|
-
try {
|
|
278
|
-
const aesgcm = crypto.createDecipheriv("aes-256-gcm", key, nonce);
|
|
279
|
-
aesgcm.setAuthTag(authTag);
|
|
280
|
-
return `${aesgcm.update(ciphertext)}${aesgcm.final()}`;
|
|
281
|
-
} catch (error) {
|
|
282
|
-
const isRange = error instanceof RangeError;
|
|
283
|
-
const invalidKeyLength = error.message === "Invalid key length";
|
|
284
|
-
const decryptionFailed = error.message === "Unsupported state or unable to authenticate data";
|
|
285
|
-
if (isRange || invalidKeyLength) {
|
|
286
|
-
const err = new Error("INVALID_DOTENV_KEY: It must be 64 characters long (or more)");
|
|
287
|
-
err.code = "INVALID_DOTENV_KEY";
|
|
288
|
-
throw err;
|
|
289
|
-
} else if (decryptionFailed) {
|
|
290
|
-
const err = new Error("DECRYPTION_FAILED: Please check your DOTENV_KEY");
|
|
291
|
-
err.code = "DECRYPTION_FAILED";
|
|
292
|
-
throw err;
|
|
293
|
-
} else {
|
|
294
|
-
throw error;
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
function populate(processEnv, parsed, options = {}) {
|
|
299
|
-
const debug = Boolean(options && options.debug);
|
|
300
|
-
const override = Boolean(options && options.override);
|
|
301
|
-
const populated = {};
|
|
302
|
-
if (typeof parsed !== "object") {
|
|
303
|
-
const err = new Error("OBJECT_REQUIRED: Please check the processEnv argument being passed to populate");
|
|
304
|
-
err.code = "OBJECT_REQUIRED";
|
|
305
|
-
throw err;
|
|
306
|
-
}
|
|
307
|
-
for (const key of Object.keys(parsed)) {
|
|
308
|
-
if (Object.prototype.hasOwnProperty.call(processEnv, key)) {
|
|
309
|
-
if (override === true) {
|
|
310
|
-
processEnv[key] = parsed[key];
|
|
311
|
-
populated[key] = parsed[key];
|
|
312
|
-
}
|
|
313
|
-
if (debug) {
|
|
314
|
-
if (override === true) {
|
|
315
|
-
_debug(`"${key}" is already defined and WAS overwritten`);
|
|
316
|
-
} else {
|
|
317
|
-
_debug(`"${key}" is already defined and was NOT overwritten`);
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
} else {
|
|
321
|
-
processEnv[key] = parsed[key];
|
|
322
|
-
populated[key] = parsed[key];
|
|
323
|
-
}
|
|
324
|
-
}
|
|
325
|
-
return populated;
|
|
326
|
-
}
|
|
327
|
-
var DotenvModule = {
|
|
328
|
-
configDotenv,
|
|
329
|
-
_configVault,
|
|
330
|
-
_parseVault,
|
|
331
|
-
config,
|
|
332
|
-
decrypt,
|
|
333
|
-
parse,
|
|
334
|
-
populate
|
|
335
|
-
};
|
|
336
|
-
module.exports.configDotenv = DotenvModule.configDotenv;
|
|
337
|
-
module.exports._configVault = DotenvModule._configVault;
|
|
338
|
-
module.exports._parseVault = DotenvModule._parseVault;
|
|
339
|
-
module.exports.config = DotenvModule.config;
|
|
340
|
-
module.exports.decrypt = DotenvModule.decrypt;
|
|
341
|
-
module.exports.parse = DotenvModule.parse;
|
|
342
|
-
module.exports.populate = DotenvModule.populate;
|
|
343
|
-
module.exports = DotenvModule;
|
|
344
|
-
}
|
|
345
|
-
});
|
|
346
|
-
|
|
347
|
-
// ../../../node_modules/dotenv/lib/env-options.js
|
|
348
|
-
var require_env_options = __commonJS({
|
|
349
|
-
"../../../node_modules/dotenv/lib/env-options.js"(exports, module) {
|
|
350
|
-
"use strict";
|
|
351
|
-
var options = {};
|
|
352
|
-
if (process.env.DOTENV_CONFIG_ENCODING != null) {
|
|
353
|
-
options.encoding = process.env.DOTENV_CONFIG_ENCODING;
|
|
354
|
-
}
|
|
355
|
-
if (process.env.DOTENV_CONFIG_PATH != null) {
|
|
356
|
-
options.path = process.env.DOTENV_CONFIG_PATH;
|
|
357
|
-
}
|
|
358
|
-
if (process.env.DOTENV_CONFIG_QUIET != null) {
|
|
359
|
-
options.quiet = process.env.DOTENV_CONFIG_QUIET;
|
|
360
|
-
}
|
|
361
|
-
if (process.env.DOTENV_CONFIG_DEBUG != null) {
|
|
362
|
-
options.debug = process.env.DOTENV_CONFIG_DEBUG;
|
|
363
|
-
}
|
|
364
|
-
if (process.env.DOTENV_CONFIG_OVERRIDE != null) {
|
|
365
|
-
options.override = process.env.DOTENV_CONFIG_OVERRIDE;
|
|
366
|
-
}
|
|
367
|
-
if (process.env.DOTENV_CONFIG_DOTENV_KEY != null) {
|
|
368
|
-
options.DOTENV_KEY = process.env.DOTENV_CONFIG_DOTENV_KEY;
|
|
369
|
-
}
|
|
370
|
-
module.exports = options;
|
|
371
|
-
}
|
|
372
|
-
});
|
|
373
|
-
|
|
374
|
-
// ../../../node_modules/dotenv/lib/cli-options.js
|
|
375
|
-
var require_cli_options = __commonJS({
|
|
376
|
-
"../../../node_modules/dotenv/lib/cli-options.js"(exports, module) {
|
|
377
|
-
"use strict";
|
|
378
|
-
var re = /^dotenv_config_(encoding|path|quiet|debug|override|DOTENV_KEY)=(.+)$/;
|
|
379
|
-
module.exports = function optionMatcher(args) {
|
|
380
|
-
const options = args.reduce(function(acc, cur) {
|
|
381
|
-
const matches = cur.match(re);
|
|
382
|
-
if (matches) {
|
|
383
|
-
acc[matches[1]] = matches[2];
|
|
384
|
-
}
|
|
385
|
-
return acc;
|
|
386
|
-
}, {});
|
|
387
|
-
if (!("quiet" in options)) {
|
|
388
|
-
options.quiet = "true";
|
|
389
|
-
}
|
|
390
|
-
return options;
|
|
391
|
-
};
|
|
392
|
-
}
|
|
393
|
-
});
|
|
15
|
+
__require
|
|
16
|
+
} from "./chunk-3RG5ZIWI.js";
|
|
394
17
|
|
|
395
18
|
// src/index.ts
|
|
396
19
|
import { Command } from "commander";
|
|
397
20
|
import chalk from "chalk";
|
|
398
21
|
import ora from "ora";
|
|
399
|
-
|
|
400
|
-
// ../../../node_modules/dotenv/config.js
|
|
401
|
-
(function() {
|
|
402
|
-
require_main().config(
|
|
403
|
-
Object.assign(
|
|
404
|
-
{},
|
|
405
|
-
require_env_options(),
|
|
406
|
-
require_cli_options()(process.argv)
|
|
407
|
-
)
|
|
408
|
-
);
|
|
409
|
-
})();
|
|
22
|
+
import "dotenv/config";
|
|
410
23
|
|
|
411
24
|
// ../infrastructure/src/db/SQLiteStateStore.ts
|
|
412
|
-
import { DatabaseSync } from "sqlite";
|
|
25
|
+
import { DatabaseSync } from "node:sqlite";
|
|
413
26
|
import { join as join2 } from "path";
|
|
414
27
|
import { mkdirSync } from "fs";
|
|
415
28
|
var SQLiteStateStore = class {
|
|
@@ -580,9 +193,9 @@ var SQLiteStateStore = class {
|
|
|
580
193
|
};
|
|
581
194
|
|
|
582
195
|
// ../infrastructure/src/tools/AstTools.ts
|
|
583
|
-
|
|
196
|
+
import { Project } from "ts-morph";
|
|
584
197
|
import { existsSync } from "fs";
|
|
585
|
-
var project = new
|
|
198
|
+
var project = new Project();
|
|
586
199
|
function createReadFileTool() {
|
|
587
200
|
return {
|
|
588
201
|
type: "function",
|
|
@@ -1379,7 +992,7 @@ async function createApiServer(store, migrationRunner) {
|
|
|
1379
992
|
});
|
|
1380
993
|
app.get("/api/detect", async (req, res) => {
|
|
1381
994
|
try {
|
|
1382
|
-
const { detectTechnologies: detectTechnologies2 } = await import("./TechDetector-
|
|
995
|
+
const { detectTechnologies: detectTechnologies2 } = await import("./TechDetector-TKTX5YAM.js");
|
|
1383
996
|
const targetPath = req.query.path ? String(req.query.path) : ".";
|
|
1384
997
|
const detected = detectTechnologies2(targetPath);
|
|
1385
998
|
res.json({
|
|
@@ -1479,7 +1092,7 @@ async function createApiServer(store, migrationRunner) {
|
|
|
1479
1092
|
}
|
|
1480
1093
|
const path6 = await import("path");
|
|
1481
1094
|
const fs7 = await import("fs");
|
|
1482
|
-
const publicDir = path6.join(
|
|
1095
|
+
const publicDir = path6.join(import.meta.dirname, "../public");
|
|
1483
1096
|
if (fs7.existsSync(publicDir)) {
|
|
1484
1097
|
app.use(express.static(publicDir));
|
|
1485
1098
|
app.get("*", (_req, res) => {
|
|
@@ -1492,6 +1105,10 @@ async function createApiServer(store, migrationRunner) {
|
|
|
1492
1105
|
// ../application/src/agents/MapperAgent.ts
|
|
1493
1106
|
import * as fs3 from "fs";
|
|
1494
1107
|
import * as path2 from "path";
|
|
1108
|
+
import {
|
|
1109
|
+
createAgent,
|
|
1110
|
+
SituationSpecification
|
|
1111
|
+
} from "@mozaik-ai/core";
|
|
1495
1112
|
var WhenMigrationStarts = class extends SituationSpecification {
|
|
1496
1113
|
isSatisfiedBy({ event }) {
|
|
1497
1114
|
return event.type === "migration.started" /* MIGRATION_STARTED */;
|
|
@@ -1559,6 +1176,10 @@ function createMapperAgent() {
|
|
|
1559
1176
|
|
|
1560
1177
|
// ../application/src/agents/WorkerAgent.ts
|
|
1561
1178
|
import * as fs4 from "fs";
|
|
1179
|
+
import {
|
|
1180
|
+
createAgent as createAgent2,
|
|
1181
|
+
SituationSpecification as SituationSpecification2
|
|
1182
|
+
} from "@mozaik-ai/core";
|
|
1562
1183
|
|
|
1563
1184
|
// ../application/src/utils/FileTreeBuilder.ts
|
|
1564
1185
|
import * as path3 from "path";
|
|
@@ -1651,22 +1272,22 @@ var ConcurrencyQueue = class {
|
|
|
1651
1272
|
}
|
|
1652
1273
|
};
|
|
1653
1274
|
var workerQueue = new ConcurrencyQueue(2);
|
|
1654
|
-
var WhenFileDiscovered = class extends
|
|
1275
|
+
var WhenFileDiscovered = class extends SituationSpecification2 {
|
|
1655
1276
|
isSatisfiedBy({ event }) {
|
|
1656
1277
|
return event.type === "file.discovered" /* FILE_DISCOVERED */;
|
|
1657
1278
|
}
|
|
1658
1279
|
};
|
|
1659
|
-
var WhenFileRejected = class extends
|
|
1280
|
+
var WhenFileRejected = class extends SituationSpecification2 {
|
|
1660
1281
|
isSatisfiedBy({ event }) {
|
|
1661
1282
|
return event.type === "file.rejected" /* FILE_REJECTED */;
|
|
1662
1283
|
}
|
|
1663
1284
|
};
|
|
1664
|
-
var WhenFileFatalMismatch = class extends
|
|
1285
|
+
var WhenFileFatalMismatch = class extends SituationSpecification2 {
|
|
1665
1286
|
isSatisfiedBy({ event }) {
|
|
1666
1287
|
return event.type === "file.fatal_mismatch" /* FILE_FATAL_MISMATCH */;
|
|
1667
1288
|
}
|
|
1668
1289
|
};
|
|
1669
|
-
var WhenInferenceCompleted = class extends
|
|
1290
|
+
var WhenInferenceCompleted = class extends SituationSpecification2 {
|
|
1670
1291
|
isSatisfiedBy({ event, participant }) {
|
|
1671
1292
|
return event.type === "model.answer" && event.producerId === participant.getId();
|
|
1672
1293
|
}
|
|
@@ -1684,7 +1305,7 @@ async function startWorkerLoop(planId, filePath, prompt, participant) {
|
|
|
1684
1305
|
const repository = runtime.state.repository;
|
|
1685
1306
|
console.log(`[WorkerAgent] Marking file as 'in_progress' in database...`);
|
|
1686
1307
|
await repository.updateTaskStatus(planId, filePath, "in_progress");
|
|
1687
|
-
const { createAgent: createMozaikAgent } = await import("
|
|
1308
|
+
const { createAgent: createMozaikAgent } = await import("@mozaik-ai/core");
|
|
1688
1309
|
const tempAgent = createMozaikAgent({
|
|
1689
1310
|
name: `Worker-${Date.now()}-${Math.floor(Math.random() * 1e3)}`,
|
|
1690
1311
|
capabilities: ["code_refactoring", "inference"],
|
|
@@ -1888,7 +1509,7 @@ var fatalMismatchProcessor = {
|
|
|
1888
1509
|
}
|
|
1889
1510
|
};
|
|
1890
1511
|
function createWorkerAgent(tools) {
|
|
1891
|
-
return
|
|
1512
|
+
return createAgent2({
|
|
1892
1513
|
name: "Worker",
|
|
1893
1514
|
capabilities: ["code_refactoring", "inference"],
|
|
1894
1515
|
instruction: "You are the Programmer Worker. You migrate code and adapt file structures.",
|
|
@@ -1902,6 +1523,10 @@ function createWorkerAgent(tools) {
|
|
|
1902
1523
|
}
|
|
1903
1524
|
|
|
1904
1525
|
// ../application/src/agents/ReviewerAgent.ts
|
|
1526
|
+
import {
|
|
1527
|
+
createAgent as createAgent3,
|
|
1528
|
+
SituationSpecification as SituationSpecification3
|
|
1529
|
+
} from "@mozaik-ai/core";
|
|
1905
1530
|
var ConcurrencyQueue2 = class {
|
|
1906
1531
|
constructor(concurrencyLimit) {
|
|
1907
1532
|
this.concurrencyLimit = concurrencyLimit;
|
|
@@ -1931,18 +1556,18 @@ var ConcurrencyQueue2 = class {
|
|
|
1931
1556
|
}
|
|
1932
1557
|
};
|
|
1933
1558
|
var reviewerQueue = new ConcurrencyQueue2(2);
|
|
1934
|
-
var WhenFileMigrated = class extends
|
|
1559
|
+
var WhenFileMigrated = class extends SituationSpecification3 {
|
|
1935
1560
|
isSatisfiedBy({ event }) {
|
|
1936
1561
|
return event.type === "file.migrated" /* FILE_MIGRATED */;
|
|
1937
1562
|
}
|
|
1938
1563
|
};
|
|
1939
|
-
var WhenReviewCompleted = class extends
|
|
1564
|
+
var WhenReviewCompleted = class extends SituationSpecification3 {
|
|
1940
1565
|
isSatisfiedBy({ event, participant }) {
|
|
1941
1566
|
console.log(`[DEBUG:WhenReviewCompleted] Event received -> type: "${event.type}", producerId: "${event.producerId}", participantId: "${participant.getId()}", match: ${event.type === "model.answer" && event.producerId === participant.getId()}`);
|
|
1942
1567
|
return event.type === "model.answer" && event.producerId === participant.getId();
|
|
1943
1568
|
}
|
|
1944
1569
|
};
|
|
1945
|
-
var WhenAnythingHappens = class extends
|
|
1570
|
+
var WhenAnythingHappens = class extends SituationSpecification3 {
|
|
1946
1571
|
isSatisfiedBy() {
|
|
1947
1572
|
return true;
|
|
1948
1573
|
}
|
|
@@ -1961,8 +1586,8 @@ var reviewFileProcessor = {
|
|
|
1961
1586
|
originalResolve();
|
|
1962
1587
|
}
|
|
1963
1588
|
};
|
|
1964
|
-
const { createAgent: createMozaikAgent } = await import("
|
|
1965
|
-
const { sendEvent: sendEvent3 } = await import("./runtime-
|
|
1589
|
+
const { createAgent: createMozaikAgent } = await import("@mozaik-ai/core");
|
|
1590
|
+
const { sendEvent: sendEvent3 } = await import("./runtime-MOEIRP73.js");
|
|
1966
1591
|
const reviewerId = `Reviewer-${Date.now()}-${Math.floor(Math.random() * 1e3)}`;
|
|
1967
1592
|
const tempAgent = createMozaikAgent({
|
|
1968
1593
|
name: reviewerId,
|
|
@@ -2062,14 +1687,14 @@ var reviewFileProcessor = {
|
|
|
2062
1687
|
const runtime = resolveRuntime();
|
|
2063
1688
|
if (payload.filePath.endsWith(".ts") || payload.filePath.endsWith(".tsx")) {
|
|
2064
1689
|
try {
|
|
2065
|
-
const { Project: Project2 } = await import("
|
|
1690
|
+
const { Project: Project2 } = await import("ts-morph");
|
|
2066
1691
|
const tsProject = new Project2();
|
|
2067
1692
|
const sf = tsProject.addSourceFileAtPath(payload.filePath);
|
|
2068
1693
|
const diagnostics = sf.getPreEmitDiagnostics();
|
|
2069
1694
|
const syntaxErrors = diagnostics.filter((d) => d.getCode() >= 1e3 && d.getCode() < 2e3);
|
|
2070
1695
|
if (syntaxErrors.length > 0) {
|
|
2071
1696
|
console.error(`[ReviewerAgent:${reviewerId}] Syntax Error in ${payload.filePath}. Rejecting immediately.`);
|
|
2072
|
-
const { sendEvent: sendEvent4 } = await import("./runtime-
|
|
1697
|
+
const { sendEvent: sendEvent4 } = await import("./runtime-MOEIRP73.js");
|
|
2073
1698
|
sendEvent4({
|
|
2074
1699
|
type: "file.rejected" /* FILE_REJECTED */,
|
|
2075
1700
|
producerId: tempAgent.getId(),
|
|
@@ -2132,7 +1757,7 @@ Does it meet the criteria? You MUST respond in JSON.`;
|
|
|
2132
1757
|
setTimeout(async () => {
|
|
2133
1758
|
if (!isDone) {
|
|
2134
1759
|
console.error(`[ReviewerAgent:${reviewerId}] \u23F0 TIMEOUT after 45s for ${payload.filePath}. Model never responded.`);
|
|
2135
|
-
const { resolveRuntime: resolveRuntime2 } = await import("./runtime-
|
|
1760
|
+
const { resolveRuntime: resolveRuntime2 } = await import("./runtime-MOEIRP73.js");
|
|
2136
1761
|
const runtime2 = resolveRuntime2();
|
|
2137
1762
|
await runtime2.state.repository.updateTaskStatus(payload.planId, payload.filePath, "failed", "Inference timed out after 45s");
|
|
2138
1763
|
leave(tempAgent);
|
|
@@ -2142,7 +1767,7 @@ Does it meet the criteria? You MUST respond in JSON.`;
|
|
|
2142
1767
|
} catch (error) {
|
|
2143
1768
|
console.error(`[ReviewerAgent:${reviewerId}] Sync error:`, error);
|
|
2144
1769
|
if (!isDone) {
|
|
2145
|
-
const { resolveRuntime: resolveRuntime2 } = await import("./runtime-
|
|
1770
|
+
const { resolveRuntime: resolveRuntime2 } = await import("./runtime-MOEIRP73.js");
|
|
2146
1771
|
const runtime2 = resolveRuntime2();
|
|
2147
1772
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
2148
1773
|
await runtime2.state.repository.updateTaskStatus(payload.planId, payload.filePath, "failed", errorMessage || "Sync error");
|
|
@@ -2159,7 +1784,7 @@ var reviewFileHandler = {
|
|
|
2159
1784
|
processor: reviewFileProcessor
|
|
2160
1785
|
};
|
|
2161
1786
|
function createReviewerAgent(tools) {
|
|
2162
|
-
return
|
|
1787
|
+
return createAgent3({
|
|
2163
1788
|
name: "Reviewer",
|
|
2164
1789
|
capabilities: ["code_review", "inference"],
|
|
2165
1790
|
instruction: "You are the Reviewer Worker.",
|
|
@@ -2172,7 +1797,11 @@ function createReviewerAgent(tools) {
|
|
|
2172
1797
|
// ../application/src/agents/PackageManagerAgent.ts
|
|
2173
1798
|
import * as fs5 from "fs";
|
|
2174
1799
|
import * as path4 from "path";
|
|
2175
|
-
|
|
1800
|
+
import {
|
|
1801
|
+
createAgent as createAgent4,
|
|
1802
|
+
SituationSpecification as SituationSpecification4
|
|
1803
|
+
} from "@mozaik-ai/core";
|
|
1804
|
+
var WhenMigrationStarts2 = class extends SituationSpecification4 {
|
|
2176
1805
|
isSatisfiedBy({ event }) {
|
|
2177
1806
|
return event.type === "migration.started" /* MIGRATION_STARTED */;
|
|
2178
1807
|
}
|
|
@@ -2242,7 +1871,7 @@ var managePackagesHandler = {
|
|
|
2242
1871
|
processor: managePackagesProcessor
|
|
2243
1872
|
};
|
|
2244
1873
|
function createPackageManagerAgent() {
|
|
2245
|
-
return
|
|
1874
|
+
return createAgent4({
|
|
2246
1875
|
name: "PackageManager",
|
|
2247
1876
|
capabilities: ["package_management"],
|
|
2248
1877
|
instruction: "You are the Package Manager Agent. Your job is to resolve dependencies and clean up unused framework files.",
|
|
@@ -2254,32 +1883,36 @@ function createPackageManagerAgent() {
|
|
|
2254
1883
|
// ../application/src/agents/ReporterAgent.ts
|
|
2255
1884
|
import * as fs6 from "fs";
|
|
2256
1885
|
import * as path5 from "path";
|
|
2257
|
-
|
|
1886
|
+
import {
|
|
1887
|
+
createAgent as createAgent5,
|
|
1888
|
+
SituationSpecification as SituationSpecification5
|
|
1889
|
+
} from "@mozaik-ai/core";
|
|
1890
|
+
var WhenMigrationStarted = class extends SituationSpecification5 {
|
|
2258
1891
|
isSatisfiedBy({ event }) {
|
|
2259
1892
|
return event.type === "migration.started" /* MIGRATION_STARTED */;
|
|
2260
1893
|
}
|
|
2261
1894
|
};
|
|
2262
|
-
var WhenFileMigrated2 = class extends
|
|
1895
|
+
var WhenFileMigrated2 = class extends SituationSpecification5 {
|
|
2263
1896
|
isSatisfiedBy({ event }) {
|
|
2264
1897
|
return event.type === "file.migrated" /* FILE_MIGRATED */;
|
|
2265
1898
|
}
|
|
2266
1899
|
};
|
|
2267
|
-
var WhenFileReviewed = class extends
|
|
1900
|
+
var WhenFileReviewed = class extends SituationSpecification5 {
|
|
2268
1901
|
isSatisfiedBy({ event }) {
|
|
2269
1902
|
return event.type === "file.reviewed" /* FILE_REVIEWED */;
|
|
2270
1903
|
}
|
|
2271
1904
|
};
|
|
2272
|
-
var WhenFileRejected2 = class extends
|
|
1905
|
+
var WhenFileRejected2 = class extends SituationSpecification5 {
|
|
2273
1906
|
isSatisfiedBy({ event }) {
|
|
2274
1907
|
return event.type === "file.rejected" /* FILE_REJECTED */;
|
|
2275
1908
|
}
|
|
2276
1909
|
};
|
|
2277
|
-
var WhenFileFatalMismatch2 = class extends
|
|
1910
|
+
var WhenFileFatalMismatch2 = class extends SituationSpecification5 {
|
|
2278
1911
|
isSatisfiedBy({ event }) {
|
|
2279
1912
|
return event.type === "file.fatal_mismatch" /* FILE_FATAL_MISMATCH */;
|
|
2280
1913
|
}
|
|
2281
1914
|
};
|
|
2282
|
-
var WhenMigrationCompleted = class extends
|
|
1915
|
+
var WhenMigrationCompleted = class extends SituationSpecification5 {
|
|
2283
1916
|
isSatisfiedBy({ event }) {
|
|
2284
1917
|
return event.type === "migration.completed" /* MIGRATION_COMPLETED */;
|
|
2285
1918
|
}
|
|
@@ -2315,7 +1948,7 @@ var startedProcessor = {
|
|
|
2315
1948
|
var migratedProcessor = {
|
|
2316
1949
|
async apply({ event }) {
|
|
2317
1950
|
const p = event.payload;
|
|
2318
|
-
const { resolveRuntime: resolveRuntime2 } = await import("./runtime-
|
|
1951
|
+
const { resolveRuntime: resolveRuntime2 } = await import("./runtime-MOEIRP73.js");
|
|
2319
1952
|
const runtime = resolveRuntime2();
|
|
2320
1953
|
const plan = await runtime.state.repository.getPlan(p.planId);
|
|
2321
1954
|
if (!plan) return;
|
|
@@ -2326,7 +1959,7 @@ var migratedProcessor = {
|
|
|
2326
1959
|
var reviewedProcessor = {
|
|
2327
1960
|
async apply({ event }) {
|
|
2328
1961
|
const p = event.payload;
|
|
2329
|
-
const { resolveRuntime: resolveRuntime2 } = await import("./runtime-
|
|
1962
|
+
const { resolveRuntime: resolveRuntime2 } = await import("./runtime-MOEIRP73.js");
|
|
2330
1963
|
const runtime = resolveRuntime2();
|
|
2331
1964
|
const plan = await runtime.state.repository.getPlan(p.planId);
|
|
2332
1965
|
if (!plan) return;
|
|
@@ -2336,7 +1969,7 @@ var reviewedProcessor = {
|
|
|
2336
1969
|
var rejectedProcessor = {
|
|
2337
1970
|
async apply({ event }) {
|
|
2338
1971
|
const p = event.payload;
|
|
2339
|
-
const { resolveRuntime: resolveRuntime2 } = await import("./runtime-
|
|
1972
|
+
const { resolveRuntime: resolveRuntime2 } = await import("./runtime-MOEIRP73.js");
|
|
2340
1973
|
const runtime = resolveRuntime2();
|
|
2341
1974
|
const plan = await runtime.state.repository.getPlan(p.planId);
|
|
2342
1975
|
if (!plan) return;
|
|
@@ -2347,7 +1980,7 @@ var rejectedProcessor = {
|
|
|
2347
1980
|
var fatalProcessor = {
|
|
2348
1981
|
async apply({ event }) {
|
|
2349
1982
|
const p = event.payload;
|
|
2350
|
-
const { resolveRuntime: resolveRuntime2 } = await import("./runtime-
|
|
1983
|
+
const { resolveRuntime: resolveRuntime2 } = await import("./runtime-MOEIRP73.js");
|
|
2351
1984
|
const runtime = resolveRuntime2();
|
|
2352
1985
|
const plan = await runtime.state.repository.getPlan(p.planId);
|
|
2353
1986
|
if (!plan) return;
|
|
@@ -2358,7 +1991,7 @@ var fatalProcessor = {
|
|
|
2358
1991
|
var completedProcessor = {
|
|
2359
1992
|
async apply({ event }) {
|
|
2360
1993
|
const p = event.payload;
|
|
2361
|
-
const { resolveRuntime: resolveRuntime2 } = await import("./runtime-
|
|
1994
|
+
const { resolveRuntime: resolveRuntime2 } = await import("./runtime-MOEIRP73.js");
|
|
2362
1995
|
const runtime = resolveRuntime2();
|
|
2363
1996
|
const plan = await runtime.state.repository.getPlan(p.planId);
|
|
2364
1997
|
if (!plan) return;
|
|
@@ -2375,7 +2008,7 @@ var completedProcessor = {
|
|
|
2375
2008
|
}
|
|
2376
2009
|
};
|
|
2377
2010
|
function createReporterAgent() {
|
|
2378
|
-
return
|
|
2011
|
+
return createAgent5({
|
|
2379
2012
|
name: "Reporter",
|
|
2380
2013
|
capabilities: ["reporting"],
|
|
2381
2014
|
instruction: "You are the Reporter Agent. Your job is to compile a human-readable markdown report of the migration process.",
|
|
@@ -2391,6 +2024,9 @@ function createReporterAgent() {
|
|
|
2391
2024
|
});
|
|
2392
2025
|
}
|
|
2393
2026
|
|
|
2027
|
+
// ../application/src/index.ts
|
|
2028
|
+
import { createAgent as createAgent6, SituationSpecification as SituationSpecification6 } from "@mozaik-ai/core";
|
|
2029
|
+
|
|
2394
2030
|
// ../application/src/MigrationRunner.ts
|
|
2395
2031
|
import { randomUUID } from "crypto";
|
|
2396
2032
|
var MigrationRunner = class {
|
|
@@ -2435,7 +2071,7 @@ var MigrationRunner = class {
|
|
|
2435
2071
|
createdAt: /* @__PURE__ */ new Date()
|
|
2436
2072
|
};
|
|
2437
2073
|
await this.store.savePlan(plan);
|
|
2438
|
-
const { createHuman } = await import("
|
|
2074
|
+
const { createHuman } = await import("@mozaik-ai/core");
|
|
2439
2075
|
const human = createHuman({ name: "System", capabilities: [], handlers: [] });
|
|
2440
2076
|
join(human);
|
|
2441
2077
|
sendEvent(
|
|
@@ -2468,12 +2104,12 @@ function bootstrapMetamorph(repository, tools = []) {
|
|
|
2468
2104
|
initializeRuntime({
|
|
2469
2105
|
state: new MetamorphState(repository)
|
|
2470
2106
|
});
|
|
2471
|
-
class AllEventsSpecification extends
|
|
2107
|
+
class AllEventsSpecification extends SituationSpecification6 {
|
|
2472
2108
|
isSatisfiedBy() {
|
|
2473
2109
|
return true;
|
|
2474
2110
|
}
|
|
2475
2111
|
}
|
|
2476
|
-
const loggerAgent =
|
|
2112
|
+
const loggerAgent = createAgent6({
|
|
2477
2113
|
name: "TelemetryLogger",
|
|
2478
2114
|
capabilities: [],
|
|
2479
2115
|
instruction: "You silently log everything.",
|
|
@@ -2483,7 +2119,7 @@ function bootstrapMetamorph(repository, tools = []) {
|
|
|
2483
2119
|
specification: new AllEventsSpecification(),
|
|
2484
2120
|
processor: {
|
|
2485
2121
|
async apply({ event }) {
|
|
2486
|
-
const { resolveRuntime: resolveRuntime2 } = await import("./runtime-
|
|
2122
|
+
const { resolveRuntime: resolveRuntime2 } = await import("./runtime-MOEIRP73.js");
|
|
2487
2123
|
const runtime = resolveRuntime2();
|
|
2488
2124
|
const repository2 = runtime.state.repository;
|
|
2489
2125
|
if (event.type.includes("migration") || event.type.includes("file")) {
|
|
@@ -2526,11 +2162,11 @@ program.command("run [path]").description("Run a migration on the specified dire
|
|
|
2526
2162
|
let to = options.to;
|
|
2527
2163
|
const SUPPORTED_MIGRATIONS = {
|
|
2528
2164
|
express: ["fastify", "nestjs"],
|
|
2529
|
-
fastify: ["
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2165
|
+
fastify: ["express", "nestjs"],
|
|
2166
|
+
nestjs: ["express", "fastify"],
|
|
2167
|
+
react: ["next", "vue"],
|
|
2168
|
+
next: ["react"],
|
|
2169
|
+
vue: ["react"]
|
|
2534
2170
|
};
|
|
2535
2171
|
if (!from) {
|
|
2536
2172
|
console.log(chalk.gray(`
|