@nocobase/plugin-workflow 1.5.0-beta.27 → 1.5.0-beta.28

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.
@@ -11,24 +11,24 @@ module.exports = {
11
11
  "react": "18.2.0",
12
12
  "@formily/core": "2.3.0",
13
13
  "@formily/react": "2.3.0",
14
- "@nocobase/client": "1.5.0-beta.27",
15
- "@nocobase/utils": "1.5.0-beta.27",
14
+ "@nocobase/client": "1.5.0-beta.28",
15
+ "@nocobase/utils": "1.5.0-beta.28",
16
16
  "antd": "5.12.8",
17
17
  "@ant-design/icons": "5.2.6",
18
18
  "react-router-dom": "6.21.0",
19
19
  "react-i18next": "11.18.6",
20
20
  "@formily/shared": "2.3.2",
21
21
  "lodash": "4.17.21",
22
- "@nocobase/database": "1.5.0-beta.27",
23
- "@nocobase/server": "1.5.0-beta.27",
24
- "@nocobase/logger": "1.5.0-beta.27",
25
- "@nocobase/actions": "1.5.0-beta.27",
26
- "@nocobase/data-source-manager": "1.5.0-beta.27",
27
- "@nocobase/evaluators": "1.5.0-beta.27",
22
+ "sequelize": "6.35.2",
23
+ "@nocobase/database": "1.5.0-beta.28",
24
+ "@nocobase/server": "1.5.0-beta.28",
25
+ "@nocobase/logger": "1.5.0-beta.28",
26
+ "@nocobase/actions": "1.5.0-beta.28",
27
+ "@nocobase/data-source-manager": "1.5.0-beta.28",
28
+ "@nocobase/evaluators": "1.5.0-beta.28",
28
29
  "@formily/antd-v5": "1.1.9",
29
30
  "@formily/reactive": "2.3.0",
30
31
  "dayjs": "1.11.10",
31
- "sequelize": "6.35.2",
32
- "@nocobase/plugin-workflow-test": "1.5.0-beta.27",
33
- "@nocobase/test": "1.5.0-beta.27"
32
+ "@nocobase/plugin-workflow-test": "1.5.0-beta.28",
33
+ "@nocobase/test": "1.5.0-beta.28"
34
34
  };
@@ -157,19 +157,19 @@
157
157
  "Node type": "节点类型",
158
158
  "Unknown node": "未知节点",
159
159
  "Node with unknown type will cause error. Please delete it or check plugin which provide this type.": "未知类型的节点会导致错误,请删除或检查提供该类型的插件。",
160
- "Calculation": "运算",
161
- "Calculation engine": "运算引擎",
160
+ "Calculation": "计算",
161
+ "Calculation engine": "计算引擎",
162
162
  "Basic": "基础",
163
- "Calculation expression": "运算表达式",
163
+ "Calculation expression": "计算表达式",
164
164
  "Expression syntax error": "表达式语法错误",
165
165
  "Syntax references: ": "语法参考:",
166
- "Calculation result": "运算结果",
166
+ "Calculation result": "计算结果",
167
167
  "True": "真",
168
168
  "False": "假",
169
169
  "concat": "连接",
170
170
  "Condition": "条件判断",
171
171
  "Based on boolean result of the calculation to determine whether to \"continue\" or \"exit\" the process, or continue on different branches of \"yes\" and \"no\".":
172
- "基于运算结果的真假来决定“继续”或“退出”流程,或者在“是”与“否”的分支上分别继续。",
172
+ "基于计算结果的真假来决定“继续”或“退出”流程,或者在“是”与“否”的分支上分别继续。",
173
173
  "Mode": "模式",
174
174
  "Continue when \"Yes\"": "“是”则继续",
175
175
  "Branch into \"Yes\" and \"No\"": "“是”和“否”分别继续",
