adminforth 2.27.0-next.49 → 2.27.0-next.50
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.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +4 -0
- package/dist/index.js.map +1 -1
- package/dist/modules/restApi.d.ts.map +1 -1
- package/dist/modules/restApi.js +436 -4
- package/dist/modules/restApi.js.map +1 -1
- package/dist/modules/utils.d.ts +1 -1
- package/dist/modules/utils.d.ts.map +1 -1
- package/dist/modules/utils.js +3 -5
- package/dist/modules/utils.js.map +1 -1
- package/dist/servers/express.d.ts +2 -6
- package/dist/servers/express.d.ts.map +1 -1
- package/dist/servers/express.js +42 -1
- package/dist/servers/express.js.map +1 -1
- package/dist/servers/openapi.d.ts +25 -0
- package/dist/servers/openapi.d.ts.map +1 -0
- package/dist/servers/openapi.js +126 -0
- package/dist/servers/openapi.js.map +1 -0
- package/dist/spa/package.json +1 -0
- package/dist/spa/src/components/ResourceListTable.vue +1 -1
- package/dist/spa/src/types/Back.ts +63 -21
- package/dist/types/Back.d.ts +73 -16
- package/dist/types/Back.d.ts.map +1 -1
- package/dist/types/Back.js.map +1 -1
- package/package.json +2 -1
package/dist/modules/restApi.js
CHANGED
|
@@ -3,7 +3,7 @@ import { cascadeChildrenDelete } from './utils.js';
|
|
|
3
3
|
import { afLogger } from "./logger.js";
|
|
4
4
|
import { ADMINFORTH_VERSION, listify, getLoginPromptHTML, hookResponseError } from './utils.js';
|
|
5
5
|
import AdminForthAuth from "../auth.js";
|
|
6
|
-
import { ActionCheckSource, AdminForthDataTypes, AdminForthFilterOperators, AdminForthResourcePages, AllowedActionsEnum } from "../types/Common.js";
|
|
6
|
+
import { ActionCheckSource, AdminForthDataTypes, AdminForthFilterOperators, AdminForthResourcePages, AdminForthSortDirections, AllowedActionsEnum } from "../types/Common.js";
|
|
7
7
|
import { filtersTools } from "../modules/filtersTools.js";
|
|
8
8
|
async function resolveBoolOrFn(val, ctx) {
|
|
9
9
|
if (typeof val === 'function') {
|
|
@@ -26,6 +26,406 @@ async function isFilledOnCreate(col) {
|
|
|
26
26
|
const fillOnCreate = !!col.fillOnCreate;
|
|
27
27
|
return fillOnCreate;
|
|
28
28
|
}
|
|
29
|
+
const SIMPLE_FILTER_OPERATORS = Object.values(AdminForthFilterOperators).filter((operator) => {
|
|
30
|
+
return operator !== AdminForthFilterOperators.AND && operator !== AdminForthFilterOperators.OR;
|
|
31
|
+
});
|
|
32
|
+
const genericObjectSchema = {
|
|
33
|
+
type: 'object',
|
|
34
|
+
additionalProperties: true,
|
|
35
|
+
};
|
|
36
|
+
const errorResponseSchema = {
|
|
37
|
+
type: 'object',
|
|
38
|
+
required: ['error'],
|
|
39
|
+
properties: {
|
|
40
|
+
error: { type: 'string' },
|
|
41
|
+
},
|
|
42
|
+
additionalProperties: true,
|
|
43
|
+
};
|
|
44
|
+
const recordIdentifierSchema = {
|
|
45
|
+
anyOf: [
|
|
46
|
+
{ type: 'string' },
|
|
47
|
+
{ type: 'number' },
|
|
48
|
+
],
|
|
49
|
+
};
|
|
50
|
+
const actionIdentifierSchema = {
|
|
51
|
+
anyOf: [
|
|
52
|
+
{ type: 'string' },
|
|
53
|
+
{ type: 'number' },
|
|
54
|
+
],
|
|
55
|
+
};
|
|
56
|
+
const namedColumnSchema = {
|
|
57
|
+
type: 'object',
|
|
58
|
+
required: ['name'],
|
|
59
|
+
properties: {
|
|
60
|
+
name: { type: 'string' },
|
|
61
|
+
},
|
|
62
|
+
additionalProperties: true,
|
|
63
|
+
};
|
|
64
|
+
const validationResultSchema = {
|
|
65
|
+
type: 'object',
|
|
66
|
+
required: ['isValid'],
|
|
67
|
+
properties: {
|
|
68
|
+
isValid: { type: 'boolean' },
|
|
69
|
+
message: { type: 'string' },
|
|
70
|
+
},
|
|
71
|
+
additionalProperties: true,
|
|
72
|
+
};
|
|
73
|
+
const commonFilterSchemaDefs = {
|
|
74
|
+
singleFilter: {
|
|
75
|
+
type: 'object',
|
|
76
|
+
properties: {
|
|
77
|
+
field: { type: 'string' },
|
|
78
|
+
operator: { type: 'string', enum: SIMPLE_FILTER_OPERATORS },
|
|
79
|
+
value: {},
|
|
80
|
+
rightField: { type: 'string' },
|
|
81
|
+
insecureRawSQL: { type: 'string' },
|
|
82
|
+
insecureRawNoSQL: {},
|
|
83
|
+
},
|
|
84
|
+
additionalProperties: true,
|
|
85
|
+
},
|
|
86
|
+
filterNode: {
|
|
87
|
+
anyOf: [
|
|
88
|
+
{ $ref: '#/$defs/singleFilter' },
|
|
89
|
+
{
|
|
90
|
+
type: 'object',
|
|
91
|
+
required: ['operator', 'subFilters'],
|
|
92
|
+
properties: {
|
|
93
|
+
operator: {
|
|
94
|
+
type: 'string',
|
|
95
|
+
enum: [AdminForthFilterOperators.AND, AdminForthFilterOperators.OR],
|
|
96
|
+
},
|
|
97
|
+
subFilters: {
|
|
98
|
+
type: 'array',
|
|
99
|
+
items: { $ref: '#/$defs/filterNode' },
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
additionalProperties: true,
|
|
103
|
+
},
|
|
104
|
+
],
|
|
105
|
+
},
|
|
106
|
+
sortItem: {
|
|
107
|
+
type: 'object',
|
|
108
|
+
required: ['field', 'direction'],
|
|
109
|
+
properties: {
|
|
110
|
+
field: { type: 'string' },
|
|
111
|
+
direction: { type: 'string', enum: Object.values(AdminForthSortDirections) },
|
|
112
|
+
},
|
|
113
|
+
additionalProperties: true,
|
|
114
|
+
},
|
|
115
|
+
};
|
|
116
|
+
const commonSortSchema = {
|
|
117
|
+
type: 'array',
|
|
118
|
+
items: { $ref: '#/$defs/sortItem' },
|
|
119
|
+
};
|
|
120
|
+
const commonFiltersSchema = {
|
|
121
|
+
oneOf: [
|
|
122
|
+
{
|
|
123
|
+
type: 'array',
|
|
124
|
+
items: { $ref: '#/$defs/filterNode' },
|
|
125
|
+
},
|
|
126
|
+
{ $ref: '#/$defs/filterNode' },
|
|
127
|
+
],
|
|
128
|
+
};
|
|
129
|
+
function createErrorOrSuccessSchema(successSchema) {
|
|
130
|
+
return {
|
|
131
|
+
anyOf: [
|
|
132
|
+
errorResponseSchema,
|
|
133
|
+
successSchema,
|
|
134
|
+
],
|
|
135
|
+
};
|
|
136
|
+
}
|
|
137
|
+
const getResourceDataRequestSchema = {
|
|
138
|
+
type: 'object',
|
|
139
|
+
$defs: commonFilterSchemaDefs,
|
|
140
|
+
required: ['resourceId', 'source', 'limit', 'offset', 'filters', 'sort'],
|
|
141
|
+
properties: {
|
|
142
|
+
resourceId: { type: 'string' },
|
|
143
|
+
source: { type: 'string', enum: ['show', 'list', 'edit'] },
|
|
144
|
+
limit: { type: 'integer' },
|
|
145
|
+
offset: { type: 'integer' },
|
|
146
|
+
sort: commonSortSchema,
|
|
147
|
+
filters: commonFiltersSchema,
|
|
148
|
+
},
|
|
149
|
+
additionalProperties: true,
|
|
150
|
+
allOf: [
|
|
151
|
+
{
|
|
152
|
+
if: {
|
|
153
|
+
properties: {
|
|
154
|
+
source: { enum: ['show', 'edit'] },
|
|
155
|
+
},
|
|
156
|
+
required: ['source'],
|
|
157
|
+
},
|
|
158
|
+
then: {
|
|
159
|
+
properties: {
|
|
160
|
+
filters: {
|
|
161
|
+
type: 'array',
|
|
162
|
+
items: {
|
|
163
|
+
allOf: [
|
|
164
|
+
{ $ref: '#/$defs/singleFilter' },
|
|
165
|
+
{
|
|
166
|
+
type: 'object',
|
|
167
|
+
required: ['field'],
|
|
168
|
+
},
|
|
169
|
+
],
|
|
170
|
+
},
|
|
171
|
+
},
|
|
172
|
+
},
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
],
|
|
176
|
+
};
|
|
177
|
+
const getResourceDataResponseSchema = createErrorOrSuccessSchema({
|
|
178
|
+
type: 'object',
|
|
179
|
+
required: ['data'],
|
|
180
|
+
properties: {
|
|
181
|
+
data: {
|
|
182
|
+
type: 'array',
|
|
183
|
+
items: genericObjectSchema,
|
|
184
|
+
},
|
|
185
|
+
total: { type: 'number' },
|
|
186
|
+
options: genericObjectSchema,
|
|
187
|
+
},
|
|
188
|
+
additionalProperties: true,
|
|
189
|
+
});
|
|
190
|
+
const getMenuBadgesResponseSchema = {
|
|
191
|
+
type: 'object',
|
|
192
|
+
additionalProperties: {
|
|
193
|
+
anyOf: [
|
|
194
|
+
{ type: 'string' },
|
|
195
|
+
{ type: 'number' },
|
|
196
|
+
],
|
|
197
|
+
},
|
|
198
|
+
};
|
|
199
|
+
const getResourceRequestSchema = {
|
|
200
|
+
type: 'object',
|
|
201
|
+
required: ['resourceId'],
|
|
202
|
+
properties: {
|
|
203
|
+
resourceId: { type: 'string' },
|
|
204
|
+
},
|
|
205
|
+
additionalProperties: true,
|
|
206
|
+
};
|
|
207
|
+
const getResourceResponseSchema = createErrorOrSuccessSchema({
|
|
208
|
+
type: 'object',
|
|
209
|
+
required: ['resource'],
|
|
210
|
+
properties: {
|
|
211
|
+
resource: genericObjectSchema,
|
|
212
|
+
},
|
|
213
|
+
additionalProperties: true,
|
|
214
|
+
});
|
|
215
|
+
const getResourceForeignDataRequestSchema = {
|
|
216
|
+
type: 'object',
|
|
217
|
+
$defs: commonFilterSchemaDefs,
|
|
218
|
+
required: ['resourceId', 'column', 'limit', 'offset'],
|
|
219
|
+
properties: {
|
|
220
|
+
resourceId: { type: 'string' },
|
|
221
|
+
column: { type: 'string' },
|
|
222
|
+
limit: { type: 'integer' },
|
|
223
|
+
offset: { type: 'integer' },
|
|
224
|
+
search: { type: 'string' },
|
|
225
|
+
filters: commonFiltersSchema,
|
|
226
|
+
sort: commonSortSchema,
|
|
227
|
+
},
|
|
228
|
+
additionalProperties: true,
|
|
229
|
+
};
|
|
230
|
+
const getResourceForeignDataResponseSchema = createErrorOrSuccessSchema({
|
|
231
|
+
type: 'object',
|
|
232
|
+
required: ['items'],
|
|
233
|
+
properties: {
|
|
234
|
+
items: {
|
|
235
|
+
type: 'array',
|
|
236
|
+
items: {
|
|
237
|
+
type: 'object',
|
|
238
|
+
required: ['value', 'label'],
|
|
239
|
+
properties: {
|
|
240
|
+
value: {},
|
|
241
|
+
label: { type: 'string' },
|
|
242
|
+
},
|
|
243
|
+
additionalProperties: true,
|
|
244
|
+
},
|
|
245
|
+
},
|
|
246
|
+
},
|
|
247
|
+
additionalProperties: true,
|
|
248
|
+
});
|
|
249
|
+
const getMinMaxForColumnsRequestSchema = {
|
|
250
|
+
type: 'object',
|
|
251
|
+
required: ['resourceId'],
|
|
252
|
+
properties: {
|
|
253
|
+
resourceId: { type: 'string' },
|
|
254
|
+
},
|
|
255
|
+
additionalProperties: true,
|
|
256
|
+
};
|
|
257
|
+
const getMinMaxForColumnsResponseSchema = createErrorOrSuccessSchema({
|
|
258
|
+
type: 'object',
|
|
259
|
+
additionalProperties: {
|
|
260
|
+
type: 'object',
|
|
261
|
+
required: ['min', 'max'],
|
|
262
|
+
properties: {
|
|
263
|
+
min: {},
|
|
264
|
+
max: {},
|
|
265
|
+
},
|
|
266
|
+
additionalProperties: true,
|
|
267
|
+
},
|
|
268
|
+
});
|
|
269
|
+
const createRecordRequestSchema = {
|
|
270
|
+
type: 'object',
|
|
271
|
+
required: ['resourceId', 'record', 'requiredColumnsToSkip'],
|
|
272
|
+
properties: {
|
|
273
|
+
resourceId: { type: 'string' },
|
|
274
|
+
record: genericObjectSchema,
|
|
275
|
+
requiredColumnsToSkip: {
|
|
276
|
+
type: 'array',
|
|
277
|
+
items: namedColumnSchema,
|
|
278
|
+
},
|
|
279
|
+
meta: genericObjectSchema,
|
|
280
|
+
},
|
|
281
|
+
additionalProperties: true,
|
|
282
|
+
};
|
|
283
|
+
const createRecordResponseSchema = createErrorOrSuccessSchema({
|
|
284
|
+
type: 'object',
|
|
285
|
+
required: ['ok', 'newRecordId', 'redirectToRecordId'],
|
|
286
|
+
properties: {
|
|
287
|
+
ok: { const: true },
|
|
288
|
+
newRecordId: recordIdentifierSchema,
|
|
289
|
+
redirectToRecordId: recordIdentifierSchema,
|
|
290
|
+
},
|
|
291
|
+
additionalProperties: true,
|
|
292
|
+
});
|
|
293
|
+
const updateRecordRequestSchema = {
|
|
294
|
+
type: 'object',
|
|
295
|
+
required: ['resourceId', 'recordId', 'record'],
|
|
296
|
+
properties: {
|
|
297
|
+
resourceId: { type: 'string' },
|
|
298
|
+
recordId: recordIdentifierSchema,
|
|
299
|
+
record: genericObjectSchema,
|
|
300
|
+
meta: genericObjectSchema,
|
|
301
|
+
},
|
|
302
|
+
additionalProperties: true,
|
|
303
|
+
};
|
|
304
|
+
const updateRecordResponseSchema = createErrorOrSuccessSchema({
|
|
305
|
+
type: 'object',
|
|
306
|
+
required: ['ok'],
|
|
307
|
+
properties: {
|
|
308
|
+
ok: { const: true },
|
|
309
|
+
recordId: recordIdentifierSchema,
|
|
310
|
+
},
|
|
311
|
+
additionalProperties: true,
|
|
312
|
+
});
|
|
313
|
+
const deleteRecordRequestSchema = {
|
|
314
|
+
type: 'object',
|
|
315
|
+
required: ['resourceId', 'primaryKey'],
|
|
316
|
+
properties: {
|
|
317
|
+
resourceId: { type: 'string' },
|
|
318
|
+
primaryKey: recordIdentifierSchema,
|
|
319
|
+
},
|
|
320
|
+
additionalProperties: true,
|
|
321
|
+
};
|
|
322
|
+
const deleteRecordResponseSchema = createErrorOrSuccessSchema({
|
|
323
|
+
type: 'object',
|
|
324
|
+
required: ['ok', 'recordId'],
|
|
325
|
+
properties: {
|
|
326
|
+
ok: { const: true },
|
|
327
|
+
recordId: recordIdentifierSchema,
|
|
328
|
+
},
|
|
329
|
+
additionalProperties: true,
|
|
330
|
+
});
|
|
331
|
+
const startCustomActionRequestSchema = {
|
|
332
|
+
type: 'object',
|
|
333
|
+
required: ['resourceId', 'actionId', 'recordId'],
|
|
334
|
+
properties: {
|
|
335
|
+
resourceId: { type: 'string' },
|
|
336
|
+
actionId: actionIdentifierSchema,
|
|
337
|
+
recordId: recordIdentifierSchema,
|
|
338
|
+
extra: genericObjectSchema,
|
|
339
|
+
},
|
|
340
|
+
additionalProperties: true,
|
|
341
|
+
};
|
|
342
|
+
const startCustomActionResponseSchema = {
|
|
343
|
+
anyOf: [
|
|
344
|
+
errorResponseSchema,
|
|
345
|
+
{
|
|
346
|
+
type: 'object',
|
|
347
|
+
required: ['actionId', 'resourceId', 'recordId', 'redirectUrl'],
|
|
348
|
+
properties: {
|
|
349
|
+
actionId: actionIdentifierSchema,
|
|
350
|
+
resourceId: { type: 'string' },
|
|
351
|
+
recordId: recordIdentifierSchema,
|
|
352
|
+
redirectUrl: { type: 'string' },
|
|
353
|
+
},
|
|
354
|
+
additionalProperties: true,
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
type: 'object',
|
|
358
|
+
required: ['actionId', 'resourceId', 'recordId', 'ok'],
|
|
359
|
+
properties: {
|
|
360
|
+
actionId: actionIdentifierSchema,
|
|
361
|
+
resourceId: { type: 'string' },
|
|
362
|
+
recordId: recordIdentifierSchema,
|
|
363
|
+
ok: { const: true },
|
|
364
|
+
},
|
|
365
|
+
additionalProperties: true,
|
|
366
|
+
},
|
|
367
|
+
],
|
|
368
|
+
};
|
|
369
|
+
const startCustomBulkActionRequestSchema = {
|
|
370
|
+
type: 'object',
|
|
371
|
+
required: ['resourceId', 'actionId', 'recordIds'],
|
|
372
|
+
properties: {
|
|
373
|
+
resourceId: { type: 'string' },
|
|
374
|
+
actionId: actionIdentifierSchema,
|
|
375
|
+
recordIds: {
|
|
376
|
+
type: 'array',
|
|
377
|
+
items: recordIdentifierSchema,
|
|
378
|
+
},
|
|
379
|
+
extra: genericObjectSchema,
|
|
380
|
+
},
|
|
381
|
+
additionalProperties: true,
|
|
382
|
+
};
|
|
383
|
+
const startCustomBulkActionResponseSchema = createErrorOrSuccessSchema({
|
|
384
|
+
type: 'object',
|
|
385
|
+
required: ['actionId', 'resourceId', 'recordIds', 'ok'],
|
|
386
|
+
properties: {
|
|
387
|
+
actionId: actionIdentifierSchema,
|
|
388
|
+
resourceId: { type: 'string' },
|
|
389
|
+
recordIds: {
|
|
390
|
+
type: 'array',
|
|
391
|
+
items: recordIdentifierSchema,
|
|
392
|
+
},
|
|
393
|
+
ok: { const: true },
|
|
394
|
+
},
|
|
395
|
+
additionalProperties: true,
|
|
396
|
+
});
|
|
397
|
+
const validateColumnsRequestSchema = {
|
|
398
|
+
type: 'object',
|
|
399
|
+
required: ['resourceId', 'editableColumns', 'record'],
|
|
400
|
+
properties: {
|
|
401
|
+
resourceId: { type: 'string' },
|
|
402
|
+
editableColumns: {
|
|
403
|
+
type: 'array',
|
|
404
|
+
items: {
|
|
405
|
+
type: 'object',
|
|
406
|
+
required: ['name'],
|
|
407
|
+
properties: {
|
|
408
|
+
name: { type: 'string' },
|
|
409
|
+
value: {},
|
|
410
|
+
},
|
|
411
|
+
additionalProperties: true,
|
|
412
|
+
},
|
|
413
|
+
},
|
|
414
|
+
record: genericObjectSchema,
|
|
415
|
+
},
|
|
416
|
+
additionalProperties: true,
|
|
417
|
+
};
|
|
418
|
+
const validateColumnsResponseSchema = createErrorOrSuccessSchema({
|
|
419
|
+
type: 'object',
|
|
420
|
+
required: ['validationResults'],
|
|
421
|
+
properties: {
|
|
422
|
+
validationResults: {
|
|
423
|
+
type: 'object',
|
|
424
|
+
additionalProperties: validationResultSchema,
|
|
425
|
+
},
|
|
426
|
+
},
|
|
427
|
+
additionalProperties: true,
|
|
428
|
+
});
|
|
29
429
|
export async function interpretResource(adminUser, resource, meta, source, adminforth) {
|
|
30
430
|
afLogger.trace(`🪲Interpreting resource, ${resource.resourceId}, ${source}, 'adminUser', ${adminUser}`);
|
|
31
431
|
const allowedActions = {};
|
|
@@ -182,7 +582,7 @@ export default class AdminForthRestAPI {
|
|
|
182
582
|
handler: async ({ tr }) => {
|
|
183
583
|
const loginPromptHTML = await getLoginPromptHTML(this.adminforth.config.auth.loginPromptHTML);
|
|
184
584
|
return {
|
|
185
|
-
loginPromptHTML: await tr(loginPromptHTML, 'system.loginPromptHTML'),
|
|
585
|
+
loginPromptHTML: loginPromptHTML ? await tr(loginPromptHTML, 'system.loginPromptHTML') : null,
|
|
186
586
|
};
|
|
187
587
|
}
|
|
188
588
|
});
|
|
@@ -222,7 +622,7 @@ export default class AdminForthRestAPI {
|
|
|
222
622
|
server.endpoint({
|
|
223
623
|
method: 'GET',
|
|
224
624
|
path: '/get_base_config',
|
|
225
|
-
handler: async ({
|
|
625
|
+
handler: async ({ adminUser, cookies, tr, response }) => {
|
|
226
626
|
var _a, _b, _c, _d, _e;
|
|
227
627
|
let username = '';
|
|
228
628
|
let userFullName = '';
|
|
@@ -385,6 +785,8 @@ export default class AdminForthRestAPI {
|
|
|
385
785
|
server.endpoint({
|
|
386
786
|
method: 'GET',
|
|
387
787
|
path: '/get_menu_badges',
|
|
788
|
+
description: 'Computes the current menu badge values for the authenticated admin user. Static badges are returned directly, and dynamic badge callbacks are resolved for all configured menu items, including nested items.',
|
|
789
|
+
response_schema: getMenuBadgesResponseSchema,
|
|
388
790
|
handler: async ({ adminUser }) => {
|
|
389
791
|
const badges = {};
|
|
390
792
|
const badgeFunctions = [];
|
|
@@ -421,6 +823,9 @@ export default class AdminForthRestAPI {
|
|
|
421
823
|
server.endpoint({
|
|
422
824
|
method: 'POST',
|
|
423
825
|
path: '/get_resource',
|
|
826
|
+
description: 'Returns the definition of a single resource. The response includes translated labels, column metadata, allowed actions, visible bulk actions, frontend action metadata, and resource options after permission checks and removal of backend-only internals.',
|
|
827
|
+
request_schema: getResourceRequestSchema,
|
|
828
|
+
response_schema: getResourceResponseSchema,
|
|
424
829
|
handler: async ({ body, adminUser, tr }) => {
|
|
425
830
|
var _a, _b;
|
|
426
831
|
const { resourceId } = body;
|
|
@@ -508,7 +913,7 @@ export default class AdminForthRestAPI {
|
|
|
508
913
|
col.foreignResource.unsetLabel = await tr(col.foreignResource.unsetLabel, `resource.${resource.resourceId}.foreignResource.unsetLabel`);
|
|
509
914
|
}
|
|
510
915
|
if (inCol.suggestOnCreate && typeof inCol.suggestOnCreate === 'function') {
|
|
511
|
-
col.suggestOnCreate = await inCol.suggestOnCreate(adminUser);
|
|
916
|
+
col.suggestOnCreate = await inCol.suggestOnCreate({ adminUser });
|
|
512
917
|
}
|
|
513
918
|
return Object.assign(Object.assign({}, col), { showIn,
|
|
514
919
|
validation, label: translated[`resCol${i}`], enum: enumItems });
|
|
@@ -526,6 +931,9 @@ export default class AdminForthRestAPI {
|
|
|
526
931
|
server.endpoint({
|
|
527
932
|
method: 'POST',
|
|
528
933
|
path: '/get_resource_data',
|
|
934
|
+
description: 'Loads resource rows for list, show, or edit views. The endpoint validates access, applies request hooks, filters, sorting, pagination, record labels, and row click URLs, then returns the final dataset with resource options.',
|
|
935
|
+
request_schema: getResourceDataRequestSchema,
|
|
936
|
+
response_schema: getResourceDataResponseSchema,
|
|
529
937
|
handler: async ({ body, adminUser, headers, query, cookies, requestUrl, abortSignal }) => {
|
|
530
938
|
var _a, _b, _c, _d, _e, _f;
|
|
531
939
|
const { resourceId, source } = body;
|
|
@@ -793,6 +1201,9 @@ export default class AdminForthRestAPI {
|
|
|
793
1201
|
server.endpoint({
|
|
794
1202
|
method: 'POST',
|
|
795
1203
|
path: '/get_resource_foreign_data',
|
|
1204
|
+
description: 'Loads dropdown options for a foreign-key column. It resolves the referenced resource or polymorphic resources, applies optional search text, hook-injected filters, pagination, and per-record labels, then returns sanitized option items.',
|
|
1205
|
+
request_schema: getResourceForeignDataRequestSchema,
|
|
1206
|
+
response_schema: getResourceForeignDataResponseSchema,
|
|
796
1207
|
handler: async ({ body, adminUser, headers, query, cookies, requestUrl }) => {
|
|
797
1208
|
const { resourceId, column, search } = body;
|
|
798
1209
|
if (!this.adminforth.statuses.dbDiscover) {
|
|
@@ -953,6 +1364,9 @@ export default class AdminForthRestAPI {
|
|
|
953
1364
|
server.endpoint({
|
|
954
1365
|
method: 'POST',
|
|
955
1366
|
path: '/get_min_max_for_columns',
|
|
1367
|
+
description: 'Returns min and max values for resource columns that explicitly opt in to min/max queries. This is used to build range-based filter controls without exposing columns that do not allow the query.',
|
|
1368
|
+
request_schema: getMinMaxForColumnsRequestSchema,
|
|
1369
|
+
response_schema: getMinMaxForColumnsResponseSchema,
|
|
956
1370
|
handler: async ({ body }) => {
|
|
957
1371
|
const { resourceId } = body;
|
|
958
1372
|
if (!this.adminforth.statuses.dbDiscover) {
|
|
@@ -982,6 +1396,9 @@ export default class AdminForthRestAPI {
|
|
|
982
1396
|
server.endpoint({
|
|
983
1397
|
method: 'POST',
|
|
984
1398
|
path: '/create_record',
|
|
1399
|
+
description: 'Creates a new record in the specified resource. The endpoint validates create permissions, required fields, hidden or backend-only field rules, polymorphic foreign keys, and resource hooks before persisting and returning the created primary key.',
|
|
1400
|
+
request_schema: createRecordRequestSchema,
|
|
1401
|
+
response_schema: createRecordResponseSchema,
|
|
985
1402
|
handler: async ({ body, adminUser, query, headers, cookies, requestUrl, response }) => {
|
|
986
1403
|
var _a, _b, _c, _d;
|
|
987
1404
|
const resource = this.adminforth.config.resources.find((res) => res.resourceId == body['resourceId']);
|
|
@@ -1111,6 +1528,9 @@ export default class AdminForthRestAPI {
|
|
|
1111
1528
|
server.endpoint({
|
|
1112
1529
|
method: 'POST',
|
|
1113
1530
|
path: '/update_record',
|
|
1531
|
+
description: 'Updates an existing record by primary key. The endpoint validates edit permissions, current record existence, hidden, backend-only, and read-only field rules, polymorphic foreign keys, and resource hooks before saving changes.',
|
|
1532
|
+
request_schema: updateRecordRequestSchema,
|
|
1533
|
+
response_schema: updateRecordResponseSchema,
|
|
1114
1534
|
handler: async ({ body, adminUser, query, headers, cookies, requestUrl, response }) => {
|
|
1115
1535
|
var _a, _b;
|
|
1116
1536
|
const resource = this.adminforth.config.resources.find((res) => res.resourceId == body['resourceId']);
|
|
@@ -1229,6 +1649,9 @@ export default class AdminForthRestAPI {
|
|
|
1229
1649
|
server.endpoint({
|
|
1230
1650
|
method: 'POST',
|
|
1231
1651
|
path: '/delete_record',
|
|
1652
|
+
description: 'Deletes an existing record by primary key. The endpoint validates delete permissions, loads the current record, executes configured cascade child deletion, and then removes the record.',
|
|
1653
|
+
request_schema: deleteRecordRequestSchema,
|
|
1654
|
+
response_schema: deleteRecordResponseSchema,
|
|
1232
1655
|
handler: async ({ body, adminUser, query, headers, cookies, requestUrl, response }) => {
|
|
1233
1656
|
const resource = this.adminforth.config.resources.find((res) => res.resourceId == body['resourceId']);
|
|
1234
1657
|
if (!resource) {
|
|
@@ -1289,6 +1712,9 @@ export default class AdminForthRestAPI {
|
|
|
1289
1712
|
server.endpoint({
|
|
1290
1713
|
method: 'POST',
|
|
1291
1714
|
path: '/start_custom_action',
|
|
1715
|
+
description: 'Executes a custom resource action for a single record. The endpoint validates the resource, action existence, and action permissions, then either returns a redirect URL or executes the action handler and returns its result together with action context.',
|
|
1716
|
+
request_schema: startCustomActionRequestSchema,
|
|
1717
|
+
response_schema: startCustomActionResponseSchema,
|
|
1292
1718
|
handler: async ({ body, adminUser, tr, cookies, response, headers }) => {
|
|
1293
1719
|
const { resourceId, actionId, recordId, extra } = body;
|
|
1294
1720
|
const resource = this.adminforth.config.resources.find((res) => res.resourceId == resourceId);
|
|
@@ -1323,6 +1749,9 @@ export default class AdminForthRestAPI {
|
|
|
1323
1749
|
server.endpoint({
|
|
1324
1750
|
method: 'POST',
|
|
1325
1751
|
path: '/start_custom_bulk_action',
|
|
1752
|
+
description: 'Executes a custom resource action in bulk mode for multiple records. The endpoint validates the resource, action existence, bulk handler availability, and permissions, then runs the bulk handler and returns its result together with action context.',
|
|
1753
|
+
request_schema: startCustomBulkActionRequestSchema,
|
|
1754
|
+
response_schema: startCustomBulkActionResponseSchema,
|
|
1326
1755
|
handler: async ({ body, adminUser, tr, response, cookies, headers }) => {
|
|
1327
1756
|
const { resourceId, actionId, recordIds, extra } = body;
|
|
1328
1757
|
const resource = this.adminforth.config.resources.find((res) => res.resourceId == resourceId);
|
|
@@ -1358,6 +1787,9 @@ export default class AdminForthRestAPI {
|
|
|
1358
1787
|
server.endpoint({
|
|
1359
1788
|
method: 'POST',
|
|
1360
1789
|
path: '/validate_columns',
|
|
1790
|
+
description: 'Runs server-side custom validators for editable columns in a resource form. Only validators defined on submitted columns are executed, and the response maps each invalid column to its validation result.',
|
|
1791
|
+
request_schema: validateColumnsRequestSchema,
|
|
1792
|
+
response_schema: validateColumnsResponseSchema,
|
|
1361
1793
|
handler: async ({ body, adminUser, query, headers, cookies, requestUrl, response }) => {
|
|
1362
1794
|
const { resourceId, editableColumns, record } = body;
|
|
1363
1795
|
const resource = this.adminforth.config.resources.find((res) => res.resourceId == resourceId);
|