@nocobase/plugin-workflow 2.0.61 → 2.0.62
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/dist/externalVersion.js +12 -12
- package/dist/node_modules/cron-parser/package.json +1 -1
- package/dist/node_modules/lru-cache/package.json +1 -1
- package/dist/node_modules/nodejs-snowflake/package.json +1 -1
- package/dist/server/Dispatcher.d.ts +2 -0
- package/dist/server/Dispatcher.js +111 -44
- package/package.json +2 -2
package/dist/externalVersion.js
CHANGED
|
@@ -11,8 +11,8 @@ module.exports = {
|
|
|
11
11
|
"react": "18.2.0",
|
|
12
12
|
"@formily/core": "2.3.7",
|
|
13
13
|
"@formily/react": "2.3.7",
|
|
14
|
-
"@nocobase/client": "2.0.
|
|
15
|
-
"@nocobase/utils": "2.0.
|
|
14
|
+
"@nocobase/client": "2.0.62",
|
|
15
|
+
"@nocobase/utils": "2.0.62",
|
|
16
16
|
"antd": "5.24.2",
|
|
17
17
|
"@ant-design/icons": "5.6.1",
|
|
18
18
|
"react-router-dom": "6.30.1",
|
|
@@ -20,20 +20,20 @@ module.exports = {
|
|
|
20
20
|
"lodash": "4.18.1",
|
|
21
21
|
"@dnd-kit/core": "6.1.0",
|
|
22
22
|
"@formily/shared": "2.3.7",
|
|
23
|
-
"@nocobase/flow-engine": "2.0.
|
|
24
|
-
"@nocobase/plugin-mobile": "2.0.
|
|
23
|
+
"@nocobase/flow-engine": "2.0.62",
|
|
24
|
+
"@nocobase/plugin-mobile": "2.0.62",
|
|
25
25
|
"sequelize": "6.35.2",
|
|
26
|
-
"@nocobase/server": "2.0.
|
|
27
|
-
"@nocobase/database": "2.0.
|
|
28
|
-
"@nocobase/data-source-manager": "2.0.
|
|
29
|
-
"@nocobase/logger": "2.0.
|
|
30
|
-
"@nocobase/evaluators": "2.0.
|
|
26
|
+
"@nocobase/server": "2.0.62",
|
|
27
|
+
"@nocobase/database": "2.0.62",
|
|
28
|
+
"@nocobase/data-source-manager": "2.0.62",
|
|
29
|
+
"@nocobase/logger": "2.0.62",
|
|
30
|
+
"@nocobase/evaluators": "2.0.62",
|
|
31
31
|
"@formily/antd-v5": "1.2.3",
|
|
32
32
|
"@formily/reactive": "2.3.7",
|
|
33
33
|
"@emotion/css": "11.13.0",
|
|
34
34
|
"@formily/json-schema": "2.3.7",
|
|
35
|
-
"@nocobase/actions": "2.0.
|
|
35
|
+
"@nocobase/actions": "2.0.62",
|
|
36
36
|
"dayjs": "1.11.13",
|
|
37
|
-
"@nocobase/plugin-workflow-test": "2.0.
|
|
38
|
-
"@nocobase/test": "2.0.
|
|
37
|
+
"@nocobase/plugin-workflow-test": "2.0.62",
|
|
38
|
+
"@nocobase/test": "2.0.62"
|
|
39
39
|
};
|
|
@@ -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":"2026-06-
|
|
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":"2026-06-10T17:43:37.897Z"}
|
|
@@ -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":"2026-06-
|
|
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":"2026-06-10T17:43:37.569Z"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"nodejs-snowflake","collaborators":["Utkarsh Srivastava <utkarsh@sagacious.dev>"],"description":"Generate time sortable 64 bits unique ids for distributed systems (inspired from twitter snowflake)","version":"2.0.1","license":"Apache 2.0","repository":{"type":"git","url":"https://github.com/utkarsh-pro/nodejs-snowflake.git"},"files":["nodejs_snowflake_bg.wasm","nodejs_snowflake.js","nodejs_snowflake.d.ts"],"main":"nodejs_snowflake.js","types":"nodejs_snowflake.d.ts","_lastModified":"2026-06-
|
|
1
|
+
{"name":"nodejs-snowflake","collaborators":["Utkarsh Srivastava <utkarsh@sagacious.dev>"],"description":"Generate time sortable 64 bits unique ids for distributed systems (inspired from twitter snowflake)","version":"2.0.1","license":"Apache 2.0","repository":{"type":"git","url":"https://github.com/utkarsh-pro/nodejs-snowflake.git"},"files":["nodejs_snowflake_bg.wasm","nodejs_snowflake.js","nodejs_snowflake.d.ts"],"main":"nodejs_snowflake.js","types":"nodejs_snowflake.d.ts","_lastModified":"2026-06-10T17:43:37.364Z"}
|
|
@@ -55,8 +55,10 @@ export default class Dispatcher {
|
|
|
55
55
|
private createExecution;
|
|
56
56
|
private acquirePendingExecution;
|
|
57
57
|
private acquireQueueingExecution;
|
|
58
|
+
private acquireWithRetry;
|
|
58
59
|
private getExecutionLockKey;
|
|
59
60
|
private isLockAcquireError;
|
|
61
|
+
private isConcurrentAcquireError;
|
|
60
62
|
private process;
|
|
61
63
|
}
|
|
62
64
|
export {};
|
|
@@ -33,6 +33,7 @@ var import_node_crypto = require("node:crypto");
|
|
|
33
33
|
var import_sequelize = require("sequelize");
|
|
34
34
|
var import_constants = require("./constants");
|
|
35
35
|
var import_Plugin = require("./Plugin");
|
|
36
|
+
const EXECUTION_ACQUIRE_MAX_ATTEMPTS = 5;
|
|
36
37
|
class Dispatcher {
|
|
37
38
|
constructor(plugin) {
|
|
38
39
|
this.plugin = plugin;
|
|
@@ -338,27 +339,38 @@ class Dispatcher {
|
|
|
338
339
|
async acquirePendingExecution(execution) {
|
|
339
340
|
const logger = this.plugin.getLogger(execution.workflowId);
|
|
340
341
|
const isolationLevel = this.plugin.db.options.dialect === "sqlite" ? [][0] : import_sequelize.Transaction.ISOLATION_LEVELS.REPEATABLE_READ;
|
|
341
|
-
let fetched =
|
|
342
|
+
let fetched = null;
|
|
342
343
|
try {
|
|
343
|
-
await this.
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
344
|
+
await this.acquireWithRetry(
|
|
345
|
+
async () => {
|
|
346
|
+
await this.plugin.db.sequelize.transaction({ isolationLevel }, async (transaction) => {
|
|
347
|
+
const ExecutionModelClass = this.plugin.db.getModel("executions");
|
|
348
|
+
const [affected] = await ExecutionModelClass.update(
|
|
349
|
+
{ dispatched: true, status: import_constants.EXECUTION_STATUS.STARTED },
|
|
350
|
+
{
|
|
351
|
+
where: {
|
|
352
|
+
id: execution.id,
|
|
353
|
+
dispatched: false
|
|
354
|
+
},
|
|
355
|
+
transaction
|
|
356
|
+
}
|
|
357
|
+
);
|
|
358
|
+
if (!affected) {
|
|
359
|
+
return;
|
|
360
|
+
}
|
|
361
|
+
await execution.reload({ transaction });
|
|
362
|
+
fetched = execution;
|
|
363
|
+
});
|
|
364
|
+
return false;
|
|
365
|
+
},
|
|
366
|
+
{
|
|
367
|
+
logger,
|
|
368
|
+
conflictMessage: `acquiring pending execution (${execution.id}) conflicted with another worker, retrying`,
|
|
369
|
+
maxAttemptsMessage: `acquiring pending execution (${execution.id}) reached max retry attempts`
|
|
358
370
|
}
|
|
359
|
-
|
|
360
|
-
});
|
|
371
|
+
);
|
|
361
372
|
} catch (error) {
|
|
373
|
+
fetched = null;
|
|
362
374
|
logger.error(`acquiring pending execution failed: ${error.message}`, { error });
|
|
363
375
|
}
|
|
364
376
|
return fetched;
|
|
@@ -367,33 +379,57 @@ class Dispatcher {
|
|
|
367
379
|
const isolationLevel = this.plugin.db.options.dialect === "sqlite" ? [][0] : import_sequelize.Transaction.ISOLATION_LEVELS.REPEATABLE_READ;
|
|
368
380
|
let fetched = null;
|
|
369
381
|
try {
|
|
370
|
-
await this.
|
|
371
|
-
{
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
filter: {
|
|
377
|
-
dispatched: false,
|
|
378
|
-
"workflow.enabled": true
|
|
382
|
+
await this.acquireWithRetry(
|
|
383
|
+
async () => {
|
|
384
|
+
let shouldRetry = false;
|
|
385
|
+
await this.plugin.db.sequelize.transaction(
|
|
386
|
+
{
|
|
387
|
+
isolationLevel
|
|
379
388
|
},
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
389
|
+
async (transaction) => {
|
|
390
|
+
const execution = await this.plugin.db.getRepository("executions").findOne({
|
|
391
|
+
filter: {
|
|
392
|
+
dispatched: false,
|
|
393
|
+
"workflow.enabled": true
|
|
394
|
+
},
|
|
395
|
+
sort: "id",
|
|
396
|
+
transaction
|
|
397
|
+
});
|
|
398
|
+
if (!execution) {
|
|
399
|
+
this.plugin.getLogger("dispatcher").debug(`no execution in db queued to process`);
|
|
400
|
+
return;
|
|
401
|
+
}
|
|
402
|
+
const ExecutionModelClass = this.plugin.db.getModel("executions");
|
|
403
|
+
const [affected] = await ExecutionModelClass.update(
|
|
404
|
+
{
|
|
405
|
+
dispatched: true,
|
|
406
|
+
status: import_constants.EXECUTION_STATUS.STARTED
|
|
407
|
+
},
|
|
408
|
+
{
|
|
409
|
+
where: {
|
|
410
|
+
id: execution.id,
|
|
411
|
+
dispatched: false
|
|
412
|
+
},
|
|
413
|
+
transaction
|
|
414
|
+
}
|
|
415
|
+
);
|
|
416
|
+
if (!affected) {
|
|
417
|
+
shouldRetry = true;
|
|
418
|
+
this.plugin.getLogger(execution.workflowId).warn(`execution (${execution.id}) was already acquired by another worker, retrying`);
|
|
419
|
+
return;
|
|
420
|
+
}
|
|
421
|
+
this.plugin.getLogger(execution.workflowId).info(`execution (${execution.id}) fetched from db`);
|
|
422
|
+
await execution.reload({ transaction });
|
|
423
|
+
execution.workflow = this.plugin.enabledCache.get(execution.workflowId);
|
|
424
|
+
fetched = execution;
|
|
425
|
+
}
|
|
426
|
+
);
|
|
427
|
+
return shouldRetry;
|
|
428
|
+
},
|
|
429
|
+
{
|
|
430
|
+
logger: this.plugin.getLogger("dispatcher"),
|
|
431
|
+
conflictMessage: `acquiring execution conflicted with another worker, retrying`,
|
|
432
|
+
maxAttemptsMessage: `acquiring execution reached max retry attempts, will retry on next dispatch`
|
|
397
433
|
}
|
|
398
434
|
);
|
|
399
435
|
} catch (error) {
|
|
@@ -401,12 +437,43 @@ class Dispatcher {
|
|
|
401
437
|
}
|
|
402
438
|
return fetched;
|
|
403
439
|
}
|
|
440
|
+
async acquireWithRetry(acquire, options) {
|
|
441
|
+
for (let attempt = 1; attempt <= EXECUTION_ACQUIRE_MAX_ATTEMPTS; attempt++) {
|
|
442
|
+
let shouldRetry = false;
|
|
443
|
+
try {
|
|
444
|
+
shouldRetry = await acquire();
|
|
445
|
+
} catch (error) {
|
|
446
|
+
if (!this.isConcurrentAcquireError(error)) {
|
|
447
|
+
throw error;
|
|
448
|
+
}
|
|
449
|
+
shouldRetry = true;
|
|
450
|
+
options.logger.warn(options.conflictMessage, { error });
|
|
451
|
+
}
|
|
452
|
+
if (!shouldRetry) {
|
|
453
|
+
break;
|
|
454
|
+
}
|
|
455
|
+
if (attempt >= EXECUTION_ACQUIRE_MAX_ATTEMPTS) {
|
|
456
|
+
options.logger.warn(options.maxAttemptsMessage);
|
|
457
|
+
break;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
}
|
|
404
461
|
getExecutionLockKey(executionId) {
|
|
405
462
|
return `workflow:execution:${executionId}`;
|
|
406
463
|
}
|
|
407
464
|
isLockAcquireError(error) {
|
|
408
465
|
return error instanceof Error && error.constructor.name === "LockAcquireError";
|
|
409
466
|
}
|
|
467
|
+
isConcurrentAcquireError(error) {
|
|
468
|
+
var _a, _b, _c, _d;
|
|
469
|
+
if (!(error instanceof Error)) {
|
|
470
|
+
return false;
|
|
471
|
+
}
|
|
472
|
+
const databaseError = error;
|
|
473
|
+
const code = ((_a = databaseError.parent) == null ? void 0 : _a.code) || ((_b = databaseError.original) == null ? void 0 : _b.code);
|
|
474
|
+
const errno = ((_c = databaseError.parent) == null ? void 0 : _c.errno) || ((_d = databaseError.original) == null ? void 0 : _d.errno);
|
|
475
|
+
return code === "40001" || code === "40P01" || code === "ER_LOCK_DEADLOCK" || errno === 1205 || errno === 1213;
|
|
476
|
+
}
|
|
410
477
|
async process(execution, job = null, options = {}) {
|
|
411
478
|
const { rerun, ...processorOptions } = options;
|
|
412
479
|
const logger = this.plugin.getLogger(execution.workflowId);
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"description": "A powerful BPM tool that provides foundational support for business automation, with the capability to extend unlimited triggers and nodes.",
|
|
7
7
|
"description.zh-CN": "一个强大的 BPM 工具,为业务自动化提供基础支持,并且可任意扩展更多的触发器和节点。",
|
|
8
8
|
"description.ru-RU": "Мощный инструмент BPM, обеспечивающий базовую поддержку автоматизации бизнес-процессов с возможностью неограниченного расширения триггеров и узлов.",
|
|
9
|
-
"version": "2.0.
|
|
9
|
+
"version": "2.0.62",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"main": "./dist/server/index.js",
|
|
12
12
|
"homepage": "https://docs.nocobase.com/handbook/workflow",
|
|
@@ -48,7 +48,7 @@
|
|
|
48
48
|
"@nocobase/test": "2.x",
|
|
49
49
|
"@nocobase/utils": "2.x"
|
|
50
50
|
},
|
|
51
|
-
"gitHead": "
|
|
51
|
+
"gitHead": "b21b0a5111d188ba495eb579fdae674c5680fff2",
|
|
52
52
|
"keywords": [
|
|
53
53
|
"Workflow"
|
|
54
54
|
]
|