@adminforth/crud-approve-plugin 1.0.13 → 1.0.15

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
@@ -7,11 +7,242 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
7
7
  step((generator = generator.apply(thisArg, _arguments || [])).next());
8
8
  });
9
9
  };
10
- import { AdminForthPlugin } from "adminforth";
11
- import { ApprovalStatusEnum } from './types.js';
10
+ import { ActionCheckSource, AdminForthPlugin, AdminForthSortDirections, Filters } from "adminforth";
11
+ import { AdminForthDataTypes, AllowedActionsEnum } from "adminforth";
12
+ import { AllowedForReviewActionsEnum, ApprovalStatusEnum } from './types.js';
13
+ import dayjs from "dayjs";
14
+ import utc from "dayjs/plugin/utc.js";
15
+ import { randomUUID } from "crypto";
16
+ dayjs.extend(utc);
12
17
  export default class CRUDApprovePlugin extends AdminForthPlugin {
13
18
  constructor(options) {
14
19
  super(options, import.meta.url);
20
+ this.createApprovalRequest = (_a) => __awaiter(this, [_a], void 0, function* ({ resource, action, data, user, oldRecord, updates, extra, record }) {
21
+ var _b;
22
+ //@ts-ignore
23
+ if (extra && extra.adminforth_plugin_crud_approve && extra.adminforth_plugin_crud_approve.callingFromApprovalPlugin) {
24
+ return { ok: true, error: 'Approval request creation aborted to avoid infinite loop' };
25
+ }
26
+ const recordIdFieldName = (_b = resource.columns.find((c) => c.primaryKey === true)) === null || _b === void 0 ? void 0 : _b.name;
27
+ const recordId = (data === null || data === void 0 ? void 0 : data[recordIdFieldName]) || (oldRecord === null || oldRecord === void 0 ? void 0 : oldRecord[recordIdFieldName]);
28
+ let newRecord = {};
29
+ const connector = this.adminforth.connectors[resource.dataSource];
30
+ if (action === AllowedForReviewActionsEnum.create) {
31
+ oldRecord = {};
32
+ newRecord = updates || record;
33
+ }
34
+ else if (action === AllowedForReviewActionsEnum.edit) {
35
+ newRecord = yield connector.getRecordByPrimaryKey(resource, recordId);
36
+ for (const key in updates) {
37
+ newRecord[key] = updates[key];
38
+ }
39
+ }
40
+ else if (action === AllowedForReviewActionsEnum.delete) {
41
+ oldRecord = yield connector.getRecordByPrimaryKey(resource, recordId);
42
+ }
43
+ const checks = yield Promise.all(resource.columns.map((c) => __awaiter(this, void 0, void 0, function* () {
44
+ var _a;
45
+ if (typeof c.backendOnly === "function") {
46
+ const result = yield c.backendOnly({
47
+ adminUser: user,
48
+ resource,
49
+ meta: {},
50
+ source: ActionCheckSource.ShowRequest,
51
+ adminforth: this.adminforth,
52
+ });
53
+ return { col: c, result };
54
+ }
55
+ return { col: c, result: (_a = c.backendOnly) !== null && _a !== void 0 ? _a : false };
56
+ })));
57
+ const backendOnlyColumns = checks
58
+ .filter(({ result }) => result === true)
59
+ .map(({ col }) => col);
60
+ backendOnlyColumns.forEach((c) => {
61
+ if (JSON.stringify(oldRecord[c.name]) != JSON.stringify(newRecord[c.name])) {
62
+ if (action !== AllowedForReviewActionsEnum.delete) {
63
+ newRecord[c.name] = '<hidden value after>';
64
+ }
65
+ if (action !== AllowedForReviewActionsEnum.create) {
66
+ oldRecord[c.name] = '<hidden value before>';
67
+ }
68
+ }
69
+ else {
70
+ delete oldRecord[c.name];
71
+ delete newRecord[c.name];
72
+ }
73
+ });
74
+ if (action === AllowedForReviewActionsEnum.edit) {
75
+ for (const key in oldRecord) {
76
+ if (JSON.stringify(oldRecord[key]) === JSON.stringify(newRecord[key])) {
77
+ delete oldRecord[key];
78
+ delete newRecord[key];
79
+ }
80
+ }
81
+ }
82
+ const createdAt = dayjs.utc().format();
83
+ const diffRecord = {
84
+ [this.options.resourceColumns.idColumnName]: randomUUID(),
85
+ [this.options.resourceColumns.resourceIdColumnName]: resource.resourceId,
86
+ [this.options.resourceColumns.actionColumnName]: action,
87
+ [this.options.resourceColumns.statusColumnName]: ApprovalStatusEnum.pending,
88
+ [this.options.resourceColumns.dataColumnName]: { 'oldRecord': oldRecord, 'newRecord': newRecord },
89
+ [this.options.resourceColumns.userIdColumnName]: user.pk,
90
+ [this.options.resourceColumns.recordIdColumnName]: recordId,
91
+ [this.options.resourceColumns.createdAtColumnName]: createdAt,
92
+ [this.options.resourceColumns.extraColumnName]: extra || {},
93
+ };
94
+ const diffResource = this.adminforth.config.resources.find((r) => r.resourceId === this.diffResource.resourceId);
95
+ yield this.adminforth.createResourceRecord({ resource: diffResource, record: diffRecord, adminUser: user });
96
+ return { ok: true, error: null };
97
+ });
98
+ this.callBeforeSaveHooks = (
99
+ // resource: AdminForthResource, action: AllowedActionsEnum, record: any,
100
+ // adminUser: AdminUser, recordId?: any, extra?: HttpExtra
101
+ resource, action, record, adminUser, recordId, updates, oldRecord, adminforth, extra) => __awaiter(this, void 0, void 0, function* () {
102
+ let hooks = [];
103
+ if (action === AllowedActionsEnum.create) {
104
+ hooks = resource.hooks.create.beforeSave;
105
+ }
106
+ else if (action === AllowedActionsEnum.edit) {
107
+ hooks = resource.hooks.edit.beforeSave;
108
+ }
109
+ else if (action === AllowedActionsEnum.delete) {
110
+ hooks = resource.hooks.delete.beforeSave;
111
+ }
112
+ if (extra === undefined) {
113
+ extra = {};
114
+ }
115
+ //@ts-ignore
116
+ extra.adminforth_plugin_crud_approve = {
117
+ //@ts-ignore
118
+ callingFromApprovalPlugin: true
119
+ //@ts-ignore
120
+ };
121
+ for (const hook of hooks) {
122
+ const resp = yield hook({
123
+ resource,
124
+ record,
125
+ adminUser,
126
+ recordId,
127
+ adminforth: this.adminforth,
128
+ extra,
129
+ updates,
130
+ oldRecord,
131
+ });
132
+ if (!resp || (typeof resp.ok !== 'boolean' && (!resp.error && !resp.newRecordId))) {
133
+ throw new Error(`Invalid return value from beforeSave hook. Expected: { ok: boolean, error?: string | null, newRecordId?: any }.\n` +
134
+ `Note: Return { ok: false, error: null, newRecordId } to stop creation and redirect to an existing record.`);
135
+ }
136
+ if (resp.ok === false && !resp.error) {
137
+ const { error, ok, newRecordId } = resp;
138
+ return {
139
+ error: error !== null && error !== void 0 ? error : 'Operation aborted by hook',
140
+ newRecordId: newRecordId
141
+ };
142
+ }
143
+ if (resp.error) {
144
+ return { error: resp.error };
145
+ }
146
+ }
147
+ return { ok: true, error: null };
148
+ });
149
+ this.callAfterSaveHooks = (
150
+ // resource: AdminForthResource, action: AllowedActionsEnum, record: any,
151
+ // adminUser: AdminUser, recordId: any, extra?: HttpExtra
152
+ resource, action, record, adminUser, recordId, updates, oldRecord, adminforth, extra) => __awaiter(this, void 0, void 0, function* () {
153
+ let hooks = [];
154
+ if (action === AllowedActionsEnum.create) {
155
+ hooks = resource.hooks.create.afterSave;
156
+ }
157
+ else if (action === AllowedActionsEnum.edit) {
158
+ hooks = resource.hooks.edit.afterSave;
159
+ }
160
+ else if (action === AllowedActionsEnum.delete) {
161
+ hooks = resource.hooks.delete.afterSave;
162
+ }
163
+ for (const hook of hooks) {
164
+ const resp = yield hook({
165
+ resource,
166
+ record,
167
+ adminUser,
168
+ recordId,
169
+ adminforth: this.adminforth,
170
+ extra,
171
+ updates,
172
+ oldRecord,
173
+ });
174
+ if (!resp || (!resp.ok && !resp.error)) {
175
+ throw new Error(`Hook afterSave must return object with {ok: true} or { error: 'Error' } `);
176
+ }
177
+ if (resp.error) {
178
+ return { error: resp.error };
179
+ }
180
+ }
181
+ });
182
+ this.verifyAuth = (cookies) => __awaiter(this, void 0, void 0, function* () {
183
+ let authCookie;
184
+ for (const i in cookies) {
185
+ if (cookies[i].key === `adminforth_${this.adminforth.config.customization.brandNameSlug}_jwt`) {
186
+ authCookie = cookies[i].value;
187
+ }
188
+ }
189
+ const authRes = yield this.adminforth.auth.verify(authCookie, 'auth', true);
190
+ if ('error' in authRes) {
191
+ return { error: authRes.error, authRes: null };
192
+ }
193
+ return { error: null, authRes: authRes };
194
+ });
195
+ this.createRecord = (resource, diffData, adminUser) => __awaiter(this, void 0, void 0, function* () {
196
+ const connector = this.adminforth.connectors[resource.dataSource];
197
+ //@ts-ignore
198
+ const err = this.adminforth.validateRecordValues(resource, diffData['newRecord'], 'create');
199
+ if (err) {
200
+ return { ok: false, error: err, createdRecord: null };
201
+ }
202
+ // remove virtual columns from record
203
+ for (const column of resource.columns.filter((col) => col.virtual)) {
204
+ if (diffData['newRecord'][column.name]) {
205
+ delete diffData['newRecord'][column.name];
206
+ }
207
+ }
208
+ return yield connector.createRecord({ resource, record: diffData['newRecord'], adminUser });
209
+ });
210
+ this.editRecord = (resource, diffData, targetRecordId, connector) => __awaiter(this, void 0, void 0, function* () {
211
+ let oldRecord;
212
+ const dataToUse = diffData['newRecord'];
213
+ //@ts-ignore
214
+ const err = this.adminforth.validateRecordValues(resource, dataToUse, 'edit', targetRecordId);
215
+ if (err) {
216
+ return { error: err };
217
+ }
218
+ // remove editReadonly columns from record
219
+ oldRecord = yield connector.getRecordByPrimaryKey(resource, targetRecordId);
220
+ for (const column of resource.columns.filter((col) => col.editReadonly)) {
221
+ if (column.name in dataToUse)
222
+ delete dataToUse[column.name];
223
+ }
224
+ const newValues = {};
225
+ for (const recordField in dataToUse) {
226
+ if (dataToUse[recordField] !== oldRecord[recordField]) {
227
+ // leave only changed fields to reduce data transfer/modifications in db
228
+ const column = resource.columns.find((col) => col.name === recordField);
229
+ if (!column || !column.virtual) {
230
+ // exclude virtual columns
231
+ newValues[recordField] = dataToUse[recordField];
232
+ }
233
+ }
234
+ }
235
+ if (Object.keys(newValues).length > 0) {
236
+ const { error } = yield connector.updateRecord({ resource, recordId: targetRecordId, newValues });
237
+ if (error) {
238
+ return { ok: false, error };
239
+ }
240
+ }
241
+ return { ok: true, error: null };
242
+ });
243
+ this.deleteRecord = (resource, targetRecordId, connector) => __awaiter(this, void 0, void 0, function* () {
244
+ return yield connector.deleteRecord({ resource, recordId: targetRecordId });
245
+ });
15
246
  this.options = options;
16
247
  }
17
248
  modifyResourceConfig(adminforth, resourceConfig) {
@@ -19,25 +250,31 @@ export default class CRUDApprovePlugin extends AdminForthPlugin {
19
250
  modifyResourceConfig: { get: () => super.modifyResourceConfig }
20
251
  });
21
252
  return __awaiter(this, void 0, void 0, function* () {
22
- _super.modifyResourceConfig.call(this, adminforth, resourceConfig);
23
253
  // simply modify resourceConfig or adminforth.config. You can get access to plugin options via this.options;
24
- });
25
- }
26
- createApprovalRequest(resource, action, oldData, newData, user, extra) {
27
- return __awaiter(this, void 0, void 0, function* () {
28
- // create a record in diff table with oldData and newData
29
- const record = {
30
- [this.options.resourceColumns.resourceIdColumnName]: resource.resourceId,
31
- [this.options.resourceColumns.resourceActionColumnName]: action,
32
- [this.options.resourceColumns.resourceOldDataColumnName]: oldData ? JSON.stringify(oldData) : null,
33
- [this.options.resourceColumns.resourceNewDataColumnName]: newData ? JSON.stringify(newData) : null,
34
- [this.options.resourceColumns.resourceStatusColumnName]: ApprovalStatusEnum.PENDING,
35
- [this.options.resourceColumns.resourceCreatedAtColumnName]: new Date().toISOString(),
36
- // You can add userId from extra if you have authentication implemented
37
- [this.options.resourceColumns.resourceUserIdColumnName]: user.pk,
254
+ _super.modifyResourceConfig.call(this, adminforth, resourceConfig);
255
+ this.adminforth = adminforth;
256
+ this.diffResource = this.resourceConfig;
257
+ let diffColumn = resourceConfig.columns.find((c) => c.name === this.options.resourceColumns.dataColumnName);
258
+ if (!diffColumn) {
259
+ throw new Error(`Column ${this.options.resourceColumns.dataColumnName} not found in ${resourceConfig.label}`);
260
+ }
261
+ if (diffColumn.type !== AdminForthDataTypes.JSON) {
262
+ // throw new Error(`Column ${this.options.resourceColumns.dataColumnName} must be of type 'json'`)
263
+ }
264
+ diffColumn.components = {
265
+ show: {
266
+ file: this.componentPath('ShowPageDiffView.vue'),
267
+ meta: Object.assign(Object.assign({}, this.options), { pluginInstanceId: this.pluginInstanceId })
268
+ },
269
+ list: {
270
+ file: this.componentPath('ListPageDiffView.vue'),
271
+ meta: Object.assign(Object.assign({}, this.options), { pluginInstanceId: this.pluginInstanceId })
272
+ }
273
+ };
274
+ resourceConfig.options.defaultSort = {
275
+ columnName: this.options.resourceColumns.createdAtColumnName,
276
+ direction: AdminForthSortDirections.desc
38
277
  };
39
- const approvalResource = this.adminforth.config.resources.find(r => r.resourceId === this.options.diffTableName);
40
- yield this.adminforth.createResourceRecord({ resource: approvalResource, record, adminUser: user });
41
278
  });
42
279
  }
43
280
  validateConfigAfterDiscover(adminforth, resourceConfig) {
@@ -48,4 +285,119 @@ export default class CRUDApprovePlugin extends AdminForthPlugin {
48
285
  // Needed if plugin can have multiple instances on one resource
49
286
  return `single`;
50
287
  }
288
+ setupEndpoints(server) {
289
+ server.endpoint({
290
+ method: 'POST',
291
+ path: `/plugin/crud-approve/update-status`,
292
+ noAuth: true,
293
+ handler: (_a) => __awaiter(this, [_a], void 0, function* ({ body, response, cookies }) {
294
+ const authRes = yield this.verifyAuth(cookies);
295
+ if (authRes.error) {
296
+ //@ts-ignore
297
+ response.status = 403;
298
+ return { error: authRes.error };
299
+ }
300
+ const adminUser = authRes.authRes;
301
+ const { resourceId, diffId, recordId, action, approved, code } = body;
302
+ const diffRecord = yield this.adminforth.resource(this.diffResource.resourceId).get(Filters.EQ(this.options.resourceColumns.idColumnName, diffId));
303
+ if (!diffRecord) {
304
+ //@ts-ignore
305
+ response.status = 404;
306
+ return { error: 'Diff record not found' };
307
+ }
308
+ if (diffRecord[this.options.resourceColumns.statusColumnName] !== ApprovalStatusEnum.pending) {
309
+ //@ts-ignore
310
+ response.status = 400;
311
+ return { error: 'Diff record is not pending' };
312
+ }
313
+ let beforeSaveResp;
314
+ if (approved === true) {
315
+ const resource = this.adminforth.config.resources.find((res) => res.resourceId == diffRecord[this.options.resourceColumns.resourceIdColumnName]);
316
+ const diffData = diffRecord[this.options.resourceColumns.dataColumnName];
317
+ const extra = diffRecord[this.options.resourceColumns.extraColumnName] || {};
318
+ extra.body = body;
319
+ extra.cookies = cookies;
320
+ let oldRecord = undefined;
321
+ if (action !== AllowedActionsEnum.create) {
322
+ oldRecord = yield this.adminforth.connectors[resource.dataSource].getRecordByPrimaryKey(resource, diffRecord[this.options.resourceColumns.recordIdColumnName]);
323
+ }
324
+ beforeSaveResp = yield this.callBeforeSaveHooks(resource, action, diffData['newRecord'], adminUser, diffRecord[this.options.resourceColumns.recordIdColumnName], diffData['newRecord'], oldRecord, this.adminforth, extra);
325
+ if (beforeSaveResp.error && beforeSaveResp.error !== 'Operation aborted by hook') {
326
+ //@ts-ignore
327
+ response.status = 500;
328
+ return { error: `Failed to apply approved changes: ${beforeSaveResp.error}` };
329
+ }
330
+ if (beforeSaveResp.error !== 'Operation aborted by hook') {
331
+ let recordUpdateResult;
332
+ const connector = this.adminforth.connectors[resource.dataSource];
333
+ if (action === AllowedActionsEnum.create) {
334
+ recordUpdateResult = yield this.createRecord(resource, diffData, adminUser);
335
+ }
336
+ else if (action === AllowedActionsEnum.edit) {
337
+ recordUpdateResult = yield this.editRecord(resource, diffData, diffRecord[this.options.resourceColumns.recordIdColumnName], connector);
338
+ }
339
+ else if (action === AllowedActionsEnum.delete) {
340
+ recordUpdateResult = yield this.deleteRecord(resource, diffRecord[this.options.resourceColumns.recordIdColumnName], connector);
341
+ }
342
+ if (recordUpdateResult === null || recordUpdateResult === void 0 ? void 0 : recordUpdateResult.error) {
343
+ //@ts-ignore
344
+ response.status = 500;
345
+ console.error('Error applying approved changes:', recordUpdateResult);
346
+ return { error: `Failed to apply approved changes: ${recordUpdateResult.error}` };
347
+ }
348
+ let afterSaveResp;
349
+ if (action === AllowedActionsEnum.create) {
350
+ const newRecord = recordUpdateResult.createdRecord;
351
+ afterSaveResp = yield this.callAfterSaveHooks(resource, action, newRecord, adminUser, diffRecord[this.options.resourceColumns.recordIdColumnName],
352
+ //@ts-ignore
353
+ newRecord, {}, this.adminforth, { body });
354
+ }
355
+ else if (action === AllowedActionsEnum.edit) {
356
+ const newRecord = diffData['newRecord'];
357
+ const oldRecord = yield this.adminforth.connectors[resource.dataSource].getRecordByPrimaryKey(resource, diffRecord[this.options.resourceColumns.recordIdColumnName]);
358
+ afterSaveResp = yield this.callAfterSaveHooks(resource, action, newRecord, adminUser,
359
+ //@ts-ignore
360
+ recordId, newRecord, oldRecord, this.adminforth, { body });
361
+ }
362
+ else if (action === AllowedActionsEnum.delete) {
363
+ const newRecord = diffData['newRecord'];
364
+ afterSaveResp = yield this.callAfterSaveHooks(resource, action, newRecord, adminUser, diffRecord[this.options.resourceColumns.recordIdColumnName],
365
+ //@ts-ignore
366
+ {}, diffData['oldRecord'], this.adminforth, { body });
367
+ }
368
+ if (afterSaveResp === null || afterSaveResp === void 0 ? void 0 : afterSaveResp.error) {
369
+ //@ts-ignore
370
+ response.status = 500;
371
+ return { error: `Failed to apply approved changes: ${afterSaveResp.error}` };
372
+ }
373
+ }
374
+ }
375
+ const r = yield this.adminforth.updateResourceRecord({
376
+ resource: this.diffResource, recordId: diffId,
377
+ adminUser: adminUser, oldRecord: diffRecord,
378
+ updates: {
379
+ [this.options.resourceColumns.statusColumnName]: approved ? ApprovalStatusEnum.approved : ApprovalStatusEnum.rejected,
380
+ [this.options.resourceColumns.responserIdColumnName]: authRes.authRes.pk,
381
+ },
382
+ extra: {
383
+ //@ts-ignore
384
+ adminforth_plugin_crud_approve: {
385
+ //@ts-ignore
386
+ callingFromApprovalPlugin: true
387
+ //@ts-ignore
388
+ }
389
+ }
390
+ });
391
+ if (r.error) {
392
+ //@ts-ignore
393
+ response.status = 500;
394
+ return { error: `Failed to update diff record status: ${r.error}` };
395
+ }
396
+ if ((beforeSaveResp === null || beforeSaveResp === void 0 ? void 0 : beforeSaveResp.error) === 'Operation aborted by hook') {
397
+ return beforeSaveResp;
398
+ }
399
+ return { ok: true };
400
+ })
401
+ });
402
+ }
51
403
  }
package/dist/types.js CHANGED
@@ -1,6 +1,13 @@
1
+ export var AllowedForReviewActionsEnum;
2
+ (function (AllowedForReviewActionsEnum) {
3
+ AllowedForReviewActionsEnum["create"] = "create";
4
+ AllowedForReviewActionsEnum["edit"] = "edit";
5
+ AllowedForReviewActionsEnum["delete"] = "delete";
6
+ AllowedForReviewActionsEnum["custom"] = "custom";
7
+ })(AllowedForReviewActionsEnum || (AllowedForReviewActionsEnum = {}));
1
8
  export var ApprovalStatusEnum;
2
9
  (function (ApprovalStatusEnum) {
3
- ApprovalStatusEnum["PENDING"] = "pending";
4
- ApprovalStatusEnum["APPROVED"] = "approved";
5
- ApprovalStatusEnum["REJECTED"] = "rejected";
10
+ ApprovalStatusEnum[ApprovalStatusEnum["pending"] = 1] = "pending";
11
+ ApprovalStatusEnum[ApprovalStatusEnum["approved"] = 2] = "approved";
12
+ ApprovalStatusEnum[ApprovalStatusEnum["rejected"] = 3] = "rejected";
6
13
  })(ApprovalStatusEnum || (ApprovalStatusEnum = {}));
package/index.ts CHANGED
@@ -58,6 +58,7 @@ export default class CRUDApprovePlugin extends AdminForthPlugin {
58
58
  {resource, action, data, user, oldRecord, updates, extra, record}:
59
59
  {resource: AdminForthResource, action: AllowedForReviewActionsEnum, data: Object, user: AdminUser, record?: Object, oldRecord?: Object, updates?: Object, extra?: HttpExtra}
60
60
  ) => {
61
+ //@ts-ignore
61
62
  if (extra && extra.adminforth_plugin_crud_approve && extra.adminforth_plugin_crud_approve.callingFromApprovalPlugin) {
62
63
  return { ok: true, error: 'Approval request creation aborted to avoid infinite loop' };
63
64
  }
@@ -168,8 +169,11 @@ export default class CRUDApprovePlugin extends AdminForthPlugin {
168
169
  if (extra === undefined) {
169
170
  extra = {};
170
171
  }
172
+ //@ts-ignore
171
173
  extra.adminforth_plugin_crud_approve = {
174
+ //@ts-ignore
172
175
  callingFromApprovalPlugin: true
176
+ //@ts-ignore
173
177
  }
174
178
  for (const hook of hooks) {
175
179
  const resp = await hook({
@@ -263,6 +267,7 @@ export default class CRUDApprovePlugin extends AdminForthPlugin {
263
267
 
264
268
  createRecord = async (resource: AdminForthResource, diffData: any, adminUser: AdminUser) => {
265
269
  const connector = this.adminforth.connectors[resource.dataSource];
270
+ //@ts-ignore
266
271
  const err = this.adminforth.validateRecordValues(resource, diffData['newRecord'], 'create');
267
272
  if (err) {
268
273
  return { ok: false, error: err, createdRecord: null };
@@ -280,6 +285,7 @@ export default class CRUDApprovePlugin extends AdminForthPlugin {
280
285
  editRecord = async (resource: AdminForthResource, diffData: any, targetRecordId: any, connector: IAdminForthDataSourceConnectorBase) => {
281
286
  let oldRecord;
282
287
  const dataToUse = diffData['newRecord'];
288
+ //@ts-ignore
283
289
  const err = this.adminforth.validateRecordValues(resource, dataToUse, 'edit', targetRecordId);
284
290
  if (err) {
285
291
  return { error: err };
@@ -323,6 +329,7 @@ export default class CRUDApprovePlugin extends AdminForthPlugin {
323
329
  handler: async ({ body, response, cookies }) => {
324
330
  const authRes = await this.verifyAuth(cookies);
325
331
  if (authRes.error) {
332
+ //@ts-ignore
326
333
  response.status = 403;
327
334
  return { error: authRes.error };
328
335
  }
@@ -333,11 +340,13 @@ export default class CRUDApprovePlugin extends AdminForthPlugin {
333
340
  Filters.EQ(this.options.resourceColumns.idColumnName, diffId),
334
341
  )
335
342
  if (!diffRecord) {
343
+ //@ts-ignore
336
344
  response.status = 404;
337
345
  return { error: 'Diff record not found' };
338
346
  }
339
347
 
340
348
  if (diffRecord[this.options.resourceColumns.statusColumnName] !== ApprovalStatusEnum.pending) {
349
+ //@ts-ignore
341
350
  response.status = 400;
342
351
  return { error: 'Diff record is not pending' };
343
352
  }
@@ -362,6 +371,7 @@ export default class CRUDApprovePlugin extends AdminForthPlugin {
362
371
  diffData['newRecord'], oldRecord, this.adminforth, extra
363
372
  );
364
373
  if (beforeSaveResp.error && beforeSaveResp.error !== 'Operation aborted by hook') {
374
+ //@ts-ignore
365
375
  response.status = 500;
366
376
  return { error: `Failed to apply approved changes: ${beforeSaveResp.error}` };
367
377
  }
@@ -382,6 +392,7 @@ export default class CRUDApprovePlugin extends AdminForthPlugin {
382
392
  );
383
393
  }
384
394
  if (recordUpdateResult?.error) {
395
+ //@ts-ignore
385
396
  response.status = 500;
386
397
  console.error('Error applying approved changes:', recordUpdateResult);
387
398
  return { error: `Failed to apply approved changes: ${recordUpdateResult.error}` };
@@ -393,6 +404,7 @@ export default class CRUDApprovePlugin extends AdminForthPlugin {
393
404
  afterSaveResp = await this.callAfterSaveHooks(
394
405
  resource, action as AllowedActionsEnum, newRecord, adminUser,
395
406
  diffRecord[this.options.resourceColumns.recordIdColumnName],
407
+ //@ts-ignore
396
408
  newRecord, {}, this.adminforth, { body }
397
409
  );
398
410
  } else if (action === AllowedActionsEnum.edit) {
@@ -402,6 +414,7 @@ export default class CRUDApprovePlugin extends AdminForthPlugin {
402
414
  );
403
415
  afterSaveResp = await this.callAfterSaveHooks(
404
416
  resource, action as AllowedActionsEnum, newRecord, adminUser,
417
+ //@ts-ignore
405
418
  recordId, newRecord, oldRecord, this.adminforth, { body }
406
419
  );
407
420
  } else if (action === AllowedActionsEnum.delete) {
@@ -409,11 +422,13 @@ export default class CRUDApprovePlugin extends AdminForthPlugin {
409
422
  afterSaveResp = await this.callAfterSaveHooks(
410
423
  resource, action as AllowedActionsEnum, newRecord, adminUser,
411
424
  diffRecord[this.options.resourceColumns.recordIdColumnName],
425
+ //@ts-ignore
412
426
  {}, diffData['oldRecord'], this.adminforth, { body }
413
427
  );
414
428
  }
415
429
 
416
430
  if (afterSaveResp?.error) {
431
+ //@ts-ignore
417
432
  response.status = 500;
418
433
  return { error: `Failed to apply approved changes: ${afterSaveResp.error}` };
419
434
  }
@@ -427,12 +442,16 @@ export default class CRUDApprovePlugin extends AdminForthPlugin {
427
442
  [this.options.resourceColumns.responserIdColumnName]: authRes.authRes.pk,
428
443
  },
429
444
  extra: {
445
+ //@ts-ignore
430
446
  adminforth_plugin_crud_approve: {
447
+ //@ts-ignore
431
448
  callingFromApprovalPlugin: true
449
+ //@ts-ignore
432
450
  }
433
451
  }
434
452
  });
435
453
  if (r.error) {
454
+ //@ts-ignore
436
455
  response.status = 500;
437
456
  return { error: `Failed to update diff record status: ${r.error}` };
438
457
  }
@@ -443,4 +462,4 @@ export default class CRUDApprovePlugin extends AdminForthPlugin {
443
462
  }
444
463
  })
445
464
  }
446
- }
465
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@adminforth/crud-approve-plugin",
3
- "version": "1.0.13",
3
+ "version": "1.0.15",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -14,18 +14,16 @@
14
14
  "url": "https://github.com/devforth/af-crud-approve-plugin.git"
15
15
  },
16
16
  "scripts": {
17
- "build": "tsc && rsync -av --exclude 'node_modules' custom dist/",
18
- "prepare": "npm link adminforth"
17
+ "build": "tsc && rsync -av --exclude 'node_modules' custom dist/"
19
18
  },
20
19
  "author": "devforth",
21
20
  "license": "ISC",
22
21
  "dependencies": {
23
22
  "@adminforth/two-factors-auth": "^2.10.4",
24
- "adminforth": "next",
25
23
  "dayjs": "^1.11.11"
26
24
  },
27
25
  "peerDependencies": {
28
- "adminforth": "next"
26
+ "adminforth": "^3.1.2"
29
27
  },
30
28
  "release": {
31
29
  "plugins": [
@@ -36,6 +34,7 @@
36
34
  [
37
35
  "semantic-release-slack-bot",
38
36
  {
37
+ "packageName": "@adminforth/crud-approve-plugin",
39
38
  "notifyOnSuccess": true,
40
39
  "notifyOnFail": true,
41
40
  "slackIcon": ":package:",
@@ -53,6 +52,7 @@
53
52
  },
54
53
  "devDependencies": {
55
54
  "@types/node": "^22.10.7",
55
+ "adminforth": "^3.1.2",
56
56
  "semantic-release": "^24.2.1",
57
57
  "semantic-release-slack-bot": "^4.0.2",
58
58
  "typescript": "^5.7.3"
@@ -0,0 +1,4 @@
1
+ allowBuilds:
2
+ adminforth: true
3
+ minimumReleaseAgeExclude:
4
+ - adminforth