adminforth 1.1.103 → 1.1.105

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
@@ -573,7 +573,7 @@ class AdminForth {
573
573
  method: 'POST',
574
574
  path: '/login',
575
575
  handler: (_b) => __awaiter(this, [_b], void 0, function* ({ body, response }) {
576
- var _c, _d, _e, _f, _g, _h;
576
+ var _c, _d, _e, _f;
577
577
  const INVALID_MESSAGE = 'Invalid username or password';
578
578
  const { username, password } = body;
579
579
  let adminUser;
@@ -622,14 +622,9 @@ class AdminForth {
622
622
  const beforeLoginConfirmation = this.config.auth.beforeLoginConfirmation;
623
623
  if (beforeLoginConfirmation === null || beforeLoginConfirmation === void 0 ? void 0 : beforeLoginConfirmation.length) {
624
624
  for (const hook of beforeLoginConfirmation) {
625
- const resp = yield hook({ adminUser });
626
- if ((_d = resp === null || resp === void 0 ? void 0 : resp.body) === null || _d === void 0 ? void 0 : _d.setCookie) {
627
- (_e = resp === null || resp === void 0 ? void 0 : resp.body) === null || _e === void 0 ? void 0 : _e.setCookie.forEach((cookie) => {
628
- this.auth.setCustomCookie({ response, payload: cookie });
629
- });
630
- }
631
- if ((_f = resp === null || resp === void 0 ? void 0 : resp.body) === null || _f === void 0 ? void 0 : _f.redirectTo) {
632
- toReturn = { ok: resp.ok, redirectTo: (_g = resp === null || resp === void 0 ? void 0 : resp.body) === null || _g === void 0 ? void 0 : _g.redirectTo, allowedLogin: (_h = resp === null || resp === void 0 ? void 0 : resp.body) === null || _h === void 0 ? void 0 : _h.allowedLogin };
625
+ const resp = yield hook({ adminUser, response });
626
+ if ((_d = resp === null || resp === void 0 ? void 0 : resp.body) === null || _d === void 0 ? void 0 : _d.redirectTo) {
627
+ toReturn = { ok: resp.ok, redirectTo: (_e = resp === null || resp === void 0 ? void 0 : resp.body) === null || _e === void 0 ? void 0 : _e.redirectTo, allowedLogin: (_f = resp === null || resp === void 0 ? void 0 : resp.body) === null || _f === void 0 ? void 0 : _f.allowedLogin };
633
628
  break;
634
629
  }
635
630
  }
@@ -648,7 +643,7 @@ class AdminForth {
648
643
  server.endpoint({
649
644
  method: 'POST',
650
645
  path: '/check_auth',
651
- handler: (_j) => __awaiter(this, [_j], void 0, function* ({ adminUser }) {
646
+ handler: (_g) => __awaiter(this, [_g], void 0, function* ({ adminUser }) {
652
647
  return { ok: true };
653
648
  }),
654
649
  });
@@ -656,7 +651,7 @@ class AdminForth {
656
651
  noAuth: true,
657
652
  method: 'POST',
658
653
  path: '/logout',
659
- handler: (_k) => __awaiter(this, [_k], void 0, function* ({ response }) {
654
+ handler: (_h) => __awaiter(this, [_h], void 0, function* ({ response }) {
660
655
  this.auth.removeAuthCookie(response);
661
656
  return { ok: true };
662
657
  }),
@@ -665,8 +660,8 @@ class AdminForth {
665
660
  noAuth: true,
666
661
  method: 'GET',
667
662
  path: '/get_public_config',
668
- handler: (_l) => __awaiter(this, [_l], void 0, function* ({ body }) {
669
- var _m;
663
+ handler: (_j) => __awaiter(this, [_j], void 0, function* ({ body }) {
664
+ var _k;
670
665
  // find resource
671
666
  if (!this.config.auth) {
672
667
  throw new Error('No config.auth defined');
@@ -678,15 +673,15 @@ class AdminForth {
678
673
  brandName: this.config.customization.brandName,
679
674
  usernameFieldName: usernameColumn.label,
680
675
  loginBackgroundImage: this.config.auth.loginBackgroundImage,
681
- title: (_m = this.config.customization) === null || _m === void 0 ? void 0 : _m.title,
676
+ title: (_k = this.config.customization) === null || _k === void 0 ? void 0 : _k.title,
682
677
  };
683
678
  }),
684
679
  });
685
680
  server.endpoint({
686
681
  method: 'GET',
687
682
  path: '/get_base_config',
688
- handler: (_o) => __awaiter(this, [_o], void 0, function* ({ input, adminUser, cookies }) {
689
- var _p, _q;
683
+ handler: (_l) => __awaiter(this, [_l], void 0, function* ({ input, adminUser, cookies }) {
684
+ var _m, _o;
690
685
  let username = '';
691
686
  let userFullName = '';
692
687
  if (adminUser.isRoot) {
@@ -747,8 +742,8 @@ class AdminForth {
747
742
  deleteConfirmation: this.config.deleteConfirmation,
748
743
  auth: this.config.auth,
749
744
  usernameField: this.config.auth.usernameField,
750
- title: (_p = this.config.customization) === null || _p === void 0 ? void 0 : _p.title,
751
- emptyFieldPlaceholder: (_q = this.config.customization) === null || _q === void 0 ? void 0 : _q.emptyFieldPlaceholder,
745
+ title: (_m = this.config.customization) === null || _m === void 0 ? void 0 : _m.title,
746
+ emptyFieldPlaceholder: (_o = this.config.customization) === null || _o === void 0 ? void 0 : _o.emptyFieldPlaceholder,
752
747
  },
753
748
  adminUser,
754
749
  version: ADMINFORTH_VERSION,
@@ -787,7 +782,7 @@ class AdminForth {
787
782
  server.endpoint({
788
783
  method: 'POST',
789
784
  path: '/get_resource',
790
- handler: (_r) => __awaiter(this, [_r], void 0, function* ({ body, adminUser }) {
785
+ handler: (_p) => __awaiter(this, [_p], void 0, function* ({ body, adminUser }) {
791
786
  const { resourceId } = body;
792
787
  if (!this.statuses.dbDiscover) {
793
788
  return { error: 'Database discovery not started' };
@@ -809,8 +804,8 @@ class AdminForth {
809
804
  server.endpoint({
810
805
  method: 'POST',
811
806
  path: '/get_resource_data',
812
- handler: (_s) => __awaiter(this, [_s], void 0, function* ({ body, adminUser }) {
813
- var _t, _u, _v, _w;
807
+ handler: (_q) => __awaiter(this, [_q], void 0, function* ({ body, adminUser }) {
808
+ var _r, _s, _t, _u;
814
809
  const { resourceId, source } = body;
815
810
  if (['show', 'list'].includes(source) === false) {
816
811
  return { error: 'Invalid source, should be list or show' };
@@ -830,7 +825,7 @@ class AdminForth {
830
825
  if (!allowed) {
831
826
  return { error };
832
827
  }
833
- for (const hook of listify((_u = (_t = resource.hooks) === null || _t === void 0 ? void 0 : _t[source]) === null || _u === void 0 ? void 0 : _u.beforeDatasourceRequest)) {
828
+ for (const hook of listify((_s = (_r = resource.hooks) === null || _r === void 0 ? void 0 : _r[source]) === null || _s === void 0 ? void 0 : _s.beforeDatasourceRequest)) {
834
829
  const resp = yield hook({ resource, query: body, adminUser });
835
830
  if (!resp || (!resp.ok && !resp.error)) {
836
831
  throw new Error(`Hook must return object with {ok: true} or { error: 'Error' } `);
@@ -897,7 +892,7 @@ class AdminForth {
897
892
  item[col.name] = targetDataMap[item[col.name]];
898
893
  });
899
894
  })));
900
- for (const hook of listify((_w = (_v = resource.hooks) === null || _v === void 0 ? void 0 : _v[source]) === null || _w === void 0 ? void 0 : _w.afterDatasourceResponse)) {
895
+ for (const hook of listify((_u = (_t = resource.hooks) === null || _t === void 0 ? void 0 : _t[source]) === null || _u === void 0 ? void 0 : _u.afterDatasourceResponse)) {
901
896
  const resp = yield hook({ resource, response: data.data, adminUser });
902
897
  if (!resp || (!resp.ok && !resp.error)) {
903
898
  throw new Error(`Hook must return object with {ok: true} or { error: 'Error' } `);
@@ -923,8 +918,8 @@ class AdminForth {
923
918
  server.endpoint({
924
919
  method: 'POST',
925
920
  path: '/get_resource_foreign_data',
926
- handler: (_x) => __awaiter(this, [_x], void 0, function* ({ body, adminUser }) {
927
- var _y, _z, _0, _1;
921
+ handler: (_v) => __awaiter(this, [_v], void 0, function* ({ body, adminUser }) {
922
+ var _w, _x, _y, _z;
928
923
  const { resourceId, column } = body;
929
924
  if (!this.statuses.dbDiscover) {
930
925
  return { error: 'Database discovery not started' };
@@ -945,7 +940,7 @@ class AdminForth {
945
940
  }
946
941
  const targetResourceId = columnConfig.foreignResource.resourceId;
947
942
  const targetResource = this.config.resources.find((res) => res.resourceId == targetResourceId);
948
- for (const hook of listify((_z = (_y = columnConfig.foreignResource.hooks) === null || _y === void 0 ? void 0 : _y.dropdownList) === null || _z === void 0 ? void 0 : _z.beforeDatasourceRequest)) {
943
+ for (const hook of listify((_x = (_w = columnConfig.foreignResource.hooks) === null || _w === void 0 ? void 0 : _w.dropdownList) === null || _x === void 0 ? void 0 : _x.beforeDatasourceRequest)) {
949
944
  const resp = yield hook({ query: body, adminUser, resource: targetResource });
950
945
  if (!resp || (!resp.ok && !resp.error)) {
951
946
  throw new Error(`Hook must return object with {ok: true} or { error: 'Error' } `);
@@ -974,7 +969,7 @@ class AdminForth {
974
969
  const response = {
975
970
  items
976
971
  };
977
- for (const hook of listify((_1 = (_0 = columnConfig.foreignResource.hooks) === null || _0 === void 0 ? void 0 : _0.dropdownList) === null || _1 === void 0 ? void 0 : _1.afterDatasourceResponse)) {
972
+ for (const hook of listify((_z = (_y = columnConfig.foreignResource.hooks) === null || _y === void 0 ? void 0 : _y.dropdownList) === null || _z === void 0 ? void 0 : _z.afterDatasourceResponse)) {
978
973
  const resp = yield hook({ response, adminUser, resource: targetResource });
979
974
  if (!resp || (!resp.ok && !resp.error)) {
980
975
  throw new Error(`Hook must return object with {ok: true} or { error: 'Error' } `);
@@ -989,7 +984,7 @@ class AdminForth {
989
984
  server.endpoint({
990
985
  method: 'POST',
991
986
  path: '/get_min_max_for_columns',
992
- handler: (_2) => __awaiter(this, [_2], void 0, function* ({ body }) {
987
+ handler: (_0) => __awaiter(this, [_0], void 0, function* ({ body }) {
993
988
  const { resourceId } = body;
994
989
  if (!this.statuses.dbDiscover) {
995
990
  return { error: 'Database discovery not started' };
@@ -1018,7 +1013,7 @@ class AdminForth {
1018
1013
  server.endpoint({
1019
1014
  method: 'POST',
1020
1015
  path: '/create_record',
1021
- handler: (_3) => __awaiter(this, [_3], void 0, function* ({ body, adminUser }) {
1016
+ handler: (_1) => __awaiter(this, [_1], void 0, function* ({ body, adminUser }) {
1022
1017
  const resource = this.config.resources.find((res) => res.resourceId == body['resourceId']);
1023
1018
  if (!resource) {
1024
1019
  return { error: `Resource '${body['resourceId']}' not found` };
@@ -1039,8 +1034,8 @@ class AdminForth {
1039
1034
  server.endpoint({
1040
1035
  method: 'POST',
1041
1036
  path: '/update_record',
1042
- handler: (_4) => __awaiter(this, [_4], void 0, function* ({ body, adminUser }) {
1043
- var _5, _6, _7, _8;
1037
+ handler: (_2) => __awaiter(this, [_2], void 0, function* ({ body, adminUser }) {
1038
+ var _3, _4, _5, _6;
1044
1039
  const resource = this.config.resources.find((res) => res.resourceId == body['resourceId']);
1045
1040
  if (!resource) {
1046
1041
  return { error: `Resource '${body['resourceId']}' not found` };
@@ -1059,7 +1054,7 @@ class AdminForth {
1059
1054
  return { error };
1060
1055
  }
1061
1056
  // execute hook if needed
1062
- for (const hook of listify((_6 = (_5 = resource.hooks) === null || _5 === void 0 ? void 0 : _5.edit) === null || _6 === void 0 ? void 0 : _6.beforeSave)) {
1057
+ for (const hook of listify((_4 = (_3 = resource.hooks) === null || _3 === void 0 ? void 0 : _3.edit) === null || _4 === void 0 ? void 0 : _4.beforeSave)) {
1063
1058
  const resp = yield hook({ resource, record, adminUser });
1064
1059
  if (!resp || (!resp.ok && !resp.error)) {
1065
1060
  throw new Error(`Hook beforeSave must return object with {ok: true} or { error: 'Error' } `);
@@ -1086,7 +1081,7 @@ class AdminForth {
1086
1081
  yield connector.updateRecord({ resource, recordId, newValues });
1087
1082
  }
1088
1083
  // execute hook if needed
1089
- for (const hook of listify((_8 = (_7 = resource.hooks) === null || _7 === void 0 ? void 0 : _7.edit) === null || _8 === void 0 ? void 0 : _8.afterSave)) {
1084
+ for (const hook of listify((_6 = (_5 = resource.hooks) === null || _5 === void 0 ? void 0 : _5.edit) === null || _6 === void 0 ? void 0 : _6.afterSave)) {
1090
1085
  const resp = yield hook({ resource, record, adminUser, oldRecord });
1091
1086
  if (!resp || (!resp.ok && !resp.error)) {
1092
1087
  throw new Error(`Hook afterSave must return object with {ok: true} or { error: 'Error' } `);
@@ -1103,8 +1098,8 @@ class AdminForth {
1103
1098
  server.endpoint({
1104
1099
  method: 'POST',
1105
1100
  path: '/delete_record',
1106
- handler: (_9) => __awaiter(this, [_9], void 0, function* ({ body, adminUser }) {
1107
- var _10, _11, _12, _13;
1101
+ handler: (_7) => __awaiter(this, [_7], void 0, function* ({ body, adminUser }) {
1102
+ var _8, _9, _10, _11;
1108
1103
  const resource = this.config.resources.find((res) => res.resourceId == body['resourceId']);
1109
1104
  const record = yield this.connectors[resource.dataSource].getRecordByPrimaryKey(resource, body['primaryKey']);
1110
1105
  if (!resource) {
@@ -1122,7 +1117,7 @@ class AdminForth {
1122
1117
  return { error };
1123
1118
  }
1124
1119
  // execute hook if needed
1125
- for (const hook of listify((_11 = (_10 = resource.hooks) === null || _10 === void 0 ? void 0 : _10.delete) === null || _11 === void 0 ? void 0 : _11.beforeSave)) {
1120
+ for (const hook of listify((_9 = (_8 = resource.hooks) === null || _8 === void 0 ? void 0 : _8.delete) === null || _9 === void 0 ? void 0 : _9.beforeSave)) {
1126
1121
  const resp = yield hook({ resource, record, adminUser });
1127
1122
  if (!resp || (!resp.ok && !resp.error)) {
1128
1123
  throw new Error(`Hook beforeSave must return object with {ok: true} or { error: 'Error' } `);
@@ -1134,7 +1129,7 @@ class AdminForth {
1134
1129
  const connector = this.connectors[resource.dataSource];
1135
1130
  yield connector.deleteRecord({ resource, recordId: body['primaryKey'] });
1136
1131
  // execute hook if needed
1137
- for (const hook of listify((_13 = (_12 = resource.hooks) === null || _12 === void 0 ? void 0 : _12.delete) === null || _13 === void 0 ? void 0 : _13.afterSave)) {
1132
+ for (const hook of listify((_11 = (_10 = resource.hooks) === null || _10 === void 0 ? void 0 : _10.delete) === null || _11 === void 0 ? void 0 : _11.afterSave)) {
1138
1133
  const resp = yield hook({ resource, record, adminUser });
1139
1134
  if (!resp || (!resp.ok && !resp.error)) {
1140
1135
  throw new Error(`Hook afterSave must return object with {ok: true} or { error: 'Error' } `);
@@ -1151,7 +1146,7 @@ class AdminForth {
1151
1146
  server.endpoint({
1152
1147
  method: 'POST',
1153
1148
  path: '/start_bulk_action',
1154
- handler: (_14) => __awaiter(this, [_14], void 0, function* ({ body }) {
1149
+ handler: (_12) => __awaiter(this, [_12], void 0, function* ({ body }) {
1155
1150
  const { resourceId, actionId, recordIds } = body;
1156
1151
  const resource = this.config.resources.find((res) => res.resourceId == resourceId);
1157
1152
  if (!resource) {
@@ -91,7 +91,7 @@ class CodeInjector {
91
91
  }
92
92
  prepareSources(_a) {
93
93
  return __awaiter(this, arguments, void 0, function* ({ filesUpdated, verbose = false }) {
94
- var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l;
94
+ var _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m;
95
95
  // check SPA_TMP_PATH exists and create if not
96
96
  try {
97
97
  yield fs.promises.access(CodeInjector.SPA_TMP_PATH, fs.constants.F_OK);
@@ -245,7 +245,7 @@ class CodeInjector {
245
245
  // icons are collectionName:iconName. Get list of all unique collection names:
246
246
  const collections = new Set(icons.map((icon) => icon.split(':')[0]));
247
247
  // package names @iconify-prerendered/vue-<collection name>
248
- const packageNames = Array.from(collections).map((collection) => `@iconify-prerendered/vue-${collection}`);
248
+ const iconPackageNames = Array.from(collections).map((collection) => `@iconify-prerendered/vue-${collection}`);
249
249
  // for each icon generate import statement
250
250
  const iconImports = uniqueIcons.map((icon) => {
251
251
  const [collection, iconName] = icon.split(':');
@@ -358,47 +358,67 @@ class CodeInjector {
358
358
  const spaPackageLock = JSON.parse(yield fs.promises.readFile(spaPackageLockPath, 'utf-8'));
359
359
  const spaLockHash = hashify(spaPackageLock);
360
360
  /* customPackageLock */
361
- const usersPackagePath = path.join('./package.json');
362
- const usersPackage = JSON.parse(yield fs.promises.readFile(usersPackagePath, 'utf-8'));
363
- const usersLockPath = path.join('./package-lock.json');
364
- const usersLock = JSON.parse(yield fs.promises.readFile(usersLockPath, 'utf-8'));
365
- const usersLockHash = hashify(usersLock);
366
- const packagesNamesHash = hashify(packageNames);
367
- const fullHash = `${spaLockHash}::${packagesNamesHash}::${usersLockHash}`;
368
- const hashPath = path.join(CodeInjector.SPA_TMP_PATH, 'node_modules', '.adminforth_hash');
369
- try {
370
- const existingHash = yield fs.promises.readFile(hashPath, 'utf-8');
371
- if (existingHash === fullHash) {
372
- console.log('Hashes match, skipping npm ci/install');
373
- return;
361
+ let usersLockHash = '';
362
+ let usersLock = null;
363
+ if ((_m = this.adminforth.config.customization) === null || _m === void 0 ? void 0 : _m.customComponentsDir) {
364
+ const usersPackagePath = path.join(this.adminforth.config.customization.customComponentsDir, 'package.json');
365
+ let usersPackage = null;
366
+ try {
367
+ usersPackage = JSON.parse(yield fs.promises.readFile(usersPackagePath, 'utf-8'));
374
368
  }
375
- else {
369
+ catch (e) {
370
+ // user package.json does not exist, user does not have custom components
371
+ }
372
+ if (usersPackage) {
373
+ const usersLockPath = path.join(this.adminforth.config.customization.customComponentsDir, 'package-lock.json');
374
+ try {
375
+ usersLock = JSON.parse(yield fs.promises.readFile(usersLockPath, 'utf-8'));
376
+ }
377
+ catch (e) {
378
+ throw new Error(`Custom package-lock.json does not exist in ${this.adminforth.config.customization.customComponentsDir}, but package.json does.
379
+ We can't determine version of packages without package-lock.json. Please run npm install in ${this.adminforth.config.customization.customComponentsDir}`);
380
+ }
381
+ usersLockHash = hashify(usersLock);
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
+ console.log('Hashes match, skipping npm ci/install');
390
+ return;
391
+ }
392
+ else {
393
+ if (verbose) {
394
+ console.log(`Hashes do not match: existing ${existingHash} new ${fullHash}, proceeding with npm ci/install`);
395
+ }
396
+ }
397
+ }
398
+ catch (e) {
399
+ // ignore
376
400
  if (verbose) {
377
- console.log(`Hashes do not match: existing ${existingHash} new ${fullHash}, proceeding with npm ci/install`);
401
+ console.log('Hash file does not exist, proceeding with npm ci/install');
378
402
  }
379
403
  }
380
- }
381
- catch (e) {
382
- // ignore
383
- if (verbose) {
384
- console.log('Hash file does not exist, proceeding with npm ci/install');
404
+ yield this.runNpmShell({ command: 'ci', verbose, cwd: CodeInjector.SPA_TMP_PATH });
405
+ let customPackgeNames = [];
406
+ if (usersPackage && usersLock) {
407
+ customPackgeNames = [
408
+ ...Object.keys(usersPackage.dependencies),
409
+ ...Object.keys(usersPackage.devDependencies || [])
410
+ ].reduce((acc, packageName) => {
411
+ const version = usersLock.packages[`node_modules/${packageName}`].version;
412
+ acc.push(`${packageName}@${version}`);
413
+ return acc;
414
+ }, []);
385
415
  }
416
+ if (iconPackageNames.length) {
417
+ const npmInstallCommand = `install ${[...iconPackageNames, ...customPackgeNames].join(' ')}`;
418
+ yield this.runNpmShell({ command: npmInstallCommand, cwd: CodeInjector.SPA_TMP_PATH });
419
+ }
420
+ yield fs.promises.writeFile(hashPath, fullHash);
386
421
  }
387
- yield this.runNpmShell({ command: 'ci', verbose, cwd: CodeInjector.SPA_TMP_PATH });
388
- // get packages with version from customPackage
389
- const IGNORE_PACKAGES = ['tsx', 'typescript', 'express', 'nodemon', 'adminforth'];
390
- const customPackgeNames = [...Object.keys(usersPackage.dependencies), ...Object.keys(usersPackage.devDependencies || [])]
391
- .filter((packageName) => !IGNORE_PACKAGES.includes(packageName))
392
- .reduce((acc, packageName) => {
393
- const version = usersLock.packages[`node_modules/${packageName}`].version;
394
- acc.push(`${packageName}@${version}`);
395
- return acc;
396
- }, []);
397
- if (packageNames.length) {
398
- const npmInstallCommand = `install ${[...packageNames, ...customPackgeNames].join(' ')}`;
399
- yield this.runNpmShell({ command: npmInstallCommand, cwd: CodeInjector.SPA_TMP_PATH });
400
- }
401
- yield fs.promises.writeFile(hashPath, fullHash);
402
422
  });
403
423
  }
404
424
  watchForReprepare(_a) {
@@ -1,3 +1,4 @@
1
+ ;
1
2
  export var AdminForthMenuTypes;
2
3
  (function (AdminForthMenuTypes) {
3
4
  /**
package/index.ts CHANGED
@@ -717,11 +717,8 @@ class AdminForth implements IAdminForth {
717
717
  const beforeLoginConfirmation = this.config.auth.beforeLoginConfirmation as (BeforeLoginConfirmationFunction[] | undefined);
718
718
  if (beforeLoginConfirmation?.length){
719
719
  for (const hook of beforeLoginConfirmation) {
720
- const resp = await hook({ adminUser });
721
- if (resp?.body?.setCookie){
722
- resp?.body?.setCookie.forEach((cookie) => {
723
- this.auth.setCustomCookie({response,payload:cookie})});
724
- }
720
+ const resp = await hook({ adminUser, response });
721
+
725
722
  if (resp?.body?.redirectTo) {
726
723
  toReturn = {ok:resp.ok, redirectTo:resp?.body?.redirectTo, allowedLogin:resp?.body?.allowedLogin};
727
724
  break;
@@ -271,7 +271,7 @@ class CodeInjector implements ICodeInjector {
271
271
  const collections = new Set(icons.map((icon) => icon.split(':')[0]));
272
272
 
273
273
  // package names @iconify-prerendered/vue-<collection name>
274
- const packageNames = Array.from(collections).map((collection) => `@iconify-prerendered/vue-${collection}`);
274
+ const iconPackageNames = Array.from(collections).map((collection) => `@iconify-prerendered/vue-${collection}`);
275
275
 
276
276
  // for each icon generate import statement
277
277
  const iconImports = uniqueIcons.map((icon) => {
@@ -411,16 +411,30 @@ class CodeInjector implements ICodeInjector {
411
411
  const spaLockHash = hashify(spaPackageLock);
412
412
 
413
413
  /* customPackageLock */
414
- const usersPackagePath = path.join('./package.json');
415
- const usersPackage = JSON.parse(await fs.promises.readFile(usersPackagePath, 'utf-8'));
416
-
417
- const usersLockPath = path.join('./package-lock.json');
418
- const usersLock = JSON.parse(await fs.promises.readFile(usersLockPath, 'utf-8'));
419
- const usersLockHash = hashify(usersLock);
414
+ let usersLockHash = '';
415
+ let usersLock = null;
416
+ if (this.adminforth.config.customization?.customComponentsDir) {
417
+ const usersPackagePath = path.join(this.adminforth.config.customization.customComponentsDir, 'package.json');
418
+ let usersPackage = null;
419
+ try {
420
+ usersPackage = JSON.parse(await fs.promises.readFile(usersPackagePath, 'utf-8'));
421
+ } catch (e) {
422
+ // user package.json does not exist, user does not have custom components
423
+ }
424
+ if (usersPackage) {
425
+ const usersLockPath = path.join(this.adminforth.config.customization.customComponentsDir, 'package-lock.json');
426
+ try {
427
+ usersLock = JSON.parse(await fs.promises.readFile(usersLockPath, 'utf-8'));
428
+ } catch (e) {
429
+ throw new Error(`Custom package-lock.json does not exist in ${this.adminforth.config.customization.customComponentsDir}, but package.json does.
430
+ We can't determine version of packages without package-lock.json. Please run npm install in ${this.adminforth.config.customization.customComponentsDir}`);
431
+ }
432
+ usersLockHash = hashify(usersLock);
433
+ }
420
434
 
421
- const packagesNamesHash = hashify(packageNames);
435
+ const iconPackagesNamesHash = hashify(iconPackageNames);
422
436
 
423
- const fullHash = `${spaLockHash}::${packagesNamesHash}::${usersLockHash}`;
437
+ const fullHash = `${spaLockHash}::${iconPackagesNamesHash}::${usersLockHash}`;
424
438
  const hashPath = path.join(CodeInjector.SPA_TMP_PATH, 'node_modules', '.adminforth_hash');
425
439
 
426
440
  try {
@@ -442,25 +456,29 @@ class CodeInjector implements ICodeInjector {
442
456
 
443
457
  await this.runNpmShell({command: 'ci', verbose, cwd: CodeInjector.SPA_TMP_PATH});
444
458
 
445
- // get packages with version from customPackage
446
- const IGNORE_PACKAGES = ['tsx', 'typescript', 'express', 'nodemon', 'adminforth'];
447
- const customPackgeNames = [...Object.keys(usersPackage.dependencies), ...Object.keys(usersPackage.devDependencies || [])]
448
- .filter((packageName) => !IGNORE_PACKAGES.includes(packageName))
449
- .reduce(
450
- (acc, packageName) => {
451
- const version = usersLock.packages[`node_modules/${packageName}`].version;
452
- acc.push(`${packageName}@${version}`);
453
- return acc;
454
- }, []);
455
-
456
- if (packageNames.length) {
457
- const npmInstallCommand = `install ${[...packageNames, ...customPackgeNames].join(' ')}`;
459
+ let customPackgeNames = [];
460
+ if (usersPackage && usersLock) {
461
+ customPackgeNames = [
462
+ ...Object.keys(usersPackage.dependencies),
463
+ ...Object.keys(usersPackage.devDependencies || [])
464
+ ].reduce(
465
+ (acc, packageName) => {
466
+ const version = usersLock.packages[`node_modules/${packageName}`].version;
467
+ acc.push(`${packageName}@${version}`);
468
+ return acc;
469
+ }, []
470
+ );
471
+ }
472
+
473
+ if (iconPackageNames.length) {
474
+ const npmInstallCommand = `install ${[...iconPackageNames, ...customPackgeNames].join(' ')}`;
458
475
  await this.runNpmShell({command: npmInstallCommand, cwd: CodeInjector.SPA_TMP_PATH});
459
476
  }
460
477
 
461
478
  await fs.promises.writeFile(hashPath, fullHash);
462
479
 
463
480
  }
481
+ }
464
482
 
465
483
  async watchForReprepare({ verbose }) {
466
484
  const spaPath = path.join(ADMIN_FORTH_ABSOLUTE_PATH, 'spa');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "adminforth",
3
- "version": "1.1.103",
3
+ "version": "1.1.105",
4
4
  "description": "OpenSource Vue3 powered forth-generation admin panel",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -5,6 +5,11 @@ export interface ICodeInjector {
5
5
  allComponentNames: Object;
6
6
  }
7
7
 
8
+ export interface IAdminForthHttpResponse {
9
+ setHeader: (key: string, value: string) => void,
10
+ setStatus: (code: number, message: string) => void,
11
+ };
12
+
8
13
  /**
9
14
  * Implement this interface to create custom HTTP server adapter for AdminForth.
10
15
  */
@@ -28,10 +33,13 @@ export interface IHttpServer {
28
33
  method: string,
29
34
  noAuth?: boolean,
30
35
  path: string,
31
- handler: (body: any, adminUser: any, query: {[key: string]: string}, headers: {[key: string]: string}, cookies: {[key: string]: string}, response: {
32
- setHeader: (key: string, value: string) => void,
33
- setStatus: (code: number, message: string) => void,
34
- }) => void,
36
+ handler: (
37
+ body: any,
38
+ adminUser: any,
39
+ query: {[key: string]: string},
40
+ headers: {[key: string]: string}, cookies: {[key: string]: string},
41
+ response: IAdminForthHttpResponse,
42
+ ) => void,
35
43
  }): void;
36
44
 
37
45
  }
@@ -615,7 +623,17 @@ export type AfterSaveFunction = (params: {resource: AdminForthResource, adminUse
615
623
  /**
616
624
  * Allow to get user data before login confirmation, will triger when user try to login.
617
625
  */
618
- export type BeforeLoginConfirmationFunction = (params?: { adminUser: AdminUser }) => Promise<{ok:boolean, error?:string, body:{setCookie?:[], redirectTo?: 'string', allowedLogin?: boolean }}>;
626
+ export type BeforeLoginConfirmationFunction = (params?: {
627
+ adminUser: AdminUser,
628
+ response: IAdminForthHttpResponse,
629
+ }) => Promise<{
630
+ ok:boolean,
631
+ error?:string,
632
+ body: {
633
+ redirectTo?: 'string',
634
+ allowedLogin?: boolean,
635
+ }
636
+ }>;
619
637
 
620
638
  /**
621
639
  * Resource describes one table or collection in database.