@nocobase/server 2.1.0-alpha.4 → 2.1.0-alpha.45
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/LICENSE +201 -661
- package/README.md +79 -10
- package/lib/acl/available-action.js +1 -1
- package/lib/aes-encryptor.js +3 -2
- package/lib/app-supervisor/app-options-factory.d.ts +1 -0
- package/lib/app-supervisor/index.d.ts +13 -5
- package/lib/app-supervisor/index.js +48 -13
- package/lib/app-supervisor/main-only-adapter.d.ts +4 -1
- package/lib/app-supervisor/main-only-adapter.js +24 -12
- package/lib/app-supervisor/types.d.ts +18 -3
- package/lib/application.d.ts +1 -2
- package/lib/application.js +3 -24
- package/lib/audit-manager/index.d.ts +2 -0
- package/lib/audit-manager/index.js +5 -2
- package/lib/commands/ai.js +1 -6
- package/lib/commands/create-migration.js +1 -1
- package/lib/commands/install.js +0 -2
- package/lib/commands/pm.js +7 -0
- package/lib/commands/start.js +2 -5
- package/lib/commands/upgrade.js +0 -2
- package/lib/{ai/create-docs-index.d.ts → constants.d.ts} +1 -5
- package/lib/constants.js +36 -0
- package/lib/event-queue.js +1 -1
- package/lib/gateway/index.d.ts +15 -3
- package/lib/gateway/index.js +161 -20
- package/lib/gateway/static-file-security.d.ts +10 -0
- package/lib/gateway/static-file-security.js +69 -0
- package/lib/gateway/utils.d.ts +17 -0
- package/lib/gateway/utils.js +115 -0
- package/lib/helper.js +33 -1
- package/lib/index.d.ts +3 -1
- package/lib/index.js +5 -4
- package/lib/locale/locale.d.ts +24 -0
- package/lib/locale/locale.js +29 -5
- package/lib/main-data-source.js +12 -5
- package/lib/plugin-manager/deps.js +3 -2
- package/lib/plugin-manager/findPackageNames.js +4 -2
- package/lib/plugin-manager/options/resource.d.ts +12 -1
- package/lib/plugin-manager/options/resource.js +212 -53
- package/lib/plugin-manager/plugin-manager.d.ts +7 -2
- package/lib/plugin-manager/plugin-manager.js +65 -56
- package/lib/plugin-manager/utils.d.ts +9 -1
- package/lib/plugin-manager/utils.js +68 -10
- package/lib/plugin.js +46 -2
- package/lib/pub-sub-manager/handler-manager.d.ts +1 -0
- package/lib/pub-sub-manager/handler-manager.js +11 -0
- package/lib/pub-sub-manager/pub-sub-manager.js +2 -1
- package/lib/swagger/app.d.ts +102 -0
- package/lib/swagger/app.js +124 -0
- package/lib/swagger/base.d.ts +244 -0
- package/lib/swagger/base.js +292 -0
- package/lib/swagger/collections.d.ts +996 -0
- package/lib/swagger/collections.js +1264 -0
- package/lib/swagger/index.d.ts +1774 -0
- package/lib/swagger/index.js +70 -0
- package/lib/swagger/pm.d.ts +462 -0
- package/lib/swagger/pm.js +422 -0
- package/lib/sync-message-manager.js +8 -1
- package/lib/worker-mode.d.ts +19 -0
- package/lib/worker-mode.js +67 -0
- package/package.json +19 -19
- package/lib/ai/create-docs-index.js +0 -892
- package/lib/swagger/index.json +0 -1569
package/lib/helper.js
CHANGED
|
@@ -239,14 +239,46 @@ function isNumeric(str) {
|
|
|
239
239
|
return !isNaN(str) && !isNaN(parseFloat(str));
|
|
240
240
|
}
|
|
241
241
|
__name(isNumeric, "isNumeric");
|
|
242
|
+
function getFieldFromCollectionManager(ctx, resourceName, fieldPath) {
|
|
243
|
+
var _a;
|
|
244
|
+
const collectionManager = (_a = ctx.dataSource) == null ? void 0 : _a.collectionManager;
|
|
245
|
+
if (!(collectionManager == null ? void 0 : collectionManager.getCollection)) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const collection = collectionManager.getCollection(resourceName);
|
|
249
|
+
if (!(collection == null ? void 0 : collection.getField)) {
|
|
250
|
+
return;
|
|
251
|
+
}
|
|
252
|
+
const [firstName, ...others] = fieldPath.split(".");
|
|
253
|
+
let field = collection.getField(firstName);
|
|
254
|
+
if (!field || !others.length) {
|
|
255
|
+
return field;
|
|
256
|
+
}
|
|
257
|
+
let currentCollection = typeof field.targetCollection === "function" ? field.targetCollection() : field.targetCollection;
|
|
258
|
+
for (const name of others) {
|
|
259
|
+
if (!(currentCollection == null ? void 0 : currentCollection.getField)) {
|
|
260
|
+
return;
|
|
261
|
+
}
|
|
262
|
+
field = currentCollection.getField(name);
|
|
263
|
+
if (!field) {
|
|
264
|
+
return;
|
|
265
|
+
}
|
|
266
|
+
currentCollection = typeof field.targetCollection === "function" ? field.targetCollection() : field.targetCollection;
|
|
267
|
+
}
|
|
268
|
+
return field;
|
|
269
|
+
}
|
|
270
|
+
__name(getFieldFromCollectionManager, "getFieldFromCollectionManager");
|
|
242
271
|
function createContextVariablesScope(ctx) {
|
|
243
272
|
const state = JSON.parse(JSON.stringify(ctx.state));
|
|
244
273
|
return {
|
|
245
274
|
timezone: ctx.get("x-timezone"),
|
|
246
275
|
now: (/* @__PURE__ */ new Date()).toISOString(),
|
|
247
276
|
getField: /* @__PURE__ */ __name((path) => {
|
|
248
|
-
const fieldPath = path.split(".").filter((p) => !p.startsWith("$") && !isNumeric(p)).join(".");
|
|
249
277
|
const { resourceName } = ctx.action;
|
|
278
|
+
const fieldPath = path.split(".").filter((p) => !p.startsWith("$") && !isNumeric(p)).join(".");
|
|
279
|
+
if (!ctx.database) {
|
|
280
|
+
return getFieldFromCollectionManager(ctx, resourceName, fieldPath);
|
|
281
|
+
}
|
|
250
282
|
return ctx.database.getFieldByPath(`${resourceName}.${fieldPath}`);
|
|
251
283
|
}, "getField"),
|
|
252
284
|
vars: {
|
package/lib/index.d.ts
CHANGED
|
@@ -20,9 +20,11 @@ export * from './plugin-manager';
|
|
|
20
20
|
export * from './pub-sub-manager';
|
|
21
21
|
export * from './event-queue';
|
|
22
22
|
export * from './worker-id-allocator';
|
|
23
|
+
export * from './worker-mode';
|
|
23
24
|
export * from './redis-connection-manager';
|
|
24
25
|
export * from './main-data-source';
|
|
25
|
-
export
|
|
26
|
+
export * from './constants';
|
|
27
|
+
export type { LocaleSource, LocaleSourceText } from './locale';
|
|
26
28
|
export { appendToBuiltInPlugins, findAllPlugins, findBuiltInPlugins, findLocalPlugins, packageNameTrim, } from './plugin-manager/findPackageNames';
|
|
27
29
|
export { runPluginStaticImports } from './run-plugin-static-imports';
|
|
28
30
|
export { createContextVariablesScope } from './helper';
|
package/lib/index.js
CHANGED
|
@@ -37,7 +37,6 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
37
37
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
38
38
|
var src_exports = {};
|
|
39
39
|
__export(src_exports, {
|
|
40
|
-
OFFICIAL_PLUGIN_PREFIX: () => OFFICIAL_PLUGIN_PREFIX,
|
|
41
40
|
appendToBuiltInPlugins: () => import_findPackageNames.appendToBuiltInPlugins,
|
|
42
41
|
createContextVariablesScope: () => import_helper.createContextVariablesScope,
|
|
43
42
|
default: () => import_application.Application,
|
|
@@ -63,15 +62,15 @@ __reExport(src_exports, require("./plugin-manager"), module.exports);
|
|
|
63
62
|
__reExport(src_exports, require("./pub-sub-manager"), module.exports);
|
|
64
63
|
__reExport(src_exports, require("./event-queue"), module.exports);
|
|
65
64
|
__reExport(src_exports, require("./worker-id-allocator"), module.exports);
|
|
65
|
+
__reExport(src_exports, require("./worker-mode"), module.exports);
|
|
66
66
|
__reExport(src_exports, require("./redis-connection-manager"), module.exports);
|
|
67
67
|
__reExport(src_exports, require("./main-data-source"), module.exports);
|
|
68
|
+
__reExport(src_exports, require("./constants"), module.exports);
|
|
68
69
|
var import_findPackageNames = require("./plugin-manager/findPackageNames");
|
|
69
70
|
var import_run_plugin_static_imports = require("./run-plugin-static-imports");
|
|
70
71
|
var import_helper = require("./helper");
|
|
71
|
-
const OFFICIAL_PLUGIN_PREFIX = "@nocobase/plugin-";
|
|
72
72
|
// Annotate the CommonJS export names for ESM import in node:
|
|
73
73
|
0 && (module.exports = {
|
|
74
|
-
OFFICIAL_PLUGIN_PREFIX,
|
|
75
74
|
appendToBuiltInPlugins,
|
|
76
75
|
createContextVariablesScope,
|
|
77
76
|
findAllPlugins,
|
|
@@ -92,6 +91,8 @@ const OFFICIAL_PLUGIN_PREFIX = "@nocobase/plugin-";
|
|
|
92
91
|
...require("./pub-sub-manager"),
|
|
93
92
|
...require("./event-queue"),
|
|
94
93
|
...require("./worker-id-allocator"),
|
|
94
|
+
...require("./worker-mode"),
|
|
95
95
|
...require("./redis-connection-manager"),
|
|
96
|
-
...require("./main-data-source")
|
|
96
|
+
...require("./main-data-source"),
|
|
97
|
+
...require("./constants")
|
|
97
98
|
});
|
package/lib/locale/locale.d.ts
CHANGED
|
@@ -15,6 +15,24 @@ export interface ResourceStorer {
|
|
|
15
15
|
}>;
|
|
16
16
|
reset?: () => Promise<void>;
|
|
17
17
|
}
|
|
18
|
+
export type LocaleSourceText = {
|
|
19
|
+
text: string;
|
|
20
|
+
module: string;
|
|
21
|
+
};
|
|
22
|
+
export type LocaleSource = {
|
|
23
|
+
title: string;
|
|
24
|
+
sync?: (ctx: any) => Promise<{
|
|
25
|
+
[module: string]: {
|
|
26
|
+
[text: string]: string;
|
|
27
|
+
};
|
|
28
|
+
}>;
|
|
29
|
+
namespace?: string;
|
|
30
|
+
collections?: {
|
|
31
|
+
collection: string;
|
|
32
|
+
fields?: string[];
|
|
33
|
+
getTexts?: (instance: any, options?: any) => LocaleSourceText[] | Promise<LocaleSourceText[]>;
|
|
34
|
+
}[];
|
|
35
|
+
};
|
|
18
36
|
export declare class Locale {
|
|
19
37
|
app: Application;
|
|
20
38
|
cache: Cache;
|
|
@@ -23,18 +41,24 @@ export declare class Locale {
|
|
|
23
41
|
resourceCached: Map<any, any>;
|
|
24
42
|
i18nInstances: Map<any, any>;
|
|
25
43
|
resourceStorers: Registry<ResourceStorer>;
|
|
44
|
+
sources: Registry<LocaleSource>;
|
|
26
45
|
constructor(app: Application);
|
|
27
46
|
load(): Promise<void>;
|
|
28
47
|
reset(): Promise<void>;
|
|
29
48
|
reload(): Promise<void>;
|
|
30
49
|
setLocaleFn(name: string, fn: (lang: string) => Promise<any>): void;
|
|
31
50
|
registerResourceStorer(name: string, storer: ResourceStorer): void;
|
|
51
|
+
registerSource(name: string, source: LocaleSource): void;
|
|
52
|
+
syncSources(ctx: any, types: string[]): Promise<{
|
|
53
|
+
[module: string]: any;
|
|
54
|
+
}>;
|
|
32
55
|
get(lang: string): Promise<{
|
|
33
56
|
resources: any;
|
|
34
57
|
}>;
|
|
35
58
|
wrapCache(key: string, fn: () => any): Promise<any>;
|
|
36
59
|
loadResourcesByLang(lang: string): Promise<void>;
|
|
37
60
|
getCacheResources(lang: string): Promise<any>;
|
|
61
|
+
getBuiltInResources(lang: string): Promise<{}>;
|
|
38
62
|
getResources(lang: string): Promise<{}>;
|
|
39
63
|
getI18nInstance(lang: string): Promise<any>;
|
|
40
64
|
}
|
package/lib/locale/locale.js
CHANGED
|
@@ -41,8 +41,8 @@ __export(locale_exports, {
|
|
|
41
41
|
});
|
|
42
42
|
module.exports = __toCommonJS(locale_exports);
|
|
43
43
|
var import_utils = require("@nocobase/utils");
|
|
44
|
+
var import_constants = require("../constants");
|
|
44
45
|
var import_resource = require("./resource");
|
|
45
|
-
var import__ = require("..");
|
|
46
46
|
var import_deepmerge = __toESM(require("deepmerge"));
|
|
47
47
|
const _Locale = class _Locale {
|
|
48
48
|
app;
|
|
@@ -52,6 +52,7 @@ const _Locale = class _Locale {
|
|
|
52
52
|
resourceCached = /* @__PURE__ */ new Map();
|
|
53
53
|
i18nInstances = /* @__PURE__ */ new Map();
|
|
54
54
|
resourceStorers = new import_utils.Registry();
|
|
55
|
+
sources = new import_utils.Registry();
|
|
55
56
|
constructor(app) {
|
|
56
57
|
this.app = app;
|
|
57
58
|
this.app.on("afterLoad", async () => {
|
|
@@ -92,6 +93,25 @@ const _Locale = class _Locale {
|
|
|
92
93
|
registerResourceStorer(name, storer) {
|
|
93
94
|
this.resourceStorers.register(name, storer);
|
|
94
95
|
}
|
|
96
|
+
registerSource(name, source) {
|
|
97
|
+
this.sources.register(name, source);
|
|
98
|
+
}
|
|
99
|
+
async syncSources(ctx, types) {
|
|
100
|
+
const resources = { client: {} };
|
|
101
|
+
const sources = Array.from(this.sources.getKeys());
|
|
102
|
+
const syncSources = sources.filter((source) => types.includes(source) && this.sources.get(source).sync);
|
|
103
|
+
const promises = syncSources.map((source) => this.sources.get(source).sync(ctx));
|
|
104
|
+
const results = await Promise.all(promises);
|
|
105
|
+
return results.reduce((result, resource) => {
|
|
106
|
+
Object.entries(resource).forEach(([module2, texts]) => {
|
|
107
|
+
result[module2] = {
|
|
108
|
+
...result[module2] || {},
|
|
109
|
+
...texts
|
|
110
|
+
};
|
|
111
|
+
});
|
|
112
|
+
return result;
|
|
113
|
+
}, resources);
|
|
114
|
+
}
|
|
95
115
|
async get(lang) {
|
|
96
116
|
const defaults = {
|
|
97
117
|
resources: await this.getCacheResources(lang)
|
|
@@ -124,7 +144,7 @@ const _Locale = class _Locale {
|
|
|
124
144
|
}
|
|
125
145
|
return await this.wrapCache(`resources:${lang}`, () => this.getResources(lang));
|
|
126
146
|
}
|
|
127
|
-
async
|
|
147
|
+
async getBuiltInResources(lang) {
|
|
128
148
|
var _a;
|
|
129
149
|
const resources = {};
|
|
130
150
|
const names = this.app.pm.getPlugins().keys();
|
|
@@ -141,13 +161,17 @@ const _Locale = class _Locale {
|
|
|
141
161
|
const res = await (0, import_resource.getResource)(packageName, lang);
|
|
142
162
|
if (res) {
|
|
143
163
|
resources[packageName] = { ...res };
|
|
144
|
-
if (packageName.includes(
|
|
145
|
-
resources[packageName.substring(
|
|
164
|
+
if (packageName.includes(import_constants.OFFICIAL_PLUGIN_PREFIX)) {
|
|
165
|
+
resources[packageName.substring(import_constants.OFFICIAL_PLUGIN_PREFIX.length)] = { ...res };
|
|
146
166
|
}
|
|
147
167
|
}
|
|
148
168
|
} catch (err) {
|
|
149
169
|
}
|
|
150
170
|
}
|
|
171
|
+
return resources;
|
|
172
|
+
}
|
|
173
|
+
async getResources(lang) {
|
|
174
|
+
const resources = await this.getBuiltInResources(lang);
|
|
151
175
|
const storers = this.resourceStorers.getValues();
|
|
152
176
|
for (const storer of storers) {
|
|
153
177
|
const custom = await storer.getResources(lang);
|
|
@@ -156,7 +180,7 @@ const _Locale = class _Locale {
|
|
|
156
180
|
const resource = resources[module2];
|
|
157
181
|
const customResource = custom[key];
|
|
158
182
|
resources[module2] = resource ? (0, import_deepmerge.default)(resource, customResource) : customResource;
|
|
159
|
-
const pkgName = `${
|
|
183
|
+
const pkgName = `${import_constants.OFFICIAL_PLUGIN_PREFIX}${module2}`;
|
|
160
184
|
if (resources[pkgName]) {
|
|
161
185
|
resources[pkgName] = { ...resources[module2] };
|
|
162
186
|
}
|
package/lib/main-data-source.js
CHANGED
|
@@ -96,6 +96,7 @@ const _MainDataSource = class _MainDataSource extends import_data_source_manager
|
|
|
96
96
|
const results = await this.tables2Collections(toAddTables);
|
|
97
97
|
const values = results.map((result) => ({
|
|
98
98
|
...result,
|
|
99
|
+
from: "dbsync",
|
|
99
100
|
underscored: false
|
|
100
101
|
}));
|
|
101
102
|
await repo.create({ values, context: ctx });
|
|
@@ -115,14 +116,16 @@ const _MainDataSource = class _MainDataSource extends import_data_source_manager
|
|
|
115
116
|
...filter
|
|
116
117
|
}
|
|
117
118
|
});
|
|
118
|
-
const collections = loadedCollections.filter(
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
119
|
+
const collections = loadedCollections.filter(
|
|
120
|
+
(collection) => {
|
|
121
|
+
var _a;
|
|
122
|
+
return !["db2cm", "dbsync"].includes((_a = collection.options) == null ? void 0 : _a.from);
|
|
123
|
+
}
|
|
124
|
+
);
|
|
122
125
|
const loadedData = {};
|
|
123
126
|
for (const collection of collections) {
|
|
124
127
|
const c = db.getCollection(collection.name);
|
|
125
|
-
loadedData[c.tableName
|
|
128
|
+
loadedData[c.model.tableName] = {
|
|
126
129
|
...collection.toJSON(),
|
|
127
130
|
fields: collection.fields.map((field) => {
|
|
128
131
|
const f = c.getField(field.name);
|
|
@@ -155,7 +158,11 @@ const _MainDataSource = class _MainDataSource extends import_data_source_manager
|
|
|
155
158
|
ctx.log.error(err);
|
|
156
159
|
}
|
|
157
160
|
const toLoadCollections = this.mergeWithLoadedCollections(collections, loadedCollections);
|
|
161
|
+
const currentSchema = process.env.COLLECTION_MANAGER_SCHEMA || db.options.schema || "public";
|
|
158
162
|
for (const values of toLoadCollections) {
|
|
163
|
+
if (values.schema === currentSchema) {
|
|
164
|
+
delete values.schema;
|
|
165
|
+
}
|
|
159
166
|
const existsFields = loadedCollections[values.tableName].fields;
|
|
160
167
|
const deletedFields = existsFields.filter((field) => !values.fields.find((f) => f.name === field.name));
|
|
161
168
|
await db.sequelize.transaction(async (transaction) => {
|
|
@@ -44,7 +44,7 @@ const deps = {
|
|
|
44
44
|
mathjs: "15.x",
|
|
45
45
|
winston: "3.x",
|
|
46
46
|
"winston-daily-rotate-file": "4.x",
|
|
47
|
-
koa: "
|
|
47
|
+
koa: "3.x",
|
|
48
48
|
"@koa/cors": "5.x",
|
|
49
49
|
"@koa/router": "13.x",
|
|
50
50
|
multer: "1.x",
|
|
@@ -76,6 +76,7 @@ const deps = {
|
|
|
76
76
|
lodash: "4.x",
|
|
77
77
|
"china-division": "2.x",
|
|
78
78
|
cronstrue: "2.x",
|
|
79
|
-
"@nocobase/license-kit": "0.3.x"
|
|
79
|
+
"@nocobase/license-kit": "0.3.x",
|
|
80
|
+
joi: "17.x"
|
|
80
81
|
};
|
|
81
82
|
var deps_default = deps;
|
|
@@ -46,6 +46,7 @@ __export(findPackageNames_exports, {
|
|
|
46
46
|
});
|
|
47
47
|
module.exports = __toCommonJS(findPackageNames_exports);
|
|
48
48
|
var import_fast_glob = __toESM(require("fast-glob"));
|
|
49
|
+
var import_utils = require("@nocobase/utils");
|
|
49
50
|
var import_fs_extra = __toESM(require("fs-extra"));
|
|
50
51
|
var import_lodash = __toESM(require("lodash"));
|
|
51
52
|
var import_path = __toESM(require("path"));
|
|
@@ -81,12 +82,13 @@ const excludes = [
|
|
|
81
82
|
"@nocobase/plugin-workflow-test"
|
|
82
83
|
];
|
|
83
84
|
async function findPackageNames() {
|
|
85
|
+
const pluginStoragePath = (0, import_utils.resolvePluginStoragePath)();
|
|
84
86
|
const patterns = [
|
|
85
87
|
"./packages/plugins/*/package.json",
|
|
86
88
|
"./packages/plugins/*/*/package.json",
|
|
87
89
|
"./packages/pro-plugins/*/*/package.json",
|
|
88
|
-
"
|
|
89
|
-
"
|
|
90
|
+
import_path.default.join(pluginStoragePath, "*/package.json"),
|
|
91
|
+
import_path.default.join(pluginStoragePath, "*/*/package.json")
|
|
90
92
|
];
|
|
91
93
|
try {
|
|
92
94
|
const packageJsonPaths = await (0, import_fast_glob.default)(patterns, {
|
|
@@ -6,6 +6,16 @@
|
|
|
6
6
|
* This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
|
+
export type PluginClientLane = 'client' | 'client-v2';
|
|
10
|
+
export declare class PackageUrls {
|
|
11
|
+
static items: Record<string, string | undefined>;
|
|
12
|
+
static clear(): void;
|
|
13
|
+
static getCacheKey(packageName: string, lane: PluginClientLane): string;
|
|
14
|
+
static get(packageName: string, lane?: PluginClientLane): Promise<string>;
|
|
15
|
+
static getAppDevUrl(packageName: string, lane: PluginClientLane): string;
|
|
16
|
+
static hasClientEntry(packageName: string, lane: PluginClientLane): Promise<boolean>;
|
|
17
|
+
static fetch(packageName: string, lane?: PluginClientLane): Promise<string>;
|
|
18
|
+
}
|
|
9
19
|
declare const _default: {
|
|
10
20
|
name: string;
|
|
11
21
|
actions: {
|
|
@@ -15,8 +25,9 @@ declare const _default: {
|
|
|
15
25
|
enable(ctx: any, next: any): Promise<void>;
|
|
16
26
|
disable(ctx: any, next: any): Promise<void>;
|
|
17
27
|
remove(ctx: any, next: any): Promise<void>;
|
|
18
|
-
list(ctx: any, next: any): Promise<
|
|
28
|
+
list(ctx: any, next: any): Promise<any>;
|
|
19
29
|
listEnabled(ctx: any, next: any): Promise<void>;
|
|
30
|
+
listEnabledV2(ctx: any, next: any): Promise<void>;
|
|
20
31
|
get(ctx: any, next: any): Promise<void>;
|
|
21
32
|
};
|
|
22
33
|
};
|