@@ -1 +1 @@
1
- {"name":"cron-parser","version":"4.4.0","description":"Node.js library for parsing crontab instructions","main":"lib/parser.js","types":"index.d.ts","typesVersions":{"<4.1":{"*":["types/ts3/*"]}},"directories":{"test":"test"},"scripts":{"test:tsd":"tsd","test:unit":"TZ=UTC tap ./test/*.js","test:cover":"TZ=UTC tap --coverage-report=html ./test/*.js","lint":"eslint .","lint:fix":"eslint --fix .","test":"npm run lint && npm run test:unit && npm run test:tsd"},"repository":{"type":"git","url":"https://github.com/harrisiirak/cron-parser.git"},"keywords":["cron","crontab","parser"],"author":"Harri Siirak","contributors":["Nicholas Clawson","Daniel Prentis <daniel@salsitasoft.com>","Renault John Lecoultre","Richard Astbury <richard.astbury@gmail.com>","Meaglin Wasabi <Meaglin.wasabi@gmail.com>","Mike Kusold <hello@mikekusold.com>","Alex Kit <alex.kit@atmajs.com>","Santiago Gimeno <santiago.gimeno@gmail.com>","Daniel <darc.tec@gmail.com>","Christian Steininger <christian.steininger.cs@gmail.com>","Mykola Piskovyi <m.piskovyi@gmail.com>","Brian Vaughn <brian.david.vaughn@gmail.com>","Nicholas Clawson <nickclaw@gmail.com>","Yasuhiroki <yasuhiroki.duck@gmail.com>","Nicholas Clawson <nickclaw@gmail.com>","Brendan Warkentin <faazshift@gmail.com>","Charlie Fish <fishcharlie.code@gmail.com>","Ian Graves <ian+diskimage@iangrav.es>","Andy Thompson <me@andytson.com>","Regev Brody <regevbr@gmail.com>"],"license":"MIT","dependencies":{"luxon":"^1.28.0"},"devDependencies":{"eslint":"^8.2.0","sinon":"^10.0.0","tap":"^16.0.1","tsd":"^0.19.0"},"engines":{"node":">=0.8"},"browser":{"fs":false},"tap":{"check-coverage":false},"tsd":{"directory":"test","compilerOptions":{"lib":["es2017","dom"]}},"_lastModified":"2025-01-10T04:58:29.034Z"}
1
+ {"name":"cron-parser","version":"4.4.0","description":"Node.js library for parsing crontab instructions","main":"lib/parser.js","types":"index.d.ts","typesVersions":{"<4.1":{"*":["types/ts3/*"]}},"directories":{"test":"test"},"scripts":{"test:tsd":"tsd","test:unit":"TZ=UTC tap ./test/*.js","test:cover":"TZ=UTC tap --coverage-report=html ./test/*.js","lint":"eslint .","lint:fix":"eslint --fix .","test":"npm run lint && npm run test:unit && npm run test:tsd"},"repository":{"type":"git","url":"https://github.com/harrisiirak/cron-parser.git"},"keywords":["cron","crontab","parser"],"author":"Harri Siirak","contributors":["Nicholas Clawson","Daniel Prentis <daniel@salsitasoft.com>","Renault John Lecoultre","Richard Astbury <richard.astbury@gmail.com>","Meaglin Wasabi <Meaglin.wasabi@gmail.com>","Mike Kusold <hello@mikekusold.com>","Alex Kit <alex.kit@atmajs.com>","Santiago Gimeno <santiago.gimeno@gmail.com>","Daniel <darc.tec@gmail.com>","Christian Steininger <christian.steininger.cs@gmail.com>","Mykola Piskovyi <m.piskovyi@gmail.com>","Brian Vaughn <brian.david.vaughn@gmail.com>","Nicholas Clawson <nickclaw@gmail.com>","Yasuhiroki <yasuhiroki.duck@gmail.com>","Nicholas Clawson <nickclaw@gmail.com>","Brendan Warkentin <faazshift@gmail.com>","Charlie Fish <fishcharlie.code@gmail.com>","Ian Graves <ian+diskimage@iangrav.es>","Andy Thompson <me@andytson.com>","Regev Brody <regevbr@gmail.com>"],"license":"MIT","dependencies":{"luxon":"^1.28.0"},"devDependencies":{"eslint":"^8.2.0","sinon":"^10.0.0","tap":"^16.0.1","tsd":"^0.19.0"},"engines":{"node":">=0.8"},"browser":{"fs":false},"tap":{"check-coverage":false},"tsd":{"directory":"test","compilerOptions":{"lib":["es2017","dom"]}},"_lastModified":"2025-01-14T08:42:50.531Z"}
@@ -1 +1 @@
1
- {"name":"lru-cache","description":"A cache object that deletes the least-recently-used items.","version":"8.0.5","author":"Isaac Z. Schlueter <i@izs.me>","keywords":["mru","lru","cache"],"sideEffects":false,"scripts":{"build":"npm run prepare","preprepare":"rm -rf dist","prepare":"tsc -p tsconfig.json && tsc -p tsconfig-esm.json","postprepare":"bash fixup.sh","pretest":"npm run prepare","presnap":"npm run prepare","test":"c8 tap","snap":"c8 tap","preversion":"npm test","postversion":"npm publish","prepublishOnly":"git push origin --follow-tags","format":"prettier --write .","typedoc":"typedoc --tsconfig tsconfig-esm.json ./src/*.ts","benchmark-results-typedoc":"bash scripts/benchmark-results-typedoc.sh","prebenchmark":"npm run prepare","benchmark":"make -C benchmark","preprofile":"npm run prepare","profile":"make -C benchmark profile"},"main":"./dist/cjs/index-cjs.js","module":"./dist/mjs/index.js","types":"./dist/mjs/index.d.ts","exports":{"./min":{"import":{"types":"./dist/mjs/index.d.ts","default":"./dist/mjs/index.min.js"},"require":{"types":"./dist/cjs/index.d.ts","default":"./dist/cjs/index.min.js"}},".":{"import":{"types":"./dist/mjs/index.d.ts","default":"./dist/mjs/index.js"},"require":{"types":"./dist/cjs/index.d.ts","default":"./dist/cjs/index-cjs.js"}}},"repository":"git://github.com/isaacs/node-lru-cache.git","devDependencies":{"@size-limit/preset-small-lib":"^7.0.8","@types/node":"^17.0.31","@types/tap":"^15.0.6","benchmark":"^2.1.4","c8":"^7.11.2","clock-mock":"^1.0.6","esbuild":"^0.17.11","eslint-config-prettier":"^8.5.0","marked":"^4.2.12","mkdirp":"^2.1.5","prettier":"^2.6.2","size-limit":"^7.0.8","tap":"^16.3.4","ts-node":"^10.7.0","tslib":"^2.4.0","typedoc":"^0.23.24","typescript":"^4.6.4"},"license":"ISC","files":["dist"],"engines":{"node":">=16.14"},"prettier":{"semi":false,"printWidth":70,"tabWidth":2,"useTabs":false,"singleQuote":true,"jsxSingleQuote":false,"bracketSameLine":true,"arrowParens":"avoid","endOfLine":"lf"},"tap":{"coverage":false,"node-arg":["--expose-gc","--no-warnings","--loader","ts-node/esm"],"ts":false},"size-limit":[{"path":"./dist/mjs/index.js"}],"_lastModified":"2025-01-10T04:58:28.655Z"}
1
+ {"name":"lru-cache","description":"A cache object that deletes the least-recently-used items.","version":"8.0.5","author":"Isaac Z. Schlueter <i@izs.me>","keywords":["mru","lru","cache"],"sideEffects":false,"scripts":{"build":"npm run prepare","preprepare":"rm -rf dist","prepare":"tsc -p tsconfig.json && tsc -p tsconfig-esm.json","postprepare":"bash fixup.sh","pretest":"npm run prepare","presnap":"npm run prepare","test":"c8 tap","snap":"c8 tap","preversion":"npm test","postversion":"npm publish","prepublishOnly":"git push origin --follow-tags","format":"prettier --write .","typedoc":"typedoc --tsconfig tsconfig-esm.json ./src/*.ts","benchmark-results-typedoc":"bash scripts/benchmark-results-typedoc.sh","prebenchmark":"npm run prepare","benchmark":"make -C benchmark","preprofile":"npm run prepare","profile":"make -C benchmark profile"},"main":"./dist/cjs/index-cjs.js","module":"./dist/mjs/index.js","types":"./dist/mjs/index.d.ts","exports":{"./min":{"import":{"types":"./dist/mjs/index.d.ts","default":"./dist/mjs/index.min.js"},"require":{"types":"./dist/cjs/index.d.ts","default":"./dist/cjs/index.min.js"}},".":{"import":{"types":"./dist/mjs/index.d.ts","default":"./dist/mjs/index.js"},"require":{"types":"./dist/cjs/index.d.ts","default":"./dist/cjs/index-cjs.js"}}},"repository":"git://github.com/isaacs/node-lru-cache.git","devDependencies":{"@size-limit/preset-small-lib":"^7.0.8","@types/node":"^17.0.31","@types/tap":"^15.0.6","benchmark":"^2.1.4","c8":"^7.11.2","clock-mock":"^1.0.6","esbuild":"^0.17.11","eslint-config-prettier":"^8.5.0","marked":"^4.2.12","mkdirp":"^2.1.5","prettier":"^2.6.2","size-limit":"^7.0.8","tap":"^16.3.4","ts-node":"^10.7.0","tslib":"^2.4.0","typedoc":"^0.23.24","typescript":"^4.6.4"},"license":"ISC","files":["dist"],"engines":{"node":">=16.14"},"prettier":{"semi":false,"printWidth":70,"tabWidth":2,"useTabs":false,"singleQuote":true,"jsxSingleQuote":false,"bracketSameLine":true,"arrowParens":"avoid","endOfLine":"lf"},"tap":{"coverage":false,"node-arg":["--expose-gc","--no-warnings","--loader","ts-node/esm"],"ts":false},"size-limit":[{"path":"./dist/mjs/index.js"}],"_lastModified":"2025-01-14T08:42:50.127Z"}
@@ -6,7 +6,7 @@
6
6
  * This project is dual-licensed under AGPL-3.0 and NocoBase Commercial License.
