adminforth 2.25.0-test.2 → 2.25.0-test.20
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/commands/bundle.js +2 -1
- package/commands/createApp/templates/Dockerfile.hbs +12 -0
- package/commands/createApp/templates/package.json.hbs +12 -0
- package/commands/createApp/templates/pnpm_templates/pnpm-lock.yaml.hbs +8 -0
- package/commands/createApp/templates/readme.md.hbs +20 -1
- package/commands/createApp/utils.js +105 -29
- package/commands/createPlugin/utils.js +1 -1
- package/dist/modules/codeInjector.d.ts +2 -1
- package/dist/modules/codeInjector.d.ts.map +1 -1
- package/dist/modules/codeInjector.js +58 -24
- package/dist/modules/codeInjector.js.map +1 -1
- package/dist/spa/package-lock.json +5618 -0
- package/dist/spa/vite.config.ts +20 -40
- package/package.json +4 -3
- package/scripts/postinstall.js +25 -0
- /package/commands/createApp/templates/{pnpm-workspace.yaml.hbs → pnpm_templates/pnpm-workspace.yaml.hbs} +0 -0
package/commands/bundle.js
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
|
|
2
|
+
{{#unless useNpm}}
|
|
3
|
+
FROM devforth/node20-pnpm:latest
|
|
4
|
+
WORKDIR /code/
|
|
5
|
+
ADD package.json pnpm-lock.yaml pnpm-workspace.yaml /code/
|
|
6
|
+
RUN pnpm i
|
|
7
|
+
ADD . /code/
|
|
8
|
+
RUN pnpm exec adminforth bundle
|
|
9
|
+
CMD ["sh", "-c", "pnpm migrate:prod && pnpm prod"]
|
|
10
|
+
{{/unless}}
|
|
11
|
+
{{#if useNpm}}
|
|
1
12
|
FROM node:{{nodeMajor}}-slim
|
|
2
13
|
WORKDIR /code/
|
|
3
14
|
ADD package.json package-lock.json /code/
|
|
@@ -5,3 +16,4 @@ RUN npm ci
|
|
|
5
16
|
ADD . /code/
|
|
6
17
|
RUN npx adminforth bundle
|
|
7
18
|
CMD ["sh", "-c", "npm run migrate:prod && npm run prod"]
|
|
19
|
+
{{/if}}
|
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
"license": "ISC",
|
|
9
9
|
"description": "",
|
|
10
10
|
"scripts": {
|
|
11
|
+
{{#unless useNpm}}
|
|
11
12
|
"dev": "pnpm _env:dev tsx watch index.ts",
|
|
12
13
|
"prod": "pnpm _env:prod tsx index.ts",
|
|
13
14
|
"start": "pnpm dev",
|
|
@@ -16,6 +17,17 @@
|
|
|
16
17
|
"migrate:prod": "pnpm _env:prod npx --yes prisma migrate deploy",
|
|
17
18
|
"_env:dev": "dotenvx run -f .env -f .env.local --",
|
|
18
19
|
"_env:prod": "dotenvx run -f .env.prod --"
|
|
20
|
+
{{/unless}}
|
|
21
|
+
{{#if useNpm}}
|
|
22
|
+
"dev": "npm run _env:dev -- tsx watch index.ts",
|
|
23
|
+
"prod": "npm run _env:prod -- tsx index.ts",
|
|
24
|
+
"start": "npm run dev",
|
|
25
|
+
"makemigration": "npm run _env:dev -- npx --yes prisma migrate dev --create-only",
|
|
26
|
+
"migrate:local": "npm run _env:dev -- npx --yes prisma migrate deploy",
|
|
27
|
+
"migrate:prod": "npm run _env:prod -- npx --yes prisma migrate deploy",
|
|
28
|
+
"_env:dev": "dotenvx run -f .env -f .env.local --",
|
|
29
|
+
"_env:prod": "dotenvx run -f .env.prod --"
|
|
30
|
+
{{/if}}
|
|
19
31
|
},
|
|
20
32
|
"engines": {
|
|
21
33
|
"node": ">=20"
|
|
@@ -1,7 +1,25 @@
|
|
|
1
1
|
## Starting the application
|
|
2
2
|
|
|
3
3
|
Install dependencies:
|
|
4
|
+
{{#if useNpm}}
|
|
5
|
+
```bash
|
|
6
|
+
npm i
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Migrate the database:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
npm run migrate:local
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Start the server:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
npm run dev
|
|
19
|
+
```
|
|
20
|
+
{{/if}}
|
|
4
21
|
|
|
22
|
+
{{#unless useNpm}}
|
|
5
23
|
```bash
|
|
6
24
|
pnpm i
|
|
7
25
|
```
|
|
@@ -17,6 +35,7 @@ Start the server:
|
|
|
17
35
|
```bash
|
|
18
36
|
pnpm dev
|
|
19
37
|
```
|
|
38
|
+
{{/unless}}
|
|
20
39
|
|
|
21
40
|
{{#if prismaDbUrl}}
|
|
22
41
|
## Changing schema
|
|
@@ -26,7 +45,7 @@ Open `schema.prisma` and change schema as needed: add new tables, columns, etc (
|
|
|
26
45
|
Run the following command to generate a new migration and apply it instantly in local database:
|
|
27
46
|
|
|
28
47
|
```bash
|
|
29
|
-
pnpm makemigration --
|
|
48
|
+
pnpm makemigration --name <name_of_changes>
|
|
30
49
|
```
|
|
31
50
|
|
|
32
51
|
Your colleagues will need to pull the changes and run `pnpm migrate:local` to apply the migration in their local database.
|
|
@@ -44,6 +44,7 @@ export function parseArgumentsIntoOptions(rawArgs) {
|
|
|
44
44
|
{
|
|
45
45
|
'--app-name': String,
|
|
46
46
|
'--db': String,
|
|
47
|
+
'--use-npm': Boolean,
|
|
47
48
|
// you can add more flags here if needed
|
|
48
49
|
},
|
|
49
50
|
{
|
|
@@ -54,6 +55,7 @@ export function parseArgumentsIntoOptions(rawArgs) {
|
|
|
54
55
|
return {
|
|
55
56
|
appName: args['--app-name'],
|
|
56
57
|
db: args['--db'],
|
|
58
|
+
useNpm: args['--use-npm'],
|
|
57
59
|
};
|
|
58
60
|
}
|
|
59
61
|
|
|
@@ -78,11 +80,25 @@ export async function promptForMissingOptions(options) {
|
|
|
78
80
|
});
|
|
79
81
|
};
|
|
80
82
|
|
|
83
|
+
if (!options.useNpm) {
|
|
84
|
+
questions.push({
|
|
85
|
+
type: 'select',
|
|
86
|
+
name: 'useNpm',
|
|
87
|
+
message: 'Select your package manager >',
|
|
88
|
+
choices: [
|
|
89
|
+
{ name: 'pnpm', value: false },
|
|
90
|
+
{ name: 'npm', value: true },
|
|
91
|
+
],
|
|
92
|
+
default: false,
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
|
|
81
96
|
const answers = await inquirer.prompt(questions);
|
|
82
97
|
return {
|
|
83
98
|
...options,
|
|
84
99
|
appName: options.appName || answers.appName,
|
|
85
100
|
db: options.db || answers.db,
|
|
101
|
+
useNpm: options.useNpm || answers.useNpm,
|
|
86
102
|
};
|
|
87
103
|
}
|
|
88
104
|
|
|
@@ -230,7 +246,7 @@ async function scaffoldProject(ctx, options, cwd) {
|
|
|
230
246
|
await fse.copy(sourceAssetsDir, targetAssetsDir);
|
|
231
247
|
|
|
232
248
|
// Write templated files
|
|
233
|
-
await writeTemplateFiles(dirname, projectDir, {
|
|
249
|
+
await writeTemplateFiles(dirname, projectDir, options.useNpm, {
|
|
234
250
|
dbUrl: connectionString.toString(),
|
|
235
251
|
dbUrlProd: connectionStringProd,
|
|
236
252
|
prismaDbUrl,
|
|
@@ -244,7 +260,7 @@ async function scaffoldProject(ctx, options, cwd) {
|
|
|
244
260
|
return projectDir; // Return the new directory path
|
|
245
261
|
}
|
|
246
262
|
|
|
247
|
-
async function writeTemplateFiles(dirname, cwd, options) {
|
|
263
|
+
async function writeTemplateFiles(dirname, cwd, useNpm, options) {
|
|
248
264
|
const {
|
|
249
265
|
dbUrl, prismaDbUrl, appName, provider, nodeMajor,
|
|
250
266
|
dbUrlProd, prismaDbUrlProd, sqliteFile
|
|
@@ -268,14 +284,6 @@ async function writeTemplateFiles(dirname, cwd, options) {
|
|
|
268
284
|
dest: 'prisma.config.ts',
|
|
269
285
|
data: {},
|
|
270
286
|
},
|
|
271
|
-
{
|
|
272
|
-
src: 'package.json.hbs',
|
|
273
|
-
dest: 'package.json',
|
|
274
|
-
data: {
|
|
275
|
-
appName,
|
|
276
|
-
adminforthVersion: adminforthVersion,
|
|
277
|
-
},
|
|
278
|
-
},
|
|
279
287
|
{
|
|
280
288
|
src: 'index.ts.hbs',
|
|
281
289
|
dest: 'index.ts',
|
|
@@ -304,7 +312,7 @@ async function writeTemplateFiles(dirname, cwd, options) {
|
|
|
304
312
|
{
|
|
305
313
|
src: 'readme.md.hbs',
|
|
306
314
|
dest: 'README.md',
|
|
307
|
-
data: { dbUrl, prismaDbUrl, appName, sqliteFile },
|
|
315
|
+
data: { dbUrl, prismaDbUrl, appName, sqliteFile, useNpm },
|
|
308
316
|
},
|
|
309
317
|
{
|
|
310
318
|
// We'll write .env using the same content as .env.sample
|
|
@@ -317,21 +325,11 @@ async function writeTemplateFiles(dirname, cwd, options) {
|
|
|
317
325
|
dest: 'resources/adminuser.ts',
|
|
318
326
|
data: {},
|
|
319
327
|
},
|
|
320
|
-
{
|
|
321
|
-
src: 'custom/package.json.hbs',
|
|
322
|
-
dest: 'custom/package.json',
|
|
323
|
-
data: {},
|
|
324
|
-
},
|
|
325
328
|
{
|
|
326
329
|
src: 'custom/tsconfig.json.hbs',
|
|
327
330
|
dest: 'custom/tsconfig.json',
|
|
328
331
|
data: {},
|
|
329
332
|
},
|
|
330
|
-
{
|
|
331
|
-
src: 'Dockerfile.hbs',
|
|
332
|
-
dest: 'Dockerfile',
|
|
333
|
-
data: { nodeMajor },
|
|
334
|
-
},
|
|
335
333
|
{
|
|
336
334
|
src: '.dockerignore.hbs',
|
|
337
335
|
dest: '.dockerignore',
|
|
@@ -340,12 +338,41 @@ async function writeTemplateFiles(dirname, cwd, options) {
|
|
|
340
338
|
},
|
|
341
339
|
},
|
|
342
340
|
{
|
|
343
|
-
src: '
|
|
344
|
-
dest: '
|
|
345
|
-
data: {},
|
|
341
|
+
src: 'Dockerfile.hbs',
|
|
342
|
+
dest: 'Dockerfile',
|
|
343
|
+
data: { nodeMajor, useNpm },
|
|
344
|
+
},
|
|
345
|
+
{
|
|
346
|
+
src: 'package.json.hbs',
|
|
347
|
+
dest: 'package.json',
|
|
348
|
+
data: {
|
|
349
|
+
appName,
|
|
350
|
+
adminforthVersion: adminforthVersion,
|
|
351
|
+
useNpm
|
|
352
|
+
},
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
src: 'custom/package.json.hbs',
|
|
356
|
+
dest: 'custom/package.json',
|
|
357
|
+
data: {}
|
|
346
358
|
}
|
|
347
359
|
];
|
|
348
360
|
|
|
361
|
+
if (!useNpm) {
|
|
362
|
+
templateTasks.push(
|
|
363
|
+
{
|
|
364
|
+
src: 'pnpm_templates/pnpm-workspace.yaml.hbs',
|
|
365
|
+
dest: 'pnpm-workspace.yaml',
|
|
366
|
+
data: {},
|
|
367
|
+
},
|
|
368
|
+
{
|
|
369
|
+
src: 'pnpm_templates/pnpm-lock.yaml.hbs',
|
|
370
|
+
dest: 'custom/pnpm-lock.yaml',
|
|
371
|
+
data: {},
|
|
372
|
+
}
|
|
373
|
+
)
|
|
374
|
+
}
|
|
375
|
+
|
|
349
376
|
for (const task of templateTasks) {
|
|
350
377
|
// If a condition is specified and false, skip this file
|
|
351
378
|
if (task.condition === false) continue;
|
|
@@ -363,7 +390,7 @@ async function writeTemplateFiles(dirname, cwd, options) {
|
|
|
363
390
|
}
|
|
364
391
|
}
|
|
365
392
|
|
|
366
|
-
async function
|
|
393
|
+
async function installDependenciesPnpm(ctx, cwd) {
|
|
367
394
|
const isWindows = process.platform === 'win32';
|
|
368
395
|
|
|
369
396
|
const nodeBinary = process.execPath;
|
|
@@ -380,10 +407,28 @@ async function installDependencies(ctx, cwd) {
|
|
|
380
407
|
await execAsync(`${nodeBinary} ${npmPath} install`, { cwd: customDir, env: { PATH: process.env.PATH } }),
|
|
381
408
|
]);
|
|
382
409
|
}
|
|
383
|
-
// console.log(chalk.dim(`Dependencies installed in ${cwd} and ${customDir}: \n${res[0].stdout}${res[1].stdout}`));
|
|
384
410
|
}
|
|
385
411
|
|
|
386
|
-
function
|
|
412
|
+
async function installDependenciesNpm(ctx, cwd) {
|
|
413
|
+
const isWindows = process.platform === 'win32';
|
|
414
|
+
|
|
415
|
+
const nodeBinary = process.execPath;
|
|
416
|
+
const npmPath = path.join(path.dirname(nodeBinary), isWindows ? 'npm.cmd' : 'npm');
|
|
417
|
+
const customDir = ctx.customDir;
|
|
418
|
+
if (isWindows) {
|
|
419
|
+
const res = await Promise.all([
|
|
420
|
+
await execAsync(`npm install`, { cwd, env: { PATH: process.env.PATH } }),
|
|
421
|
+
await execAsync(`npm install`, { cwd: customDir, env: { PATH: process.env.PATH } }),
|
|
422
|
+
]);
|
|
423
|
+
} else {
|
|
424
|
+
const res = await Promise.all([
|
|
425
|
+
await execAsync(`${nodeBinary} ${npmPath} install`, { cwd, env: { PATH: process.env.PATH } }),
|
|
426
|
+
await execAsync(`${nodeBinary} ${npmPath} install`, { cwd: customDir, env: { PATH: process.env.PATH } }),
|
|
427
|
+
]);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
|
|
431
|
+
function generateFinalInstructionsPnpm(skipPrismaSetup, options) {
|
|
387
432
|
let instruction = '⏭️ Run the following commands to get started:\n';
|
|
388
433
|
if (!skipPrismaSetup)
|
|
389
434
|
instruction += `
|
|
@@ -404,6 +449,27 @@ function generateFinalInstructions(skipPrismaSetup, options) {
|
|
|
404
449
|
return instruction;
|
|
405
450
|
}
|
|
406
451
|
|
|
452
|
+
function generateFinalInstructionsNpm(skipPrismaSetup, options) {
|
|
453
|
+
let instruction = '⏭️ Run the following commands to get started:\n';
|
|
454
|
+
if (!skipPrismaSetup)
|
|
455
|
+
instruction += `
|
|
456
|
+
${chalk.dim('// Go to the project directory')}
|
|
457
|
+
${chalk.dim('$')}${chalk.cyan(` cd ${options.appName}`)}\n`;
|
|
458
|
+
|
|
459
|
+
instruction += `
|
|
460
|
+
${chalk.dim('// Generate and apply initial migration')}
|
|
461
|
+
${chalk.dim('$')}${chalk.cyan(' npm run makemigration -- --name init && npm run migrate:local')}\n`;
|
|
462
|
+
|
|
463
|
+
instruction += `
|
|
464
|
+
${chalk.dim('// Start dev server with tsx watch for hot-reloading')}
|
|
465
|
+
${chalk.dim('$')}${chalk.cyan(' npm run dev')}\n
|
|
466
|
+
`;
|
|
467
|
+
|
|
468
|
+
instruction += '😉 Happy coding!';
|
|
469
|
+
|
|
470
|
+
return instruction;
|
|
471
|
+
}
|
|
472
|
+
|
|
407
473
|
function renderHBSTemplate(templatePath, data) {
|
|
408
474
|
// Example: renderHBRTemplate('path/to/template.hbs', {name: 'John Doe'})
|
|
409
475
|
const template = fs.readFileSync(templatePath, 'utf-8');
|
|
@@ -430,13 +496,23 @@ export function prepareWorkflow(options) {
|
|
|
430
496
|
},
|
|
431
497
|
{
|
|
432
498
|
title: '📦 Installing dependencies...',
|
|
433
|
-
task: async (ctx) =>
|
|
499
|
+
task: async (ctx) => {
|
|
500
|
+
if (options.useNpm) {
|
|
501
|
+
await installDependenciesNpm(ctx, ctx.projectDir);
|
|
502
|
+
} else {
|
|
503
|
+
await installDependenciesPnpm(ctx, ctx.projectDir);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
434
506
|
},
|
|
435
507
|
{
|
|
436
508
|
title: '📝 Preparing final instructions...',
|
|
437
509
|
task: (ctx) => {
|
|
438
510
|
console.log(chalk.green(`✅ Successfully created your new Adminforth project in ${ctx.projectDir}!\n`));
|
|
439
|
-
|
|
511
|
+
if (options.useNpm) {
|
|
512
|
+
console.log(generateFinalInstructionsNpm(ctx.skipPrismaSetup, options));
|
|
513
|
+
} else {
|
|
514
|
+
console.log(generateFinalInstructionsPnpm(ctx.skipPrismaSetup, options));
|
|
515
|
+
}
|
|
440
516
|
console.log('\n\n');
|
|
441
517
|
}
|
|
442
518
|
}
|
|
@@ -158,7 +158,7 @@ async function installDependencies(ctx, cwd) {
|
|
|
158
158
|
const customDir = ctx.customDir;
|
|
159
159
|
|
|
160
160
|
await Promise.all([
|
|
161
|
-
await execa("pnpm", ["install"
|
|
161
|
+
await execa("pnpm", ["install"], { cwd }),
|
|
162
162
|
await execa("pnpm", ["install"], { cwd: customDir }),
|
|
163
163
|
]);
|
|
164
164
|
}
|
|
@@ -15,7 +15,8 @@ declare class CodeInjector implements ICodeInjector {
|
|
|
15
15
|
registerCustomComponent(filePath: string): void;
|
|
16
16
|
cleanup(): void;
|
|
17
17
|
constructor(adminforth: any);
|
|
18
|
-
|
|
18
|
+
doesUserHasPnpmLockFile(dir: string): Promise<boolean>;
|
|
19
|
+
runPackageManagerShell({ command, cwd, envOverrides }: {
|
|
19
20
|
command: string;
|
|
20
21
|
cwd: string;
|
|
21
22
|
envOverrides?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codeInjector.d.ts","sourceRoot":"","sources":["../../modules/codeInjector.ts"],"names":[],"mappings":"AAQA,OAAO,UAAwC,MAAM,aAAa,CAAC;AAEnE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAmEjD,cAAM,YAAa,YAAW,aAAa;IAEzC,WAAW,QAAM;IACjB,UAAU,EAAE,UAAU,CAAC;IACvB,iBAAiB,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAM;IAClD,gBAAgB,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAM;IACjD,aAAa,EAAE,MAAM,CAAQ;IAE7B,UAAU,IAAI,MAAM;IAQd,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE;IA8BpC,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAK/C,OAAO;gBAMK,UAAU,KAAA;
|
|
1
|
+
{"version":3,"file":"codeInjector.d.ts","sourceRoot":"","sources":["../../modules/codeInjector.ts"],"names":[],"mappings":"AAQA,OAAO,UAAwC,MAAM,aAAa,CAAC;AAEnE,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AAmEjD,cAAM,YAAa,YAAW,aAAa;IAEzC,WAAW,QAAM;IACjB,UAAU,EAAE,UAAU,CAAC;IACvB,iBAAiB,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAM;IAClD,gBAAgB,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;KAAE,CAAM;IACjD,aAAa,EAAE,MAAM,CAAQ;IAE7B,UAAU,IAAI,MAAM;IAQd,cAAc,CAAC,KAAK,EAAE,MAAM,EAAE;IA8BpC,uBAAuB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI;IAK/C,OAAO;gBAMK,UAAU,KAAA;IAYhB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAqBtD,sBAAsB,CAAC,EAAC,OAAO,EAAE,GAAG,EAAE,YAAiB,EAAC,EAAE;QAC9D,OAAO,EAAE,MAAM,CAAC;QAChB,GAAG,EAAE,MAAM,CAAC;QACZ,YAAY,CAAC,EAAE;YAAE,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAAA;SAAE,CAAA;KACzC;IAuDK,QAAQ;IAUd,WAAW;IAIL,gBAAgB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAAC;IAgFhE,SAAS;IAQH,cAAc,CAAC,EAAE,YAAY,EAAE,EAAE;QAAE,YAAY,EAAE,MAAM,EAAE,CAAA;KAAE;IAgB3D,yBAAyB,CAAC,OAAO,KAAA;IAMjC,cAAc;IA8cd,iBAAiB,CAAC,EAAE,IAAA;IA4CpB,4BAA4B,CAAC,EAAE,mBAAmB,EAAE,WAAW,EAAE;;;KAAA;IAwEjE,WAAW,CAAC,QAAQ,EAAE,MAAM;IAW5B,kBAAkB,CAAC,UAAU,GAAE,MAA0B,EAAE,QAAQ,GAAE,MAAM,EAAO;IAyBlF,SAAS,CAAC,EAAE,SAAiB,EAAE,EAAE;QAAE,SAAS,EAAE,OAAO,CAAA;KAAE;CA2H9D;AAED,eAAe,YAAY,CAAC"}
|
|
@@ -77,7 +77,7 @@ class CodeInjector {
|
|
|
77
77
|
const uniqueIcons = Array.from(new Set(icons));
|
|
78
78
|
const collections = new Set(icons.map((icon) => icon.split(':')[0]));
|
|
79
79
|
const iconPackageNames = Array.from(collections).map((collection) => `@iconify-prerendered/vue-${collection}`);
|
|
80
|
-
const iconPackages = (await Promise.allSettled(iconPackageNames.map(async (pkg) => ({ pkg: await import(this.spaTmpPath()
|
|
80
|
+
const iconPackages = (await Promise.allSettled(iconPackageNames.map(async (pkg) => ({ pkg: await import(path.join(this.spaTmpPath(), 'node_modules', pkg)), name: pkg }))));
|
|
81
81
|
const loadedIconPackages = iconPackages.filter(isFulfilled).map((res) => res.value).reduce((acc, { pkg, name }) => {
|
|
82
82
|
acc[name.slice(`@iconify-prerendered/vue-`.length)] = pkg;
|
|
83
83
|
return acc;
|
|
@@ -117,25 +117,56 @@ class CodeInjector {
|
|
|
117
117
|
process.exit();
|
|
118
118
|
}));
|
|
119
119
|
}
|
|
120
|
-
async
|
|
120
|
+
async doesUserHasPnpmLockFile(dir) {
|
|
121
|
+
const usersPackagePath = path.join(dir, 'package.json');
|
|
122
|
+
let packageContent = null;
|
|
123
|
+
try {
|
|
124
|
+
packageContent = JSON.parse(await fs.promises.readFile(usersPackagePath, 'utf-8'));
|
|
125
|
+
}
|
|
126
|
+
catch (e) {
|
|
127
|
+
// user package.json does not exist, user does not have custom components
|
|
128
|
+
}
|
|
129
|
+
if (packageContent) {
|
|
130
|
+
const lockPath = path.join(dir, 'pnpm-lock.yaml');
|
|
131
|
+
let lock = null;
|
|
132
|
+
try {
|
|
133
|
+
lock = yaml.parse(await fs.promises.readFile(lockPath, 'utf-8'));
|
|
134
|
+
return true;
|
|
135
|
+
}
|
|
136
|
+
catch (e) {
|
|
137
|
+
return false;
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
return false;
|
|
141
|
+
}
|
|
142
|
+
async runPackageManagerShell({ command, cwd, envOverrides = {} }) {
|
|
121
143
|
const nodeBinary = process.execPath; // Path to the Node.js binary running this script
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
144
|
+
const doesUserHavePnpmLock = await this.doesUserHasPnpmLockFile(this.adminforth.config.customization.customComponentsDir);
|
|
145
|
+
// On Windows, npm/pnpm is npm/pnpm.cmd, on Unix systems it's npm/pnpm
|
|
146
|
+
let packageExecutable;
|
|
147
|
+
if (doesUserHavePnpmLock) {
|
|
148
|
+
afLogger.trace(`User has pnpm-lock.yaml, using pnpm for installing custom components`);
|
|
149
|
+
packageExecutable = process.platform === 'win32' ? 'pnpm.cmd' : 'pnpm';
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
afLogger.trace(`User does not have pnpm-lock.yaml, falling back to npm for installing custom components`);
|
|
153
|
+
packageExecutable = process.platform === 'win32' ? 'npm.cmd' : 'npm';
|
|
154
|
+
}
|
|
155
|
+
const packagePath = path.join(path.dirname(nodeBinary), packageExecutable); // Path to the package executable
|
|
125
156
|
const env = Object.assign(Object.assign({ VITE_ADMINFORTH_PUBLIC_PATH: this.adminforth.config.baseUrl, FORCE_COLOR: '1' }, process.env), envOverrides);
|
|
126
|
-
afLogger.trace(`⚙️ exec:
|
|
127
|
-
afLogger.trace(`🪲
|
|
157
|
+
afLogger.trace(`⚙️ exec: ${packageExecutable} ${command}`);
|
|
158
|
+
afLogger.trace(`🪲 ${packageExecutable} ${command} cwd: ${cwd}`);
|
|
128
159
|
let execCommand;
|
|
129
160
|
if (process.platform === 'win32') {
|
|
130
161
|
// Quote path if it contains spaces
|
|
131
|
-
const
|
|
132
|
-
execCommand = `${
|
|
162
|
+
const quotedPackagePath = packagePath.includes(' ') ? `"${packagePath}"` : packagePath;
|
|
163
|
+
execCommand = `${quotedPackagePath} ${command}`;
|
|
133
164
|
}
|
|
134
165
|
else {
|
|
135
166
|
// Quote paths that contain spaces (for Unix systems)
|
|
136
167
|
const quotedNodeBinary = nodeBinary.includes(' ') ? `"${nodeBinary}"` : nodeBinary;
|
|
137
|
-
const
|
|
138
|
-
execCommand = `${quotedNodeBinary} ${
|
|
168
|
+
const quotedPackagePath = packagePath.includes(' ') ? `"${packagePath}"` : packagePath;
|
|
169
|
+
execCommand = `${quotedNodeBinary} ${quotedPackagePath} ${command}`;
|
|
139
170
|
}
|
|
140
171
|
const execOptions = {
|
|
141
172
|
cwd,
|
|
@@ -145,9 +176,9 @@ class CodeInjector {
|
|
|
145
176
|
execOptions.shell = true;
|
|
146
177
|
}
|
|
147
178
|
const { stderr: err } = await execAsync(execCommand, execOptions);
|
|
148
|
-
afLogger.trace(
|
|
179
|
+
afLogger.trace(`${packageExecutable} ${command} done in`);
|
|
149
180
|
if (err) {
|
|
150
|
-
afLogger.trace(
|
|
181
|
+
afLogger.trace(`🪲${packageExecutable} ${command} errors/warnings: ${err}`);
|
|
151
182
|
}
|
|
152
183
|
}
|
|
153
184
|
async rmTmpDir() {
|
|
@@ -187,7 +218,7 @@ class CodeInjector {
|
|
|
187
218
|
npmLock = JSON.parse(await fs.promises.readFile(npmLockPath, 'utf-8'));
|
|
188
219
|
}
|
|
189
220
|
catch (npmLockError) {
|
|
190
|
-
throw new Error(`Custom pnpm-lock.yaml does not exist in ${dir}, but package.json does.
|
|
221
|
+
throw new Error(`Custom pnpm-lock.yaml or package-lock.json does not exist in ${dir}, but package.json does.
|
|
191
222
|
We can't determine version of packages without pnpm-lock.yaml or package-lock.json. Please run pnpm install or npm install in ${dir}`);
|
|
192
223
|
}
|
|
193
224
|
lockHash = hashify(npmLock);
|
|
@@ -583,6 +614,7 @@ class CodeInjector {
|
|
|
583
614
|
routerVueContent = routerVueContent.replace('/* IMPORTANT:ADMINFORTH ROUTES */', routes);
|
|
584
615
|
await fs.promises.writeFile(routerVuePath, routerVueContent);
|
|
585
616
|
/* hash checking */
|
|
617
|
+
// Here we use pnpm-lock.yaml, because this file will be anywat, even if user doesn't use it
|
|
586
618
|
const spaPnpmLockPath = path.join(this.spaTmpPath(), 'pnpm-lock.yaml');
|
|
587
619
|
const spaPnpmLock = yaml.parse(await fs.promises.readFile(spaPnpmLockPath, 'utf-8'));
|
|
588
620
|
const spaLockHash = hashify(spaPnpmLock);
|
|
@@ -625,7 +657,8 @@ class CodeInjector {
|
|
|
625
657
|
// ignore
|
|
626
658
|
afLogger.trace(`🪲Hash file does not exist, proceeding with pnpm install, ${e}`);
|
|
627
659
|
}
|
|
628
|
-
|
|
660
|
+
// install --frozen-lockfile works for npm and pnpm
|
|
661
|
+
await this.runPackageManagerShell({ command: 'install --frozen-lockfile', cwd: this.spaTmpPath(), envOverrides: {
|
|
629
662
|
NODE_ENV: 'development' // otherwise it will not install devDependencies which we still need, e.g for extract
|
|
630
663
|
} });
|
|
631
664
|
const allPacks = [
|
|
@@ -642,9 +675,9 @@ class CodeInjector {
|
|
|
642
675
|
});
|
|
643
676
|
const allPacksUnique = Array.from(new Set(allPacksFiltered));
|
|
644
677
|
if (allPacks.length) {
|
|
645
|
-
const
|
|
646
|
-
await this.
|
|
647
|
-
command:
|
|
678
|
+
const packageManagerInstallCommand = `install ${allPacksUnique.join(' ')}`;
|
|
679
|
+
await this.runPackageManagerShell({
|
|
680
|
+
command: packageManagerInstallCommand, cwd: this.spaTmpPath(),
|
|
648
681
|
envOverrides: {
|
|
649
682
|
NODE_ENV: 'development' // otherwise it will not install devDependencies which we still need, e.g for extract
|
|
650
683
|
}
|
|
@@ -818,7 +851,7 @@ class CodeInjector {
|
|
|
818
851
|
await fs.promises.mkdir(serveDir, { recursive: true });
|
|
819
852
|
}
|
|
820
853
|
if (!skipExtract) {
|
|
821
|
-
await this.
|
|
854
|
+
await this.runPackageManagerShell({ command: 'run i18n:extract', cwd });
|
|
822
855
|
// create serveDir if not exists
|
|
823
856
|
await fs.promises.mkdir(serveDir, { recursive: true });
|
|
824
857
|
// copy i18n messages to serve dir
|
|
@@ -832,7 +865,7 @@ class CodeInjector {
|
|
|
832
865
|
if (!hotReload) {
|
|
833
866
|
if (!skipBuild) {
|
|
834
867
|
// TODO probably add option to build with tsh check (plain 'build')
|
|
835
|
-
await this.
|
|
868
|
+
await this.runPackageManagerShell({ command: 'run build-only', cwd });
|
|
836
869
|
// coy dist to serveDir
|
|
837
870
|
await fsExtra.copy(path.join(cwd, 'dist'), serveDir, { recursive: true });
|
|
838
871
|
// save hash
|
|
@@ -844,19 +877,20 @@ class CodeInjector {
|
|
|
844
877
|
}
|
|
845
878
|
else {
|
|
846
879
|
const command = 'run dev';
|
|
847
|
-
|
|
880
|
+
const usersPackageManager = await this.doesUserHasPnpmLockFile(this.adminforth.config.customization.customComponentsDir) ? 'pnpm' : 'npm';
|
|
881
|
+
afLogger.info(`⚙️ spawn: ${usersPackageManager} ${command}...`);
|
|
848
882
|
if (process.env.VITE_ADMINFORTH_PUBLIC_PATH) {
|
|
849
883
|
afLogger.info(`⚠️ Your VITE_ADMINFORTH_PUBLIC_PATH: ${process.env.VITE_ADMINFORTH_PUBLIC_PATH} has no effect`);
|
|
850
884
|
}
|
|
851
885
|
const env = Object.assign({ VITE_ADMINFORTH_PUBLIC_PATH: this.adminforth.config.baseUrl, FORCE_COLOR: '1' }, process.env);
|
|
852
886
|
const nodeBinary = process.execPath;
|
|
853
|
-
const
|
|
887
|
+
const packageManagerPath = path.join(path.dirname(nodeBinary), usersPackageManager);
|
|
854
888
|
let devServer;
|
|
855
889
|
if (process.platform === 'win32') {
|
|
856
|
-
devServer = spawn(
|
|
890
|
+
devServer = spawn(usersPackageManager, command.split(' '), { cwd, env, shell: true });
|
|
857
891
|
}
|
|
858
892
|
else {
|
|
859
|
-
devServer = spawn(`${nodeBinary}`, [`${
|
|
893
|
+
devServer = spawn(`${nodeBinary}`, [`${packageManagerPath}`, ...command.split(' ')], { cwd, env });
|
|
860
894
|
}
|
|
861
895
|
devServer.stdout.on('data', (data) => {
|
|
862
896
|
if (data.includes('➜')) {
|