@nikelyh/metamorph 2.1.0 → 2.1.2
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/LICENSE +674 -0
- package/README.md +58 -31
- package/bin/metamorph.js +0 -0
- package/dist/NextMigrationHints-BGO2W3K4.js +32 -0
- package/dist/ProjectDetector-WU3OD6WT.js +16 -0
- package/dist/{chunk-OXXEISZT.js → chunk-APRESSUR.js} +103 -44
- package/dist/chunk-H2LZEPNI.js +352 -0
- package/dist/{chunk-VEAYUIOZ.js → chunk-WLHSZWET.js} +39 -0
- package/dist/chunk-XLD7NXYU.js +528 -0
- package/dist/index.js +624 -520
- package/dist/public/assets/index-BX5N2qs-.js +63 -0
- package/dist/public/assets/index-C7odDrsP.css +1 -0
- package/dist/public/icons/angular.svg +1 -1
- package/dist/public/icons/expressjs.svg +1 -1
- package/dist/public/icons/fastify.svg +1 -1
- package/dist/public/icons/hapi.svg +1 -14
- package/dist/public/icons/nestjs.svg +1 -1
- package/dist/public/icons/nextjs.svg +1 -1
- package/dist/public/icons/react.svg +1 -1
- package/dist/public/icons/svelte.svg +1 -21
- package/dist/public/icons/vue.svg +1 -1
- package/dist/public/icons.svg +1 -24
- package/dist/public/index.html +2 -2
- package/dist/{src-2UXWWNPF.js → src-Q3DGKZEQ.js} +20 -4
- package/dist/{src-UC3SN46X.js → src-YPCIVBLZ.js} +3 -1
- package/package.json +18 -5
- package/dist/TechDetector-5YP44RVR.js +0 -6
- package/dist/chunk-3QN2Q75J.js +0 -101
- package/dist/public/assets/index-DDJRaEaa.css +0 -1
- package/dist/public/assets/index-PNJ1umlc.js +0 -63
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
// ../application/src/utils/NextMigrationHints.ts
|
|
2
|
+
import * as fs from "fs";
|
|
3
|
+
import * as path from "path";
|
|
4
|
+
function findShadowRoot(filePath) {
|
|
5
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
6
|
+
const marker = "/.metamorph/shadow/";
|
|
7
|
+
const index = normalized.indexOf(marker);
|
|
8
|
+
if (index === -1) return null;
|
|
9
|
+
const after = normalized.slice(index + marker.length);
|
|
10
|
+
const runId = after.split("/")[0];
|
|
11
|
+
if (!runId) return null;
|
|
12
|
+
return filePath.slice(0, index + marker.length + runId.length);
|
|
13
|
+
}
|
|
14
|
+
function isFsdPageComponent(filePath) {
|
|
15
|
+
return /[/\\]src[/\\]pages[/\\][^/\\]+[/\\]ui[/\\]/i.test(filePath);
|
|
16
|
+
}
|
|
17
|
+
function isSpaRootComponent(filePath) {
|
|
18
|
+
return /[/\\](App|main|index)\.(t|j)sx?$/i.test(filePath) && !/[/\\]src[/\\]app[/\\]/i.test(filePath) && !isFsdPageComponent(filePath);
|
|
19
|
+
}
|
|
20
|
+
function hasNextAppRoutes(shadowRoot) {
|
|
21
|
+
const appDir = path.join(shadowRoot, "src", "app");
|
|
22
|
+
if (!fs.existsSync(appDir)) return false;
|
|
23
|
+
const stack = [appDir];
|
|
24
|
+
while (stack.length > 0) {
|
|
25
|
+
const dir = stack.pop();
|
|
26
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
27
|
+
if (entry.isDirectory()) {
|
|
28
|
+
stack.push(path.join(dir, entry.name));
|
|
29
|
+
} else if (entry.name === "page.tsx" || entry.name === "page.jsx" || entry.name === "page.js") {
|
|
30
|
+
return true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
function nextMigrationFileHint(filePath, target) {
|
|
37
|
+
if (target !== "next") return "";
|
|
38
|
+
if (isFsdPageComponent(filePath) || isSpaPagesTreeFile(filePath)) {
|
|
39
|
+
return `
|
|
40
|
+
This file sits under src/pages. In Next.js that directory is the Pages Router.
|
|
41
|
+
Move this file out of src/pages (keep the component and its business logic) into a folder Next does not treat as routes.
|
|
42
|
+
Then add or update src/app/<route>/page.tsx so the App Router imports that screen for the former URL.
|
|
43
|
+
The home route ("/") is src/app/page.tsx and must render the former "/" screen \u2014 not an empty shell, null, a TODO, or a deleted App.tsx.
|
|
44
|
+
Delete the old src/pages copy after the screen exists elsewhere.
|
|
45
|
+
`;
|
|
46
|
+
}
|
|
47
|
+
if (isSpaRootComponent(filePath)) {
|
|
48
|
+
return `
|
|
49
|
+
This is a SPA root/entry file (App.tsx / main.tsx / index.tsx).
|
|
50
|
+
Read it and map each route to src/app/<path>/page.tsx that imports the actual screen component (after moving anything that lived under src/pages).
|
|
51
|
+
src/app/page.tsx must render the home screen. Never import App from the new page (App is being removed).
|
|
52
|
+
Never write a stub that the root component "could not be resolved". After App Router files exist with real UI, delete this legacy root file.
|
|
53
|
+
`;
|
|
54
|
+
}
|
|
55
|
+
if (/[/\\]src[/\\]app[/\\].*page\.(t|j)sx$/i.test(filePath)) {
|
|
56
|
+
return `
|
|
57
|
+
This is a Next App Router page. Import the existing screen component and return it.
|
|
58
|
+
Do not paste that screen's JSX here. Do not rename its public props at the wrapper.
|
|
59
|
+
Do not hollow out the module you imported from.
|
|
60
|
+
`;
|
|
61
|
+
}
|
|
62
|
+
return "";
|
|
63
|
+
}
|
|
64
|
+
var NEXT_PAGES_RESERVED = /(?:^|[/\\])(_app|_document|_error|404|500)\.(t|j)sx?$/i;
|
|
65
|
+
function isSpaPagesTreeFile(filePath) {
|
|
66
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
67
|
+
if (!/\/src\/pages\//i.test(normalized)) return false;
|
|
68
|
+
if (/\/src\/pages\/api\//i.test(normalized)) return false;
|
|
69
|
+
if (NEXT_PAGES_RESERVED.test(normalized)) return false;
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
72
|
+
function listFilesRecursive(dir) {
|
|
73
|
+
if (!fs.existsSync(dir)) return [];
|
|
74
|
+
const out = [];
|
|
75
|
+
const stack = [dir];
|
|
76
|
+
while (stack.length > 0) {
|
|
77
|
+
const current = stack.pop();
|
|
78
|
+
for (const entry of fs.readdirSync(current, { withFileTypes: true })) {
|
|
79
|
+
const full = path.join(current, entry.name);
|
|
80
|
+
if (entry.isDirectory()) stack.push(full);
|
|
81
|
+
else if (/\.(t|j)sx?$/.test(entry.name)) out.push(full);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return out;
|
|
85
|
+
}
|
|
86
|
+
function findAppRouterHome(shadowRoot) {
|
|
87
|
+
const candidates = [
|
|
88
|
+
path.join(shadowRoot, "src", "app", "page.tsx"),
|
|
89
|
+
path.join(shadowRoot, "src", "app", "page.jsx"),
|
|
90
|
+
path.join(shadowRoot, "app", "page.tsx"),
|
|
91
|
+
path.join(shadowRoot, "app", "page.jsx")
|
|
92
|
+
];
|
|
93
|
+
return candidates.find((file) => fs.existsSync(file)) || null;
|
|
94
|
+
}
|
|
95
|
+
function listAppRouterFiles(shadowRoot) {
|
|
96
|
+
const roots = [path.join(shadowRoot, "src", "app"), path.join(shadowRoot, "app")];
|
|
97
|
+
const names = /^(page|layout)\.(t|j)sx$/i;
|
|
98
|
+
return roots.flatMap((dir) => listFilesRecursive(dir).filter((file) => names.test(path.basename(file))));
|
|
99
|
+
}
|
|
100
|
+
function isHollowView(content) {
|
|
101
|
+
const withoutComments = content.replace(/\/\*[\s\S]*?\*\//g, "").replace(/\/\/.*$/gm, "");
|
|
102
|
+
const hasFeatureImports = /from\s+['"][^'"]*\/(features|entities|widgets)\//.test(withoutComments);
|
|
103
|
+
const tinyTree = /<h1[^>]*>[^<]{0,40}<\/h1>/.test(withoutComments) && !hasFeatureImports;
|
|
104
|
+
const emptyMain = /<main>\s*<h1>/.test(withoutComments) && !hasFeatureImports;
|
|
105
|
+
return tinyTree || emptyMain;
|
|
106
|
+
}
|
|
107
|
+
function findViewPages(shadowRoot) {
|
|
108
|
+
const viewsDir = path.join(shadowRoot, "src", "views");
|
|
109
|
+
return listFilesRecursive(viewsDir).filter((file) => /(?:^|[/\\])(?:.+Page|page)\.(t|j)sx$/i.test(file));
|
|
110
|
+
}
|
|
111
|
+
function resolveLocalImport(fromFile, specifier) {
|
|
112
|
+
const dir = path.dirname(fromFile);
|
|
113
|
+
const resolved = specifier.startsWith("@/") ? path.join(findSrcRoot(fromFile), specifier.slice(2)) : path.resolve(dir, specifier);
|
|
114
|
+
const candidates = [
|
|
115
|
+
resolved,
|
|
116
|
+
`${resolved}.tsx`,
|
|
117
|
+
`${resolved}.jsx`,
|
|
118
|
+
`${resolved}.ts`,
|
|
119
|
+
`${resolved}.js`,
|
|
120
|
+
path.join(resolved, "index.tsx"),
|
|
121
|
+
path.join(resolved, "index.ts")
|
|
122
|
+
];
|
|
123
|
+
return candidates.find((file) => {
|
|
124
|
+
try {
|
|
125
|
+
return fs.existsSync(file) && fs.statSync(file).isFile();
|
|
126
|
+
} catch {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
}) || null;
|
|
130
|
+
}
|
|
131
|
+
function localTsxImports(fromFile, content) {
|
|
132
|
+
const out = [];
|
|
133
|
+
const re = /import\s+(?:\{([^}]+)\}|(\w+))\s+from\s+['"](\.\.?\/[^'"]+|@\/[^'"]+)['"]/g;
|
|
134
|
+
let match;
|
|
135
|
+
while ((match = re.exec(content)) !== null) {
|
|
136
|
+
const absPath = resolveLocalImport(fromFile, match[3]);
|
|
137
|
+
if (!absPath) continue;
|
|
138
|
+
if (match[2]) out.push({ tag: match[2], absPath });
|
|
139
|
+
if (match[1]) {
|
|
140
|
+
for (const part of match[1].split(",")) {
|
|
141
|
+
const name = part.trim().split(/\s+as\s+/).pop()?.trim();
|
|
142
|
+
if (name) out.push({ tag: name, absPath });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return out;
|
|
147
|
+
}
|
|
148
|
+
function unresolvedLocalImports(fromFile, content) {
|
|
149
|
+
const out = [];
|
|
150
|
+
const re = /from\s+['"](\.\.?\/[^'"]+|@\/[^'"]+)['"]/g;
|
|
151
|
+
let match;
|
|
152
|
+
while ((match = re.exec(content)) !== null) {
|
|
153
|
+
if (!resolveLocalImport(fromFile, match[1])) {
|
|
154
|
+
out.push(match[1]);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
return out;
|
|
158
|
+
}
|
|
159
|
+
function analyzeUnresolvedLocalImports(shadowRoot) {
|
|
160
|
+
const issues = [];
|
|
161
|
+
const files = [
|
|
162
|
+
...listFilesRecursive(path.join(shadowRoot, "src", "app")),
|
|
163
|
+
...listFilesRecursive(path.join(shadowRoot, "app"))
|
|
164
|
+
].filter((file) => /\.(t|j)sx$/.test(file));
|
|
165
|
+
for (const file of files) {
|
|
166
|
+
const content = fs.readFileSync(file, "utf-8");
|
|
167
|
+
const missing = unresolvedLocalImports(file, content);
|
|
168
|
+
if (missing.length === 0) continue;
|
|
169
|
+
issues.push({
|
|
170
|
+
filePath: file,
|
|
171
|
+
errors: [
|
|
172
|
+
`${path.relative(shadowRoot, file)} imports modules that are not on disk: ${missing.join(", ")}. Do not import a deleted App/main from App Router pages \u2014 import the surviving screen component instead.`
|
|
173
|
+
]
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
return issues;
|
|
177
|
+
}
|
|
178
|
+
function findSrcRoot(filePath) {
|
|
179
|
+
const normalized = filePath.replace(/\\/g, "/");
|
|
180
|
+
const idx = normalized.lastIndexOf("/src/");
|
|
181
|
+
if (idx === -1) return path.dirname(filePath);
|
|
182
|
+
return filePath.slice(0, idx + 4);
|
|
183
|
+
}
|
|
184
|
+
function declaredCallbackProps(componentSource) {
|
|
185
|
+
const names = /* @__PURE__ */ new Set();
|
|
186
|
+
const iface = /interface\s+\w+\s*\{([^}]+)\}/g;
|
|
187
|
+
let block;
|
|
188
|
+
while ((block = iface.exec(componentSource)) !== null) {
|
|
189
|
+
const field = /(\b(?:on[A-Z]\w+|action[A-Z]\w+)\??)\s*:/g;
|
|
190
|
+
let f;
|
|
191
|
+
while ((f = field.exec(block[1])) !== null) names.add(f[1].replace("?", ""));
|
|
192
|
+
}
|
|
193
|
+
const dest = /export\s+(?:default\s+)?function\s+\w+\s*\(\s*\{\s*([^}]+)\}/;
|
|
194
|
+
const d = dest.exec(componentSource);
|
|
195
|
+
if (d) {
|
|
196
|
+
for (const part of d[1].split(",")) {
|
|
197
|
+
const name = part.trim().split(":")[0].trim();
|
|
198
|
+
if (/^(on[A-Z]|action[A-Z])/.test(name)) names.add(name);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return [...names];
|
|
202
|
+
}
|
|
203
|
+
function jsxCallbackProps(callerSource, tag) {
|
|
204
|
+
const names = [];
|
|
205
|
+
const tagRe = new RegExp(`<${tag}\\b([^>]*)\\/?>`, "g");
|
|
206
|
+
let match;
|
|
207
|
+
while ((match = tagRe.exec(callerSource)) !== null) {
|
|
208
|
+
const propRe = /\b((?:on|action)[A-Z]\w+)\s*=/g;
|
|
209
|
+
let p;
|
|
210
|
+
while ((p = propRe.exec(match[1])) !== null) names.push(p[1]);
|
|
211
|
+
}
|
|
212
|
+
return names;
|
|
213
|
+
}
|
|
214
|
+
function analyzeCallbackPropMismatches(shadowRoot) {
|
|
215
|
+
const issues = [];
|
|
216
|
+
const files = [
|
|
217
|
+
...listFilesRecursive(path.join(shadowRoot, "src", "app")),
|
|
218
|
+
...listFilesRecursive(path.join(shadowRoot, "app")),
|
|
219
|
+
...listFilesRecursive(path.join(shadowRoot, "src", "views"))
|
|
220
|
+
].filter((file) => /\.(t|j)sx$/.test(file));
|
|
221
|
+
for (const file of files) {
|
|
222
|
+
const content = fs.readFileSync(file, "utf-8");
|
|
223
|
+
for (const imp of localTsxImports(file, content)) {
|
|
224
|
+
let callee;
|
|
225
|
+
try {
|
|
226
|
+
callee = fs.readFileSync(imp.absPath, "utf-8");
|
|
227
|
+
} catch {
|
|
228
|
+
continue;
|
|
229
|
+
}
|
|
230
|
+
const expected = declaredCallbackProps(callee);
|
|
231
|
+
if (expected.length === 0) continue;
|
|
232
|
+
const passed = jsxCallbackProps(content, imp.tag);
|
|
233
|
+
const missing = expected.filter((name) => !passed.includes(name));
|
|
234
|
+
const extra = passed.filter((name) => !expected.includes(name));
|
|
235
|
+
if (missing.length === 0 && extra.length === 0) continue;
|
|
236
|
+
issues.push({
|
|
237
|
+
filePath: file,
|
|
238
|
+
errors: [
|
|
239
|
+
`<${imp.tag}> public callback props do not match ${path.relative(shadowRoot, imp.absPath)}. Expected: ${expected.join(", ") || "(none)"}. Passed: ${passed.join(", ") || "(none)"}. Do not rename props when wrapping a screen in a router file.`
|
|
240
|
+
]
|
|
241
|
+
});
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
return issues;
|
|
245
|
+
}
|
|
246
|
+
function analyzeReactToNextComposition(shadowRoot) {
|
|
247
|
+
const issues = [];
|
|
248
|
+
const home = findAppRouterHome(shadowRoot);
|
|
249
|
+
if (!home) return issues;
|
|
250
|
+
const homeContent = fs.readFileSync(home, "utf-8");
|
|
251
|
+
const views = findViewPages(shadowRoot);
|
|
252
|
+
const hollowViews = views.filter((file) => isHollowView(fs.readFileSync(file, "utf-8")));
|
|
253
|
+
const homeImportsView = views.some((file) => {
|
|
254
|
+
const stem = path.basename(file).replace(/\.(t|j)sx$/, "");
|
|
255
|
+
return homeContent.includes(stem);
|
|
256
|
+
});
|
|
257
|
+
const homeAssemblesFeatures = /from\s+['"][^'"]*\/(features|entities|widgets)\//.test(homeContent);
|
|
258
|
+
if (views.length > 0 && !homeImportsView && homeAssemblesFeatures) {
|
|
259
|
+
issues.push({
|
|
260
|
+
filePath: home,
|
|
261
|
+
errors: [
|
|
262
|
+
"The App Router home reassembles the UI from lower-level modules instead of importing the existing route-level screen. Import that screen and return it. Renaming props at the wrapper causes runtime TypeError while next build still succeeds."
|
|
263
|
+
]
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
for (const file of hollowViews) {
|
|
267
|
+
issues.push({
|
|
268
|
+
filePath: file,
|
|
269
|
+
errors: [
|
|
270
|
+
"This screen was hollowed out. Restore the original UI here. The App Router page should import this file, not replace it with a stub heading."
|
|
271
|
+
]
|
|
272
|
+
});
|
|
273
|
+
}
|
|
274
|
+
return issues;
|
|
275
|
+
}
|
|
276
|
+
function isStubAppRouterPage(content) {
|
|
277
|
+
const hasLocalImport = /from\s+['"](\.\.?\/|@\/)/.test(content);
|
|
278
|
+
const emptyish = /return\s*\(\s*<main\s*\/>\s*\)|return\s+null\s*;?|return\s*\(\s*<>\s*<\/>\s*\)|TODO:|could not be resolved/i.test(content);
|
|
279
|
+
const onlyLayoutShell = /<main\s*\/>/.test(content) && !hasLocalImport;
|
|
280
|
+
return !hasLocalImport || emptyish || onlyLayoutShell;
|
|
281
|
+
}
|
|
282
|
+
function analyzeReactToNextStructure(shadowRoot) {
|
|
283
|
+
const issues = [];
|
|
284
|
+
const pagesDir = path.join(shadowRoot, "src", "pages");
|
|
285
|
+
if (fs.existsSync(pagesDir)) {
|
|
286
|
+
for (const file of listFilesRecursive(pagesDir)) {
|
|
287
|
+
if (!isSpaPagesTreeFile(file)) continue;
|
|
288
|
+
issues.push({
|
|
289
|
+
filePath: file,
|
|
290
|
+
errors: [
|
|
291
|
+
"This UI still lives under src/pages. Next.js will treat it as a Pages Router route. Move it to a folder Next does not reserve, then import it from src/app/**/page.tsx for the old URL. Remove the src/pages copy."
|
|
292
|
+
]
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
const home = findAppRouterHome(shadowRoot);
|
|
297
|
+
if (!home) {
|
|
298
|
+
issues.push({
|
|
299
|
+
filePath: path.join(shadowRoot, "src", "app", "page.tsx"),
|
|
300
|
+
errors: [
|
|
301
|
+
'Missing App Router home (src/app/page.tsx). Create it so it imports and renders the screen the SPA showed at "/".'
|
|
302
|
+
]
|
|
303
|
+
});
|
|
304
|
+
return issues;
|
|
305
|
+
}
|
|
306
|
+
const homeContent = fs.readFileSync(home, "utf-8");
|
|
307
|
+
if (isStubAppRouterPage(homeContent)) {
|
|
308
|
+
issues.push({
|
|
309
|
+
filePath: home,
|
|
310
|
+
errors: [
|
|
311
|
+
"src/app/page.tsx does not render the application UI. Import the former home screen component (after moving any SPA UI out of src/pages if needed). Do not return an empty shell, null, a TODO, or a deleted App.tsx."
|
|
312
|
+
]
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
issues.push(...analyzeUnresolvedLocalImports(shadowRoot));
|
|
316
|
+
issues.push(...analyzeReactToNextComposition(shadowRoot));
|
|
317
|
+
issues.push(...analyzeCallbackPropMismatches(shadowRoot));
|
|
318
|
+
const pkgPath = path.join(shadowRoot, "package.json");
|
|
319
|
+
if (fs.existsSync(pkgPath)) {
|
|
320
|
+
try {
|
|
321
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
322
|
+
const viteScripts = Object.entries(pkg.scripts || {}).filter(([, cmd]) => /\bvite\b/.test(cmd));
|
|
323
|
+
if (viteScripts.length > 0) {
|
|
324
|
+
issues.push({
|
|
325
|
+
filePath: pkgPath,
|
|
326
|
+
errors: [
|
|
327
|
+
`package.json still runs Vite in scripts (${viteScripts.map(([name]) => name).join(", ")}). After moving to Next, drop leftover preview/vite scripts.`
|
|
328
|
+
]
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
} catch {
|
|
332
|
+
}
|
|
333
|
+
}
|
|
334
|
+
return issues;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
export {
|
|
338
|
+
findShadowRoot,
|
|
339
|
+
isFsdPageComponent,
|
|
340
|
+
isSpaRootComponent,
|
|
341
|
+
hasNextAppRoutes,
|
|
342
|
+
nextMigrationFileHint,
|
|
343
|
+
isSpaPagesTreeFile,
|
|
344
|
+
listAppRouterFiles,
|
|
345
|
+
isHollowView,
|
|
346
|
+
unresolvedLocalImports,
|
|
347
|
+
analyzeUnresolvedLocalImports,
|
|
348
|
+
analyzeCallbackPropMismatches,
|
|
349
|
+
analyzeReactToNextComposition,
|
|
350
|
+
isStubAppRouterPage,
|
|
351
|
+
analyzeReactToNextStructure
|
|
352
|
+
};
|
|
@@ -1,3 +1,41 @@
|
|
|
1
|
+
// ../domain/src/entities/PackageManagerCommands.ts
|
|
2
|
+
function resolvePackageManagerCommands(pm) {
|
|
3
|
+
switch (pm) {
|
|
4
|
+
case "pnpm":
|
|
5
|
+
return {
|
|
6
|
+
name: "pnpm",
|
|
7
|
+
install: "pnpm install",
|
|
8
|
+
cleanInstall: "pnpm install",
|
|
9
|
+
runBuild: "pnpm run build",
|
|
10
|
+
runDev: "pnpm dev"
|
|
11
|
+
};
|
|
12
|
+
case "yarn":
|
|
13
|
+
return {
|
|
14
|
+
name: "yarn",
|
|
15
|
+
install: "yarn install",
|
|
16
|
+
cleanInstall: "yarn install",
|
|
17
|
+
runBuild: "yarn build",
|
|
18
|
+
runDev: "yarn dev"
|
|
19
|
+
};
|
|
20
|
+
case "bun":
|
|
21
|
+
return {
|
|
22
|
+
name: "bun",
|
|
23
|
+
install: "bun install",
|
|
24
|
+
cleanInstall: "bun install",
|
|
25
|
+
runBuild: "bun run build",
|
|
26
|
+
runDev: "bun dev"
|
|
27
|
+
};
|
|
28
|
+
default:
|
|
29
|
+
return {
|
|
30
|
+
name: "npm",
|
|
31
|
+
install: "npm install",
|
|
32
|
+
cleanInstall: "npm install --no-fund --no-audit",
|
|
33
|
+
runBuild: "npm run build",
|
|
34
|
+
runDev: "npm run dev"
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
1
39
|
// ../domain/src/entities/catalogs/backendCatalog.ts
|
|
2
40
|
var backendCatalog = [
|
|
3
41
|
{
|
|
@@ -1235,6 +1273,7 @@ var SemanticEventName = /* @__PURE__ */ ((SemanticEventName2) => {
|
|
|
1235
1273
|
})(SemanticEventName || {});
|
|
1236
1274
|
|
|
1237
1275
|
export {
|
|
1276
|
+
resolvePackageManagerCommands,
|
|
1238
1277
|
FRAMEWORK_PACKS,
|
|
1239
1278
|
rulesForFramework,
|
|
1240
1279
|
packForFramework,
|