7
7
  * For more information, please refer to: https://www.nocobase.com/agreement.
8
8
  */
9
- import { Transactionable } from '@nocobase/database';
9
+ import { Transactionable } from 'sequelize';
10
10
  import { Plugin } from '@nocobase/server';
11
11
  import { Registry } from '@nocobase/utils';
12
12
  import { Logger } from '@nocobase/logger';
@@ -42,7 +42,7 @@ export default class PluginWorkflowServer extends Plugin {
42
42
  /**
43
43
  * @experimental
44
44
  */
45
- getLogger(workflowId: ID): Logger;
45
+ getLogger(workflowId?: ID): Logger;
46
46
  /**
47
47
  * @experimental
48
48
  * @param {WorkflowModel} workflow
@@ -70,11 +70,11 @@ export default class PluginWorkflowServer extends Plugin {
70
70
  * Start a deferred execution
71
71
  * @experimental
72
72
  */
73
- start(execution: ExecutionModel): void;
74
- createProcessor(execution: ExecutionModel, options?: {}): Processor;
73
+ start(execution: ExecutionModel): Promise<void>;
75
74
  private createExecution;
76
75
  private prepare;
77
76
  private dispatch;
77
+ createProcessor(execution: ExecutionModel, options?: {}): Processor;
78
78
  private process;
79
79
  execute(workflow: WorkflowModel, context: Context, options?: EventOptions): Promise<void | Processor>;
80
80
  /**
@@ -41,6 +41,7 @@ __export(Plugin_exports, {
41
41
  module.exports = __toCommonJS(Plugin_exports);
42
42
  var import_path = __toESM(require("path"));
43
43
  var import_crypto = require("crypto");
44
+ var import_sequelize = require("sequelize");
44
45
  var import_lru_cache = __toESM(require("lru-cache"));
45
46
  var import_database = require("@nocobase/database");
46
47
  var import_server = require("@nocobase/server");
@@ -126,7 +127,7 @@ class PluginWorkflowServer extends import_server.Plugin {
126
127
  /**
127
128
  * @experimental
128
129
  */
129
- getLogger(workflowId) {
130
+ getLogger(workflowId = "dispatcher") {
130
131
  const now = /* @__PURE__ */ new Date();
131
132
  const date = `${now.getFullYear()}-${`0${now.getMonth() + 1}`.slice(-2)}-${`0${now.getDate()}`.slice(-2)}`;
132
133
  const key = `${date}-${workflowId}}`;
@@ -256,7 +257,6 @@ class PluginWorkflowServer extends import_server.Plugin {
256
257
  (model, { transaction }) => this.toggle(model, false, { transaction })
257
258
  );
258
259
  this.app.on("afterStart", async () => {
259
- this.app.setMaintainingMessage("check for not started executions");
260
260
  this.ready = true;
261
261
  const collection = db.getCollection("workflows");
262
262
  const workflows = await collection.repository.find({
@@ -266,12 +266,14 @@ class PluginWorkflowServer extends import_server.Plugin {
266
266
  this.toggle(workflow, true, { silent: true });
267
267
  });
268
268
  this.checker = setInterval(() => {
269
+ this.getLogger("dispatcher").info(`(cycling) check for queueing executions`);
269
270
  this.dispatch();
270
271
  }, 3e5);
271
272
  this.app.on("workflow:dispatch", () => {
272
273
  this.app.logger.info("workflow:dispatch");
273
274
  this.dispatch();
274
275
  });
276
+ this.getLogger("dispatcher").info("(starting) check for queueing executions");
275
277
  this.dispatch();
276
278
  });
277
279
  this.app.on("beforeStop", async () => {
@@ -331,6 +333,15 @@ class PluginWorkflowServer extends import_server.Plugin {
331
333
  logger.warn(`workflow ${workflow.id} is not enabled, event will be ignored`);
332
334
  return;
333
335
  }
336
+ const duplicated = this.events.find(([w, c, { eventKey }]) => {
337
+ if (eventKey && options.eventKey) {
338
+ return eventKey === options.eventKey;
339
+ }
340
+ });
341
+ if (duplicated) {
342
+ logger.warn(`event of workflow ${workflow.id} is duplicated (${options.eventKey}), event will be ignored`);
343
+ return;
344
+ }
334
345
  if (context == null) {
335
346
  logger.warn(`workflow ${workflow.id} event data context is null, event will be ignored`);
336
347
  return;
@@ -344,6 +355,7 @@ class PluginWorkflowServer extends import_server.Plugin {
344
355
  logger.info(`new event triggered, now events: ${this.events.length}`);
345
356
  logger.debug(`event data:`, { context });
346
357
  if (this.events.length > 1) {
358
+ logger.info(`new event is pending to be prepared after previous preparation is finished`);
347
359
  return;
348
360
  }
349
361
  setTimeout(this.prepare);
@@ -371,22 +383,25 @@ class PluginWorkflowServer extends import_server.Plugin {
371
383
  `execution (${job.execution.id}) resuming from job (${job.id}) added to pending list`
372
384
  );
373
385
  this.pending.push([job.execution, job]);
386
+ if (this.executing) {
387
+ await this.executing;
388
+ }
374
389
  this.dispatch();
375
390
  }
376
391
  /**
377
392
  * Start a deferred execution
378
393
  * @experimental
379
394
  */
380
- start(execution) {
395
+ async start(execution) {
381
396
  if (execution.status !== import_constants.EXECUTION_STATUS.STARTED) {
382
397
  return;
383
398
  }
384
399
  this.pending.push([execution]);
400
+ if (this.executing) {
401
+ await this.executing;
402
+ }
385
403
  this.dispatch();
386
404
  }
387
- createProcessor(execution, options = {}) {
388
- return new import_Processor.default(execution, { ...options, plugin: this });
389
- }
390
405
  async createExecution(workflow, context, options) {
391
406
  const { deferred } = options;
392
407
  const transaction = await this.useDataSourceTransaction("main", options.transaction, true);
@@ -445,7 +460,7 @@ class PluginWorkflowServer extends import_server.Plugin {
445
460
  const event = this.events.shift();
446
461
  this.eventsCount = this.events.length;
447
462
  if (!event) {
448
- this.getLogger("dispatcher").warn(`events queue is empty, no need to prepare`);
463
+ this.getLogger("dispatcher").info(`events queue is empty, no need to prepare`);
449
464
  return;
450
465
  }
451
466
  const logger = this.getLogger(event[0].id);
@@ -478,38 +493,56 @@ class PluginWorkflowServer extends import_server.Plugin {
478
493
  }
479
494
  this.executing = (async () => {
480
495
  let next = null;
481
- try {
482
- if (this.pending.length) {
483
- next = this.pending.shift();
484
- this.getLogger(next[0].workflowId).info(`pending execution (${next[0].id}) ready to process`);
485
- } else {
486
- const execution = await this.db.getRepository("executions").findOne({
487
- filter: {
488
- status: import_constants.EXECUTION_STATUS.QUEUEING,
489
- "workflow.enabled": true,
490
- "workflow.id": {
491
- [import_database.Op.not]: null
492
- }
496
+ if (this.pending.length) {
497
+ next = this.pending.shift();
498
+ this.getLogger(next[0].workflowId).info(`pending execution (${next[0].id}) ready to process`);
499
+ } else {
500
+ try {
501
+ await this.db.sequelize.transaction(
502
+ {
503
+ isolationLevel: this.db.options.dialect === "sqlite" ? [][0] : import_sequelize.Transaction.ISOLATION_LEVELS.REPEATABLE_READ
493
504
  },
494
- appends: ["workflow"],
495
- sort: "id"
496
- });
497
- if (execution) {
498
- this.getLogger(execution.workflowId).info(`execution (${execution.id}) fetched from db`);
499
- next = [execution];
500
- }
501
- }
502
- if (next) {
503
- await this.process(...next);
504
- }
505
- } finally {
506
- this.executing = null;
507
- if (next) {
508
- this.dispatch();
505
+ async (transaction) => {
506
+ const execution = await this.db.getRepository("executions").findOne({
507
+ filter: {
508
+ status: import_constants.EXECUTION_STATUS.QUEUEING,
509
+ "workflow.enabled": true
510
+ },
511
+ sort: "id",
512
+ transaction
513
+ });
514
+ if (execution) {
515
+ this.getLogger(execution.workflowId).info(`execution (${execution.id}) fetched from db`);
516
+ await execution.update(
517
+ {
518
+ status: import_constants.EXECUTION_STATUS.STARTED
519
+ },
520
+ { transaction }
521
+ );
522
+ execution.workflow = this.enabledCache.get(execution.workflowId);
523
+ next = [execution];
524
+ } else {
525
+ this.getLogger("dispatcher").info(`no execution in db queued to process`);
526
+ }
527
+ }
528
+ );
529
+ } catch (error) {
530
+ this.getLogger("dispatcher").error(`fetching execution from db failed: ${error.message}`, { error });
509
531
  }
510
532
  }
533
+ if (next) {
534
+ await this.process(...next);
535
+ }
536
+ this.executing = null;
537
+ if (next) {
538
+ this.getLogger("dispatcher").info(`last process finished, will do another dispatch`);
539
+ this.dispatch();
540
+ }
511
541
  })();
512
542
  }
543
+ createProcessor(execution, options = {}) {
544
+ return new import_Processor.default(execution, { ...options, plugin: this });
545
+ }
513
546
  async process(execution, job, options = {}) {
514
547
  var _a, _b;
515
548
  if (execution.status === import_constants.EXECUTION_STATUS.QUEUEING) {
@@ -30,7 +30,7 @@ export default class DateFieldScheduleTrigger {
30
30
  constructor(workflow: Plugin);
31
31
  reload(): Promise<void>;
32
32
  inspect(workflows: WorkflowModel[]): void;
33
- loadRecordsToSchedule({ config: { collection, limit, startsOn, repeat, endsOn }, allExecuted }: WorkflowModel, currentDate: Date): Promise<import("@nocobase/database").Model<any, any>[]>;
33
+ loadRecordsToSchedule({ id, config: { collection, limit, startsOn, repeat, endsOn }, allExecuted }: WorkflowModel, currentDate: Date): Promise<import("@nocobase/database").Model<any, any>[]>;
34
34
  getRecordNextTime(workflow: WorkflowModel, record: any, nextSecond?: boolean): any;
35
35
  schedule(workflow: WorkflowModel, record: any, nextTime: any, toggle?: boolean, options?: {}): Promise<void>;
36
36
  trigger(workflow: WorkflowModel, record: any, nextTime: any, { transaction }?: Transactionable): Promise<void>;
@@ -131,6 +131,7 @@ class DateFieldScheduleTrigger {
131
131
  const now = /* @__PURE__ */ new Date();
132
132
  workflows.forEach(async (workflow) => {
133
133
  const records = await this.loadRecordsToSchedule(workflow, now);
134
+ this.workflow.getLogger(workflow.id).info(`[Schedule on date field] ${records.length} records to schedule`);
134
135
  records.forEach((record) => {
135
136
  const nextTime = this.getRecordNextTime(workflow, record);
136
137
  this.schedule(workflow, record, nextTime, Boolean(nextTime));
@@ -144,17 +145,20 @@ class DateFieldScheduleTrigger {
144
145
  // b. repeat in range (number or cron):
145
146
  // i. endsOn after now -> yes
146
147
  // ii. endsOn before now -> no
147
- async loadRecordsToSchedule({ config: { collection, limit, startsOn, repeat, endsOn }, allExecuted }, currentDate) {
148
+ async loadRecordsToSchedule({ id, config: { collection, limit, startsOn, repeat, endsOn }, allExecuted }, currentDate) {
148
149
  const { dataSourceManager } = this.workflow.app;
149
150
  if (limit && allExecuted >= limit) {
151
+ this.workflow.getLogger(id).warn(`[Schedule on date field] limit reached (all executed ${allExecuted})`);
150
152
  return [];
151
153
  }
152
154
  if (!startsOn) {
155
+ this.workflow.getLogger(id).warn(`[Schedule on date field] "startsOn" is not configured`);
153
156
  return [];
154
157
  }
155
158
  const timestamp = currentDate.getTime();
156
159
  const startTimestamp = getOnTimestampWithOffset(startsOn, currentDate);
157
160
  if (!startTimestamp) {
161
+ this.workflow.getLogger(id).warn(`[Schedule on date field] "startsOn.field" is not configured`);
158
162
  return [];
159
163
  }
160
164
  const [dataSourceName, collectionName] = (0, import_data_source_manager.parseCollectionName)(collection);
@@ -193,21 +197,21 @@ class DateFieldScheduleTrigger {
193
197
  }
194
198
  }
195
199
  if (endsOn) {
196
- const now = /* @__PURE__ */ new Date();
197
- const endTimestamp = getOnTimestampWithOffset(endsOn, now);
198
- if (!endTimestamp) {
199
- return [];
200
- }
201
200
  if (typeof endsOn === "string") {
202
- if (endTimestamp <= timestamp) {
201
+ if ((0, import_utils.parseDateWithoutMs)(endsOn) <= timestamp) {
203
202
  return [];
204
203
  }
205
204
  } else {
206
- conditions.push({
207
- [endsOn.field]: {
208
- [import_database.Op.gte]: new Date(endTimestamp)
209
- }
210
- });
205
+ const endTimestamp = getOnTimestampWithOffset(endsOn, currentDate);
206
+ if (endTimestamp) {
207
+ conditions.push({
208
+ [endsOn.field]: {
209
+ [import_database.Op.gte]: new Date(endTimestamp)
210
+ }
211
+ });
212
+ } else {
213
+ this.workflow.getLogger(id).warn(`[Schedule on date field] "endsOn.field" is not configured`);
214
+ }
211
215
  }
212
216
  }
213
217
  } else {
@@ -217,6 +221,7 @@ class DateFieldScheduleTrigger {
217
221
  }
218
222
  });
219
223
  }
224
+ this.workflow.getLogger(id).debug(`[Schedule on date field] conditions: `, { conditions });
220
225
  return model.findAll({
221
226
  where: {
222
227
  [import_database.Op.and]: conditions
package/package.json CHANGED
@@ -4,13 +4,13 @@
4
4
  "displayName.zh-CN": "工作流",
5
5
  "description": "A powerful BPM tool that provides foundational support for business automation, with the capability to extend unlimited triggers and nodes.",
6
6
  "description.zh-CN": "一个强大的 BPM 工具,为业务自动化提供基础支持,并且可任意扩展更多的触发器和节点。",
7
- "version": "1.5.0-beta.27",
7
+ "version": "1.5.0-beta.28",
8
8
  "license": "AGPL-3.0",
9
9
  "main": "./dist/server/index.js",
10
10
  "homepage": "https://docs.nocobase.com/handbook/workflow",
11
11
  "homepage.zh-CN": "https://docs-cn.nocobase.com/handbook/workflow",
12
12
  "dependencies": {
13
- "@nocobase/plugin-workflow-test": "1.5.0-beta.27"
13
+ "@nocobase/plugin-workflow-test": "1.5.0-beta.28"
14
14
  },
15
15
  "devDependencies": {
16
16
  "@ant-design/icons": "5.x",
@@ -44,7 +44,7 @@
44
44
  "@nocobase/test": "1.x",
45
45
  "@nocobase/utils": "1.x"
46
46
  },
47
- "gitHead": "c0355c8e70efbc0a0b1aba58aa011d8b3cc10ed9",
47
+ "gitHead": "51948b3d451eabe1ca31e8f56bce32e84eba57ec",
48
48
  "keywords": [
49
49
  "Workflow"
50
50
  ]