@nocobase/server 1.9.0-beta.5 → 1.9.0-beta.7
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/application.js +3 -0
- package/lib/audit-manager/index.js +3 -0
- package/lib/event-queue.d.ts +2 -0
- package/lib/event-queue.js +40 -28
- package/lib/gateway/ws-server.js +20 -0
- package/lib/pub-sub-manager/pub-sub-manager.d.ts +3 -2
- package/lib/pub-sub-manager/pub-sub-manager.js +22 -9
- package/lib/sync-message-manager.d.ts +1 -1
- package/package.json +15 -15
package/lib/application.js
CHANGED
|
@@ -279,6 +279,9 @@ const _Application = class _Application extends import_koa.default {
|
|
|
279
279
|
if (!WORKER_MODE) {
|
|
280
280
|
return true;
|
|
281
281
|
}
|
|
282
|
+
if (WORKER_MODE === "-") {
|
|
283
|
+
return false;
|
|
284
|
+
}
|
|
282
285
|
const topics = WORKER_MODE.trim().split(",");
|
|
283
286
|
if (key) {
|
|
284
287
|
if (WORKER_MODE === "*") {
|
|
@@ -252,6 +252,9 @@ const _AuditManager = class _AuditManager {
|
|
|
252
252
|
async output(ctx, reqId, metadata) {
|
|
253
253
|
var _a;
|
|
254
254
|
try {
|
|
255
|
+
if (!ctx.action) {
|
|
256
|
+
return;
|
|
257
|
+
}
|
|
255
258
|
const { resourceName, actionName } = ctx.action;
|
|
256
259
|
const action = this.getAction(actionName, resourceName);
|
|
257
260
|
if (!action) {
|
package/lib/event-queue.d.ts
CHANGED
|
@@ -7,6 +7,7 @@
|
|
|
7
7
|
* For more information, please refer to: https://www.nocobase.com/agreement.
|
|
8
8
|
*/
|
|
9
9
|
import Application from './application';
|
|
10
|
+
import { SystemLogger } from '@nocobase/logger';
|
|
10
11
|
export declare const QUEUE_DEFAULT_INTERVAL = 250;
|
|
11
12
|
export declare const QUEUE_DEFAULT_CONCURRENCY = 1;
|
|
12
13
|
export declare const QUEUE_DEFAULT_ACK_TIMEOUT = 15000;
|
|
@@ -58,6 +59,7 @@ export declare class MemoryEventQueueAdapter implements IEventQueueAdapter {
|
|
|
58
59
|
listen: (channel: string) => void;
|
|
59
60
|
constructor(options: {
|
|
60
61
|
appName: string;
|
|
62
|
+
logger: SystemLogger;
|
|
61
63
|
});
|
|
62
64
|
isConnected(): boolean;
|
|
63
65
|
setConnected(connected: boolean): void;
|
package/lib/event-queue.js
CHANGED
|
@@ -77,9 +77,10 @@ const _MemoryEventQueueAdapter = class _MemoryEventQueueAdapter {
|
|
|
77
77
|
if (!this.connected) {
|
|
78
78
|
return;
|
|
79
79
|
}
|
|
80
|
+
const { logger } = this.options;
|
|
80
81
|
const event = this.events.get(channel);
|
|
81
82
|
if (!event) {
|
|
82
|
-
|
|
83
|
+
logger.warn(`memory queue (${channel}) not found, skipping...`);
|
|
83
84
|
return;
|
|
84
85
|
}
|
|
85
86
|
if (!event.idle()) {
|
|
@@ -88,12 +89,9 @@ const _MemoryEventQueueAdapter = class _MemoryEventQueueAdapter {
|
|
|
88
89
|
const reading = this.reading.get(channel) || [];
|
|
89
90
|
const count = (event.concurrency || QUEUE_DEFAULT_CONCURRENCY) - reading.length;
|
|
90
91
|
if (count <= 0) {
|
|
91
|
-
console.debug(
|
|
92
|
-
`memory queue (${channel}) is already reading as max concurrency (${reading.length}), waiting last reading to end...`
|
|
93
|
-
);
|
|
94
92
|
return;
|
|
95
93
|
}
|
|
96
|
-
|
|
94
|
+
logger.debug(`reading more from queue (${channel}), count: ${count}`);
|
|
97
95
|
this.read(channel, count).forEach((promise) => {
|
|
98
96
|
reading.push(promise);
|
|
99
97
|
promise.finally(() => {
|
|
@@ -114,20 +112,21 @@ const _MemoryEventQueueAdapter = class _MemoryEventQueueAdapter {
|
|
|
114
112
|
async loadFromStorage() {
|
|
115
113
|
let queues = {};
|
|
116
114
|
let exists = false;
|
|
115
|
+
const { logger } = this.options;
|
|
117
116
|
try {
|
|
118
117
|
await import_promises.default.stat(this.storagePath);
|
|
119
118
|
exists = true;
|
|
120
119
|
} catch (ex) {
|
|
121
|
-
|
|
120
|
+
logger.info(`memory queue storage file not found, skip`);
|
|
122
121
|
}
|
|
123
122
|
if (exists) {
|
|
124
123
|
try {
|
|
125
124
|
const queueJson = await import_promises.default.readFile(this.storagePath);
|
|
126
125
|
queues = JSON.parse(queueJson.toString());
|
|
127
|
-
|
|
126
|
+
logger.debug("memory queue loaded from storage", queues);
|
|
128
127
|
await import_promises.default.unlink(this.storagePath);
|
|
129
128
|
} catch (ex) {
|
|
130
|
-
|
|
129
|
+
logger.error("failed to load queue from storage", ex);
|
|
131
130
|
}
|
|
132
131
|
}
|
|
133
132
|
this.queues = new Map(Object.entries(queues));
|
|
@@ -139,12 +138,13 @@ const _MemoryEventQueueAdapter = class _MemoryEventQueueAdapter {
|
|
|
139
138
|
}
|
|
140
139
|
return acc;
|
|
141
140
|
}, {});
|
|
141
|
+
const { logger } = this.options;
|
|
142
142
|
if (Object.keys(queues).length) {
|
|
143
143
|
await import_promises.default.mkdir(import_path.default.dirname(this.storagePath), { recursive: true });
|
|
144
144
|
await import_promises.default.writeFile(this.storagePath, JSON.stringify(queues));
|
|
145
|
-
|
|
145
|
+
logger.debug("memory queue saved to storage", queues);
|
|
146
146
|
} else {
|
|
147
|
-
|
|
147
|
+
logger.debug("memory queue empty, no need to save to storage");
|
|
148
148
|
}
|
|
149
149
|
}
|
|
150
150
|
async connect() {
|
|
@@ -163,13 +163,14 @@ const _MemoryEventQueueAdapter = class _MemoryEventQueueAdapter {
|
|
|
163
163
|
if (!this.connected) {
|
|
164
164
|
return;
|
|
165
165
|
}
|
|
166
|
+
const { logger } = this.options;
|
|
166
167
|
this.connected = false;
|
|
167
168
|
if (this.processing) {
|
|
168
|
-
|
|
169
|
+
logger.info("memory queue waiting for processing job...");
|
|
169
170
|
await this.processing;
|
|
170
|
-
|
|
171
|
+
logger.info("memory queue job cleaned");
|
|
171
172
|
}
|
|
172
|
-
|
|
173
|
+
logger.info("memory queue gracefully shutting down...");
|
|
173
174
|
await this.saveToStorage();
|
|
174
175
|
}
|
|
175
176
|
subscribe(channel, options) {
|
|
@@ -195,6 +196,7 @@ const _MemoryEventQueueAdapter = class _MemoryEventQueueAdapter {
|
|
|
195
196
|
publish(channel, content, options = { timestamp: Date.now() }) {
|
|
196
197
|
const event = this.events.get(channel);
|
|
197
198
|
if (!event) {
|
|
199
|
+
console.debug(`memory queue (${channel}) not subscribed, skip`);
|
|
198
200
|
return;
|
|
199
201
|
}
|
|
200
202
|
if (!this.queues.get(channel)) {
|
|
@@ -203,7 +205,8 @@ const _MemoryEventQueueAdapter = class _MemoryEventQueueAdapter {
|
|
|
203
205
|
const queue = this.queues.get(channel);
|
|
204
206
|
const message = { id: (0, import_crypto.randomUUID)(), content, options };
|
|
205
207
|
queue.push(message);
|
|
206
|
-
|
|
208
|
+
const { logger } = this.options;
|
|
209
|
+
logger.debug(`memory queue (${channel}) published message`, content);
|
|
207
210
|
setImmediate(() => {
|
|
208
211
|
this.emitter.emit(channel, channel);
|
|
209
212
|
});
|
|
@@ -227,8 +230,9 @@ const _MemoryEventQueueAdapter = class _MemoryEventQueueAdapter {
|
|
|
227
230
|
if (!(queue == null ? void 0 : queue.length)) {
|
|
228
231
|
return [];
|
|
229
232
|
}
|
|
233
|
+
const { logger } = this.options;
|
|
230
234
|
const messages = queue.slice(0, n);
|
|
231
|
-
|
|
235
|
+
logger.debug(`memory queue (${channel}) read ${messages.length} messages`, messages);
|
|
232
236
|
queue.splice(0, messages.length);
|
|
233
237
|
const batch = messages.map(({ id, ...message }) => this.process(channel, { id, message }));
|
|
234
238
|
return batch;
|
|
@@ -236,17 +240,18 @@ const _MemoryEventQueueAdapter = class _MemoryEventQueueAdapter {
|
|
|
236
240
|
async process(channel, { id, message }) {
|
|
237
241
|
const event = this.events.get(channel);
|
|
238
242
|
const { content, options: { timeout = QUEUE_DEFAULT_ACK_TIMEOUT, maxRetries = 0, retried = 0 } = {} } = message;
|
|
239
|
-
|
|
243
|
+
const { logger } = this.options;
|
|
244
|
+
logger.debug(`memory queue (${channel}) processing message (${id})...`, content);
|
|
240
245
|
return (async () => event.process(content, {
|
|
241
246
|
id,
|
|
242
247
|
retried,
|
|
243
248
|
signal: AbortSignal.timeout(timeout)
|
|
244
249
|
}))().then(() => {
|
|
245
|
-
|
|
250
|
+
logger.debug(`memory queue (${channel}) consumed message (${id})`);
|
|
246
251
|
}).catch((ex) => {
|
|
247
252
|
if (maxRetries > 0 && retried < maxRetries) {
|
|
248
253
|
const currentRetry = retried + 1;
|
|
249
|
-
|
|
254
|
+
logger.warn(
|
|
250
255
|
`memory queue (${channel}) consum message (${id}) failed, retrying (${currentRetry} / ${maxRetries})...`,
|
|
251
256
|
ex
|
|
252
257
|
);
|
|
@@ -254,7 +259,7 @@ const _MemoryEventQueueAdapter = class _MemoryEventQueueAdapter {
|
|
|
254
259
|
this.publish(channel, content, { timeout, maxRetries, retried: currentRetry, timestamp: Date.now() });
|
|
255
260
|
}, 500);
|
|
256
261
|
} else {
|
|
257
|
-
|
|
262
|
+
logger.error(ex);
|
|
258
263
|
}
|
|
259
264
|
});
|
|
260
265
|
}
|
|
@@ -265,14 +270,16 @@ const _EventQueue = class _EventQueue {
|
|
|
265
270
|
constructor(app, options = {}) {
|
|
266
271
|
this.app = app;
|
|
267
272
|
this.options = options;
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
app.
|
|
274
|
-
|
|
275
|
-
|
|
273
|
+
if (app.serving()) {
|
|
274
|
+
this.setAdapter(new MemoryEventQueueAdapter({ appName: this.app.name, logger: this.app.logger }));
|
|
275
|
+
app.on("afterStart", async () => {
|
|
276
|
+
await this.connect();
|
|
277
|
+
});
|
|
278
|
+
app.on("beforeStop", async () => {
|
|
279
|
+
app.logger.info("[queue] gracefully shutting down...");
|
|
280
|
+
await this.close();
|
|
281
|
+
});
|
|
282
|
+
}
|
|
276
283
|
}
|
|
277
284
|
adapter;
|
|
278
285
|
events = /* @__PURE__ */ new Map();
|
|
@@ -296,7 +303,12 @@ const _EventQueue = class _EventQueue {
|
|
|
296
303
|
if (!this.adapter) {
|
|
297
304
|
throw new Error("no adapter set, cannot connect");
|
|
298
305
|
}
|
|
306
|
+
if (!this.app.serving()) {
|
|
307
|
+
this.app.logger.warn("app is not serving, will not connect to event queue");
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
299
310
|
await this.adapter.connect();
|
|
311
|
+
this.app.logger.debug(`connected to adapter, using memory? ${this.adapter instanceof MemoryEventQueueAdapter}`);
|
|
300
312
|
for (const [channel, event] of this.events.entries()) {
|
|
301
313
|
this.adapter.subscribe(this.getFullChannel(channel), event);
|
|
302
314
|
}
|
|
@@ -337,7 +349,7 @@ const _EventQueue = class _EventQueue {
|
|
|
337
349
|
throw new Error("event queue not connected, cannot publish");
|
|
338
350
|
}
|
|
339
351
|
const c = this.getFullChannel(channel);
|
|
340
|
-
this.app.logger.debug(
|
|
352
|
+
this.app.logger.debug(`event queue publishing to channel(${c})`, { message });
|
|
341
353
|
await this.adapter.publish(c, message, {
|
|
342
354
|
timeout: QUEUE_DEFAULT_ACK_TIMEOUT,
|
|
343
355
|
...options,
|
package/lib/gateway/ws-server.js
CHANGED
|
@@ -172,6 +172,20 @@ const _WSServer = class _WSServer extends import_events.default {
|
|
|
172
172
|
message
|
|
173
173
|
);
|
|
174
174
|
});
|
|
175
|
+
app.on("ws:sendToUser", ({ userId, message }) => {
|
|
176
|
+
this.sendToAppUser(app.name, userId, message);
|
|
177
|
+
app.logger.trace(`[broadcasting message] ws:sendToUser for user ${userId}`, { message });
|
|
178
|
+
app.pubSubManager.publish(
|
|
179
|
+
"ws:sendToUser",
|
|
180
|
+
{
|
|
181
|
+
userId,
|
|
182
|
+
message
|
|
183
|
+
},
|
|
184
|
+
{
|
|
185
|
+
skipSelf: true
|
|
186
|
+
}
|
|
187
|
+
);
|
|
188
|
+
});
|
|
175
189
|
app.on("ws:sendToClient", ({ clientId, message }) => {
|
|
176
190
|
this.sendToClient(clientId, message);
|
|
177
191
|
});
|
|
@@ -184,6 +198,12 @@ const _WSServer = class _WSServer extends import_events.default {
|
|
|
184
198
|
app.on("ws:authorized", ({ clientId, userId }) => {
|
|
185
199
|
this.sendToClient(clientId, { type: "authorized" });
|
|
186
200
|
});
|
|
201
|
+
app.on("afterLoad", () => {
|
|
202
|
+
app.pubSubManager.subscribe("ws:sendToUser", ({ userId, message }) => {
|
|
203
|
+
app.logger.debug(`[receive broadcasting message] ws:sendToUser for user ${userId}`, { message });
|
|
204
|
+
this.sendToAppUser(app.name, userId, message);
|
|
205
|
+
});
|
|
206
|
+
});
|
|
187
207
|
}
|
|
188
208
|
addNewConnection(ws, request) {
|
|
189
209
|
const id = (0, import_nanoid.nanoid)();
|
|
@@ -11,11 +11,12 @@ import { HandlerManager } from './handler-manager';
|
|
|
11
11
|
import { PubSubCallback, type IPubSubAdapter, type PubSubManagerOptions, type PubSubManagerPublishOptions, type PubSubManagerSubscribeOptions } from './types';
|
|
12
12
|
export declare const createPubSubManager: (app: Application, options: PubSubManagerOptions) => PubSubManager;
|
|
13
13
|
export declare class PubSubManager {
|
|
14
|
+
protected app: Application;
|
|
14
15
|
protected options: PubSubManagerOptions;
|
|
15
16
|
protected publisherId: string;
|
|
16
17
|
protected adapter: IPubSubAdapter;
|
|
17
18
|
protected handlerManager: HandlerManager;
|
|
18
|
-
constructor(options?: PubSubManagerOptions);
|
|
19
|
+
constructor(app: Application, options?: PubSubManagerOptions);
|
|
19
20
|
get channelPrefix(): string;
|
|
20
21
|
setAdapter(adapter: IPubSubAdapter): void;
|
|
21
22
|
isConnected(): Promise<boolean>;
|
|
@@ -23,5 +24,5 @@ export declare class PubSubManager {
|
|
|
23
24
|
close(): Promise<any>;
|
|
24
25
|
subscribe(channel: string, callback: PubSubCallback, options?: PubSubManagerSubscribeOptions): Promise<void>;
|
|
25
26
|
unsubscribe(channel: string, callback: PubSubCallback): Promise<any>;
|
|
26
|
-
publish(channel: string, message: any, options?: PubSubManagerPublishOptions): Promise<
|
|
27
|
+
publish(channel: string, message: any, options?: PubSubManagerPublishOptions): Promise<void>;
|
|
27
28
|
}
|
|
@@ -34,17 +34,20 @@ module.exports = __toCommonJS(pub_sub_manager_exports);
|
|
|
34
34
|
var import_utils = require("@nocobase/utils");
|
|
35
35
|
var import_handler_manager = require("./handler-manager");
|
|
36
36
|
const createPubSubManager = /* @__PURE__ */ __name((app, options) => {
|
|
37
|
-
const pubSubManager = new PubSubManager(options);
|
|
38
|
-
app.
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
const pubSubManager = new PubSubManager(app, options);
|
|
38
|
+
if (app.serving()) {
|
|
39
|
+
app.on("afterStart", async () => {
|
|
40
|
+
await pubSubManager.connect();
|
|
41
|
+
});
|
|
42
|
+
app.on("afterStop", async () => {
|
|
43
|
+
await pubSubManager.close();
|
|
44
|
+
});
|
|
45
|
+
}
|
|
44
46
|
return pubSubManager;
|
|
45
47
|
}, "createPubSubManager");
|
|
46
48
|
const _PubSubManager = class _PubSubManager {
|
|
47
|
-
constructor(options = {}) {
|
|
49
|
+
constructor(app, options = {}) {
|
|
50
|
+
this.app = app;
|
|
48
51
|
this.options = options;
|
|
49
52
|
this.publisherId = (0, import_utils.uid)();
|
|
50
53
|
this.handlerManager = new import_handler_manager.HandlerManager(this.publisherId);
|
|
@@ -69,8 +72,13 @@ const _PubSubManager = class _PubSubManager {
|
|
|
69
72
|
if (!this.adapter) {
|
|
70
73
|
return;
|
|
71
74
|
}
|
|
75
|
+
if (!this.app.serving()) {
|
|
76
|
+
this.app.logger.warn("app is not serving, will not connect to event queue");
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
72
79
|
await this.adapter.connect();
|
|
73
80
|
await this.handlerManager.each(async (channel, headler) => {
|
|
81
|
+
this.app.logger.debug(`[PubSubManager] subscribe ${channel} added before connected`);
|
|
74
82
|
await this.adapter.subscribe(`${this.channelPrefix}${channel}`, headler);
|
|
75
83
|
});
|
|
76
84
|
}
|
|
@@ -84,6 +92,7 @@ const _PubSubManager = class _PubSubManager {
|
|
|
84
92
|
await this.unsubscribe(channel, callback);
|
|
85
93
|
const handler = this.handlerManager.set(channel, callback, options);
|
|
86
94
|
if (await this.isConnected()) {
|
|
95
|
+
this.app.logger.debug(`[PubSubManager] subscribe ${channel} added after connected`);
|
|
87
96
|
await this.adapter.subscribe(`${this.channelPrefix}${channel}`, handler);
|
|
88
97
|
}
|
|
89
98
|
}
|
|
@@ -97,6 +106,9 @@ const _PubSubManager = class _PubSubManager {
|
|
|
97
106
|
async publish(channel, message, options) {
|
|
98
107
|
var _a;
|
|
99
108
|
if (!((_a = this.adapter) == null ? void 0 : _a.isConnected())) {
|
|
109
|
+
this.app.logger.warn(
|
|
110
|
+
`[PubSubManager] adapter is not exist or not connected, cannot publish message to channel ${channel}`
|
|
111
|
+
);
|
|
100
112
|
return;
|
|
101
113
|
}
|
|
102
114
|
const wrappedMessage = JSON.stringify({
|
|
@@ -104,7 +116,8 @@ const _PubSubManager = class _PubSubManager {
|
|
|
104
116
|
...options,
|
|
105
117
|
message
|
|
106
118
|
});
|
|
107
|
-
|
|
119
|
+
await this.adapter.publish(`${this.channelPrefix}${channel}`, wrappedMessage);
|
|
120
|
+
this.app.logger.trace(`[PubSubManager] published message to channel ${channel}`);
|
|
108
121
|
}
|
|
109
122
|
};
|
|
110
123
|
__name(_PubSubManager, "PubSubManager");
|
|
@@ -16,7 +16,7 @@ export declare class SyncMessageManager {
|
|
|
16
16
|
protected pubSubManager: PubSubManager;
|
|
17
17
|
constructor(app: Application, options?: any);
|
|
18
18
|
get debounce(): any;
|
|
19
|
-
publish(channel: string, message: any, options?: PubSubManagerPublishOptions & Transactionable): Promise<
|
|
19
|
+
publish(channel: string, message: any, options?: PubSubManagerPublishOptions & Transactionable): Promise<unknown>;
|
|
20
20
|
subscribe(channel: string, callback: PubSubCallback): Promise<void>;
|
|
21
21
|
unsubscribe(channel: string, callback: PubSubCallback): Promise<any>;
|
|
22
22
|
sync(): Promise<void>;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocobase/server",
|
|
3
|
-
"version": "1.9.0-beta.
|
|
3
|
+
"version": "1.9.0-beta.7",
|
|
4
4
|
"main": "lib/index.js",
|
|
5
5
|
"types": "./lib/index.d.ts",
|
|
6
6
|
"license": "AGPL-3.0",
|
|
@@ -10,19 +10,19 @@
|
|
|
10
10
|
"@koa/cors": "^5.0.0",
|
|
11
11
|
"@koa/multer": "^3.1.0",
|
|
12
12
|
"@koa/router": "^13.1.0",
|
|
13
|
-
"@nocobase/acl": "1.9.0-beta.
|
|
14
|
-
"@nocobase/actions": "1.9.0-beta.
|
|
15
|
-
"@nocobase/auth": "1.9.0-beta.
|
|
16
|
-
"@nocobase/cache": "1.9.0-beta.
|
|
17
|
-
"@nocobase/data-source-manager": "1.9.0-beta.
|
|
18
|
-
"@nocobase/database": "1.9.0-beta.
|
|
19
|
-
"@nocobase/evaluators": "1.9.0-beta.
|
|
20
|
-
"@nocobase/lock-manager": "1.9.0-beta.
|
|
21
|
-
"@nocobase/logger": "1.9.0-beta.
|
|
22
|
-
"@nocobase/resourcer": "1.9.0-beta.
|
|
23
|
-
"@nocobase/sdk": "1.9.0-beta.
|
|
24
|
-
"@nocobase/telemetry": "1.9.0-beta.
|
|
25
|
-
"@nocobase/utils": "1.9.0-beta.
|
|
13
|
+
"@nocobase/acl": "1.9.0-beta.7",
|
|
14
|
+
"@nocobase/actions": "1.9.0-beta.7",
|
|
15
|
+
"@nocobase/auth": "1.9.0-beta.7",
|
|
16
|
+
"@nocobase/cache": "1.9.0-beta.7",
|
|
17
|
+
"@nocobase/data-source-manager": "1.9.0-beta.7",
|
|
18
|
+
"@nocobase/database": "1.9.0-beta.7",
|
|
19
|
+
"@nocobase/evaluators": "1.9.0-beta.7",
|
|
20
|
+
"@nocobase/lock-manager": "1.9.0-beta.7",
|
|
21
|
+
"@nocobase/logger": "1.9.0-beta.7",
|
|
22
|
+
"@nocobase/resourcer": "1.9.0-beta.7",
|
|
23
|
+
"@nocobase/sdk": "1.9.0-beta.7",
|
|
24
|
+
"@nocobase/telemetry": "1.9.0-beta.7",
|
|
25
|
+
"@nocobase/utils": "1.9.0-beta.7",
|
|
26
26
|
"@types/decompress": "4.2.7",
|
|
27
27
|
"@types/ini": "^1.3.31",
|
|
28
28
|
"@types/koa-send": "^4.1.3",
|
|
@@ -57,5 +57,5 @@
|
|
|
57
57
|
"@types/serve-handler": "^6.1.1",
|
|
58
58
|
"@types/ws": "^8.5.5"
|
|
59
59
|
},
|
|
60
|
-
"gitHead": "
|
|
60
|
+
"gitHead": "4a5055c973b51611d5db1604aaaf6c1b73b4733c"
|
|
61
61
|
}
|