@nocobase/flow-engine 2.1.37 → 2.1.39

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.
@@ -27,6 +27,9 @@ import type { RecordRef } from './utils/serverContextParams';
27
27
  import { FlowView, FlowViewer } from './views/FlowView';
28
28
  import { type RunJSVersion } from './runjs-context/registry';
29
29
  type Getter<T = any> = (ctx: FlowContext) => T | Promise<T>;
30
+ export type ResolveJsonTemplateOptions = {
31
+ contractModelUid?: string | number | null;
32
+ };
30
33
  export type FlowContextDocRef = string | {
31
34
  url: string;
32
35
  title?: string;
@@ -344,7 +347,7 @@ declare class BaseFlowEngineContext extends FlowContext {
344
347
  * @deprecated use `resolveJsonTemplate` instead
345
348
  */
346
349
  renderJson: (template: JSONValue) => Promise<any>;
347
- resolveJsonTemplate: (template: JSONValue) => Promise<any>;
350
+ resolveJsonTemplate: (template: JSONValue, options?: ResolveJsonTemplateOptions) => Promise<any>;
348
351
  getVar: (path: string) => Promise<any>;
349
352
  request: (options: RequestOptions) => Promise<any>;
350
353
  runjs: (code: string, variables?: Record<string, any>, options?: JSRunnerOptions) => Promise<any>;
@@ -2383,7 +2383,7 @@ const _FlowEngineContext = class _FlowEngineContext extends BaseFlowEngineContex
2383
2383
  this.defineMethod("renderJson", function(template) {
2384
2384
  return this.resolveJsonTemplate(template);
2385
2385
  });
2386
- this.defineMethod("resolveJsonTemplate", async function(template) {
2386
+ const resolveJsonTemplate = /* @__PURE__ */ __name(async function(template, options) {
2387
2387
  var _a, _b, _c;
2388
2388
  const used = (0, import_utils.extractUsedVariablePaths)(template);
2389
2389
  const usedVarNames = Object.keys(used || {});
@@ -2516,7 +2516,12 @@ const _FlowEngineContext = class _FlowEngineContext extends BaseFlowEngineContex
2516
2516
  }
2517
2517
  if (this.api) {
2518
2518
  try {
2519
+ const contractRd = (0, import_params_resolvers.buildFlowModelResolveDescriptor)(
2520
+ this,
2521
+ options == null ? void 0 : options.contractModelUid
2522
+ );
2519
2523
  serverResolved = await (0, import_params_resolvers.enqueueVariablesResolve)(this, {
2524
+ ...contractRd ? { contractRd } : {},
2520
2525
  rd: (0, import_params_resolvers.buildFlowModelResolveDescriptor)(this, (_a = this.model) == null ? void 0 : _a.uid),
2521
2526
  template,
2522
2527
  contextParams: autoContextParams || {}
@@ -2528,7 +2533,8 @@ const _FlowEngineContext = class _FlowEngineContext extends BaseFlowEngineContex
2528
2533
  }
2529
2534
  }
2530
2535
  return (0, import_utils.resolveExpressions)(serverResolved, this);
2531
- });
2536
+ }, "resolveJsonTemplate");
2537
+ this.defineMethod("resolveJsonTemplate", resolveJsonTemplate);
2532
2538
  this.defineMethod(
2533
2539
  "getVar",
2534
2540
  async function(varPath) {
@@ -3495,8 +3501,13 @@ function __mergeRunJSDocMeta(base, patch) {
3495
3501
  __name(__mergeRunJSDocMeta, "__mergeRunJSDocMeta");
3496
3502
  const _FlowRunJSContext = class _FlowRunJSContext extends FlowContext {
3497
3503
  constructor(delegate) {
3504
+ var _a, _b;
3498
3505
  super();
3499
3506
  this.addDelegate(delegate);
3507
+ const submit = (_b = (_a = delegate.blockModel) == null ? void 0 : _a.submitFromRunJs) == null ? void 0 : _b.bind(delegate.blockModel);
3508
+ if (delegate.form && submit) {
3509
+ this.defineProperty("form", { value: { ...delegate.form, submit } });
3510
+ }
3500
3511
  this.defineProperty("React", { value: import_react.default });
3501
3512
  this.defineProperty("antd", { value: antd });
3502
3513
  this.defineProperty("dayjs", {
@@ -27,6 +27,7 @@ export type JSONValue = string | {
27
27
  [key: string]: JSONValue;
28
28
  } | JSONValue[];
29
29
  type BatchPayload = {
30
+ contractRd?: string;
30
31
  rd?: string;
31
32
  template: JSONValue;
32
33
  contextParams?: ServerContextParams | undefined;
@@ -146,6 +146,7 @@ function enqueueVariablesResolve(ctx, payload) {
146
146
  try {
147
147
  const batch = items.map((it) => ({
148
148
  id: it.id,
149
+ contractRd: it.payload.contractRd,
149
150
  rd: it.payload.rd,
150
151
  template: it.payload.template,
151
152
  contextParams: it.payload.contextParams || {}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nocobase/flow-engine",
3
- "version": "2.1.37",
3
+ "version": "2.1.39",
4
4
  "private": false,
5
5
  "description": "A standalone flow engine for NocoBase, managing workflows, models, and actions.",
6
6
  "main": "lib/index.js",
@@ -8,8 +8,8 @@
8
8
  "dependencies": {
9
9
  "@formily/antd-v5": "1.x",
10
10
  "@formily/reactive": "2.x",
11
- "@nocobase/sdk": "2.1.37",
12
- "@nocobase/shared": "2.1.37",
11
+ "@nocobase/sdk": "2.1.39",
12
+ "@nocobase/shared": "2.1.39",
13
13
  "ahooks": "^3.7.2",
14
14
  "axios": "^1.7.0",
15
15
  "dayjs": "^1.11.9",
@@ -37,5 +37,5 @@
37
37
  ],
38
38
  "author": "NocoBase Team",
39
39
  "license": "Apache-2.0",
40
- "gitHead": "a0c3201363ae028058845af0176ee902a9eeb3e1"
40
+ "gitHead": "ddbf88ac2a5de1ad94ff4779618cdf1b81aae037"
41
41
  }
@@ -8,6 +8,7 @@
8
8
  */
9
9
 
10
10
  import { describe, expect, it, vi } from 'vitest';
11
+ import { generateFlowModelRdFromToken } from '@nocobase/utils/client';
11
12
  import { FlowContext } from '../flowContext';
12
13
  import { FlowEngine } from '../flowEngine';
13
14
  import {
@@ -122,7 +123,10 @@ describe('objectVariable utilities', () => {
122
123
 
123
124
  // Provide API stub to intercept variables:resolve
124
125
  const calls: any[] = [];
126
+ const payload = Buffer.from(JSON.stringify({ userId: 1, signInTime: 'contract-owner-test' })).toString('base64url');
127
+ const token = `test.${payload}.sig`;
125
128
  (ctx as any).api = {
129
+ auth: { token },
126
130
  request: vi.fn(async ({ url, data, method }) => {
127
131
  calls.push({ url, data, method });
128
132
  const batch = (data?.values?.batch as any[]) || [];
@@ -146,13 +150,14 @@ describe('objectVariable utilities', () => {
146
150
  });
147
151
 
148
152
  const template = { x: '{{ ctx.obj.author.name }}' } as any;
149
- await (ctx as any).resolveJsonTemplate(template);
153
+ await (ctx as any).resolveJsonTemplate(template, { contractModelUid: 'form-grid' });
150
154
 
151
155
  // Assert variables:resolve was called with proper flattened contextParams
152
156
  expect((ctx as any).api.request).toHaveBeenCalled();
153
157
  const call = calls.find((c) => c.url === 'variables:resolve');
154
158
  expect(call).toBeTruthy();
155
159
  const batch0 = call.data?.values?.batch?.[0];
160
+ expect(batch0?.contractRd).toBe(generateFlowModelRdFromToken('form-grid', token));
156
161
  expect(batch0?.contextParams).toBeTruthy();
157
162
  // Flattened key should be 'obj.author'
158
163
  const cp = batch0.contextParams as Record<string, any>;
@@ -0,0 +1,45 @@
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
+ import { describe, expect, it, vi } from 'vitest';
11
+ import { FlowContext, FlowRunJSContext } from '../flowContext';
12
+ import { JSItemRunJSContext } from '../runjs-context/contexts/JSItemRunJSContext';
13
+
14
+ describe('FlowRunJSContext form submission', () => {
15
+ it('uses the form block RunJS submit capability without changing the native form', () => {
16
+ const nativeSubmit = vi.fn();
17
+ const getFieldsValue = vi.fn(() => ({ name: 'Alice' }));
18
+ const form = { submit: nativeSubmit, getFieldsValue };
19
+ const submitFromRunJs = vi.fn();
20
+ const delegate = new FlowContext();
21
+ delegate.defineProperty('form', { value: form });
22
+ delegate.defineProperty('blockModel', { value: { submitFromRunJs } });
23
+
24
+ const ctx = new JSItemRunJSContext(delegate);
25
+
26
+ expect(ctx.form.getFieldsValue()).toEqual({ name: 'Alice' });
27
+ ctx.form.submit();
28
+ expect(submitFromRunJs).toHaveBeenCalledOnce();
29
+ expect(nativeSubmit).not.toHaveBeenCalled();
30
+ expect(form.submit).toBe(nativeSubmit);
31
+ });
32
+
33
+ it('keeps the native submit method when the block has no RunJS submit capability', () => {
34
+ const nativeSubmit = vi.fn();
35
+ const form = { submit: nativeSubmit };
36
+ const delegate = new FlowContext();
37
+ delegate.defineProperty('form', { value: form });
38
+ delegate.defineProperty('blockModel', { value: {} });
39
+
40
+ const ctx = new FlowRunJSContext(delegate);
41
+
42
+ ctx.form.submit();
43
+ expect(nativeSubmit).toHaveBeenCalledOnce();
44
+ });
45
+ });
@@ -165,6 +165,10 @@ function inferSelectsFromUsage(paths: string[] = []): { generatedAppends?: strin
165
165
 
166
166
  type Getter<T = any> = (ctx: FlowContext) => T | Promise<T>;
167
167
 
168
+ export type ResolveJsonTemplateOptions = {
169
+ contractModelUid?: string | number | null;
170
+ };
171
+
168
172
  export type FlowContextDocRef = string | { url: string; title?: string };
169
173
 
170
174
  export type FlowDeprecationDoc =
@@ -3046,7 +3050,7 @@ class BaseFlowEngineContext extends FlowContext {
3046
3050
  * @deprecated use `resolveJsonTemplate` instead
3047
3051
  */
3048
3052
  declare renderJson: (template: JSONValue) => Promise<any>;
3049
- declare resolveJsonTemplate: (template: JSONValue) => Promise<any>;
3053
+ declare resolveJsonTemplate: (template: JSONValue, options?: ResolveJsonTemplateOptions) => Promise<any>;
3050
3054
  declare getVar: (path: string) => Promise<any>;
3051
3055
  declare request: (options: RequestOptions) => Promise<any>;
3052
3056
  declare runjs: (code: string, variables?: Record<string, any>, options?: JSRunnerOptions) => Promise<any>;
@@ -3229,7 +3233,11 @@ export class FlowEngineContext extends BaseFlowEngineContext {
3229
3233
  this.defineMethod('renderJson', function (template: any) {
3230
3234
  return this.resolveJsonTemplate(template);
3231
3235
  });
3232
- this.defineMethod('resolveJsonTemplate', async function (this: BaseFlowEngineContext, template: any) {
3236
+ const resolveJsonTemplate = async function (
3237
+ this: BaseFlowEngineContext,
3238
+ template: any,
3239
+ options?: ResolveJsonTemplateOptions,
3240
+ ) {
3233
3241
  // 提取模板使用到的变量及其子路径
3234
3242
  const used = extractUsedVariablePaths(template);
3235
3243
  const usedVarNames = Object.keys(used || {});
@@ -3398,7 +3406,12 @@ export class FlowEngineContext extends BaseFlowEngineContext {
3398
3406
 
3399
3407
  if (this.api) {
3400
3408
  try {
3409
+ const contractRd = buildFlowModelResolveDescriptor(
3410
+ this as FlowRuntimeContext<FlowModel>,
3411
+ options?.contractModelUid,
3412
+ );
3401
3413
  serverResolved = await enqueueVariablesResolve(this as FlowRuntimeContext<FlowModel>, {
3414
+ ...(contractRd ? { contractRd } : {}),
3402
3415
  rd: buildFlowModelResolveDescriptor(this as FlowRuntimeContext<FlowModel>, this.model?.uid),
3403
3416
  template,
3404
3417
  contextParams: autoContextParams || {},
@@ -3411,7 +3424,8 @@ export class FlowEngineContext extends BaseFlowEngineContext {
3411
3424
  }
3412
3425
 
3413
3426
  return resolveExpressions(serverResolved, this);
3414
- });
3427
+ };
3428
+ this.defineMethod('resolveJsonTemplate', resolveJsonTemplate);
3415
3429
 
3416
3430
  // Helper: resolve a single ctx expression value via resolveJsonTemplate behavior.
3417
3431
  // Example: await ctx.getVar('ctx.record.id')
@@ -4587,6 +4601,10 @@ export class FlowRunJSContext extends FlowContext {
4587
4601
  constructor(delegate: FlowContext) {
4588
4602
  super();
4589
4603
  this.addDelegate(delegate);
4604
+ const submit = delegate.blockModel?.submitFromRunJs?.bind(delegate.blockModel);
4605
+ if (delegate.form && submit) {
4606
+ this.defineProperty('form', { value: { ...delegate.form, submit } });
4607
+ }
4590
4608
  this.defineProperty('React', { value: React });
4591
4609
  this.defineProperty('antd', { value: antd });
4592
4610
  this.defineProperty('dayjs', {
@@ -79,6 +79,7 @@ export type JSONValue = string | { [key: string]: JSONValue } | JSONValue[];
79
79
  // =========================
80
80
 
81
81
  type BatchPayload = {
82
+ contractRd?: string;
82
83
  rd?: string;
83
84
  template: JSONValue;
84
85
  contextParams?: ServerContextParams | undefined;
@@ -172,6 +173,7 @@ export function enqueueVariablesResolve(ctx: FlowRuntimeContext, payload: BatchP
172
173
  try {
173
174
  const batch = items.map((it) => ({
174
175
  id: it.id,
176
+ contractRd: it.payload.contractRd,
175
177
  rd: it.payload.rd,
176
178
  template: it.payload.template,
177
179
  contextParams: it.payload.contextParams || {},