adminforth 1.2.10 → 1.2.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -104,8 +104,8 @@ class AdminForth {
104
104
  });
105
105
  }
106
106
  bundleNow(_b) {
107
- return __awaiter(this, arguments, void 0, function* ({ hotReload = false, verbose = false }) {
108
- yield this.codeInjector.bundleNow({ hotReload, verbose });
107
+ return __awaiter(this, arguments, void 0, function* ({ hotReload = false }) {
108
+ yield this.codeInjector.bundleNow({ hotReload });
109
109
  });
110
110
  }
111
111
  getUserByPk(pk) {
@@ -51,7 +51,7 @@ class CodeInjector {
51
51
  process.exit();
52
52
  }));
53
53
  }
54
- // async runShell({command, verbose = false}) {
54
+ // async runShell({ command }) {
55
55
  // console.log(`⚙️ Running shell ${command}...`);
56
56
  // console.time(`${command} done in`);
57
57
  // const { stdout: out, stderr: err } = await execAsync(command);
@@ -59,22 +59,20 @@ class CodeInjector {
59
59
  // console.log(`Command ${command} output:`, out, err);
60
60
  // }
61
61
  runNpmShell(_a) {
62
- return __awaiter(this, arguments, void 0, function* ({ command, verbose = false, cwd }) {
62
+ return __awaiter(this, arguments, void 0, function* ({ command, cwd }) {
63
63
  const nodeBinary = process.execPath; // Path to the Node.js binary running this script
64
64
  const npmPath = path.join(path.dirname(nodeBinary), 'npm'); // Path to the npm executable
65
65
  const env = Object.assign({ VITE_ADMINFORTH_PUBLIC_PATH: this.adminforth.config.baseUrl, FORCE_COLOR: '1' }, process.env);
66
- console.log(`⚙️ Running npm ${command}...`);
66
+ console.log(`⚙️ exec: npm ${command}...`);
67
67
  console.time(`npm ${command} done in`);
68
68
  const { stdout: out, stderr: err } = yield execAsync(`${nodeBinary} ${npmPath} ${command}`, {
69
69
  cwd,
70
70
  env,
71
71
  });
72
72
  console.timeEnd(`npm ${command} done in`);
73
- if (verbose) {
74
- console.log(`npm ${command} output:`, out);
75
- }
73
+ process.env.HEAVY_DEBUG && console.log(`🪲 npm ${command} output:`, out);
76
74
  if (err) {
77
- console.error(`npm ${command} errors/warnings:`, err);
75
+ process.env.HEAVY_DEBUG && console.error(`🪲npm ${command} errors/warnings:`, err);
78
76
  }
79
77
  });
80
78
  }
@@ -90,7 +88,7 @@ class CodeInjector {
90
88
  });
91
89
  }
92
90
  prepareSources(_a) {
93
- return __awaiter(this, arguments, void 0, function* ({ filesUpdated, verbose = false }) {
91
+ return __awaiter(this, arguments, void 0, function* ({ filesUpdated }) {
94
92
  var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
95
93
  // check SPA_TMP_PATH exists and create if not
96
94
  try {
@@ -361,9 +359,9 @@ class CodeInjector {
361
359
  /* customPackageLock */
362
360
  let usersLockHash = '';
363
361
  let usersLock = null;
362
+ let usersPackage = null;
364
363
  if ((_m = this.adminforth.config.customization) === null || _m === void 0 ? void 0 : _m.customComponentsDir) {
365
364
  const usersPackagePath = path.join(this.adminforth.config.customization.customComponentsDir, 'package.json');
366
- let usersPackage = null;
367
365
  try {
368
366
  usersPackage = JSON.parse(yield fs.promises.readFile(usersPackagePath, 'utf-8'));
369
367
  }
@@ -381,49 +379,45 @@ class CodeInjector {
381
379
  }
382
380
  usersLockHash = hashify(usersLock);
383
381
  }
384
- const iconPackagesNamesHash = hashify(iconPackageNames);
385
- const fullHash = `${spaLockHash}::${iconPackagesNamesHash}::${usersLockHash}`;
386
- const hashPath = path.join(CodeInjector.SPA_TMP_PATH, 'node_modules', '.adminforth_hash');
387
- try {
388
- const existingHash = yield fs.promises.readFile(hashPath, 'utf-8');
389
- if (existingHash === fullHash) {
390
- console.log('Hashes match, skipping npm ci/install');
391
- return;
392
- }
393
- else {
394
- if (verbose) {
395
- console.log(`Hashes do not match: existing ${existingHash} new ${fullHash}, proceeding with npm ci/install`);
396
- }
397
- }
398
- }
399
- catch (e) {
400
- // ignore
401
- if (verbose) {
402
- console.log('Hash file does not exist, proceeding with npm ci/install');
403
- }
404
- }
405
- yield this.runNpmShell({ command: 'ci', verbose, cwd: CodeInjector.SPA_TMP_PATH });
406
- let customPackgeNames = [];
407
- if (usersPackage && usersLock) {
408
- customPackgeNames = [
409
- ...Object.keys(usersPackage.dependencies || []),
410
- ...Object.keys(usersPackage.devDependencies || [])
411
- ].reduce((acc, packageName) => {
412
- const version = usersLock.packages[`node_modules/${packageName}`].version;
413
- acc.push(`${packageName}@${version}`);
414
- return acc;
415
- }, []);
382
+ }
383
+ const iconPackagesNamesHash = hashify(iconPackageNames);
384
+ const fullHash = `${spaLockHash}::${iconPackagesNamesHash}::${usersLockHash}`;
385
+ const hashPath = path.join(CodeInjector.SPA_TMP_PATH, 'node_modules', '.adminforth_hash');
386
+ try {
387
+ const existingHash = yield fs.promises.readFile(hashPath, 'utf-8');
388
+ if (existingHash === fullHash) {
389
+ process.env.HEAVY_DEBUG && console.log(`🪲Hashes match, skipping npm ci/install, from file: ${existingHash}, actual: ${fullHash}`);
390
+ return;
416
391
  }
417
- if (iconPackageNames.length) {
418
- const npmInstallCommand = `install ${[...iconPackageNames, ...customPackgeNames].join(' ')}`;
419
- yield this.runNpmShell({ command: npmInstallCommand, cwd: CodeInjector.SPA_TMP_PATH });
392
+ else {
393
+ process.env.HEAVY_DEBUG && console.log(`🪲 Hashes do not match: from file: ${existingHash} actual: ${fullHash}, proceeding with npm ci/install`);
420
394
  }
421
- yield fs.promises.writeFile(hashPath, fullHash);
422
395
  }
396
+ catch (e) {
397
+ // ignore
398
+ process.env.HEAVY_DEBUG && console.log('🪲Hash file does not exist, proceeding with npm ci/install');
399
+ }
400
+ yield this.runNpmShell({ command: 'ci', cwd: CodeInjector.SPA_TMP_PATH });
401
+ let customPackgeNames = [];
402
+ if (usersPackage && usersLock) {
403
+ customPackgeNames = [
404
+ ...Object.keys(usersPackage.dependencies || []),
405
+ ...Object.keys(usersPackage.devDependencies || [])
406
+ ].reduce((acc, packageName) => {
407
+ const version = usersLock.packages[`node_modules/${packageName}`].version;
408
+ acc.push(`${packageName}@${version}`);
409
+ return acc;
410
+ }, []);
411
+ }
412
+ if (iconPackageNames.length) {
413
+ const npmInstallCommand = `install ${[...iconPackageNames, ...customPackgeNames].join(' ')}`;
414
+ yield this.runNpmShell({ command: npmInstallCommand, cwd: CodeInjector.SPA_TMP_PATH });
415
+ }
416
+ yield fs.promises.writeFile(hashPath, fullHash);
423
417
  });
424
418
  }
425
419
  watchForReprepare(_a) {
426
- return __awaiter(this, arguments, void 0, function* ({ verbose }) {
420
+ return __awaiter(this, arguments, void 0, function* ({}) {
427
421
  const spaPath = path.join(ADMIN_FORTH_ABSOLUTE_PATH, 'spa');
428
422
  // get list of all subdirectories in spa recursively
429
423
  const directories = [];
@@ -456,7 +450,7 @@ class CodeInjector {
456
450
  });
457
451
  }
458
452
  watchCustomComponentsForCopy(_a) {
459
- return __awaiter(this, arguments, void 0, function* ({ verbose, customComponentsDir, destination }) {
453
+ return __awaiter(this, arguments, void 0, function* ({ customComponentsDir, destination }) {
460
454
  if (!customComponentsDir) {
461
455
  return;
462
456
  }
@@ -465,9 +459,7 @@ class CodeInjector {
465
459
  yield fs.promises.access(customComponentsDir, fs.constants.F_OK);
466
460
  }
467
461
  catch (e) {
468
- if (verbose) {
469
- console.log(`Custom components dir ${customComponentsDir} does not exist, skipping watching`);
470
- }
462
+ process.env.HEAVY_DEBUG && console.log(`🪲Custom components dir ${customComponentsDir} does not exist, skipping watching`);
471
463
  return;
472
464
  }
473
465
  // get all subdirs
@@ -520,16 +512,15 @@ class CodeInjector {
520
512
  });
521
513
  }
522
514
  bundleNow(_a) {
523
- return __awaiter(this, arguments, void 0, function* ({ hotReload = false, verbose = false }) {
515
+ return __awaiter(this, arguments, void 0, function* ({ hotReload = false }) {
524
516
  console.log(`AdminForth bundling ${hotReload ? ' and listening for changes (🔥 Hotreload)' : ' (no hot reload)'}`);
525
517
  this.adminforth.runningHotReload = hotReload;
526
- yield this.prepareSources({ verbose });
518
+ yield this.prepareSources({});
527
519
  if (hotReload) {
528
520
  yield Promise.all([
529
- this.watchForReprepare({ verbose }),
521
+ this.watchForReprepare({}),
530
522
  ...Object.entries(this.srcFoldersToSync).map((_b) => __awaiter(this, [_b], void 0, function* ([src, dest]) {
531
523
  yield this.watchCustomComponentsForCopy({
532
- verbose,
533
524
  customComponentsDir: src,
534
525
  destination: dest,
535
526
  });
@@ -540,11 +531,11 @@ class CodeInjector {
540
531
  const cwd = CodeInjector.SPA_TMP_PATH;
541
532
  if (!hotReload) {
542
533
  // probably add option to build with tsh check (plain 'build')
543
- yield this.runNpmShell({ command: 'run build-only', verbose, cwd });
534
+ yield this.runNpmShell({ command: 'run build-only', cwd });
544
535
  }
545
536
  else {
546
537
  const command = 'run dev';
547
- console.log(`⚙️ Running npm ${command}...`);
538
+ console.log(`⚙️ spawn: npm ${command}...`);
548
539
  const nodeBinary = process.execPath;
549
540
  const npmPath = path.join(path.dirname(nodeBinary), 'npm');
550
541
  const env = Object.assign({ VITE_ADMINFORTH_PUBLIC_PATH: this.adminforth.config.baseUrl, FORCE_COLOR: '1' }, process.env);
@@ -339,15 +339,6 @@ export default class AdminForthRestAPI {
339
339
  item[col.name] = targetDataMap[item[col.name]];
340
340
  });
341
341
  })));
342
- for (const hook of listify((_t = (_s = resource.hooks) === null || _s === void 0 ? void 0 : _s[source]) === null || _t === void 0 ? void 0 : _t.afterDatasourceResponse)) {
343
- const resp = yield hook({ resource, response: data.data, adminUser });
344
- if (!resp || (!resp.ok && !resp.error)) {
345
- throw new Error(`Hook must return object with {ok: true} or { error: 'Error' } `);
346
- }
347
- if (resp.error) {
348
- return { error: resp.error };
349
- }
350
- }
351
342
  // remove all columns which are not defined in resources, or defined but backendOnly
352
343
  data.data.forEach((item) => {
353
344
  Object.keys(item).forEach((key) => {
@@ -359,6 +350,16 @@ export default class AdminForthRestAPI {
359
350
  data.data.forEach((item) => {
360
351
  item._label = resource.recordLabel(item);
361
352
  });
353
+ // only after adminforth made all post processing, give user ability to edit it
354
+ for (const hook of listify((_t = (_s = resource.hooks) === null || _s === void 0 ? void 0 : _s[source]) === null || _t === void 0 ? void 0 : _t.afterDatasourceResponse)) {
355
+ const resp = yield hook({ resource, response: data.data, adminUser });
356
+ if (!resp || (!resp.ok && !resp.error)) {
357
+ throw new Error(`Hook must return object with {ok: true} or { error: 'Error' } `);
358
+ }
359
+ if (resp.error) {
360
+ return { error: resp.error };
361
+ }
362
+ }
362
363
  return Object.assign(Object.assign({}, data), { options: resource === null || resource === void 0 ? void 0 : resource.options });
363
364
  }),
364
365
  });
@@ -28,8 +28,7 @@ export const useUserStore = defineStore('user', () => {
28
28
  await router.isReady();
29
29
  await coreStore.fetchMenuAndResource();
30
30
  setTimeout(() => {
31
- initFlowbite();
32
-
31
+ initFlowbite();
33
32
  });
34
33
  }
35
34
 
package/index.ts CHANGED
@@ -138,8 +138,8 @@ class AdminForth implements IAdminForth {
138
138
  // console.log('⚙️⚙️⚙️ Database discovery done', JSON.stringify(this.config.resources, null, 2));
139
139
  }
140
140
 
141
- async bundleNow({ hotReload=false, verbose=false }) {
142
- await this.codeInjector.bundleNow({ hotReload, verbose });
141
+ async bundleNow({ hotReload=false }) {
142
+ await this.codeInjector.bundleNow({ hotReload });
143
143
  }
144
144
 
145
145
  async getUserByPk(pk: string) {
@@ -62,7 +62,7 @@ class CodeInjector implements ICodeInjector {
62
62
 
63
63
  }
64
64
 
65
- // async runShell({command, verbose = false}) {
65
+ // async runShell({ command }) {
66
66
  // console.log(`⚙️ Running shell ${command}...`);
67
67
  // console.time(`${command} done in`);
68
68
  // const { stdout: out, stderr: err } = await execAsync(command);
@@ -70,7 +70,7 @@ class CodeInjector implements ICodeInjector {
70
70
  // console.log(`Command ${command} output:`, out, err);
71
71
  // }
72
72
 
73
- async runNpmShell({command, verbose = false, cwd}) {
73
+ async runNpmShell({command, cwd}) {
74
74
  const nodeBinary = process.execPath; // Path to the Node.js binary running this script
75
75
  const npmPath = path.join(path.dirname(nodeBinary), 'npm'); // Path to the npm executable
76
76
 
@@ -80,7 +80,7 @@ class CodeInjector implements ICodeInjector {
80
80
  ...process.env,
81
81
  };
82
82
 
83
- console.log(`⚙️ Running npm ${command}...`);
83
+ console.log(`⚙️ exec: npm ${command}...`);
84
84
  console.time(`npm ${command} done in`);
85
85
  const { stdout: out, stderr: err } = await execAsync(`${nodeBinary} ${npmPath} ${command}`, {
86
86
  cwd,
@@ -88,11 +88,9 @@ class CodeInjector implements ICodeInjector {
88
88
  });
89
89
  console.timeEnd(`npm ${command} done in`);
90
90
 
91
- if (verbose) {
92
- console.log(`npm ${command} output:`, out);
93
- }
91
+ process.env.HEAVY_DEBUG && console.log(`🪲 npm ${command} output:`, out);
94
92
  if (err) {
95
- console.error(`npm ${command} errors/warnings:`, err);
93
+ process.env.HEAVY_DEBUG && console.error(`🪲npm ${command} errors/warnings:`, err);
96
94
  }
97
95
  }
98
96
 
@@ -105,7 +103,7 @@ class CodeInjector implements ICodeInjector {
105
103
  }
106
104
  }
107
105
 
108
- async prepareSources({ filesUpdated, verbose = false }: { filesUpdated?: string[], verbose?: boolean }) {
106
+ async prepareSources({ filesUpdated }: { filesUpdated?: string[] }) {
109
107
  // check SPA_TMP_PATH exists and create if not
110
108
  try {
111
109
  await fs.promises.access(CodeInjector.SPA_TMP_PATH, fs.constants.F_OK);
@@ -386,7 +384,6 @@ class CodeInjector implements ICodeInjector {
386
384
  await fs.promises.writeFile(indexHtmlPath, indexHtmlContent);
387
385
 
388
386
 
389
-
390
387
  /* generate custom routes */
391
388
  const homepageMenuItem = this.adminforth.config.menu.find((mi)=>mi.homepage);
392
389
  let childrenHomePageMenuItem = this.adminforth.config.menu.find((mi)=>mi.children && mi.children?.find((mi)=>mi.homepage));
@@ -414,9 +411,10 @@ class CodeInjector implements ICodeInjector {
414
411
  /* customPackageLock */
415
412
  let usersLockHash = '';
416
413
  let usersLock = null;
414
+ let usersPackage = null;
415
+
417
416
  if (this.adminforth.config.customization?.customComponentsDir) {
418
417
  const usersPackagePath = path.join(this.adminforth.config.customization.customComponentsDir, 'package.json');
419
- let usersPackage = null;
420
418
  try {
421
419
  usersPackage = JSON.parse(await fs.promises.readFile(usersPackagePath, 'utf-8'));
422
420
  } catch (e) {
@@ -432,6 +430,7 @@ class CodeInjector implements ICodeInjector {
432
430
  }
433
431
  usersLockHash = hashify(usersLock);
434
432
  }
433
+ }
435
434
 
436
435
  const iconPackagesNamesHash = hashify(iconPackageNames);
437
436
 
@@ -441,21 +440,17 @@ class CodeInjector implements ICodeInjector {
441
440
  try {
442
441
  const existingHash = await fs.promises.readFile(hashPath, 'utf-8');
443
442
  if (existingHash === fullHash) {
444
- console.log('Hashes match, skipping npm ci/install');
443
+ process.env.HEAVY_DEBUG && console.log(`🪲Hashes match, skipping npm ci/install, from file: ${existingHash}, actual: ${fullHash}`);
445
444
  return;
446
445
  } else {
447
- if (verbose) {
448
- console.log(`Hashes do not match: existing ${existingHash} new ${fullHash}, proceeding with npm ci/install`);
449
- }
446
+ process.env.HEAVY_DEBUG && console.log(`🪲 Hashes do not match: from file: ${existingHash} actual: ${fullHash}, proceeding with npm ci/install`);
450
447
  }
451
448
  } catch (e) {
452
449
  // ignore
453
- if (verbose) {
454
- console.log('Hash file does not exist, proceeding with npm ci/install');
455
- }
450
+ process.env.HEAVY_DEBUG && console.log('🪲Hash file does not exist, proceeding with npm ci/install');
456
451
  }
457
452
 
458
- await this.runNpmShell({command: 'ci', verbose, cwd: CodeInjector.SPA_TMP_PATH});
453
+ await this.runNpmShell({command: 'ci', cwd: CodeInjector.SPA_TMP_PATH});
459
454
 
460
455
  let customPackgeNames = [];
461
456
  if (usersPackage && usersLock) {
@@ -477,11 +472,9 @@ class CodeInjector implements ICodeInjector {
477
472
  }
478
473
 
479
474
  await fs.promises.writeFile(hashPath, fullHash);
480
-
481
475
  }
482
- }
483
476
 
484
- async watchForReprepare({ verbose }) {
477
+ async watchForReprepare({}) {
485
478
  const spaPath = path.join(ADMIN_FORTH_ABSOLUTE_PATH, 'spa');
486
479
  // get list of all subdirectories in spa recursively
487
480
  const directories = [];
@@ -519,7 +512,7 @@ async watchForReprepare({ verbose }) {
519
512
  this.allWatchers.push(watcher);
520
513
  }
521
514
 
522
- async watchCustomComponentsForCopy({ verbose, customComponentsDir, destination }) {
515
+ async watchCustomComponentsForCopy({ customComponentsDir, destination }) {
523
516
  if (!customComponentsDir) {
524
517
  return;
525
518
  }
@@ -527,9 +520,7 @@ async watchForReprepare({ verbose }) {
527
520
  try {
528
521
  await fs.promises.access(customComponentsDir, fs.constants.F_OK);
529
522
  } catch (e) {
530
- if (verbose) {
531
- console.log(`Custom components dir ${customComponentsDir} does not exist, skipping watching`);
532
- }
523
+ process.env.HEAVY_DEBUG && console.log(`🪲Custom components dir ${customComponentsDir} does not exist, skipping watching`);
533
524
  return;
534
525
  }
535
526
 
@@ -594,19 +585,18 @@ async watchForReprepare({ verbose }) {
594
585
  this.allWatchers.push(watcher);
595
586
  }
596
587
 
597
- async bundleNow({hotReload = false, verbose = false}: {hotReload: boolean, verbose: boolean}) {
588
+ async bundleNow({ hotReload = false }: { hotReload: boolean }) {
598
589
  console.log(`AdminForth bundling ${hotReload ? ' and listening for changes (🔥 Hotreload)' : ' (no hot reload)'}`);
599
590
  this.adminforth.runningHotReload = hotReload;
600
591
 
601
- await this.prepareSources({ verbose });
592
+ await this.prepareSources({});
602
593
 
603
594
  if (hotReload) {
604
595
  await Promise.all([
605
- this.watchForReprepare({ verbose }),
596
+ this.watchForReprepare({}),
606
597
  ...Object.entries(this.srcFoldersToSync).map(async ([src, dest]) => {
607
598
 
608
599
  await this.watchCustomComponentsForCopy({
609
- verbose,
610
600
  customComponentsDir: src,
611
601
  destination: dest,
612
602
  });
@@ -620,10 +610,10 @@ async watchForReprepare({ verbose }) {
620
610
 
621
611
  if (!hotReload) {
622
612
  // probably add option to build with tsh check (plain 'build')
623
- await this.runNpmShell({command: 'run build-only', verbose, cwd});
613
+ await this.runNpmShell({command: 'run build-only', cwd});
624
614
  } else {
625
615
  const command = 'run dev';
626
- console.log(`⚙️ Running npm ${command}...`);
616
+ console.log(`⚙️ spawn: npm ${command}...`);
627
617
  const nodeBinary = process.execPath;
628
618
  const npmPath = path.join(path.dirname(nodeBinary), 'npm');
629
619
  const env = {
@@ -391,17 +391,6 @@ export default class AdminForthRestAPI {
391
391
  })
392
392
  );
393
393
 
394
- for (const hook of listify(resource.hooks?.[source]?.afterDatasourceResponse)) {
395
- const resp = await hook({ resource, response: data.data, adminUser });
396
- if (!resp || (!resp.ok && !resp.error)) {
397
- throw new Error(`Hook must return object with {ok: true} or { error: 'Error' } `);
398
- }
399
-
400
- if (resp.error) {
401
- return { error: resp.error };
402
- }
403
- }
404
-
405
394
  // remove all columns which are not defined in resources, or defined but backendOnly
406
395
  data.data.forEach((item) => {
407
396
  Object.keys(item).forEach((key) => {
@@ -415,6 +404,18 @@ export default class AdminForthRestAPI {
415
404
  item._label = resource.recordLabel(item);
416
405
  });
417
406
 
407
+ // only after adminforth made all post processing, give user ability to edit it
408
+ for (const hook of listify(resource.hooks?.[source]?.afterDatasourceResponse)) {
409
+ const resp = await hook({ resource, response: data.data, adminUser });
410
+ if (!resp || (!resp.ok && !resp.error)) {
411
+ throw new Error(`Hook must return object with {ok: true} or { error: 'Error' } `);
412
+ }
413
+
414
+ if (resp.error) {
415
+ return { error: resp.error };
416
+ }
417
+ }
418
+
418
419
  return {
419
420
  ...data,
420
421
  options: resource?.options,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adminforth",
3
- "version": "1.2.10",
3
+ "version": "1.2.12",
4
4
  "description": "OpenSource Vue3 powered forth-generation admin panel",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -28,8 +28,7 @@ export const useUserStore = defineStore('user', () => {
28
28
  await router.isReady();
29
29
  await coreStore.fetchMenuAndResource();
30
30
  setTimeout(() => {
31
- initFlowbite();
32
-
31
+ initFlowbite();
33
32
  });
34
33
  }
35
34