@nocobase/server 2.0.0-alpha.32 → 2.0.0-alpha.34

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.
@@ -8,6 +8,7 @@
8
8
  */
9
9
  /// <reference types="node" />
10
10
  import { AsyncEmitter } from '@nocobase/utils';
11
+ import { Mutex } from 'async-mutex';
11
12
  import { EventEmitter } from 'events';
12
13
  import Application, { ApplicationOptions } from './application';
13
14
  type BootOptions = {
@@ -16,9 +17,10 @@ type BootOptions = {
16
17
  appSupervisor: AppSupervisor;
17
18
  };
18
19
  type AppBootstrapper = (bootOptions: BootOptions) => Promise<void>;
19
- type AppStatus = 'initializing' | 'initialized' | 'running' | 'commanding' | 'stopped' | 'error' | 'not_found';
20
+ export type AppStatus = 'preparing' | 'initializing' | 'initialized' | 'running' | 'commanding' | 'stopped' | 'error' | 'not_found';
20
21
  export declare class AppSupervisor extends EventEmitter implements AsyncEmitter {
21
22
  private static instance;
23
+ private bootstrapQueue;
22
24
  runningMode: 'single' | 'multiple';
23
25
  singleAppName: string | null;
24
26
  emitAsync: (event: string | symbol, ...args: any[]) => Promise<boolean>;
@@ -48,7 +50,8 @@ export declare class AppSupervisor extends EventEmitter implements AsyncEmitter
48
50
  reset(): Promise<void>;
49
51
  destroy(): Promise<void>;
50
52
  setAppStatus(appName: string, status: AppStatus, options?: {}): void;
51
- getMutexOfApp(appName: string): any;
53
+ getMutexOfApp(appName: string): Mutex;
54
+ private _bootStrapApp;
52
55
  bootStrapApp(appName: string, options?: {}): Promise<void>;
53
56
  getApp(appName: string, options?: {
54
57
  withOutBootStrap?: boolean;
@@ -47,7 +47,9 @@ var import_async_mutex = require("async-mutex");
47
47
  var import_events = require("events");
48
48
  var import_application = __toESM(require("./application"));
49
49
  var import_handler = require("./errors/handler");
50
+ var import_p_queue = __toESM(require("p-queue"));
50
51
  const _AppSupervisor = class _AppSupervisor extends import_events.EventEmitter {
52
+ bootstrapQueue;
51
53
  runningMode = "multiple";
52
54
  singleAppName = null;
53
55
  apps = {};
@@ -64,6 +66,12 @@ const _AppSupervisor = class _AppSupervisor extends import_events.EventEmitter {
64
66
  this.runningMode = "single";
65
67
  this.singleAppName = process.env.STARTUP_SUBAPP;
66
68
  }
69
+ this.bootstrapQueue = new import_p_queue.default({
70
+ concurrency: process.env.SUBAPP_BOOTSTRAP_CONCURRENCY ? parseInt(process.env.SUBAPP_BOOTSTRAP_CONCURRENCY) : Infinity,
71
+ intervalCap: process.env.SUBAPP_BOOTSTRAP_INTERVAL_CAP ? parseInt(process.env.SUBAPP_BOOTSTRAP_INTERVAL_CAP) : Infinity,
72
+ interval: process.env.SUBAPP_BOOTSTRAP_INTERVAL ? parseInt(process.env.SUBAPP_BOOTSTRAP_INTERVAL) : 0,
73
+ timeout: 1 * 60 * 1e3
74
+ });
67
75
  }
68
76
  static getInstance() {
69
77
  if (!_AppSupervisor.instance) {
@@ -113,24 +121,42 @@ const _AppSupervisor = class _AppSupervisor extends import_events.EventEmitter {
113
121
  }
114
122
  return this.appMutexes[appName];
115
123
  }
124
+ async _bootStrapApp(appName, options = {}) {
125
+ this.setAppStatus(appName, "initializing");
126
+ if (this.appBootstrapper) {
127
+ await this.appBootstrapper({
128
+ appSupervisor: this,
129
+ appName,
130
+ options
131
+ });
132
+ }
133
+ if (!this.hasApp(appName)) {
134
+ this.setAppStatus(appName, "not_found");
135
+ } else if (!this.getAppStatus(appName) || this.getAppStatus(appName) === "initializing") {
136
+ this.setAppStatus(appName, "initialized");
137
+ }
138
+ }
116
139
  async bootStrapApp(appName, options = {}) {
117
- await this.getMutexOfApp(appName).runExclusive(async () => {
118
- if (!this.hasApp(appName)) {
119
- this.setAppStatus(appName, "initializing");
120
- if (this.appBootstrapper) {
121
- await this.appBootstrapper({
122
- appSupervisor: this,
123
- appName,
124
- options
125
- });
140
+ const mutex = this.getMutexOfApp(appName);
141
+ try {
142
+ await (0, import_async_mutex.tryAcquire)(mutex).runExclusive(async () => {
143
+ if (this.hasApp(appName) && this.getAppStatus(appName) !== "preparing") {
144
+ return;
126
145
  }
127
- if (!this.hasApp(appName)) {
128
- this.setAppStatus(appName, "not_found");
129
- } else if (!this.getAppStatus(appName) || this.getAppStatus(appName) == "initializing") {
130
- this.setAppStatus(appName, "initialized");
146
+ if (appName === "main") {
147
+ return this._bootStrapApp(appName, options);
131
148
  }
149
+ this.setAppStatus(appName, "preparing");
150
+ await this.bootstrapQueue.add(async () => {
151
+ await this._bootStrapApp(appName, options);
152
+ });
153
+ });
154
+ } catch (e) {
155
+ console.log(e);
156
+ if (e === import_async_mutex.E_ALREADY_LOCKED) {
157
+ return;
132
158
  }
133
- });
159
+ }
134
160
  }
135
161
  async getApp(appName, options = {}) {
136
162
  if (!options.withOutBootStrap) {
@@ -170,7 +196,7 @@ const _AppSupervisor = class _AppSupervisor extends import_events.EventEmitter {
170
196
  this.apps[app.name] = app;
171
197
  this.emit("afterAppAdded", app);
172
198
  if (!this.getAppStatus(app.name) || this.getAppStatus(app.name) == "not_found") {
173
- this.setAppStatus(app.name, "initialized");
199
+ this.setAppStatus(app.name, "preparing");
174
200
  }
175
201
  return app;
176
202
  }
@@ -284,7 +284,7 @@ export declare class Application<StateT = DefaultState, ContextT = DefaultContex
284
284
  setMaintainingMessage(message: string): void;
285
285
  /**
286
286
  * This method is deprecated and should not be used.
287
- * Use {@link #this.version.get()} instead.
287
+ * Use {@link #this.getPackageVersion} instead.
288
288
  * @deprecated
289
289
  */
290
290
  getVersion(): string;
@@ -339,7 +339,7 @@ const _Application = class _Application extends import_koa.default {
339
339
  }
340
340
  /**
341
341
  * This method is deprecated and should not be used.
342
- * Use {@link #this.version.get()} instead.
342
+ * Use {@link #this.getPackageVersion} instead.
343
343
  * @deprecated
344
344
  */
345
345
  getVersion() {
@@ -809,7 +809,9 @@ const _Application = class _Application extends import_koa.default {
809
809
  await migrator3.afterLoad.up();
810
810
  await this.pm.repository.updateVersions();
811
811
  await this.version.update();
812
- await this.emitAsync("afterUpgrade", this, options);
812
+ if (!options.quickstart) {
813
+ await this.emitAsync("afterUpgrade", this, options);
814
+ }
813
815
  await this.restart();
814
816
  }
815
817
  toJSON() {
@@ -936,8 +938,8 @@ const _Application = class _Application extends import_koa.default {
936
938
  plugins: plugins || []
937
939
  });
938
940
  this._telemetry = new import_telemetry.Telemetry({
939
- serviceName: `nocobase-${this.name}`,
940
- version: this.getVersion(),
941
+ appName: this.name,
942
+ version: this.getPackageVersion(),
941
943
  ...options.telemetry
942
944
  });
943
945
  this._authManager = new import_auth.AuthManager({
@@ -61,7 +61,7 @@ var start_default = /* @__PURE__ */ __name((app) => {
61
61
  }
62
62
  } else if (options.quickstart) {
63
63
  if (await app.isInstalled()) {
64
- await app.upgrade();
64
+ await app.upgrade({ quickstart: true });
65
65
  } else {
66
66
  await app.install();
67
67
  }
@@ -70,6 +70,11 @@ const errors = {
70
70
  command: /* @__PURE__ */ __name(({ app }) => app.getMaintaining().command, "command"),
71
71
  maintaining: true
72
72
  },
73
+ APP_PREPARING: {
74
+ status: 503,
75
+ message: /* @__PURE__ */ __name(({ appName }) => `application ${appName} is preparing, please wait patiently`, "message"),
76
+ maintaining: true
77
+ },
73
78
  APP_STARTING: {
74
79
  status: 503,
75
80
  message: /* @__PURE__ */ __name(({ app }) => app.maintainingMessage, "message"),
@@ -77,12 +82,12 @@ const errors = {
77
82
  },
78
83
  APP_STOPPED: {
79
84
  status: 503,
80
- message: /* @__PURE__ */ __name(({ app }) => `application ${app.name} is stopped`, "message"),
85
+ message: /* @__PURE__ */ __name(({ app }) => `application ${app == null ? void 0 : app.name} is stopped`, "message"),
81
86
  maintaining: true
82
87
  },
83
88
  APP_INITIALIZED: {
84
89
  status: 503,
85
- message: /* @__PURE__ */ __name(({ app }) => `application ${app.name} is initialized, waiting for command`, "message"),
90
+ message: /* @__PURE__ */ __name(({ app }) => `application ${app == null ? void 0 : app.name} is initialized, please refresh the page`, "message"),
86
91
  maintaining: true
87
92
  },
88
93
  APP_INITIALIZING: {
@@ -23,6 +23,12 @@ export interface IncomingRequest {
23
23
  url: string;
24
24
  headers: any;
25
25
  }
26
+ export interface GatewayRequestContext {
27
+ req: IncomingMessage;
28
+ res: ServerResponse;
29
+ appName: string;
30
+ }
31
+ type GatewayMiddleware = (ctx: GatewayRequestContext, next: () => Promise<void>) => Promise<void> | void;
26
32
  export type AppSelector = (req: IncomingRequest) => string | Promise<string>;
27
33
  export type AppSelectorMiddleware = (ctx: AppSelectorMiddlewareContext, next: () => Promise<void>) => void;
28
34
  interface StartHttpServerOptions {
@@ -39,6 +45,7 @@ export interface AppSelectorMiddlewareContext {
39
45
  }
40
46
  export declare class Gateway extends EventEmitter {
41
47
  private static instance;
48
+ middlewares: Toposort<GatewayMiddleware>;
42
49
  /**
43
50
  * use main app as default app to handle request
44
51
  */
@@ -54,6 +61,7 @@ export declare class Gateway extends EventEmitter {
54
61
  private onTerminate;
55
62
  private constructor();
56
63
  static getInstance(options?: any): Gateway;
64
+ use(middleware: GatewayMiddleware, options?: ToposortOptions): void;
57
65
  static getIPCSocketClient(): Promise<false | IPCSocketClient>;
58
66
  destroy(): void;
59
67
  reset(): void;
@@ -75,6 +75,7 @@ function getSocketPath() {
75
75
  }
76
76
  __name(getSocketPath, "getSocketPath");
77
77
  const _Gateway = class _Gateway extends import_events.EventEmitter {
78
+ middlewares;
78
79
  /**
79
80
  * use main app as default app to handle request
80
81
  */
@@ -124,6 +125,9 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
124
125
  }
125
126
  return _Gateway.instance;
126
127
  }
128
+ use(middleware, options) {
129
+ this.middlewares.add(middleware, options);
130
+ }
127
131
  static async getIPCSocketClient() {
128
132
  const socketPath = getSocketPath();
129
133
  try {
@@ -139,6 +143,7 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
139
143
  _Gateway.instance = null;
140
144
  }
141
145
  reset() {
146
+ this.middlewares = new import_utils.Toposort();
142
147
  this.selectorMiddlewares = new import_utils.Toposort();
143
148
  this.addAppSelectorMiddleware(
144
149
  async (ctx, next) => {
@@ -264,11 +269,15 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
264
269
  if (!hasApp) {
265
270
  void import_app_supervisor.AppSupervisor.getInstance().bootStrapApp(handleApp);
266
271
  }
267
- let appStatus = import_app_supervisor.AppSupervisor.getInstance().getAppStatus(handleApp, "initializing");
272
+ let appStatus = import_app_supervisor.AppSupervisor.getInstance().getAppStatus(handleApp, "preparing");
268
273
  if (appStatus === "not_found") {
269
274
  this.responseErrorWithCode("APP_NOT_FOUND", res, { appName: handleApp });
270
275
  return;
271
276
  }
277
+ if (appStatus === "preparing") {
278
+ this.responseErrorWithCode("APP_PREPARING", res, { appName: handleApp });
279
+ return;
280
+ }
272
281
  if (appStatus === "initializing") {
273
282
  this.responseErrorWithCode("APP_INITIALIZING", res, { appName: handleApp });
274
283
  return;
@@ -291,7 +300,14 @@ const _Gateway = class _Gateway extends import_events.EventEmitter {
291
300
  if (handleApp !== "main") {
292
301
  import_app_supervisor.AppSupervisor.getInstance().touchApp(handleApp);
293
302
  }
294
- app.callback()(req, res);
303
+ const ctx = { req, res, appName: handleApp };
304
+ const fn = (0, import_koa_compose.default)([
305
+ ...this.middlewares.nodes,
306
+ async (_ctx) => {
307
+ await app.callback()(req, res);
308
+ }
309
+ ]);
310
+ await fn(ctx);
295
311
  }
296
312
  getAppSelectorMiddlewares() {
297
313
  return this.selectorMiddlewares;
@@ -13,6 +13,8 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
13
13
  var __getOwnPropNames = Object.getOwnPropertyNames;
14
14
  var __getProtoOf = Object.getPrototypeOf;
15
15
  var __hasOwnProp = Object.prototype.hasOwnProperty;
16
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
17
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
16
18
  var __export = (target, all) => {
17
19
  for (var name in all)
18
20
  __defProp(target, name, { get: all[name], enumerable: true });
@@ -34,6 +36,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
34
36
  mod
35
37
  ));
36
38
  var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
39
+ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
37
40
  var resource_exports = {};
38
41
  __export(resource_exports, {
39
42
  default: () => resource_default
@@ -43,6 +46,33 @@ var import_utils = require("@nocobase/utils");
43
46
  var import_fs = __toESM(require("fs"));
44
47
  var import_fs_extra = __toESM(require("fs-extra"));
45
48
  var import_path = __toESM(require("path"));
49
+ const _PackageUrls = class _PackageUrls {
50
+ static async get(packageName, version) {
51
+ if (!this.items[packageName]) {
52
+ this.items[packageName] = await this.fetch(packageName, version);
53
+ }
54
+ return this.items[packageName];
55
+ }
56
+ static async fetch(packageName, version) {
57
+ const PLUGIN_CLIENT_ENTRY_FILE = "dist/client/index.js";
58
+ const pkgPath = import_path.default.resolve(process.env.NODE_MODULES_PATH, packageName);
59
+ const r = await import_fs_extra.default.exists(pkgPath);
60
+ if (r) {
61
+ let t = "";
62
+ const dist = import_path.default.resolve(pkgPath, PLUGIN_CLIENT_ENTRY_FILE);
63
+ const distExists = await import_fs_extra.default.exists(dist);
64
+ if (distExists) {
65
+ const fsState = await import_fs_extra.default.stat(distExists ? dist : pkgPath);
66
+ t = `&t=${fsState.mtime.getTime()}`;
67
+ }
68
+ const url = `${process.env.APP_SERVER_BASE_URL}${process.env.PLUGIN_STATICS_PATH}${packageName}/${PLUGIN_CLIENT_ENTRY_FILE}?version=${version}${t}`;
69
+ return url;
70
+ }
71
+ }
72
+ };
73
+ __name(_PackageUrls, "PackageUrls");
74
+ __publicField(_PackageUrls, "items", {});
75
+ let PackageUrls = _PackageUrls;
46
76
  var resource_default = {
47
77
  name: "pm",
48
78
  actions: {
@@ -152,33 +182,26 @@ var resource_default = {
152
182
  await next();
153
183
  },
154
184
  async listEnabled(ctx, next) {
155
- const pm = ctx.db.getRepository("applicationPlugins");
156
- const PLUGIN_CLIENT_ENTRY_FILE = "dist/client/index.js";
157
- const items = await pm.find({
158
- filter: {
159
- enabled: true
160
- }
161
- });
162
- const arr = [];
163
- for (const item of items) {
164
- const pkgPath = import_path.default.resolve(process.env.NODE_MODULES_PATH, item.packageName);
165
- const r = await import_fs_extra.default.exists(pkgPath);
166
- if (r) {
167
- let t = "";
168
- const dist = import_path.default.resolve(pkgPath, PLUGIN_CLIENT_ENTRY_FILE);
169
- const distExists = await import_fs_extra.default.exists(dist);
170
- if (distExists) {
171
- const fsState = await import_fs_extra.default.stat(distExists ? dist : pkgPath);
172
- t = `&t=${fsState.mtime.getTime()}`;
185
+ const toArr = /* @__PURE__ */ __name(async () => {
186
+ const pm = ctx.db.getRepository("applicationPlugins");
187
+ const items = await pm.find({
188
+ filter: {
189
+ enabled: true
190
+ }
191
+ });
192
+ const arr = [];
193
+ for (const item of items) {
194
+ const url = await PackageUrls.get(item.packageName, item.version);
195
+ if (url) {
196
+ arr.push({
197
+ ...item.toJSON(),
198
+ url
199
+ });
173
200
  }
174
- const url = `${process.env.APP_SERVER_BASE_URL}${process.env.PLUGIN_STATICS_PATH}${item.packageName}/${PLUGIN_CLIENT_ENTRY_FILE}?version=${item.version}${t}`;
175
- arr.push({
176
- ...item.toJSON(),
177
- url
178
- });
179
201
  }
180
- }
181
- ctx.body = arr;
202
+ return arr;
203
+ }, "toArr");
204
+ ctx.body = await toArr();
182
205
  await next();
183
206
  },
184
207
  async get(ctx, next) {
@@ -17,8 +17,8 @@ export declare class PubSubManager {
17
17
  protected adapter: IPubSubAdapter;
18
18
  protected handlerManager: HandlerManager;
19
19
  constructor(app: Application, options?: PubSubManagerOptions);
20
- get channelPrefix(): string;
21
20
  setAdapter(adapter: IPubSubAdapter): void;
21
+ getFullChannel(channel: string): string;
22
22
  isConnected(): Promise<boolean>;
23
23
  connect(): Promise<void>;
24
24
  close(): Promise<any>;
@@ -55,13 +55,13 @@ const _PubSubManager = class _PubSubManager {
55
55
  publisherId;
56
56
  adapter;
57
57
  handlerManager;
58
- get channelPrefix() {
59
- var _a;
60
- return ((_a = this.options) == null ? void 0 : _a.channelPrefix) ? `${this.options.channelPrefix}.` : "";
61
- }
62
58
  setAdapter(adapter) {
63
59
  this.adapter = adapter;
64
60
  }
61
+ getFullChannel(channel) {
62
+ var _a;
63
+ return [this.app.name, (_a = this.options) == null ? void 0 : _a.channelPrefix, channel].filter(Boolean).join(".");
64
+ }
65
65
  async isConnected() {
66
66
  if (this.adapter) {
67
67
  return this.adapter.isConnected();
@@ -79,7 +79,7 @@ const _PubSubManager = class _PubSubManager {
79
79
  await this.adapter.connect();
80
80
  await this.handlerManager.each(async (channel, headler) => {
81
81
  this.app.logger.debug(`[PubSubManager] subscribe ${channel} added before connected`);
82
- await this.adapter.subscribe(`${this.channelPrefix}${channel}`, headler);
82
+ await this.adapter.subscribe(this.getFullChannel(channel), headler);
83
83
  });
84
84
  }
85
85
  async close() {
@@ -93,7 +93,7 @@ const _PubSubManager = class _PubSubManager {
93
93
  const handler = this.handlerManager.set(channel, callback, options);
94
94
  if (await this.isConnected()) {
95
95
  this.app.logger.debug(`[PubSubManager] subscribe ${channel} added after connected`);
96
- await this.adapter.subscribe(`${this.channelPrefix}${channel}`, handler);
96
+ await this.adapter.subscribe(this.getFullChannel(channel), handler);
97
97
  }
98
98
  }
99
99
  async unsubscribe(channel, callback) {
@@ -101,7 +101,7 @@ const _PubSubManager = class _PubSubManager {
101
101
  if (!this.adapter || !handler) {
102
102
  return;
103
103
  }
104
- return this.adapter.unsubscribe(`${this.channelPrefix}${channel}`, handler);
104
+ return this.adapter.unsubscribe(this.getFullChannel(channel), handler);
105
105
  }
106
106
  async publish(channel, message, options) {
107
107
  var _a;
@@ -116,7 +116,7 @@ const _PubSubManager = class _PubSubManager {
116
116
  ...options,
117
117
  message
118
118
  });
119
- await this.adapter.publish(`${this.channelPrefix}${channel}`, wrappedMessage);
119
+ await this.adapter.publish(this.getFullChannel(channel), wrappedMessage);
120
120
  this.app.logger.trace(`[PubSubManager] published message to channel ${channel}`);
121
121
  }
122
122
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/server",
3
- "version": "2.0.0-alpha.32",
3
+ "version": "2.0.0-alpha.34",
4
4
  "main": "lib/index.js",
5
5
  "types": "./lib/index.d.ts",
6
6
  "license": "AGPL-3.0",
@@ -10,20 +10,20 @@
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.0.0-alpha.32",
14
- "@nocobase/actions": "2.0.0-alpha.32",
15
- "@nocobase/auth": "2.0.0-alpha.32",
16
- "@nocobase/cache": "2.0.0-alpha.32",
17
- "@nocobase/data-source-manager": "2.0.0-alpha.32",
18
- "@nocobase/database": "2.0.0-alpha.32",
19
- "@nocobase/evaluators": "2.0.0-alpha.32",
20
- "@nocobase/lock-manager": "2.0.0-alpha.32",
21
- "@nocobase/logger": "2.0.0-alpha.32",
22
- "@nocobase/resourcer": "2.0.0-alpha.32",
23
- "@nocobase/sdk": "2.0.0-alpha.32",
24
- "@nocobase/snowflake-id": "2.0.0-alpha.32",
25
- "@nocobase/telemetry": "2.0.0-alpha.32",
26
- "@nocobase/utils": "2.0.0-alpha.32",
13
+ "@nocobase/acl": "2.0.0-alpha.34",
14
+ "@nocobase/actions": "2.0.0-alpha.34",
15
+ "@nocobase/auth": "2.0.0-alpha.34",
16
+ "@nocobase/cache": "2.0.0-alpha.34",
17
+ "@nocobase/data-source-manager": "2.0.0-alpha.34",
18
+ "@nocobase/database": "2.0.0-alpha.34",
19
+ "@nocobase/evaluators": "2.0.0-alpha.34",
20
+ "@nocobase/lock-manager": "2.0.0-alpha.34",
21
+ "@nocobase/logger": "2.0.0-alpha.34",
22
+ "@nocobase/resourcer": "2.0.0-alpha.34",
23
+ "@nocobase/sdk": "2.0.0-alpha.34",
24
+ "@nocobase/snowflake-id": "2.0.0-alpha.34",
25
+ "@nocobase/telemetry": "2.0.0-alpha.34",
26
+ "@nocobase/utils": "2.0.0-alpha.34",
27
27
  "@types/decompress": "4.2.7",
28
28
  "@types/ini": "^1.3.31",
29
29
  "@types/koa-send": "^4.1.3",
@@ -49,6 +49,7 @@
49
49
  "lodash": "^4.17.21",
50
50
  "multer": "^1.4.5-lts.2",
51
51
  "nanoid": "^3.3.11",
52
+ "p-queue": "^6.6.2",
52
53
  "semver": "^7.7.1",
53
54
  "serve-handler": "^6.1.6",
54
55
  "ws": "^8.13.0",
@@ -59,5 +60,5 @@
59
60
  "@types/serve-handler": "^6.1.1",
60
61
  "@types/ws": "^8.5.5"
61
62
  },
62
- "gitHead": "50bb60d2f42e0fc2c1cd1eee397f9c0da94084df"
63
+ "gitHead": "d7bda14bac775be7ef207cb25986511740b2ed70"
63
64
  }