@nocobase/server 2.2.0-beta.15 → 2.2.0-beta.17
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/lib/event-queue.d.ts +3 -2
- package/lib/event-queue.js +22 -13
- package/lib/gateway/index.js +7 -4
- package/lib/gateway/static-file-security.js +13 -1
- package/lib/helper.d.ts +1 -0
- package/lib/helper.js +9 -8
- package/lib/index.d.ts +1 -0
- package/lib/index.js +2 -0
- package/lib/swagger/app.d.ts +17 -1
- package/lib/swagger/app.js +16 -1
- package/lib/swagger/index.d.ts +17 -1
- package/package.json +17 -17
package/lib/event-queue.d.ts
CHANGED
|
@@ -53,17 +53,18 @@ export interface EventQueueOptions {
|
|
|
53
53
|
export declare class MemoryEventQueueAdapter implements IEventQueueAdapter {
|
|
54
54
|
private options;
|
|
55
55
|
private connected;
|
|
56
|
-
private emitter;
|
|
57
56
|
private reading;
|
|
57
|
+
private scheduledChannels;
|
|
58
58
|
protected events: Map<string, QueueEventOptions>;
|
|
59
59
|
protected queues: Map<string, {
|
|
60
60
|
id: string;
|
|
61
61
|
content: any;
|
|
62
62
|
options?: QueueMessageOptions;
|
|
63
63
|
}[]>;
|
|
64
|
-
get processing(): Promise<
|
|
64
|
+
get processing(): Promise<void[]>;
|
|
65
65
|
private get storagePath();
|
|
66
66
|
listen: (channel: string) => void;
|
|
67
|
+
private scheduleListen;
|
|
67
68
|
constructor(options: {
|
|
68
69
|
appName: string;
|
|
69
70
|
logger: SystemLogger;
|
package/lib/event-queue.js
CHANGED
|
@@ -46,7 +46,6 @@ __export(event_queue_exports, {
|
|
|
46
46
|
});
|
|
47
47
|
module.exports = __toCommonJS(event_queue_exports);
|
|
48
48
|
var import_crypto = require("crypto");
|
|
49
|
-
var import_events = require("events");
|
|
50
49
|
var import_path = __toESM(require("path"));
|
|
51
50
|
var import_promises = __toESM(require("fs/promises"));
|
|
52
51
|
var import_utils = require("@nocobase/utils");
|
|
@@ -56,15 +55,14 @@ const QUEUE_DEFAULT_ACK_TIMEOUT = 15e3;
|
|
|
56
55
|
const _MemoryEventQueueAdapter = class _MemoryEventQueueAdapter {
|
|
57
56
|
constructor(options) {
|
|
58
57
|
this.options = options;
|
|
59
|
-
this.emitter.setMaxListeners(0);
|
|
60
58
|
}
|
|
61
59
|
connected = false;
|
|
62
|
-
emitter = new import_events.EventEmitter();
|
|
63
60
|
reading = /* @__PURE__ */ new Map();
|
|
61
|
+
scheduledChannels = /* @__PURE__ */ new Set();
|
|
64
62
|
events = /* @__PURE__ */ new Map();
|
|
65
63
|
queues = /* @__PURE__ */ new Map();
|
|
66
64
|
get processing() {
|
|
67
|
-
const processing = Array.from(this.reading.values());
|
|
65
|
+
const processing = Array.from(this.reading.values()).flat();
|
|
68
66
|
if (processing.length > 0) {
|
|
69
67
|
return Promise.all(processing);
|
|
70
68
|
}
|
|
@@ -80,14 +78,15 @@ const _MemoryEventQueueAdapter = class _MemoryEventQueueAdapter {
|
|
|
80
78
|
const { logger } = this.options;
|
|
81
79
|
const event = this.events.get(channel);
|
|
82
80
|
if (!event) {
|
|
83
|
-
logger.warn(`memory queue (${channel}) not found, skipping...`);
|
|
84
81
|
return;
|
|
85
82
|
}
|
|
86
83
|
if (!event.idle()) {
|
|
87
84
|
return;
|
|
88
85
|
}
|
|
89
86
|
const reading = this.reading.get(channel) || [];
|
|
90
|
-
const
|
|
87
|
+
const queue = this.queues.get(channel);
|
|
88
|
+
const concurrency = event.concurrency ?? QUEUE_DEFAULT_CONCURRENCY;
|
|
89
|
+
const count = concurrency <= 0 ? (queue == null ? void 0 : queue.length) || 0 : concurrency - reading.length;
|
|
91
90
|
if (count <= 0) {
|
|
92
91
|
return;
|
|
93
92
|
}
|
|
@@ -99,10 +98,24 @@ const _MemoryEventQueueAdapter = class _MemoryEventQueueAdapter {
|
|
|
99
98
|
if (index > -1) {
|
|
100
99
|
reading.splice(index, 1);
|
|
101
100
|
}
|
|
101
|
+
this.scheduleListen(channel);
|
|
102
102
|
});
|
|
103
103
|
});
|
|
104
104
|
this.reading.set(channel, reading);
|
|
105
105
|
}, "listen");
|
|
106
|
+
scheduleListen(channel) {
|
|
107
|
+
if (this.scheduledChannels.has(channel)) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
this.scheduledChannels.add(channel);
|
|
111
|
+
setImmediate(() => {
|
|
112
|
+
this.scheduledChannels.delete(channel);
|
|
113
|
+
if (!this.events.has(channel)) {
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
this.listen(channel);
|
|
117
|
+
});
|
|
118
|
+
}
|
|
106
119
|
isConnected() {
|
|
107
120
|
return this.connected;
|
|
108
121
|
}
|
|
@@ -181,7 +194,6 @@ const _MemoryEventQueueAdapter = class _MemoryEventQueueAdapter {
|
|
|
181
194
|
if (!this.queues.has(channel)) {
|
|
182
195
|
this.queues.set(channel, []);
|
|
183
196
|
}
|
|
184
|
-
this.emitter.on(channel, this.listen);
|
|
185
197
|
if (this.connected) {
|
|
186
198
|
this.consume(channel);
|
|
187
199
|
}
|
|
@@ -191,12 +203,12 @@ const _MemoryEventQueueAdapter = class _MemoryEventQueueAdapter {
|
|
|
191
203
|
return;
|
|
192
204
|
}
|
|
193
205
|
this.events.delete(channel);
|
|
194
|
-
this.emitter.off(channel, this.listen);
|
|
195
206
|
}
|
|
196
207
|
publish(channel, content, options = { timestamp: Date.now() }) {
|
|
208
|
+
const { logger } = this.options;
|
|
197
209
|
const event = this.events.get(channel);
|
|
198
210
|
if (!event) {
|
|
199
|
-
|
|
211
|
+
logger.debug(`memory queue (${channel}) not subscribed, skip`);
|
|
200
212
|
return;
|
|
201
213
|
}
|
|
202
214
|
if (!this.queues.get(channel)) {
|
|
@@ -205,11 +217,8 @@ const _MemoryEventQueueAdapter = class _MemoryEventQueueAdapter {
|
|
|
205
217
|
const queue = this.queues.get(channel);
|
|
206
218
|
const message = { id: (0, import_crypto.randomUUID)(), content, options };
|
|
207
219
|
queue.push(message);
|
|
208
|
-
const { logger } = this.options;
|
|
209
220
|
logger.debug(`memory queue (${channel}) published message`, content);
|
|
210
|
-
|
|
211
|
-
this.emitter.emit(channel, channel);
|
|
212
|
-
});
|
|
221
|
+
this.scheduleListen(channel);
|
|
213
222
|
}
|
|
214
223
|
async consume(channel, once = false) {
|
|
215
224
|
while (this.connected && this.events.get(channel)) {
|
package/lib/gateway/index.js
CHANGED
|
@@ -390,14 +390,17 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
|
|
|
390
390
|
}
|
|
391
391
|
}
|
|
392
392
|
const headers = (0, import_static_file_security.getStorageUploadSecurityHeaders)(`${pathname}${search || ""}`);
|
|
393
|
-
for (const [key, value] of Object.entries(headers)) {
|
|
394
|
-
res.setHeader(key, value);
|
|
395
|
-
}
|
|
396
393
|
req.url = req.url.substring(APP_PUBLIC_PATH.length + "storage".length);
|
|
397
394
|
await compress(req, res);
|
|
398
395
|
return (0, import_serve_handler.default)(req, res, {
|
|
399
396
|
public: (0, import_utils.resolveStorageRoot)(),
|
|
400
|
-
directoryListing: false
|
|
397
|
+
directoryListing: false,
|
|
398
|
+
headers: [
|
|
399
|
+
{
|
|
400
|
+
source: "**/*",
|
|
401
|
+
headers: Object.entries(headers).map(([key, value]) => ({ key, value }))
|
|
402
|
+
}
|
|
403
|
+
]
|
|
401
404
|
});
|
|
402
405
|
}
|
|
403
406
|
if (pathname.startsWith(APP_PUBLIC_PATH + "dist/")) {
|
|
@@ -42,7 +42,18 @@ __export(static_file_security_exports, {
|
|
|
42
42
|
});
|
|
43
43
|
module.exports = __toCommonJS(static_file_security_exports);
|
|
44
44
|
var import_node_path = __toESM(require("node:path"));
|
|
45
|
-
const ACTIVE_CONTENT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
45
|
+
const ACTIVE_CONTENT_EXTENSIONS = /* @__PURE__ */ new Set([
|
|
46
|
+
".htm",
|
|
47
|
+
".html",
|
|
48
|
+
".pdf",
|
|
49
|
+
".svg",
|
|
50
|
+
".svgz",
|
|
51
|
+
".xht",
|
|
52
|
+
".xhtml",
|
|
53
|
+
".xml",
|
|
54
|
+
".xsl",
|
|
55
|
+
".xslt"
|
|
56
|
+
]);
|
|
46
57
|
function stripQueryAndHash(pathname = "") {
|
|
47
58
|
return pathname.split("?")[0].split("#")[0];
|
|
48
59
|
}
|
|
@@ -63,6 +74,7 @@ function hasActiveContentExtension(pathname = "") {
|
|
|
63
74
|
__name(hasActiveContentExtension, "hasActiveContentExtension");
|
|
64
75
|
function getStorageUploadSecurityHeaders(pathname = "") {
|
|
65
76
|
const headers = {
|
|
77
|
+
"Content-Security-Policy": "sandbox",
|
|
66
78
|
"X-Content-Type-Options": "nosniff"
|
|
67
79
|
};
|
|
68
80
|
if (hasActiveContentExtension(pathname) || shouldDownload(pathname)) {
|
package/lib/helper.d.ts
CHANGED
|
@@ -11,6 +11,7 @@ import { Command } from 'commander';
|
|
|
11
11
|
import Application, { ApplicationOptions } from './application';
|
|
12
12
|
export declare function createI18n(options: ApplicationOptions): import("i18next").i18n;
|
|
13
13
|
export declare function createResourcer(options: ApplicationOptions): Resourcer;
|
|
14
|
+
export declare function resolveCorsOrigin(ctx: any): any;
|
|
14
15
|
export declare function registerMiddlewares(app: Application, options: ApplicationOptions): void;
|
|
15
16
|
export declare const createAppProxy: (app: Application) => Application<import("./application").DefaultState, import("./application").DefaultContext>;
|
|
16
17
|
export declare const getCommandFullName: (command: Command) => string;
|
package/lib/helper.js
CHANGED
|
@@ -45,6 +45,7 @@ __export(helper_exports, {
|
|
|
45
45
|
getBodyLimit: () => getBodyLimit,
|
|
46
46
|
getCommandFullName: () => getCommandFullName,
|
|
47
47
|
registerMiddlewares: () => registerMiddlewares,
|
|
48
|
+
resolveCorsOrigin: () => resolveCorsOrigin,
|
|
48
49
|
tsxRerunning: () => tsxRerunning
|
|
49
50
|
});
|
|
50
51
|
module.exports = __toCommonJS(helper_exports);
|
|
@@ -78,26 +79,23 @@ function createResourcer(options) {
|
|
|
78
79
|
__name(createResourcer, "createResourcer");
|
|
79
80
|
function isWhitelistedCorsOrigin(ctx) {
|
|
80
81
|
const origin = ctx.get("origin");
|
|
81
|
-
const whitelist = (0, import_utils.getCorsWhitelist)();
|
|
82
82
|
if (!origin) {
|
|
83
83
|
return false;
|
|
84
84
|
}
|
|
85
|
-
|
|
86
|
-
return (0, import_utils.isTrustedOrigin)(ctx, origin);
|
|
87
|
-
}
|
|
88
|
-
return whitelist.has(origin);
|
|
85
|
+
return (0, import_utils.isTrustedOrigin)(ctx, origin);
|
|
89
86
|
}
|
|
90
87
|
__name(isWhitelistedCorsOrigin, "isWhitelistedCorsOrigin");
|
|
91
88
|
function resolveCorsOrigin(ctx) {
|
|
92
89
|
const origin = ctx.get("origin");
|
|
93
90
|
const disallowNoOrigin = process.env.CORS_DISALLOW_NO_ORIGIN === "true";
|
|
91
|
+
const whitelist = (0, import_utils.getCorsWhitelist)();
|
|
94
92
|
if (!origin && disallowNoOrigin) {
|
|
95
93
|
return false;
|
|
96
94
|
}
|
|
97
95
|
if (isWhitelistedCorsOrigin(ctx)) {
|
|
98
96
|
return origin;
|
|
99
97
|
}
|
|
100
|
-
return
|
|
98
|
+
return whitelist ? false : origin;
|
|
101
99
|
}
|
|
102
100
|
__name(resolveCorsOrigin, "resolveCorsOrigin");
|
|
103
101
|
function registerMiddlewares(app, options) {
|
|
@@ -114,7 +112,7 @@ function registerMiddlewares(app, options) {
|
|
|
114
112
|
app.use(
|
|
115
113
|
(0, import_cors.default)({
|
|
116
114
|
credentials: isWhitelistedCorsOrigin,
|
|
117
|
-
exposeHeaders: ["content-disposition"],
|
|
115
|
+
exposeHeaders: ["content-disposition", "x-new-token"],
|
|
118
116
|
origin: resolveCorsOrigin,
|
|
119
117
|
...options.cors
|
|
120
118
|
}),
|
|
@@ -140,6 +138,7 @@ function registerMiddlewares(app, options) {
|
|
|
140
138
|
}
|
|
141
139
|
app.use(/* @__PURE__ */ __name(async function getBearerToken(ctx, next) {
|
|
142
140
|
ctx.getBearerToken = () => {
|
|
141
|
+
var _a2;
|
|
143
142
|
const authorization = ctx.get("Authorization");
|
|
144
143
|
if (authorization) {
|
|
145
144
|
ctx.state.pendingAuthTokenSource = "authorization";
|
|
@@ -149,7 +148,8 @@ function registerMiddlewares(app, options) {
|
|
|
149
148
|
ctx.state.pendingAuthTokenSource = "query";
|
|
150
149
|
return ctx.query.token;
|
|
151
150
|
}
|
|
152
|
-
const
|
|
151
|
+
const canUseAuthCookie = Boolean((_a2 = ctx.state) == null ? void 0 : _a2.fileAccess) && ["GET", "HEAD"].includes(ctx.method);
|
|
152
|
+
const cookieToken = canUseAuthCookie ? ctx.cookies.get((0, import_utils.getAuthCookieName)("authToken", app.name)) : void 0;
|
|
153
153
|
ctx.state.pendingAuthTokenSource = cookieToken ? "cookie" : void 0;
|
|
154
154
|
return cookieToken;
|
|
155
155
|
};
|
|
@@ -325,5 +325,6 @@ __name(createContextVariablesScope, "createContextVariablesScope");
|
|
|
325
325
|
getBodyLimit,
|
|
326
326
|
getCommandFullName,
|
|
327
327
|
registerMiddlewares,
|
|
328
|
+
resolveCorsOrigin,
|
|
328
329
|
tsxRerunning
|
|
329
330
|
});
|
package/lib/index.d.ts
CHANGED
|
@@ -13,6 +13,7 @@ export * from './gateway/ws-server';
|
|
|
13
13
|
export { Application as default } from './application';
|
|
14
14
|
export * from './audit-manager';
|
|
15
15
|
export * from './gateway';
|
|
16
|
+
export * from './gateway/static-file-security';
|
|
16
17
|
export * as middlewares from './middlewares';
|
|
17
18
|
export * from './migration';
|
|
18
19
|
export * from './plugin';
|
package/lib/index.js
CHANGED
|
@@ -55,6 +55,7 @@ __reExport(src_exports, require("./gateway/ws-server"), module.exports);
|
|
|
55
55
|
var import_application = require("./application");
|
|
56
56
|
__reExport(src_exports, require("./audit-manager"), module.exports);
|
|
57
57
|
__reExport(src_exports, require("./gateway"), module.exports);
|
|
58
|
+
__reExport(src_exports, require("./gateway/static-file-security"), module.exports);
|
|
58
59
|
var middlewares = __toESM(require("./middlewares"));
|
|
59
60
|
__reExport(src_exports, require("./migration"), module.exports);
|
|
60
61
|
__reExport(src_exports, require("./plugin"), module.exports);
|
|
@@ -85,6 +86,7 @@ var import_helper = require("./helper");
|
|
|
85
86
|
...require("./gateway/ws-server"),
|
|
86
87
|
...require("./audit-manager"),
|
|
87
88
|
...require("./gateway"),
|
|
89
|
+
...require("./gateway/static-file-security"),
|
|
88
90
|
...require("./migration"),
|
|
89
91
|
...require("./plugin"),
|
|
90
92
|
...require("./plugin-manager"),
|
package/lib/swagger/app.d.ts
CHANGED
|
@@ -12,7 +12,23 @@ declare const _default: {
|
|
|
12
12
|
readonly tags: readonly ["app"];
|
|
13
13
|
readonly summary: "Get the current application language";
|
|
14
14
|
readonly description: "Return the current locale used by the server.";
|
|
15
|
-
readonly parameters: readonly [
|
|
15
|
+
readonly parameters: readonly [{
|
|
16
|
+
readonly name: "locale";
|
|
17
|
+
readonly in: "query";
|
|
18
|
+
readonly required: false;
|
|
19
|
+
readonly schema: {
|
|
20
|
+
readonly type: "string";
|
|
21
|
+
};
|
|
22
|
+
readonly description: "Requested application locale. The server validates it against enabled languages.";
|
|
23
|
+
}, {
|
|
24
|
+
readonly name: "ns";
|
|
25
|
+
readonly in: "query";
|
|
26
|
+
readonly required: false;
|
|
27
|
+
readonly schema: {
|
|
28
|
+
readonly type: "string";
|
|
29
|
+
};
|
|
30
|
+
readonly description: "Comma-separated resource namespaces to return. Omit it to preserve the full legacy payload.";
|
|
31
|
+
}];
|
|
16
32
|
readonly responses: {
|
|
17
33
|
readonly 200: {
|
|
18
34
|
readonly description: "OK";
|
package/lib/swagger/app.js
CHANGED
|
@@ -35,7 +35,22 @@ var app_default = {
|
|
|
35
35
|
tags: ["app"],
|
|
36
36
|
summary: "Get the current application language",
|
|
37
37
|
description: "Return the current locale used by the server.",
|
|
38
|
-
parameters: [
|
|
38
|
+
parameters: [
|
|
39
|
+
{
|
|
40
|
+
name: "locale",
|
|
41
|
+
in: "query",
|
|
42
|
+
required: false,
|
|
43
|
+
schema: { type: "string" },
|
|
44
|
+
description: "Requested application locale. The server validates it against enabled languages."
|
|
45
|
+
},
|
|
46
|
+
{
|
|
47
|
+
name: "ns",
|
|
48
|
+
in: "query",
|
|
49
|
+
required: false,
|
|
50
|
+
schema: { type: "string" },
|
|
51
|
+
description: "Comma-separated resource namespaces to return. Omit it to preserve the full legacy payload."
|
|
52
|
+
}
|
|
53
|
+
],
|
|
39
54
|
responses: {
|
|
40
55
|
200: {
|
|
41
56
|
description: "OK",
|
package/lib/swagger/index.d.ts
CHANGED
|
@@ -694,7 +694,23 @@ declare const _default: {
|
|
|
694
694
|
readonly tags: readonly ["app"];
|
|
695
695
|
readonly summary: "Get the current application language";
|
|
696
696
|
readonly description: "Return the current locale used by the server.";
|
|
697
|
-
readonly parameters: readonly [
|
|
697
|
+
readonly parameters: readonly [{
|
|
698
|
+
readonly name: "locale";
|
|
699
|
+
readonly in: "query";
|
|
700
|
+
readonly required: false;
|
|
701
|
+
readonly schema: {
|
|
702
|
+
readonly type: "string";
|
|
703
|
+
};
|
|
704
|
+
readonly description: "Requested application locale. The server validates it against enabled languages.";
|
|
705
|
+
}, {
|
|
706
|
+
readonly name: "ns";
|
|
707
|
+
readonly in: "query";
|
|
708
|
+
readonly required: false;
|
|
709
|
+
readonly schema: {
|
|
710
|
+
readonly type: "string";
|
|
711
|
+
};
|
|
712
|
+
readonly description: "Comma-separated resource namespaces to return. Omit it to preserve the full legacy payload.";
|
|
713
|
+
}];
|
|
698
714
|
readonly responses: {
|
|
699
715
|
readonly 200: {
|
|
700
716
|
readonly description: "OK";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/server",
|
|
3
|
-
"version": "2.2.0-beta.
|
|
3
|
+
"version": "2.2.0-beta.17",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "./lib/index.d.ts",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -10,21 +10,21 @@
|
|
|
10
10
|
"@koa/cors": "^5.0.0",
|
|
11
11
|
"@koa/multer": "^3.1.0",
|
|
12
12
|
"@koa/router": "^13.1.0",
|
|
13
|
-
"@nocobase/acl": "2.2.0-beta.
|
|
14
|
-
"@nocobase/actions": "2.2.0-beta.
|
|
15
|
-
"@nocobase/ai": "2.2.0-beta.
|
|
16
|
-
"@nocobase/auth": "2.2.0-beta.
|
|
17
|
-
"@nocobase/cache": "2.2.0-beta.
|
|
18
|
-
"@nocobase/data-source-manager": "2.2.0-beta.
|
|
19
|
-
"@nocobase/database": "2.2.0-beta.
|
|
20
|
-
"@nocobase/evaluators": "2.2.0-beta.
|
|
21
|
-
"@nocobase/lock-manager": "2.2.0-beta.
|
|
22
|
-
"@nocobase/logger": "2.2.0-beta.
|
|
23
|
-
"@nocobase/resourcer": "2.2.0-beta.
|
|
24
|
-
"@nocobase/sdk": "2.2.0-beta.
|
|
25
|
-
"@nocobase/snowflake-id": "2.2.0-beta.
|
|
26
|
-
"@nocobase/telemetry": "2.2.0-beta.
|
|
27
|
-
"@nocobase/utils": "2.2.0-beta.
|
|
13
|
+
"@nocobase/acl": "2.2.0-beta.17",
|
|
14
|
+
"@nocobase/actions": "2.2.0-beta.17",
|
|
15
|
+
"@nocobase/ai": "2.2.0-beta.17",
|
|
16
|
+
"@nocobase/auth": "2.2.0-beta.17",
|
|
17
|
+
"@nocobase/cache": "2.2.0-beta.17",
|
|
18
|
+
"@nocobase/data-source-manager": "2.2.0-beta.17",
|
|
19
|
+
"@nocobase/database": "2.2.0-beta.17",
|
|
20
|
+
"@nocobase/evaluators": "2.2.0-beta.17",
|
|
21
|
+
"@nocobase/lock-manager": "2.2.0-beta.17",
|
|
22
|
+
"@nocobase/logger": "2.2.0-beta.17",
|
|
23
|
+
"@nocobase/resourcer": "2.2.0-beta.17",
|
|
24
|
+
"@nocobase/sdk": "2.2.0-beta.17",
|
|
25
|
+
"@nocobase/snowflake-id": "2.2.0-beta.17",
|
|
26
|
+
"@nocobase/telemetry": "2.2.0-beta.17",
|
|
27
|
+
"@nocobase/utils": "2.2.0-beta.17",
|
|
28
28
|
"@types/decompress": "4.2.7",
|
|
29
29
|
"@types/ini": "^1.3.31",
|
|
30
30
|
"@types/koa-send": "^4.1.3",
|
|
@@ -61,5 +61,5 @@
|
|
|
61
61
|
"@types/serve-handler": "^6.1.1",
|
|
62
62
|
"@types/ws": "^8.5.5"
|
|
63
63
|
},
|
|
64
|
-
"gitHead": "
|
|
64
|
+
"gitHead": "d7a69c4f47fe38b17a2ce1408258902cf64f6c83"
|
|
65
65
|
}
|