adminforth 2.33.1 → 2.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/commands/createApp/templates/api.ts.hbs +25 -16
- package/commands/createApp/templates/package.json.hbs +2 -1
- package/dist/basePlugin.js +1 -1
- package/dist/basePlugin.js.map +1 -1
- 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 +495 -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 +18 -7
- package/dist/servers/express.d.ts.map +1 -1
- package/dist/servers/express.js +137 -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 +92 -0
- package/dist/servers/openapi.js.map +1 -0
- package/dist/servers/openapiDocument.d.ts +12 -0
- package/dist/servers/openapiDocument.d.ts.map +1 -0
- package/dist/servers/openapiDocument.js +313 -0
- package/dist/servers/openapiDocument.js.map +1 -0
- package/dist/spa/package.json +1 -0
- package/dist/spa/pnpm-lock.yaml +346 -310
- package/dist/spa/pnpm-workspace.yaml +4 -0
- package/dist/spa/src/App.vue +1 -0
- package/dist/spa/src/afcl/Skeleton.vue +1 -1
- package/dist/spa/src/stores/core.ts +15 -1
- package/dist/spa/src/types/Back.ts +109 -23
- package/dist/spa/src/types/adapters/CompletionAdapter.ts +10 -0
- package/dist/spa/src/views/CreateEditSkeleton.vue +49 -34
- package/dist/spa/src/views/EditView.vue +1 -1
- package/dist/types/Back.d.ts +113 -18
- package/dist/types/Back.d.ts.map +1 -1
- package/dist/types/Back.js.map +1 -1
- package/dist/types/adapters/CompletionAdapter.d.ts +8 -1
- package/dist/types/adapters/CompletionAdapter.d.ts.map +1 -1
- package/package.json +5 -2
package/dist/spa/src/App.vue
CHANGED
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
<div>
|
|
3
3
|
<nav
|
|
4
4
|
v-if="loggedIn && routerIsReady && loginRedirectCheckIsReady && defaultLayout"
|
|
5
|
+
id="af-header-nav"
|
|
5
6
|
class="fixed h-14 top-0 z-30 w-full border-b drop-shadow-sm bg-lightNavbar dark:bg-darkNavbar dark:border-darkSidebarDevider"
|
|
6
7
|
>
|
|
7
8
|
<div class="af-header px-3 lg:px-5 lg:pl-3 flex items-center justify-between h-full w-full" >
|
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
<div
|
|
18
18
|
v-else-if="type === 'input'"
|
|
19
19
|
role="input"
|
|
20
|
-
:class="['animate-pulse bg-gray-100 dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded', $attrs.class]"
|
|
20
|
+
:class="['animate-pulse bg-gray-100 dark:bg-gray-700 border border-gray-200 dark:border-gray-600 rounded-default', $attrs.class]"
|
|
21
21
|
></div>
|
|
22
22
|
<div v-else role="status" class="flex items-center justify-center animate-pulse bg-lightSkeletonIconColor rounded-full dark:bg-darkSkeletonBackgroundColor">
|
|
23
23
|
<span class="sr-only">Loading...</span>
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ref, computed } from 'vue'
|
|
1
|
+
import { ref, computed, onMounted, onUnmounted } from 'vue'
|
|
2
2
|
import { defineStore } from 'pinia'
|
|
3
3
|
import { callAdminForthApi } from '@/utils';
|
|
4
4
|
import websocket from '@/websocket';
|
|
@@ -21,6 +21,19 @@ export const useCoreStore = defineStore('core', () => {
|
|
|
21
21
|
const userData: Ref<UserData | null> = ref(null);
|
|
22
22
|
const isResourceFetching = ref(false);
|
|
23
23
|
const isInternetError = ref(false);
|
|
24
|
+
const screenWidth = ref(window.innerWidth);
|
|
25
|
+
|
|
26
|
+
onMounted(() => {
|
|
27
|
+
window.addEventListener('resize', updateWidth);
|
|
28
|
+
});
|
|
29
|
+
onUnmounted(() => {
|
|
30
|
+
window.removeEventListener('resize', updateWidth);
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
const isMobile = computed(() => screenWidth.value <= 768);
|
|
34
|
+
const updateWidth = () => {
|
|
35
|
+
screenWidth.value = window.innerWidth
|
|
36
|
+
}
|
|
24
37
|
|
|
25
38
|
const resourceColumnsWithFilters = computed(() => {
|
|
26
39
|
if (!resource.value) {
|
|
@@ -261,5 +274,6 @@ export const useCoreStore = defineStore('core', () => {
|
|
|
261
274
|
isResourceFetching,
|
|
262
275
|
isIos,
|
|
263
276
|
isInternetError,
|
|
277
|
+
isMobile,
|
|
264
278
|
}
|
|
265
279
|
})
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { Express, Request, Response } from 'express';
|
|
2
|
+
import type { AnySchemaObject } from 'ajv';
|
|
2
3
|
import type { Writable } from 'stream';
|
|
4
|
+
import type { ZodType } from 'zod';
|
|
3
5
|
|
|
4
6
|
import { ActionCheckSource, AdminForthFilterOperators, AdminForthSortDirections, AllowedActionsEnum, AdminForthResourcePages,
|
|
5
7
|
type AdminForthComponentDeclaration,
|
|
@@ -38,6 +40,81 @@ export interface IAdminForthHttpResponse {
|
|
|
38
40
|
blobStream: () => Writable,
|
|
39
41
|
};
|
|
40
42
|
|
|
43
|
+
export interface IAdminForthEndpointHandlerInput {
|
|
44
|
+
body: any;
|
|
45
|
+
adminUser: AdminUser | undefined;
|
|
46
|
+
query: {[key: string]: any};
|
|
47
|
+
headers: {[key: string]: any};
|
|
48
|
+
cookies: Array<{ key: string, value: string }>;
|
|
49
|
+
response: IAdminForthHttpResponse;
|
|
50
|
+
requestUrl: string;
|
|
51
|
+
abortSignal: AbortSignal;
|
|
52
|
+
_raw_express_req: Request;
|
|
53
|
+
_raw_express_res: Response;
|
|
54
|
+
tr: ITranslateFunction;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export interface IAdminForthEndpointOptions {
|
|
58
|
+
method: string,
|
|
59
|
+
noAuth?: boolean,
|
|
60
|
+
path: string,
|
|
61
|
+
description?: string,
|
|
62
|
+
request_schema?: AnySchemaObject,
|
|
63
|
+
response_schema?: AnySchemaObject,
|
|
64
|
+
responce_schema?: AnySchemaObject,
|
|
65
|
+
handler: (input: IAdminForthEndpointHandlerInput) => void | Promise<any>,
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export type AdminForthExpressSchemaInput = AnySchemaObject | ZodType;
|
|
69
|
+
|
|
70
|
+
export interface IAdminForthExpressRouteSchema {
|
|
71
|
+
/**
|
|
72
|
+
* Detailed OpenAPI operation description for a custom Express route.
|
|
73
|
+
*/
|
|
74
|
+
description?: string;
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* JSON schema or Zod schema describing the request body for a custom Express route.
|
|
78
|
+
*/
|
|
79
|
+
request?: AdminForthExpressSchemaInput;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* JSON schema or Zod schema describing the JSON response body for a custom Express route.
|
|
83
|
+
*/
|
|
84
|
+
response?: AdminForthExpressSchemaInput;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export interface IRegisteredApiSchema {
|
|
88
|
+
method: string;
|
|
89
|
+
path: string;
|
|
90
|
+
description?: string;
|
|
91
|
+
request_schema?: AnySchemaObject;
|
|
92
|
+
response_schema?: AnySchemaObject;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export interface IAdminForthApiValidationError {
|
|
96
|
+
instancePath: string;
|
|
97
|
+
schemaPath: string;
|
|
98
|
+
keyword: string;
|
|
99
|
+
message?: string;
|
|
100
|
+
params: {[key: string]: any};
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
export interface IAdminForthApiValidationResult {
|
|
104
|
+
valid: boolean;
|
|
105
|
+
errors?: IAdminForthApiValidationError[];
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export interface IOpenApiRegistry {
|
|
109
|
+
registeredSchemas: IRegisteredApiSchema[];
|
|
110
|
+
|
|
111
|
+
registerApiSchema(options: IAdminForthEndpointOptions): IRegisteredApiSchema;
|
|
112
|
+
register_api_schema(options: IAdminForthEndpointOptions): IRegisteredApiSchema;
|
|
113
|
+
validateRequestSchema(route: IRegisteredApiSchema | null, payload: any): IAdminForthApiValidationResult;
|
|
114
|
+
validateResponseSchema(route: IRegisteredApiSchema | null, payload: any): IAdminForthApiValidationResult;
|
|
115
|
+
renderOpenApiDocument(): {[key: string]: any};
|
|
116
|
+
}
|
|
117
|
+
|
|
41
118
|
/**
|
|
42
119
|
* Implement this interface to create custom HTTP server adapter for AdminForth.
|
|
43
120
|
*/
|
|
@@ -57,23 +134,7 @@ export interface IHttpServer {
|
|
|
57
134
|
*
|
|
58
135
|
* @param options : Object with method, path and handler properties.
|
|
59
136
|
*/
|
|
60
|
-
endpoint(options:
|
|
61
|
-
method: string,
|
|
62
|
-
noAuth?: boolean,
|
|
63
|
-
path: string,
|
|
64
|
-
handler: (
|
|
65
|
-
body: any,
|
|
66
|
-
adminUser: any,
|
|
67
|
-
query: {[key: string]: string},
|
|
68
|
-
headers: {[key: string]: string},
|
|
69
|
-
cookies: {[key: string]: string},
|
|
70
|
-
response: IAdminForthHttpResponse,
|
|
71
|
-
requestUrl: string,
|
|
72
|
-
abortSignal: AbortSignal,
|
|
73
|
-
_raw_express_req: Request,
|
|
74
|
-
_raw_express_res: Response,
|
|
75
|
-
) => void,
|
|
76
|
-
}): void;
|
|
137
|
+
endpoint(options: IAdminForthEndpointOptions): void;
|
|
77
138
|
|
|
78
139
|
}
|
|
79
140
|
|
|
@@ -107,14 +168,38 @@ export interface IExpressHttpServer extends IHttpServer {
|
|
|
107
168
|
* ```
|
|
108
169
|
*
|
|
109
170
|
*/
|
|
110
|
-
authorize(callable:
|
|
171
|
+
authorize(callable: (...args: any[]) => any): (...args: any[]) => any;
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Method (middleware) to inject translation helper into Express request object.
|
|
175
|
+
*/
|
|
176
|
+
translatable(callable: (...args: any[]) => any): (...args: any[]) => any;
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Registers OpenAPI schemas for a custom Express route.
|
|
180
|
+
*
|
|
181
|
+
* Wrap this around the handler passed to `app.get/post/...`.
|
|
182
|
+
* If you also need authorization, make `withSchema` the outer wrapper:
|
|
183
|
+
*
|
|
184
|
+
* ```ts
|
|
185
|
+
* import * as z from 'zod';
|
|
186
|
+
*
|
|
187
|
+
* app.get('/myApi', admin.express.withSchema({
|
|
188
|
+
* description: 'Returns current user profile',
|
|
189
|
+
* response: z.object({ user: z.unknown() }),
|
|
190
|
+
* }, admin.express.authorize((req, res) => {
|
|
191
|
+
* res.json({ user: req.adminUser });
|
|
192
|
+
* })));
|
|
193
|
+
* ```
|
|
194
|
+
*/
|
|
195
|
+
withSchema(schema: IAdminForthExpressRouteSchema, callable: (...args: any[]) => any): (...args: any[]) => any;
|
|
111
196
|
}
|
|
112
197
|
|
|
113
198
|
export interface ITranslateFunction {
|
|
114
199
|
(
|
|
115
200
|
msg: string,
|
|
116
201
|
category: string,
|
|
117
|
-
params
|
|
202
|
+
params?: any,
|
|
118
203
|
pluralizationNumber?: number
|
|
119
204
|
): Promise<string>;
|
|
120
205
|
}
|
|
@@ -359,7 +444,8 @@ export interface IAdminForthRestAPI {
|
|
|
359
444
|
export interface IAdminForth {
|
|
360
445
|
config: AdminForthConfig;
|
|
361
446
|
codeInjector: ICodeInjector;
|
|
362
|
-
express:
|
|
447
|
+
express: IExpressHttpServer;
|
|
448
|
+
openApi: IOpenApiRegistry;
|
|
363
449
|
|
|
364
450
|
restApi: IAdminForthRestAPI;
|
|
365
451
|
activatedPlugins: Array<IAdminForthPlugin>;
|
|
@@ -535,7 +621,7 @@ export type BeforeDataSourceRequestFunction = (params: {
|
|
|
535
621
|
body: any,
|
|
536
622
|
query: Record<string, string>,
|
|
537
623
|
headers: Record<string, string>,
|
|
538
|
-
cookies:
|
|
624
|
+
cookies: { key: string, value: string }[],
|
|
539
625
|
requestUrl: string,
|
|
540
626
|
},
|
|
541
627
|
filtersTools: any,
|
|
@@ -573,7 +659,7 @@ export interface HttpExtra {
|
|
|
573
659
|
body: any,
|
|
574
660
|
query: Record<string, string>,
|
|
575
661
|
headers: Record<string, string>,
|
|
576
|
-
cookies:
|
|
662
|
+
cookies: { key: string, value: string }[],
|
|
577
663
|
requestUrl: string,
|
|
578
664
|
meta?: any,
|
|
579
665
|
response: IAdminForthHttpResponse
|
|
@@ -2021,7 +2107,7 @@ export interface AdminForthBulkAction extends AdminForthBulkActionCommon {
|
|
|
2021
2107
|
* It should return Promise which will be resolved when action is done.
|
|
2022
2108
|
*/
|
|
2023
2109
|
action: ({ resource, selectedIds, adminUser, response, tr }: {
|
|
2024
|
-
resource: AdminForthResource, selectedIds: Array<any>, adminUser: AdminUser, response: IAdminForthHttpResponse, tr:
|
|
2110
|
+
resource: AdminForthResource, selectedIds: Array<any>, adminUser: AdminUser, response: IAdminForthHttpResponse, tr: ITranslateFunction
|
|
2025
2111
|
}) => Promise<{ ok: boolean, error?: string, successMessage?: string }>,
|
|
2026
2112
|
|
|
2027
2113
|
/**
|
|
@@ -1,9 +1,18 @@
|
|
|
1
|
+
import type { JSONSchemaType } from "ajv";
|
|
2
|
+
|
|
1
3
|
export type CompletionStreamEvent = {
|
|
2
4
|
type: "output" | "reasoning";
|
|
3
5
|
delta: string;
|
|
4
6
|
text: string;
|
|
5
7
|
source?: "summary" | "text";
|
|
6
8
|
};
|
|
9
|
+
|
|
10
|
+
export type CompletionTool<Input = Record<string, any>, Output = any> = {
|
|
11
|
+
name: string;
|
|
12
|
+
input_schema: JSONSchemaType<Input>;
|
|
13
|
+
description?: string;
|
|
14
|
+
handler: (input: Input) => Promise<Output> | Output;
|
|
15
|
+
};
|
|
7
16
|
export interface CompletionAdapter {
|
|
8
17
|
|
|
9
18
|
/**
|
|
@@ -26,6 +35,7 @@ export interface CompletionAdapter {
|
|
|
26
35
|
maxTokens: number,
|
|
27
36
|
outputSchema?: any,
|
|
28
37
|
reasoningEffort?: 'none' | 'minimal' | 'low' | 'medium' | 'high' | 'xhigh',
|
|
38
|
+
tools?: CompletionTool[],
|
|
29
39
|
onChunk?: (
|
|
30
40
|
chunk: string,
|
|
31
41
|
event?: CompletionStreamEvent,
|
|
@@ -11,50 +11,32 @@
|
|
|
11
11
|
</div>
|
|
12
12
|
</div>
|
|
13
13
|
|
|
14
|
-
<
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
14
|
+
<template v-for="column in visibleColumns" :key="column.name">
|
|
15
|
+
<div
|
|
16
|
+
class="flex items-center bg-lightForm dark:bg-darkForm border-b border-gray-100 dark:border-darkFormBorder"
|
|
17
|
+
:style="{ height: getFieldHeight(column) }"
|
|
18
|
+
>
|
|
19
|
+
<div class="w-[208px] flex-shrink-0 px-6 flex items-center">
|
|
19
20
|
<Skeleton class="w-24 h-[10px]" />
|
|
20
21
|
</div>
|
|
21
|
-
|
|
22
|
-
<div class="flex-1 px-6">
|
|
23
|
-
<div v-if="i === 2">
|
|
24
|
-
<Skeleton type="input" class="h-[42px] w-[160px]" />
|
|
25
|
-
<Skeleton class="mt-1 h-[12px] w-20" />
|
|
26
|
-
</div>
|
|
27
|
-
<Skeleton type="input" v-else-if="i === 4 || i === 5" class="h-[42px] w-[160px]" />
|
|
28
|
-
<Skeleton v-else type="input" class="h-[42px] w-full" />
|
|
29
|
-
</div>
|
|
30
|
-
</div>
|
|
31
22
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
<div class="flex flex-wrap items-center gap-3 p-1.5 border border-gray-300 dark:border-gray-600 rounded-t-lg bg-gray-50 dark:bg-gray-800 w-full box-border h-[44px]">
|
|
39
|
-
<template v-for="btn in skeletonButtons" :key="btn.id">
|
|
40
|
-
<div class=" animate-pulse flex items-center justify-center h-8 px-1 text-gray-300 dark:text-gray-600">
|
|
41
|
-
<component :is="btn.icon" class="w-5 h-5" />
|
|
42
|
-
</div>
|
|
43
|
-
<div v-if="btn.sep" class="w-px h-4 bg-gray-300 dark:bg-gray-600 mx-1"></div>
|
|
44
|
-
</template>
|
|
23
|
+
<div class="flex-1 px-6">
|
|
24
|
+
<Skeleton type="input" :class="getSkeletonInputClass(column)" />
|
|
25
|
+
|
|
26
|
+
<div v-if="hasEditingNote(column)" class="mt-1">
|
|
27
|
+
<Skeleton class="h-[12px] w-20" />
|
|
28
|
+
</div>
|
|
45
29
|
</div>
|
|
46
|
-
<div class="flex-1 animate-pulse bg-white dark:bg-gray-950 border-x border-b border-gray-200 dark:border-gray-700 rounded-b-lg w-full shadow-inner"></div>
|
|
47
|
-
<div class="h-10"></div>
|
|
48
30
|
</div>
|
|
49
|
-
|
|
31
|
+
|
|
32
|
+
</template>
|
|
50
33
|
</div>
|
|
51
34
|
</div>
|
|
52
35
|
</template>
|
|
53
36
|
|
|
54
37
|
<script setup lang="ts">
|
|
55
|
-
import { markRaw } from 'vue';
|
|
56
|
-
import {
|
|
57
|
-
import {
|
|
38
|
+
import { computed, markRaw } from 'vue';
|
|
39
|
+
import {
|
|
58
40
|
IconLinkOutline, IconCodeOutline, IconRectangleListOutline,
|
|
59
41
|
IconOrderedListOutline, IconLetterBoldOutline, IconLetterUnderlineOutline,
|
|
60
42
|
IconLetterItalicOutline, IconTextSlashOutline
|
|
@@ -62,6 +44,39 @@ import {
|
|
|
62
44
|
import { IconH116Solid, IconH216Solid, IconH316Solid } from '@iconify-prerendered/vue-heroicons';
|
|
63
45
|
import { Skeleton } from '@/afcl';
|
|
64
46
|
|
|
47
|
+
interface Props {
|
|
48
|
+
resource?: any;
|
|
49
|
+
page?: string;}
|
|
50
|
+
|
|
51
|
+
const props = withDefaults(defineProps<Props>(), {
|
|
52
|
+
page: 'edit'
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
const visibleColumns = computed(() => {
|
|
56
|
+
if (!props.resource?.columns) return [];
|
|
57
|
+
|
|
58
|
+
return props.resource.columns.filter((col: any) => {
|
|
59
|
+
if (col.virtual) return false;
|
|
60
|
+
if (col.primaryKey) return false;
|
|
61
|
+
if (col.backendOnly) return false;
|
|
62
|
+
if (col.showIn?.[props.page] === false) return false;
|
|
63
|
+
return true;
|
|
64
|
+
});
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
const hasEditingNote = (column: any) => !!column.editingNote;
|
|
69
|
+
|
|
70
|
+
const getFieldHeight = (column: any) =>
|
|
71
|
+
hasEditingNote(column) ? '95px' : '75px';
|
|
72
|
+
|
|
73
|
+
const getSkeletonInputClass = (column: any) => {
|
|
74
|
+
if (['integer', 'decimal', 'float'].includes(column.type)) {
|
|
75
|
+
return 'h-[42px] w-[160px]';
|
|
76
|
+
}
|
|
77
|
+
return 'h-[42px] w-full';
|
|
78
|
+
};
|
|
79
|
+
|
|
65
80
|
const skeletonButtons = [
|
|
66
81
|
{ id: 'bold', icon: markRaw(IconLetterBoldOutline), sep: false },
|
|
67
82
|
{ id: 'italic', icon: markRaw(IconLetterItalicOutline), sep: false },
|
package/dist/types/Back.d.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
import type { Express, Request, Response } from 'express';
|
|
2
|
+
import type { AnySchemaObject } from 'ajv';
|
|
2
3
|
import type { Writable } from 'stream';
|
|
4
|
+
import type { ZodType } from 'zod';
|
|
3
5
|
import { ActionCheckSource, AdminForthFilterOperators, AdminForthSortDirections, AllowedActionsEnum, AdminForthResourcePages, type AdminForthComponentDeclaration, type AdminUser, type AllowedActionsResolved, type AdminForthBulkActionCommon, type AdminForthForeignResourceCommon, type AdminForthResourceColumnCommon, type AdminForthResourceInputCommon, type AdminForthComponentDeclarationFull, type AdminForthConfigMenuItem, type AnnouncementBadgeResponse, type AdminForthResourceColumnInputCommon, type ColumnMinMaxValue } from './Common.js';
|
|
4
6
|
export interface ICodeInjector {
|
|
5
7
|
srcFoldersToSync: Object;
|
|
@@ -19,6 +21,81 @@ export interface IAdminForthHttpResponse {
|
|
|
19
21
|
setStatus: (code: number, message: string) => void;
|
|
20
22
|
blobStream: () => Writable;
|
|
21
23
|
}
|
|
24
|
+
export interface IAdminForthEndpointHandlerInput {
|
|
25
|
+
body: any;
|
|
26
|
+
adminUser: AdminUser | undefined;
|
|
27
|
+
query: {
|
|
28
|
+
[key: string]: any;
|
|
29
|
+
};
|
|
30
|
+
headers: {
|
|
31
|
+
[key: string]: any;
|
|
32
|
+
};
|
|
33
|
+
cookies: Array<{
|
|
34
|
+
key: string;
|
|
35
|
+
value: string;
|
|
36
|
+
}>;
|
|
37
|
+
response: IAdminForthHttpResponse;
|
|
38
|
+
requestUrl: string;
|
|
39
|
+
abortSignal: AbortSignal;
|
|
40
|
+
_raw_express_req: Request;
|
|
41
|
+
_raw_express_res: Response;
|
|
42
|
+
tr: ITranslateFunction;
|
|
43
|
+
}
|
|
44
|
+
export interface IAdminForthEndpointOptions {
|
|
45
|
+
method: string;
|
|
46
|
+
noAuth?: boolean;
|
|
47
|
+
path: string;
|
|
48
|
+
description?: string;
|
|
49
|
+
request_schema?: AnySchemaObject;
|
|
50
|
+
response_schema?: AnySchemaObject;
|
|
51
|
+
responce_schema?: AnySchemaObject;
|
|
52
|
+
handler: (input: IAdminForthEndpointHandlerInput) => void | Promise<any>;
|
|
53
|
+
}
|
|
54
|
+
export type AdminForthExpressSchemaInput = AnySchemaObject | ZodType;
|
|
55
|
+
export interface IAdminForthExpressRouteSchema {
|
|
56
|
+
/**
|
|
57
|
+
* Detailed OpenAPI operation description for a custom Express route.
|
|
58
|
+
*/
|
|
59
|
+
description?: string;
|
|
60
|
+
/**
|
|
61
|
+
* JSON schema or Zod schema describing the request body for a custom Express route.
|
|
62
|
+
*/
|
|
63
|
+
request?: AdminForthExpressSchemaInput;
|
|
64
|
+
/**
|
|
65
|
+
* JSON schema or Zod schema describing the JSON response body for a custom Express route.
|
|
66
|
+
*/
|
|
67
|
+
response?: AdminForthExpressSchemaInput;
|
|
68
|
+
}
|
|
69
|
+
export interface IRegisteredApiSchema {
|
|
70
|
+
method: string;
|
|
71
|
+
path: string;
|
|
72
|
+
description?: string;
|
|
73
|
+
request_schema?: AnySchemaObject;
|
|
74
|
+
response_schema?: AnySchemaObject;
|
|
75
|
+
}
|
|
76
|
+
export interface IAdminForthApiValidationError {
|
|
77
|
+
instancePath: string;
|
|
78
|
+
schemaPath: string;
|
|
79
|
+
keyword: string;
|
|
80
|
+
message?: string;
|
|
81
|
+
params: {
|
|
82
|
+
[key: string]: any;
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
export interface IAdminForthApiValidationResult {
|
|
86
|
+
valid: boolean;
|
|
87
|
+
errors?: IAdminForthApiValidationError[];
|
|
88
|
+
}
|
|
89
|
+
export interface IOpenApiRegistry {
|
|
90
|
+
registeredSchemas: IRegisteredApiSchema[];
|
|
91
|
+
registerApiSchema(options: IAdminForthEndpointOptions): IRegisteredApiSchema;
|
|
92
|
+
register_api_schema(options: IAdminForthEndpointOptions): IRegisteredApiSchema;
|
|
93
|
+
validateRequestSchema(route: IRegisteredApiSchema | null, payload: any): IAdminForthApiValidationResult;
|
|
94
|
+
validateResponseSchema(route: IRegisteredApiSchema | null, payload: any): IAdminForthApiValidationResult;
|
|
95
|
+
renderOpenApiDocument(): {
|
|
96
|
+
[key: string]: any;
|
|
97
|
+
};
|
|
98
|
+
}
|
|
22
99
|
/**
|
|
23
100
|
* Implement this interface to create custom HTTP server adapter for AdminForth.
|
|
24
101
|
*/
|
|
@@ -34,18 +111,7 @@ export interface IHttpServer {
|
|
|
34
111
|
*
|
|
35
112
|
* @param options : Object with method, path and handler properties.
|
|
36
113
|
*/
|
|
37
|
-
endpoint(options:
|
|
38
|
-
method: string;
|
|
39
|
-
noAuth?: boolean;
|
|
40
|
-
path: string;
|
|
41
|
-
handler: (body: any, adminUser: any, query: {
|
|
42
|
-
[key: string]: string;
|
|
43
|
-
}, headers: {
|
|
44
|
-
[key: string]: string;
|
|
45
|
-
}, cookies: {
|
|
46
|
-
[key: string]: string;
|
|
47
|
-
}, response: IAdminForthHttpResponse, requestUrl: string, abortSignal: AbortSignal, _raw_express_req: Request, _raw_express_res: Response) => void;
|
|
48
|
-
}): void;
|
|
114
|
+
endpoint(options: IAdminForthEndpointOptions): void;
|
|
49
115
|
}
|
|
50
116
|
export interface IExpressHttpServer extends IHttpServer {
|
|
51
117
|
/**
|
|
@@ -73,10 +139,32 @@ export interface IExpressHttpServer extends IHttpServer {
|
|
|
73
139
|
* ```
|
|
74
140
|
*
|
|
75
141
|
*/
|
|
76
|
-
authorize(callable:
|
|
142
|
+
authorize(callable: (...args: any[]) => any): (...args: any[]) => any;
|
|
143
|
+
/**
|
|
144
|
+
* Method (middleware) to inject translation helper into Express request object.
|
|
145
|
+
*/
|
|
146
|
+
translatable(callable: (...args: any[]) => any): (...args: any[]) => any;
|
|
147
|
+
/**
|
|
148
|
+
* Registers OpenAPI schemas for a custom Express route.
|
|
149
|
+
*
|
|
150
|
+
* Wrap this around the handler passed to `app.get/post/...`.
|
|
151
|
+
* If you also need authorization, make `withSchema` the outer wrapper:
|
|
152
|
+
*
|
|
153
|
+
* ```ts
|
|
154
|
+
* import * as z from 'zod';
|
|
155
|
+
*
|
|
156
|
+
* app.get('/myApi', admin.express.withSchema({
|
|
157
|
+
* description: 'Returns current user profile',
|
|
158
|
+
* response: z.object({ user: z.unknown() }),
|
|
159
|
+
* }, admin.express.authorize((req, res) => {
|
|
160
|
+
* res.json({ user: req.adminUser });
|
|
161
|
+
* })));
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
withSchema(schema: IAdminForthExpressRouteSchema, callable: (...args: any[]) => any): (...args: any[]) => any;
|
|
77
165
|
}
|
|
78
166
|
export interface ITranslateFunction {
|
|
79
|
-
(msg: string, category: string, params
|
|
167
|
+
(msg: string, category: string, params?: any, pluralizationNumber?: number): Promise<string>;
|
|
80
168
|
}
|
|
81
169
|
export interface IAdminUserExpressRequest extends Omit<Request, 'protocol' | 'param' | 'unshift'> {
|
|
82
170
|
adminUser: AdminUser;
|
|
@@ -333,7 +421,8 @@ export interface IAdminForthRestAPI {
|
|
|
333
421
|
export interface IAdminForth {
|
|
334
422
|
config: AdminForthConfig;
|
|
335
423
|
codeInjector: ICodeInjector;
|
|
336
|
-
express:
|
|
424
|
+
express: IExpressHttpServer;
|
|
425
|
+
openApi: IOpenApiRegistry;
|
|
337
426
|
restApi: IAdminForthRestAPI;
|
|
338
427
|
activatedPlugins: Array<IAdminForthPlugin>;
|
|
339
428
|
websocket: IWebSocketBroker;
|
|
@@ -477,7 +566,10 @@ export type BeforeDataSourceRequestFunction = (params: {
|
|
|
477
566
|
body: any;
|
|
478
567
|
query: Record<string, string>;
|
|
479
568
|
headers: Record<string, string>;
|
|
480
|
-
cookies:
|
|
569
|
+
cookies: {
|
|
570
|
+
key: string;
|
|
571
|
+
value: string;
|
|
572
|
+
}[];
|
|
481
573
|
requestUrl: string;
|
|
482
574
|
};
|
|
483
575
|
filtersTools: any;
|
|
@@ -519,7 +611,10 @@ export interface HttpExtra {
|
|
|
519
611
|
body: any;
|
|
520
612
|
query: Record<string, string>;
|
|
521
613
|
headers: Record<string, string>;
|
|
522
|
-
cookies:
|
|
614
|
+
cookies: {
|
|
615
|
+
key: string;
|
|
616
|
+
value: string;
|
|
617
|
+
}[];
|
|
523
618
|
requestUrl: string;
|
|
524
619
|
meta?: any;
|
|
525
620
|
response: IAdminForthHttpResponse;
|
|
@@ -1756,7 +1851,7 @@ export interface AdminForthBulkAction extends AdminForthBulkActionCommon {
|
|
|
1756
1851
|
selectedIds: Array<any>;
|
|
1757
1852
|
adminUser: AdminUser;
|
|
1758
1853
|
response: IAdminForthHttpResponse;
|
|
1759
|
-
tr:
|
|
1854
|
+
tr: ITranslateFunction;
|
|
1760
1855
|
}) => Promise<{
|
|
1761
1856
|
ok: boolean;
|
|
1762
1857
|
error?: string;
|