@nocobase/server 1.9.0-beta.16 → 1.9.0-beta.18

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.
@@ -56,7 +56,7 @@ const availableActions = {
56
56
  update: {
57
57
  displayName: '{{t("Edit")}}',
58
58
  type: "old-data",
59
- aliases: ["update", "move", "add", "set", "remove", "toggle"],
59
+ aliases: ["update", "move"],
60
60
  allowConfigureFields: true
61
61
  },
62
62
  destroy: {
@@ -36,7 +36,6 @@ import { AuditManager } from './audit-manager';
36
36
  import { Environment } from './environment';
37
37
  import { ServiceContainer } from './service-container';
38
38
  import { EventQueue, EventQueueOptions } from './event-queue';
39
- import { BackgroundJobManager, BackgroundJobManagerOptions } from './background-job-manager';
40
39
  import { RedisConfig, RedisConnectionManager } from './redis-connection-manager';
41
40
  import { WorkerIdAllocator } from './worker-id-allocator';
42
41
  export type PluginType = string | typeof Plugin;
@@ -89,7 +88,6 @@ export interface ApplicationOptions {
89
88
  auditManager?: AuditManager;
90
89
  lockManager?: LockManagerOptions;
91
90
  eventQueue?: EventQueueOptions;
92
- backgroundJobManager?: BackgroundJobManagerOptions;
93
91
  /**
94
92
  * @internal
95
93
  */
@@ -190,7 +188,6 @@ export declare class Application<StateT = DefaultState, ContextT = DefaultContex
190
188
  container: ServiceContainer;
191
189
  lockManager: LockManager;
192
190
  eventQueue: EventQueue;
193
- backgroundJobManager: BackgroundJobManager;
194
191
  constructor(options: ApplicationOptions);
195
192
  private static staticCommands;
196
193
  static addCommand(callback: (app: Application) => void): void;
@@ -83,7 +83,6 @@ var import_audit_manager = require("./audit-manager");
83
83
  var import_environment = require("./environment");
84
84
  var import_service_container = require("./service-container");
85
85
  var import_event_queue = require("./event-queue");
86
- var import_background_job_manager = require("./background-job-manager");
87
86
  var import_redis_connection_manager = require("./redis-connection-manager");
88
87
  var import_worker_id_allocator = require("./worker-id-allocator");
89
88
  var import_snowflake_id_field = require("./snowflake-id-field");
@@ -142,7 +141,6 @@ const _Application = class _Application extends import_koa.default {
142
141
  container = new import_service_container.ServiceContainer();
143
142
  lockManager;
144
143
  eventQueue;
145
- backgroundJobManager;
146
144
  static addCommand(callback) {
147
145
  this.staticCommands.push(callback);
148
146
  }
@@ -911,7 +909,6 @@ const _Application = class _Application extends import_koa.default {
911
909
  this.pubSubManager = (0, import_pub_sub_manager.createPubSubManager)(this, options.pubSubManager);
912
910
  this.syncMessageManager = new import_sync_message_manager.SyncMessageManager(this, options.syncMessageManager);
913
911
  this.eventQueue = new import_event_queue.EventQueue(this, options.eventQueue);
914
- this.backgroundJobManager = new import_background_job_manager.BackgroundJobManager(this, options.backgroundJobManager);
915
912
  this.lockManager = new import_lock_manager.LockManager({
916
913
  defaultAdapter: process.env.LOCK_ADAPTER_DEFAULT,
917
914
  ...options.lockManager
@@ -53,6 +53,7 @@ var import_start = __toESM(require("./start"));
53
53
  var import_stop = __toESM(require("./stop"));
54
54
  var import_upgrade = __toESM(require("./upgrade"));
55
55
  var import_console = __toESM(require("./console"));
56
+ var import_repair = __toESM(require("./repair"));
56
57
  /* istanbul ignore file -- @preserve */
57
58
  function registerCli(app) {
58
59
  (0, import_console.default)(app);
@@ -68,6 +69,7 @@ function registerCli(app) {
68
69
  (0, import_destroy.default)(app);
69
70
  (0, import_start.default)(app);
70
71
  (0, import_refresh.default)(app);
72
+ (0, import_repair.default)(app);
71
73
  app.command("build").argument("[packages...]");
72
74
  app.command("clean");
73
75
  app.command("dev").usage("[options]").option("-p, --port [port]").option("--client").option("--server");
@@ -0,0 +1,11 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+ import Application from '../application';
10
+ declare const _default: (app: Application) => void;
11
+ export default _default;
@@ -0,0 +1,43 @@
1
+ /**
2
+ * This file is part of the NocoBase (R) project.
3
+ * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
+ * Authors: NocoBase Team.
5
+ *
6
+ * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
+ * For more information, please refer to: https://www.nocobase.com/agreement.
8
+ */
9
+
10
+ var __defProp = Object.defineProperty;
11
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
+ var __getOwnPropNames = Object.getOwnPropertyNames;
13
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
14
+ var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
15
+ var __export = (target, all) => {
16
+ for (var name in all)
17
+ __defProp(target, name, { get: all[name], enumerable: true });
18
+ };
19
+ var __copyProps = (to, from, except, desc) => {
20
+ if (from && typeof from === "object" || typeof from === "function") {
21
+ for (let key of __getOwnPropNames(from))
22
+ if (!__hasOwnProp.call(to, key) && key !== except)
23
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
24
+ }
25
+ return to;
26
+ };
27
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
28
+ var repair_exports = {};
29
+ __export(repair_exports, {
30
+ default: () => repair_default
31
+ });
32
+ module.exports = __toCommonJS(repair_exports);
33
+ var repair_default = /* @__PURE__ */ __name((app) => {
34
+ app.command("repair").auth().preload().action(async (options) => {
35
+ app.log.info("start repair data...");
36
+ const Collection = app.db.getCollection("collections");
37
+ if (Collection) {
38
+ await Collection.repository.setApp(app);
39
+ await Collection.repository.load();
40
+ }
41
+ await app.emitAsync("repair", options);
42
+ });
43
+ }, "default");
@@ -23,6 +23,12 @@ export type QueueEventOptions = {
23
23
  */
24
24
  interval?: number;
25
25
  concurrency?: number;
26
+ /**
27
+ * Shared across multiple applications.
28
+ * Will not use app prefix for channel name.
29
+ * @experimental
30
+ */
31
+ shared?: boolean;
26
32
  idle(): boolean;
27
33
  process: QueueCallback;
28
34
  };
@@ -84,7 +90,7 @@ export declare class EventQueue {
84
90
  protected events: Map<string, QueueEventOptions>;
85
91
  get channelPrefix(): string;
86
92
  constructor(app: Application, options?: EventQueueOptions);
87
- getFullChannel(channel: string): string;
93
+ getFullChannel(channel: string, shared?: boolean): string;
88
94
  setAdapter<A extends IEventQueueAdapter>(adapter: A): void;
89
95
  isConnected(): boolean;
90
96
  connect(): Promise<void>;
@@ -270,16 +270,14 @@ const _EventQueue = class _EventQueue {
270
270
  constructor(app, options = {}) {
271
271
  this.app = app;
272
272
  this.options = options;
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
- }
273
+ this.setAdapter(new MemoryEventQueueAdapter({ appName: this.app.name, logger: this.app.logger }));
274
+ app.on("afterStart", async () => {
275
+ await this.connect();
276
+ });
277
+ app.on("afterStop", async () => {
278
+ app.logger.info("[queue] gracefully shutting down...");
279
+ await this.close();
280
+ });
283
281
  }
284
282
  adapter;
285
283
  events = /* @__PURE__ */ new Map();
@@ -287,7 +285,10 @@ const _EventQueue = class _EventQueue {
287
285
  var _a;
288
286
  return (_a = this.options) == null ? void 0 : _a.channelPrefix;
289
287
  }
290
- getFullChannel(channel) {
288
+ getFullChannel(channel, shared = false) {
289
+ if (shared) {
290
+ return [this.channelPrefix, channel].filter(Boolean).join(".");
291
+ }
291
292
  return [this.app.name, this.channelPrefix, channel].filter(Boolean).join(".");
292
293
  }
293
294
  setAdapter(adapter) {
@@ -303,14 +304,10 @@ const _EventQueue = class _EventQueue {
303
304
  if (!this.adapter) {
304
305
  throw new Error("no adapter set, cannot connect");
305
306
  }
306
- if (!this.app.serving()) {
307
- this.app.logger.warn("app is not serving, will not connect to event queue");
308
- return;
309
- }
310
307
  await this.adapter.connect();
311
308
  this.app.logger.debug(`connected to adapter, using memory? ${this.adapter instanceof MemoryEventQueueAdapter}`);
312
309
  for (const [channel, event] of this.events.entries()) {
313
- this.adapter.subscribe(this.getFullChannel(channel), event);
310
+ this.adapter.subscribe(this.getFullChannel(channel, event.shared), event);
314
311
  }
315
312
  }
316
313
  async close() {
@@ -318,8 +315,8 @@ const _EventQueue = class _EventQueue {
318
315
  return;
319
316
  }
320
317
  await this.adapter.close();
321
- for (const channel of this.events.keys()) {
322
- this.adapter.unsubscribe(this.getFullChannel(channel));
318
+ for (const [channel, event] of this.events.entries()) {
319
+ this.adapter.unsubscribe(this.getFullChannel(channel, event.shared));
323
320
  }
324
321
  }
325
322
  subscribe(channel, options) {
@@ -329,16 +326,17 @@ const _EventQueue = class _EventQueue {
329
326
  }
330
327
  this.events.set(channel, options);
331
328
  if (this.isConnected()) {
332
- this.adapter.subscribe(this.getFullChannel(channel), options);
329
+ this.adapter.subscribe(this.getFullChannel(channel, options.shared), this.events.get(channel));
333
330
  }
334
331
  }
335
332
  unsubscribe(channel) {
333
+ var _a;
336
334
  if (!this.events.has(channel)) {
337
335
  return;
338
336
  }
339
337
  this.events.delete(channel);
340
338
  if (this.isConnected()) {
341
- this.adapter.unsubscribe(this.getFullChannel(channel));
339
+ this.adapter.unsubscribe(this.getFullChannel(channel, (_a = this.events.get(channel)) == null ? void 0 : _a.shared));
342
340
  }
343
341
  }
344
342
  async publish(channel, message, options = {}) {
@@ -348,7 +346,11 @@ const _EventQueue = class _EventQueue {
348
346
  if (!this.isConnected()) {
349
347
  throw new Error("event queue not connected, cannot publish");
350
348
  }
351
- const c = this.getFullChannel(channel);
349
+ const event = this.events.get(channel);
350
+ if (!event) {
351
+ throw new Error(`event queue not subscribed on channel "${channel}", cannot publish`);
352
+ }
353
+ const c = this.getFullChannel(channel, event.shared);
352
354
  this.app.logger.debug(`event queue publishing to channel(${c})`, { message });
353
355
  await this.adapter.publish(c, message, {
354
356
  timeout: QUEUE_DEFAULT_ACK_TIMEOUT,
package/lib/helper.d.ts CHANGED
@@ -17,3 +17,362 @@ export declare const getCommandFullName: (command: Command) => string;
17
17
  export declare const tsxRerunning: () => Promise<void>;
18
18
  export declare const enablePerfHooks: (app: Application) => void;
19
19
  export declare function getBodyLimit(): string;
20
+ export declare function createContextVariablesScope(ctx: any): {
21
+ timezone: any;
22
+ now: string;
23
+ getField: (path: any) => any;
24
+ vars: {
25
+ ctx: {
26
+ state: any;
27
+ };
28
+ $system: {
29
+ now: string;
30
+ };
31
+ $date: {
32
+ now: string;
33
+ today: ({ now, timezone, field }: {
34
+ now?: any;
35
+ timezone?: string | number;
36
+ field?: {
37
+ timezone?: string | number;
38
+ };
39
+ }) => any;
40
+ yesterday: ({ now, timezone, field }: {
41
+ now?: any;
42
+ timezone?: string | number;
43
+ field?: {
44
+ timezone?: string | number;
45
+ };
46
+ }) => any;
47
+ tomorrow: ({ now, timezone, field }: {
48
+ now?: any;
49
+ timezone?: string | number;
50
+ field?: {
51
+ timezone?: string | number;
52
+ };
53
+ }) => any;
54
+ thisWeek: ({ now, timezone, field }: {
55
+ now?: any;
56
+ timezone?: string | number;
57
+ field?: {
58
+ timezone?: string | number;
59
+ };
60
+ }) => any;
61
+ lastWeek: ({ now, timezone, field }: {
62
+ now?: any;
63
+ timezone?: string | number;
64
+ field?: {
65
+ timezone?: string | number;
66
+ };
67
+ }) => any;
68
+ nextWeek: ({ now, timezone, field }: {
69
+ now?: any;
70
+ timezone?: string | number;
71
+ field?: {
72
+ timezone?: string | number;
73
+ };
74
+ }) => any;
75
+ thisIsoWeek: ({ now, timezone, field }: {
76
+ now?: any;
77
+ timezone?: string | number;
78
+ field?: {
79
+ timezone?: string | number;
80
+ };
81
+ }) => any;
82
+ lastIsoWeek: ({ now, timezone, field }: {
83
+ now?: any;
84
+ timezone?: string | number;
85
+ field?: {
86
+ timezone?: string | number;
87
+ };
88
+ }) => any;
89
+ nextIsoWeek: ({ now, timezone, field }: {
90
+ now?: any;
91
+ timezone?: string | number;
92
+ field?: {
93
+ timezone?: string | number;
94
+ };
95
+ }) => any;
96
+ thisMonth: ({ now, timezone, field }: {
97
+ now?: any;
98
+ timezone?: string | number;
99
+ field?: {
100
+ timezone?: string | number;
101
+ };
102
+ }) => any;
103
+ lastMonth: ({ now, timezone, field }: {
104
+ now?: any;
105
+ timezone?: string | number;
106
+ field?: {
107
+ timezone?: string | number;
108
+ };
109
+ }) => any;
110
+ nextMonth: ({ now, timezone, field }: {
111
+ now?: any;
112
+ timezone?: string | number;
113
+ field?: {
114
+ timezone?: string | number;
115
+ };
116
+ }) => any;
117
+ thisQuarter: ({ now, timezone, field }: {
118
+ now?: any;
119
+ timezone?: string | number;
120
+ field?: {
121
+ timezone?: string | number;
122
+ };
123
+ }) => any;
124
+ lastQuarter: ({ now, timezone, field }: {
125
+ now?: any;
126
+ timezone?: string | number;
127
+ field?: {
128
+ timezone?: string | number;
129
+ };
130
+ }) => any;
131
+ nextQuarter: ({ now, timezone, field }: {
132
+ now?: any;
133
+ timezone?: string | number;
134
+ field?: {
135
+ timezone?: string | number;
136
+ };
137
+ }) => any;
138
+ thisYear: ({ now, timezone, field }: {
139
+ now?: any;
140
+ timezone?: string | number;
141
+ field?: {
142
+ timezone?: string | number;
143
+ };
144
+ }) => any;
145
+ lastYear: ({ now, timezone, field }: {
146
+ now?: any;
147
+ timezone?: string | number;
148
+ field?: {
149
+ timezone?: string | number;
150
+ };
151
+ }) => any;
152
+ nextYear: ({ now, timezone, field }: {
153
+ now?: any;
154
+ timezone?: string | number;
155
+ field?: {
156
+ timezone?: string | number;
157
+ };
158
+ }) => any;
159
+ last7Days: ({ now, timezone, field }: {
160
+ now?: any;
161
+ timezone?: string | number;
162
+ field?: {
163
+ timezone?: string | number;
164
+ };
165
+ }) => (string | number)[];
166
+ next7Days: ({ now, timezone, field }: {
167
+ now?: any;
168
+ timezone?: string | number;
169
+ field?: {
170
+ timezone?: string | number;
171
+ };
172
+ }) => (string | number)[];
173
+ last30Days: ({ now, timezone, field }: {
174
+ now?: any;
175
+ timezone?: string | number;
176
+ field?: {
177
+ timezone?: string | number;
178
+ };
179
+ }) => (string | number)[];
180
+ next30Days: ({ now, timezone, field }: {
181
+ now?: any;
182
+ timezone?: string | number;
183
+ field?: {
184
+ timezone?: string | number;
185
+ };
186
+ }) => (string | number)[];
187
+ last90Days: ({ now, timezone, field }: {
188
+ now?: any;
189
+ timezone?: string | number;
190
+ field?: {
191
+ timezone?: string | number;
192
+ };
193
+ }) => (string | number)[];
194
+ next90Days: ({ now, timezone, field }: {
195
+ now?: any;
196
+ timezone?: string | number;
197
+ field?: {
198
+ timezone?: string | number;
199
+ };
200
+ }) => (string | number)[];
201
+ };
202
+ $nDate: {
203
+ now: string;
204
+ today: ({ now, timezone, field }: {
205
+ now?: any;
206
+ timezone?: string | number;
207
+ field?: {
208
+ timezone?: string | number;
209
+ };
210
+ }) => any;
211
+ yesterday: ({ now, timezone, field }: {
212
+ now?: any;
213
+ timezone?: string | number;
214
+ field?: {
215
+ timezone?: string | number;
216
+ };
217
+ }) => any;
218
+ tomorrow: ({ now, timezone, field }: {
219
+ now?: any;
220
+ timezone?: string | number;
221
+ field?: {
222
+ timezone?: string | number;
223
+ };
224
+ }) => any;
225
+ thisWeek: ({ now, timezone, field }: {
226
+ now?: any;
227
+ timezone?: string | number;
228
+ field?: {
229
+ timezone?: string | number;
230
+ };
231
+ }) => any;
232
+ lastWeek: ({ now, timezone, field }: {
233
+ now?: any;
234
+ timezone?: string | number;
235
+ field?: {
236
+ timezone?: string | number;
237
+ };
238
+ }) => any;
239
+ nextWeek: ({ now, timezone, field }: {
240
+ now?: any;
241
+ timezone?: string | number;
242
+ field?: {
243
+ timezone?: string | number;
244
+ };
245
+ }) => any;
246
+ thisIsoWeek: ({ now, timezone, field }: {
247
+ now?: any;
248
+ timezone?: string | number;
249
+ field?: {
250
+ timezone?: string | number;
251
+ };
252
+ }) => any;
253
+ lastIsoWeek: ({ now, timezone, field }: {
254
+ now?: any;
255
+ timezone?: string | number;
256
+ field?: {
257
+ timezone?: string | number;
258
+ };
259
+ }) => any;
260
+ nextIsoWeek: ({ now, timezone, field }: {
261
+ now?: any;
262
+ timezone?: string | number;
263
+ field?: {
264
+ timezone?: string | number;
265
+ };
266
+ }) => any;
267
+ thisMonth: ({ now, timezone, field }: {
268
+ now?: any;
269
+ timezone?: string | number;
270
+ field?: {
271
+ timezone?: string | number;
272
+ };
273
+ }) => any;
274
+ lastMonth: ({ now, timezone, field }: {
275
+ now?: any;
276
+ timezone?: string | number;
277
+ field?: {
278
+ timezone?: string | number;
279
+ };
280
+ }) => any;
281
+ nextMonth: ({ now, timezone, field }: {
282
+ now?: any;
283
+ timezone?: string | number;
284
+ field?: {
285
+ timezone?: string | number;
286
+ };
287
+ }) => any;
288
+ thisQuarter: ({ now, timezone, field }: {
289
+ now?: any;
290
+ timezone?: string | number;
291
+ field?: {
292
+ timezone?: string | number;
293
+ };
294
+ }) => any;
295
+ lastQuarter: ({ now, timezone, field }: {
296
+ now?: any;
297
+ timezone?: string | number;
298
+ field?: {
299
+ timezone?: string | number;
300
+ };
301
+ }) => any;
302
+ nextQuarter: ({ now, timezone, field }: {
303
+ now?: any;
304
+ timezone?: string | number;
305
+ field?: {
306
+ timezone?: string | number;
307
+ };
308
+ }) => any;
309
+ thisYear: ({ now, timezone, field }: {
310
+ now?: any;
311
+ timezone?: string | number;
312
+ field?: {
313
+ timezone?: string | number;
314
+ };
315
+ }) => any;
316
+ lastYear: ({ now, timezone, field }: {
317
+ now?: any;
318
+ timezone?: string | number;
319
+ field?: {
320
+ timezone?: string | number;
321
+ };
322
+ }) => any;
323
+ nextYear: ({ now, timezone, field }: {
324
+ now?: any;
325
+ timezone?: string | number;
326
+ field?: {
327
+ timezone?: string | number;
328
+ };
329
+ }) => any;
330
+ last7Days: ({ now, timezone, field }: {
331
+ now?: any;
332
+ timezone?: string | number;
333
+ field?: {
334
+ timezone?: string | number;
335
+ };
336
+ }) => (string | number)[];
337
+ next7Days: ({ now, timezone, field }: {
338
+ now?: any;
339
+ timezone?: string | number;
340
+ field?: {
341
+ timezone?: string | number;
342
+ };
343
+ }) => (string | number)[];
344
+ last30Days: ({ now, timezone, field }: {
345
+ now?: any;
346
+ timezone?: string | number;
347
+ field?: {
348
+ timezone?: string | number;
349
+ };
350
+ }) => (string | number)[];
351
+ next30Days: ({ now, timezone, field }: {
352
+ now?: any;
353
+ timezone?: string | number;
354
+ field?: {
355
+ timezone?: string | number;
356
+ };
357
+ }) => (string | number)[];
358
+ last90Days: ({ now, timezone, field }: {
359
+ now?: any;
360
+ timezone?: string | number;
361
+ field?: {
362
+ timezone?: string | number;
363
+ };
364
+ }) => (string | number)[];
365
+ next90Days: ({ now, timezone, field }: {
366
+ now?: any;
367
+ timezone?: string | number;
368
+ field?: {
369
+ timezone?: string | number;
370
+ };
371
+ }) => (string | number)[];
372
+ };
373
+ $user: ({ fields }: {
374
+ fields: any;
375
+ }) => Promise<any>;
376
+ $nRole: any;
377
+ };
378
+ };
package/lib/helper.js CHANGED
@@ -38,6 +38,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
38
38
  var helper_exports = {};
39
39
  __export(helper_exports, {
40
40
  createAppProxy: () => createAppProxy,
41
+ createContextVariablesScope: () => createContextVariablesScope,
41
42
  createI18n: () => createI18n,
42
43
  createResourcer: () => createResourcer,
43
44
  enablePerfHooks: () => enablePerfHooks,
@@ -193,9 +194,66 @@ function getBodyLimit() {
193
194
  return process.env.REQUEST_BODY_LIMIT || "10mb";
194
195
  }
195
196
  __name(getBodyLimit, "getBodyLimit");
197
+ function getUser(ctx) {
198
+ return async ({ fields }) => {
199
+ var _a, _b;
200
+ const userFields = fields.filter((f) => f && ctx.db.getFieldByPath("users." + f));
201
+ (_a = ctx.logger) == null ? void 0 : _a.info("filter-parse: ", { userFields });
202
+ if (!ctx.state.currentUser) {
203
+ return;
204
+ }
205
+ if (!userFields.length) {
206
+ return;
207
+ }
208
+ const user = await ctx.db.getRepository("users").findOne({
209
+ filterByTk: ctx.state.currentUser.id,
210
+ fields: userFields
211
+ });
212
+ (_b = ctx.logger) == null ? void 0 : _b.info("filter-parse: ", {
213
+ $user: user == null ? void 0 : user.toJSON()
214
+ });
215
+ return user;
216
+ };
217
+ }
218
+ __name(getUser, "getUser");
219
+ function isNumeric(str) {
220
+ if (typeof str === "number") return true;
221
+ if (typeof str != "string") return false;
222
+ return !isNaN(str) && !isNaN(parseFloat(str));
223
+ }
224
+ __name(isNumeric, "isNumeric");
225
+ function createContextVariablesScope(ctx) {
226
+ const state = JSON.parse(JSON.stringify(ctx.state));
227
+ return {
228
+ timezone: ctx.get("x-timezone"),
229
+ now: (/* @__PURE__ */ new Date()).toISOString(),
230
+ getField: /* @__PURE__ */ __name((path) => {
231
+ const fieldPath = path.split(".").filter((p) => !p.startsWith("$") && !isNumeric(p)).join(".");
232
+ const { resourceName } = ctx.action;
233
+ return ctx.db.getFieldByPath(`${resourceName}.${fieldPath}`);
234
+ }, "getField"),
235
+ vars: {
236
+ ctx: {
237
+ state
238
+ },
239
+ // @deprecated
240
+ $system: {
241
+ now: (/* @__PURE__ */ new Date()).toISOString()
242
+ },
243
+ // @deprecated
244
+ $date: (0, import_utils.getDateVars)(),
245
+ // 新的命名方式,防止和 formily 内置变量冲突
246
+ $nDate: (0, import_utils.getDateVars)(),
247
+ $user: getUser(ctx),
248
+ $nRole: ctx.state.currentRole === "__union__" ? ctx.state.currentRoles : ctx.state.currentRole
249
+ }
250
+ };
251
+ }
252
+ __name(createContextVariablesScope, "createContextVariablesScope");
196
253
  // Annotate the CommonJS export names for ESM import in node:
197
254
  0 && (module.exports = {
198
255
  createAppProxy,
256
+ createContextVariablesScope,
199
257
  createI18n,
200
258
  createResourcer,
201
259
  enablePerfHooks,
package/lib/index.d.ts CHANGED
@@ -18,9 +18,9 @@ export * from './plugin';
18
18
  export * from './plugin-manager';
19
19
  export * from './pub-sub-manager';
20
20
  export * from './event-queue';
21
- export * from './background-job-manager';
22
21
  export * from './worker-id-allocator';
23
22
  export * from './redis-connection-manager';
24
23
  export declare const OFFICIAL_PLUGIN_PREFIX = "@nocobase/plugin-";
25
24
  export { appendToBuiltInPlugins, findAllPlugins, findBuiltInPlugins, findLocalPlugins, packageNameTrim, } from './plugin-manager/findPackageNames';
26
25
  export { runPluginStaticImports } from './run-plugin-static-imports';
26
+ export { createContextVariablesScope } from './helper';
package/lib/index.js CHANGED
@@ -39,6 +39,7 @@ var src_exports = {};
39
39
  __export(src_exports, {
40
40
  OFFICIAL_PLUGIN_PREFIX: () => OFFICIAL_PLUGIN_PREFIX,
41
41
  appendToBuiltInPlugins: () => import_findPackageNames.appendToBuiltInPlugins,
42
+ createContextVariablesScope: () => import_helper.createContextVariablesScope,
42
43
  default: () => import_application.Application,
43
44
  findAllPlugins: () => import_findPackageNames.findAllPlugins,
44
45
  findBuiltInPlugins: () => import_findPackageNames.findBuiltInPlugins,
@@ -60,16 +61,17 @@ __reExport(src_exports, require("./plugin"), module.exports);
60
61
  __reExport(src_exports, require("./plugin-manager"), module.exports);
61
62
  __reExport(src_exports, require("./pub-sub-manager"), module.exports);
62
63
  __reExport(src_exports, require("./event-queue"), module.exports);
63
- __reExport(src_exports, require("./background-job-manager"), module.exports);
64
64
  __reExport(src_exports, require("./worker-id-allocator"), module.exports);
65
65
  __reExport(src_exports, require("./redis-connection-manager"), module.exports);
66
66
  var import_findPackageNames = require("./plugin-manager/findPackageNames");
67
67
  var import_run_plugin_static_imports = require("./run-plugin-static-imports");
68
+ var import_helper = require("./helper");
68
69
  const OFFICIAL_PLUGIN_PREFIX = "@nocobase/plugin-";
69
70
  // Annotate the CommonJS export names for ESM import in node:
70
71
  0 && (module.exports = {
71
72
  OFFICIAL_PLUGIN_PREFIX,
72
73
  appendToBuiltInPlugins,
74
+ createContextVariablesScope,
73
75
  findAllPlugins,
74
76
  findBuiltInPlugins,
75
77
  findLocalPlugins,
@@ -86,7 +88,6 @@ const OFFICIAL_PLUGIN_PREFIX = "@nocobase/plugin-";
86
88
  ...require("./plugin-manager"),
87
89
  ...require("./pub-sub-manager"),
88
90
  ...require("./event-queue"),
89
- ...require("./background-job-manager"),
90
91
  ...require("./worker-id-allocator"),
91
92
  ...require("./redis-connection-manager")
92
93
  });
@@ -31,60 +31,13 @@ __export(parse_variables_exports, {
31
31
  });
32
32
  module.exports = __toCommonJS(parse_variables_exports);
33
33
  var import_utils = require("@nocobase/utils");
34
- function getUser(ctx) {
35
- return async ({ fields }) => {
36
- var _a, _b;
37
- const userFields = fields.filter((f) => f && ctx.db.getFieldByPath("users." + f));
38
- (_a = ctx.logger) == null ? void 0 : _a.info("filter-parse: ", { userFields });
39
- if (!ctx.state.currentUser) {
40
- return;
41
- }
42
- if (!userFields.length) {
43
- return;
44
- }
45
- const user = await ctx.db.getRepository("users").findOne({
46
- filterByTk: ctx.state.currentUser.id,
47
- fields: userFields
48
- });
49
- (_b = ctx.logger) == null ? void 0 : _b.info("filter-parse: ", {
50
- $user: user == null ? void 0 : user.toJSON()
51
- });
52
- return user;
53
- };
54
- }
55
- __name(getUser, "getUser");
56
- function isNumeric(str) {
57
- if (typeof str === "number") return true;
58
- if (typeof str != "string") return false;
59
- return !isNaN(str) && !isNaN(parseFloat(str));
60
- }
61
- __name(isNumeric, "isNumeric");
34
+ var import_helper = require("../helper");
62
35
  async function parseVariables(ctx, next) {
63
36
  const filter = ctx.action.params.filter;
64
37
  if (!filter) {
65
38
  return next();
66
39
  }
67
- ctx.action.params.filter = await (0, import_utils.parseFilter)(filter, {
68
- timezone: ctx.get("x-timezone"),
69
- now: (/* @__PURE__ */ new Date()).toISOString(),
70
- getField: /* @__PURE__ */ __name((path) => {
71
- const fieldPath = path.split(".").filter((p) => !p.startsWith("$") && !isNumeric(p)).join(".");
72
- const { resourceName } = ctx.action;
73
- return ctx.db.getFieldByPath(`${resourceName}.${fieldPath}`);
74
- }, "getField"),
75
- vars: {
76
- // @deprecated
77
- $system: {
78
- now: (/* @__PURE__ */ new Date()).toISOString()
79
- },
80
- // @deprecated
81
- $date: (0, import_utils.getDateVars)(),
82
- // 新的命名方式,防止和 formily 内置变量冲突
83
- $nDate: (0, import_utils.getDateVars)(),
84
- $user: getUser(ctx),
85
- $nRole: ctx.state.currentRole === "__union__" ? ctx.state.currentRoles : ctx.state.currentRole
86
- }
87
- });
40
+ ctx.action.params.filter = await (0, import_utils.parseFilter)(filter, (0, import_helper.createContextVariablesScope)(ctx));
88
41
  await next();
89
42
  }
90
43
  __name(parseVariables, "parseVariables");
@@ -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>;
@@ -35,14 +35,12 @@ var import_utils = require("@nocobase/utils");
35
35
  var import_handler_manager = require("./handler-manager");
36
36
  const createPubSubManager = /* @__PURE__ */ __name((app, options) => {
37
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
- }
38
+ app.on("afterStart", async () => {
39
+ await pubSubManager.connect();
40
+ });
41
+ app.on("afterStop", async () => {
42
+ await pubSubManager.close();
43
+ });
46
44
  return pubSubManager;
47
45
  }, "createPubSubManager");
48
46
  const _PubSubManager = class _PubSubManager {
@@ -55,13 +53,13 @@ const _PubSubManager = class _PubSubManager {
55
53
  publisherId;
56
54
  adapter;
57
55
  handlerManager;
58
- get channelPrefix() {
59
- var _a;
60
- return ((_a = this.options) == null ? void 0 : _a.channelPrefix) ? `${this.options.channelPrefix}.` : "";
61
- }
62
56
  setAdapter(adapter) {
63
57
  this.adapter = adapter;
64
58
  }
59
+ getFullChannel(channel) {
60
+ var _a;
61
+ return [this.app.name, (_a = this.options) == null ? void 0 : _a.channelPrefix, channel].filter(Boolean).join(".");
62
+ }
65
63
  async isConnected() {
66
64
  if (this.adapter) {
67
65
  return this.adapter.isConnected();
@@ -72,14 +70,10 @@ const _PubSubManager = class _PubSubManager {
72
70
  if (!this.adapter) {
73
71
  return;
74
72
  }
75
- if (!this.app.serving()) {
76
- this.app.logger.warn("app is not serving, will not connect to event queue");
77
- return;
78
- }
79
73
  await this.adapter.connect();
80
74
  await this.handlerManager.each(async (channel, headler) => {
81
75
  this.app.logger.debug(`[PubSubManager] subscribe ${channel} added before connected`);
82
- await this.adapter.subscribe(`${this.channelPrefix}${channel}`, headler);
76
+ await this.adapter.subscribe(this.getFullChannel(channel), headler);
83
77
  });
84
78
  }
85
79
  async close() {
@@ -93,7 +87,7 @@ const _PubSubManager = class _PubSubManager {
93
87
  const handler = this.handlerManager.set(channel, callback, options);
94
88
  if (await this.isConnected()) {
95
89
  this.app.logger.debug(`[PubSubManager] subscribe ${channel} added after connected`);
96
- await this.adapter.subscribe(`${this.channelPrefix}${channel}`, handler);
90
+ await this.adapter.subscribe(this.getFullChannel(channel), handler);
97
91
  }
98
92
  }
99
93
  async unsubscribe(channel, callback) {
@@ -101,7 +95,7 @@ const _PubSubManager = class _PubSubManager {
101
95
  if (!this.adapter || !handler) {
102
96
  return;
103
97
  }
104
- return this.adapter.unsubscribe(`${this.channelPrefix}${channel}`, handler);
98
+ return this.adapter.unsubscribe(this.getFullChannel(channel), handler);
105
99
  }
106
100
  async publish(channel, message, options) {
107
101
  var _a;
@@ -116,7 +110,7 @@ const _PubSubManager = class _PubSubManager {
116
110
  ...options,
117
111
  message
118
112
  });
119
- await this.adapter.publish(`${this.channelPrefix}${channel}`, wrappedMessage);
113
+ await this.adapter.publish(this.getFullChannel(channel), wrappedMessage);
120
114
  this.app.logger.trace(`[PubSubManager] published message to channel ${channel}`);
121
115
  }
122
116
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/server",
3
- "version": "1.9.0-beta.16",
3
+ "version": "1.9.0-beta.18",
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": "1.9.0-beta.16",
14
- "@nocobase/actions": "1.9.0-beta.16",
15
- "@nocobase/auth": "1.9.0-beta.16",
16
- "@nocobase/cache": "1.9.0-beta.16",
17
- "@nocobase/data-source-manager": "1.9.0-beta.16",
18
- "@nocobase/database": "1.9.0-beta.16",
19
- "@nocobase/evaluators": "1.9.0-beta.16",
20
- "@nocobase/lock-manager": "1.9.0-beta.16",
21
- "@nocobase/logger": "1.9.0-beta.16",
22
- "@nocobase/resourcer": "1.9.0-beta.16",
23
- "@nocobase/sdk": "1.9.0-beta.16",
24
- "@nocobase/snowflake-id": "1.9.0-beta.16",
25
- "@nocobase/telemetry": "1.9.0-beta.16",
26
- "@nocobase/utils": "1.9.0-beta.16",
13
+ "@nocobase/acl": "1.9.0-beta.18",
14
+ "@nocobase/actions": "1.9.0-beta.18",
15
+ "@nocobase/auth": "1.9.0-beta.18",
16
+ "@nocobase/cache": "1.9.0-beta.18",
17
+ "@nocobase/data-source-manager": "1.9.0-beta.18",
18
+ "@nocobase/database": "1.9.0-beta.18",
19
+ "@nocobase/evaluators": "1.9.0-beta.18",
20
+ "@nocobase/lock-manager": "1.9.0-beta.18",
21
+ "@nocobase/logger": "1.9.0-beta.18",
22
+ "@nocobase/resourcer": "1.9.0-beta.18",
23
+ "@nocobase/sdk": "1.9.0-beta.18",
24
+ "@nocobase/snowflake-id": "1.9.0-beta.18",
25
+ "@nocobase/telemetry": "1.9.0-beta.18",
26
+ "@nocobase/utils": "1.9.0-beta.18",
27
27
  "@types/decompress": "4.2.7",
28
28
  "@types/ini": "^1.3.31",
29
29
  "@types/koa-send": "^4.1.3",
@@ -59,5 +59,5 @@
59
59
  "@types/serve-handler": "^6.1.1",
60
60
  "@types/ws": "^8.5.5"
61
61
  },
62
- "gitHead": "ff9b917d27840cc08e3f60d02384504ae0e35995"
62
+ "gitHead": "1c211ab8c30d9442c38d07e2ebef2c2935e0fbac"
63
63
  }
@@ -1,40 +0,0 @@
1
- /**
2
- * This file is part of the NocoBase (R) project.
3
- * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
- * Authors: NocoBase Team.
5
- *
6
- * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
- * For more information, please refer to: https://www.nocobase.com/agreement.
8
- */
9
- import Application from './application';
10
- import { QueueEventOptions, QueueMessageOptions } from './event-queue';
11
- export interface BackgroundJobManagerOptions {
12
- channel?: string;
13
- }
14
- type BackgroundJobEventOptions = Pick<QueueEventOptions, 'process' | 'idle'>;
15
- declare class BackgroundJobManager {
16
- private app;
17
- private options;
18
- static DEFAULT_CHANNEL: string;
19
- private subscriptions;
20
- private processing;
21
- private get channel();
22
- private onAfterStart;
23
- private onBeforeStop;
24
- private process;
25
- constructor(app: Application, options?: BackgroundJobManagerOptions);
26
- private get idle();
27
- /**
28
- * 订阅指定主题的任务处理器
29
- * @param options 订阅选项
30
- */
31
- subscribe(topic: string, options: BackgroundJobEventOptions): void;
32
- /**
33
- * 取消订阅指定主题
34
- * @param topic 主题名称
35
- */
36
- unsubscribe(topic: string): void;
37
- publish(topic: string, payload: any, options?: QueueMessageOptions): Promise<void>;
38
- }
39
- export { BackgroundJobManager };
40
- export default BackgroundJobManager;
@@ -1,111 +0,0 @@
1
- /**
2
- * This file is part of the NocoBase (R) project.
3
- * Copyright (c) 2020-2024 NocoBase Co., Ltd.
4
- * Authors: NocoBase Team.
5
- *
6
- * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
- * For more information, please refer to: https://www.nocobase.com/agreement.
8
- */
9
-
10
- var __defProp = Object.defineProperty;
11
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
12
- var __getOwnPropNames = Object.getOwnPropertyNames;
13
- var __hasOwnProp = Object.prototype.hasOwnProperty;
14
- var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
15
- var __name = (target, value) => __defProp(target, "name", { value, configurable: true });
16
- var __export = (target, all) => {
17
- for (var name in all)
18
- __defProp(target, name, { get: all[name], enumerable: true });
19
- };
20
- var __copyProps = (to, from, except, desc) => {
21
- if (from && typeof from === "object" || typeof from === "function") {
22
- for (let key of __getOwnPropNames(from))
23
- if (!__hasOwnProp.call(to, key) && key !== except)
24
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
25
- }
26
- return to;
27
- };
28
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
- var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
30
- var background_job_manager_exports = {};
31
- __export(background_job_manager_exports, {
32
- BackgroundJobManager: () => BackgroundJobManager,
33
- default: () => background_job_manager_default
34
- });
35
- module.exports = __toCommonJS(background_job_manager_exports);
36
- const _BackgroundJobManager = class _BackgroundJobManager {
37
- constructor(app, options = {}) {
38
- this.app = app;
39
- this.options = options;
40
- this.app.on("afterStart", this.onAfterStart);
41
- this.app.on("beforeStop", this.onBeforeStop);
42
- }
43
- subscriptions = /* @__PURE__ */ new Map();
44
- // topic -> handler
45
- processing = null;
46
- get channel() {
47
- return this.options.channel ?? _BackgroundJobManager.DEFAULT_CHANNEL;
48
- }
49
- onAfterStart = /* @__PURE__ */ __name(() => {
50
- this.app.eventQueue.subscribe(this.channel, {
51
- idle: /* @__PURE__ */ __name(() => this.idle, "idle"),
52
- process: this.process
53
- });
54
- }, "onAfterStart");
55
- onBeforeStop = /* @__PURE__ */ __name(() => {
56
- this.app.eventQueue.unsubscribe(this.channel);
57
- }, "onBeforeStop");
58
- process = /* @__PURE__ */ __name(async ({ topic, payload }, options) => {
59
- const event = this.subscriptions.get(topic);
60
- if (!event) {
61
- this.app.logger.warn(`No handler found for topic: ${topic}, event skipped.`);
62
- return;
63
- }
64
- this.processing = event.process(payload, options);
65
- try {
66
- await this.processing;
67
- this.app.logger.debug(`Completed background job ${topic}:${options.id}`);
68
- } catch (error) {
69
- this.app.logger.error(`Failed to process background job ${topic}:${options.id}`, error);
70
- throw error;
71
- } finally {
72
- this.processing = null;
73
- }
74
- }, "process");
75
- get idle() {
76
- return !this.processing && [...this.subscriptions.values()].every((event) => event.idle());
77
- }
78
- /**
79
- * 订阅指定主题的任务处理器
80
- * @param options 订阅选项
81
- */
82
- subscribe(topic, options) {
83
- if (this.subscriptions.has(topic)) {
84
- this.app.logger.warn(`Topic "${topic}" already has a handler, skip...`);
85
- return;
86
- }
87
- this.subscriptions.set(topic, options);
88
- this.app.logger.debug(`Subscribed to background job topic: ${topic}`);
89
- }
90
- /**
91
- * 取消订阅指定主题
92
- * @param topic 主题名称
93
- */
94
- unsubscribe(topic) {
95
- if (this.subscriptions.has(topic)) {
96
- this.subscriptions.delete(topic);
97
- this.app.logger.debug(`Unsubscribed from background job topic: ${topic}`);
98
- }
99
- }
100
- async publish(topic, payload, options) {
101
- await this.app.eventQueue.publish(this.channel, { topic, payload }, options);
102
- }
103
- };
104
- __name(_BackgroundJobManager, "BackgroundJobManager");
105
- __publicField(_BackgroundJobManager, "DEFAULT_CHANNEL", "background-jobs");
106
- let BackgroundJobManager = _BackgroundJobManager;
107
- var background_job_manager_default = BackgroundJobManager;
108
- // Annotate the CommonJS export names for ESM import in node:
109
- 0 && (module.exports = {
110
- BackgroundJobManager
111
- });