@nocobase/plugin-flow-engine 2.1.0-alpha.9 → 2.1.0-beta.10

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.
Files changed (51) hide show
  1. package/dist/ai/docs/runjs/context/block-model.md +35 -35
  2. package/dist/ai/docs/runjs/context/collection-field.md +51 -53
  3. package/dist/ai/docs/runjs/context/collection.md +39 -39
  4. package/dist/ai/docs/runjs/context/data-source-manager.md +30 -40
  5. package/dist/ai/docs/runjs/context/data-source.md +44 -52
  6. package/dist/ai/docs/runjs/context/element.md +38 -44
  7. package/dist/ai/docs/runjs/context/exit-all.md +35 -37
  8. package/dist/ai/docs/runjs/context/exit.md +35 -38
  9. package/dist/ai/docs/runjs/context/filter-manager.md +30 -36
  10. package/dist/ai/docs/runjs/context/form.md +57 -57
  11. package/dist/ai/docs/runjs/context/get-model.md +21 -22
  12. package/dist/ai/docs/runjs/context/get-value.md +19 -20
  13. package/dist/ai/docs/runjs/context/get-var.md +55 -61
  14. package/dist/ai/docs/runjs/context/i18n.md +14 -17
  15. package/dist/ai/docs/runjs/context/import-async.md +45 -333
  16. package/dist/ai/docs/runjs/context/init-resource.md +20 -20
  17. package/dist/ai/docs/runjs/context/libs.md +31 -31
  18. package/dist/ai/docs/runjs/context/location.md +31 -34
  19. package/dist/ai/docs/runjs/context/logger.md +40 -41
  20. package/dist/ai/docs/runjs/context/make-resource.md +26 -27
  21. package/dist/ai/docs/runjs/context/message.md +41 -42
  22. package/dist/ai/docs/runjs/context/modal.md +44 -44
  23. package/dist/ai/docs/runjs/context/model.md +33 -36
  24. package/dist/ai/docs/runjs/context/notification.md +40 -41
  25. package/dist/ai/docs/runjs/context/off.md +14 -14
  26. package/dist/ai/docs/runjs/context/on.md +29 -30
  27. package/dist/ai/docs/runjs/context/open-view.md +40 -40
  28. package/dist/ai/docs/runjs/context/render.md +32 -37
  29. package/dist/ai/docs/runjs/context/request.md +45 -46
  30. package/dist/ai/docs/runjs/context/require-async.md +25 -28
  31. package/dist/ai/docs/runjs/context/resource.md +34 -34
  32. package/dist/ai/docs/runjs/context/route.md +34 -36
  33. package/dist/ai/docs/runjs/context/router.md +31 -43
  34. package/dist/ai/docs/runjs/context/set-value.md +17 -18
  35. package/dist/ai/docs/runjs/context/t.md +17 -20
  36. package/dist/ai/docs/runjs/context/view.md +46 -49
  37. package/dist/ai/docs/runjs/document.md +0 -1
  38. package/dist/ai/docs/runjs/import-modules.md +32 -32
  39. package/dist/ai/docs/runjs/index.md +13 -13
  40. package/dist/ai/docs/runjs/jsx.md +19 -19
  41. package/dist/ai/docs/runjs/model/form-block-model.md +3 -1
  42. package/dist/ai/docs/runjs/render.md +15 -15
  43. package/dist/ai/docs/runjs/resource/api-resource.md +53 -53
  44. package/dist/ai/docs/runjs/resource/multi-record-resource.md +64 -64
  45. package/dist/ai/docs/runjs/resource/single-record-resource.md +55 -55
  46. package/dist/ai/docs/runjs/resource/sql-resource.md +57 -57
  47. package/dist/ai/docs/runjs/window.md +5 -5
  48. package/dist/externalVersion.js +10 -10
  49. package/dist/node_modules/ses/package.json +1 -1
  50. package/dist/node_modules/zod/package.json +1 -1
  51. package/package.json +2 -2
@@ -1,18 +1,18 @@
1
1
  # ctx.dataSource
2
2
 
3
- The `DataSource` instance bound to the current RunJS execution context, used to access collections, field metadata, and manage collection configurations **within the current data source**. It usually corresponds to the data source selected for the current page or block (e.g., the main database `main`).
3
+ The data source instance (`DataSource`) bound to the current RunJS context; used to access collections, field metadata, and collection config **within that data source**. Usually the current page/block’s data source (e.g. main `main`).
4
4
 
5
5
  ## Use Cases
6
6
 
7
7
  | Scenario | Description |
8
- |------|------|
9
- | **Single Data Source Operations** | Get collection and field metadata when the current data source is known. |
10
- | **Collection Management** | Get, add, update, or delete collections under the current data source. |
11
- | **Get Fields by Path** | Use the `collectionName.fieldPath` format to get field definitions (supports association paths). |
8
+ |----------|-------------|
9
+ | **Single data source** | Get collections, field metadata when the current data source is known |
10
+ | **Collection management** | Get/add/update/remove collections in the current data source |
11
+ | **Field by path** | Get field definition by `collectionName.fieldPath` (supports association path) |
12
12
 
13
- > Note: `ctx.dataSource` represents a single data source for the current context. To enumerate or access other data sources, please use [ctx.dataSourceManager](./data-source-manager.md).
13
+ > Note: `ctx.dataSource` is the single data source for the current context; to enumerate or access other data sources use [ctx.dataSourceManager](./data-source-manager.md).
14
14
 
15
- ## Type Definition
15
+ ## Type
16
16
 
17
17
  ```ts
18
18
  dataSource: DataSource;
@@ -20,18 +20,15 @@ dataSource: DataSource;
20
20
  class DataSource {
21
21
  constructor(options?: Record<string, any>);
22
22
 
23
- // Read-only properties
24
- get flowEngine(): FlowEngine; // Current FlowEngine instance
25
- get displayName(): string; // Display name (supports i18n)
26
- get key(): string; // Data source key, e.g., 'main'
27
- get name(): string; // Same as key
23
+ get flowEngine(): FlowEngine;
24
+ get displayName(): string;
25
+ get key(): string;
26
+ get name(): string;
28
27
 
29
- // Collection reading
30
- getCollections(): Collection[]; // Get all collections
31
- getCollection(name: string): Collection | undefined; // Get collection by name
32
- getAssociation(associationName: string): CollectionField | undefined; // Get association field (e.g., users.roles)
28
+ getCollections(): Collection[];
29
+ getCollection(name: string): Collection | undefined;
30
+ getAssociation(associationName: string): CollectionField | undefined;
33
31
 
34
- // Collection management
35
32
  addCollection(collection: Collection | CollectionOptions): void;
36
33
  updateCollection(newOptions: CollectionOptions): void;
37
34
  upsertCollection(options: CollectionOptions): Collection | undefined;
@@ -39,7 +36,6 @@ class DataSource {
39
36
  removeCollection(name: string): void;
40
37
  clearCollections(): void;
41
38
 
42
- // Field metadata
43
39
  getCollectionField(fieldPath: string): CollectionField | undefined;
44
40
  }
45
41
  ```
@@ -47,61 +43,57 @@ class DataSource {
47
43
  ## Common Properties
48
44
 
49
45
  | Property | Type | Description |
50
- |------|------|------|
51
- | `key` | `string` | Data source key, e.g., `'main'` |
46
+ |----------|------|-------------|
47
+ | `key` | `string` | Data source key (e.g. `main`) |
52
48
  | `name` | `string` | Same as key |
53
- | `displayName` | `string` | Display name (supports i18n) |
49
+ | `displayName` | `string` | Display name (i18n) |
54
50
  | `flowEngine` | `FlowEngine` | Current FlowEngine instance |
55
51
 
56
52
  ## Common Methods
57
53
 
58
54
  | Method | Description |
59
- |------|------|
60
- | `getCollections()` | Gets all collections under the current data source (sorted, with hidden ones filtered). |
61
- | `getCollection(name)` | Gets a collection by name; `name` can be `collectionName.fieldName` to get the target collection of an association. |
62
- | `getAssociation(associationName)` | Gets an association field definition by `collectionName.fieldName`. |
63
- | `getCollectionField(fieldPath)` | Gets a field definition by `collectionName.fieldPath`, supporting association paths like `users.profile.avatar`. |
55
+ |--------|-------------|
56
+ | `getCollections()` | All collections in this data source (sorted, hidden filtered) |
57
+ | `getCollection(name)` | Collection by name; `name` can be `collectionName.fieldName` for association target |
58
+ | `getAssociation(associationName)` | Association field by `collectionName.fieldName` |
59
+ | `getCollectionField(fieldPath)` | Field by `collectionName.fieldPath`; supports paths like `users.profile.avatar` |
64
60
 
65
- ## Relationship with ctx.dataSourceManager
61
+ ## Relation to ctx.dataSourceManager
66
62
 
67
- | Requirement | Recommended Usage |
68
- |------|----------|
69
- | **Single data source bound to current context** | `ctx.dataSource` |
70
- | **Entry point for all data sources** | `ctx.dataSourceManager` |
71
- | **Get collection within current data source** | `ctx.dataSource.getCollection(name)` |
72
- | **Get collection across data sources** | `ctx.dataSourceManager.getCollection(dataSourceKey, collectionName)` |
73
- | **Get field within current data source** | `ctx.dataSource.getCollectionField('users.profile.avatar')` |
74
- | **Get field across data sources** | `ctx.dataSourceManager.getCollectionField('main.users.profile.avatar')` |
63
+ | Need | Recommended |
64
+ |------|-------------|
65
+ | **Single data source for context** | `ctx.dataSource` |
66
+ | **Entry to all data sources** | `ctx.dataSourceManager` |
67
+ | **Collection in current data source** | `ctx.dataSource.getCollection(name)` |
68
+ | **Collection in another data source** | `ctx.dataSourceManager.getCollection(dataSourceKey, collectionName)` |
69
+ | **Field in current data source** | `ctx.dataSource.getCollectionField('users.profile.avatar')` |
70
+ | **Field across data sources** | `ctx.dataSourceManager.getCollectionField('main.users.profile.avatar')` |
75
71
 
76
- ## Example
72
+ ## Examples
77
73
 
78
- ### Get Collections and Fields
74
+ ### Get collections and fields
79
75
 
80
76
  ```ts
81
- // Get all collections
82
77
  const collections = ctx.dataSource.getCollections();
83
78
 
84
- // Get collection by name
85
79
  const users = ctx.dataSource.getCollection('users');
86
80
  const primaryKey = users?.filterTargetKey ?? 'id';
87
81
 
88
- // Get field definition by "collectionName.fieldPath" (supports associations)
89
82
  const field = ctx.dataSource.getCollectionField('users.profile.avatar');
90
83
  const userNameField = ctx.dataSource.getCollectionField('orders.createdBy.name');
91
84
  ```
92
85
 
93
- ### Get Association Fields
86
+ ### Get association field
94
87
 
95
88
  ```ts
96
- // Get association field definition by collectionName.fieldName
97
89
  const rolesField = ctx.dataSource.getAssociation('users.roles');
98
90
  if (rolesField?.isAssociationField()) {
99
91
  const targetCol = rolesField.targetCollection;
100
- // Process based on target collection structure
92
+ // ...
101
93
  }
102
94
  ```
103
95
 
104
- ### Iterate Through Collections for Dynamic Processing
96
+ ### Iterate collections
105
97
 
106
98
  ```ts
107
99
  const collections = ctx.dataSource.getCollections();
@@ -112,25 +104,25 @@ for (const col of collections) {
112
104
  }
113
105
  ```
114
106
 
115
- ### Perform Validation or Dynamic UI Based on Field Metadata
107
+ ### Validation or dynamic UI from field metadata
116
108
 
117
109
  ```ts
118
110
  const field = ctx.dataSource.getCollectionField('users.status');
119
111
  if (field) {
120
112
  const options = field.enum ?? [];
121
113
  const operators = field.getFilterOperators();
122
- // Perform UI logic or validation based on interface, enum, validation, etc.
114
+ // ...
123
115
  }
124
116
  ```
125
117
 
126
118
  ## Notes
127
119
 
128
- - The path format for `getCollectionField(fieldPath)` is `collectionName.fieldPath`, where the first segment is the collection name and the subsequent segments are the field path (supports associations, e.g., `user.name`).
129
- - `getCollection(name)` supports the `collectionName.fieldName` format, returning the target collection of the association field.
130
- - In the RunJS context, `ctx.dataSource` is usually determined by the data source of the current block or page. If no data source is bound to the context, it may be `undefined`; it is recommended to perform a null check before use.
120
+ - `getCollectionField(fieldPath)` uses path format `collectionName.fieldPath`; first segment is collection name, rest is field path (supports association, e.g. `user.name`).
121
+ - `getCollection(name)` supports `collectionName.fieldName` and returns the association target collection.
122
+ - In RunJS, `ctx.dataSource` is usually determined by the current block/page; if there is no bound data source it may be `undefined`—check before use.
131
123
 
132
124
  ## Related
133
125
 
134
- - [ctx.dataSourceManager](./data-source-manager.md): Data source manager, manages all data sources.
135
- - [ctx.collection](./collection.md): The collection associated with the current context.
136
- - [ctx.collectionField](./collection-field.md): The collection field definition for the current field.
126
+ - [ctx.dataSourceManager](./data-source-manager.md): manager for all data sources
127
+ - [ctx.collection](./collection.md): collection for current context
128
+ - [ctx.collectionField](./collection-field.md): current field’s collection field definition
@@ -1,60 +1,57 @@
1
1
  # ctx.element
2
2
 
3
- An `ElementProxy` instance pointing to the sandbox DOM container, serving as the default rendering target for `ctx.render()`. It is available in scenarios where a rendering container exists, such as `JSBlock`, `JSField`, `JSItem`, and `JSColumn`.
3
+ The ElementProxy instance for the sandbox DOM container; it is the default render target of `ctx.render()`. Available in JSBlock, JSField, JSItem, JSColumn, and other contexts that have a render container.
4
4
 
5
- ## Applicable Scenarios
5
+ ## Use Cases
6
6
 
7
7
  | Scenario | Description |
8
- |------|------|
9
- | **JSBlock** | The DOM container for the block, used to render custom block content. |
10
- | **JSField / JSItem / FormJSFieldItem** | The rendering container for a field or form item (usually a `<span>`). |
11
- | **JSColumn** | The DOM container for a table cell, used to render custom column content. |
8
+ |----------|-------------|
9
+ | **JSBlock** | Block’s DOM container for custom content |
10
+ | **JSField / JSItem / FormJSFieldItem** | Field/item render container (often a `<span>`) |
11
+ | **JSColumn** | Table cell DOM container for custom column content |
12
12
 
13
- > Note: `ctx.element` is only available in RunJS contexts that have a rendering container. In contexts without a UI (such as pure backend logic), it may be `undefined`. It is recommended to perform a null check before use.
13
+ > Note: `ctx.element` is only available in RunJS contexts that have a render container; in contexts without UI (e.g. pure backend) it may be `undefined`—check before use.
14
14
 
15
- ## Type Definition
15
+ ## Type
16
16
 
17
17
  ```typescript
18
18
  element: ElementProxy | undefined;
19
19
 
20
- // ElementProxy is a proxy for the raw HTMLElement, exposing a secure API
21
20
  class ElementProxy {
22
- __el: HTMLElement; // The internal raw DOM element (accessible only in specific scenarios)
23
- innerHTML: string; // Sanitized via DOMPurify during read/write
24
- outerHTML: string; // Same as above
21
+ __el: HTMLElement; // Internal native DOM (only for specific cases)
22
+ innerHTML: string; // Read/write sanitized with DOMPurify
23
+ outerHTML: string;
25
24
  appendChild(child: HTMLElement | string): void;
26
- // Other HTMLElement methods are passed through (direct use is not recommended)
25
+ // Other HTMLElement methods passed through (not recommended)
27
26
  }
28
27
  ```
29
28
 
30
- ## Security Requirements
29
+ ## Security
31
30
 
32
- **Recommended: All rendering should be performed via `ctx.render()`.** Avoid using the DOM APIs of `ctx.element` directly (e.g., `innerHTML`, `appendChild`, `querySelector`, etc.).
31
+ **Recommended: do all rendering via `ctx.render()`.** Do not use `ctx.element`’s DOM APIs directly (e.g. `innerHTML`, `appendChild`, `querySelector`).
33
32
 
34
- ### Why ctx.render() is Recommended
33
+ ### Why use ctx.render()
35
34
 
36
- | Advantage | Description |
37
- |------|------|
38
- | **Security** | Centralized security control to prevent XSS and improper DOM operations. |
39
- | **React Support** | Full support for JSX, React components, and lifecycles. |
40
- | **Context Inheritance** | Automatically inherits the application's `ConfigProvider`, themes, etc. |
41
- | **Conflict Handling** | Automatically manages React root creation/unmounting to avoid multi-instance conflicts. |
35
+ | Benefit | Description |
36
+ |---------|-------------|
37
+ | **Security** | Centralized control, avoids XSS and unsafe DOM use |
38
+ | **React** | Full JSX, components, and lifecycle |
39
+ | **Context** | Inherits app ConfigProvider, theme, etc. |
40
+ | **Conflicts** | Manages React root create/unmount, avoids multiple instances |
42
41
 
43
- ### ❌ Not Recommended: Direct Manipulation of ctx.element
42
+ ### ❌ Not recommended: direct ctx.element use
44
43
 
45
44
  ```ts
46
- // ❌ Not recommended: Using ctx.element APIs directly
47
45
  ctx.element.innerHTML = '<div>Content</div>';
48
46
  ctx.element.appendChild(node);
49
47
  ctx.element.querySelector('.class');
50
48
  ```
51
49
 
52
- > `ctx.element.innerHTML` is deprecated. Please use `ctx.render()` instead.
50
+ > `ctx.element.innerHTML` is deprecated; use `ctx.render()` instead.
53
51
 
54
- ### ✅ Recommended: Using ctx.render()
52
+ ### ✅ Recommended: ctx.render()
55
53
 
56
54
  ```ts
57
- // ✅ Rendering a React component
58
55
  const { Button, Card } = ctx.libs.antd;
59
56
  ctx.render(
60
57
  <Card title={ctx.t('Welcome')}>
@@ -62,43 +59,40 @@ ctx.render(
62
59
  </Card>
63
60
  );
64
61
 
65
- // ✅ Rendering an HTML string
66
62
  ctx.render('<div style="padding:16px;">' + ctx.t('Content') + '</div>');
67
63
 
68
- // ✅ Rendering a DOM node
69
64
  const div = document.createElement('div');
70
65
  div.textContent = ctx.t('Hello');
71
66
  ctx.render(div);
72
67
  ```
73
68
 
74
- ## Special Case: As a Popover Anchor
69
+ ## Exception: popover anchor
75
70
 
76
- When you need to open a Popover using the current element as an anchor, you can access `ctx.element?.__el` to get the raw DOM as the `target`:
71
+ When you need the current element as a popover anchor, use `ctx.element?.__el` as the native DOM `target`:
77
72
 
78
73
  ```ts
79
- // ctx.viewer.popover requires a raw DOM as the target
80
74
  await ctx.viewer.popover({
81
75
  target: ctx.element?.__el,
82
- content: <div>Popup Content</div>,
76
+ content: <div>Popover content</div>,
83
77
  });
84
78
  ```
85
79
 
86
- > Use `__el` only in scenarios like "using the current container as an anchor"; do not manipulate the DOM directly in other cases.
80
+ > Use `__el` only for this current container as anchor” case; do not touch DOM otherwise.
87
81
 
88
- ## Relationship with ctx.render
82
+ ## Relation to ctx.render
89
83
 
90
- - If `ctx.render(vnode)` is called without a `container` argument, it renders into the `ctx.element` container by default.
91
- - If both `ctx.element` is missing and no `container` is provided, an error will be thrown.
92
- - You can explicitly specify a container: `ctx.render(vnode, customContainer)`.
84
+ - `ctx.render(vnode)` without a `container` argument renders into `ctx.element`.
85
+ - If there is no `ctx.element` and no `container`, an error is thrown.
86
+ - You can pass a container: `ctx.render(vnode, customContainer)`.
93
87
 
94
88
  ## Notes
95
89
 
96
- - `ctx.element` is intended for internal use by `ctx.render()`. Directly accessing or modifying its properties/methods is not recommended.
97
- - In contexts without a rendering container, `ctx.element` will be `undefined`. Ensure the container is available or pass a `container` manually before calling `ctx.render()`.
98
- - Although `innerHTML`/`outerHTML` in `ElementProxy` are sanitized via DOMPurify, it is still recommended to use `ctx.render()` for unified rendering management.
90
+ - Treat `ctx.element` as the internal container for `ctx.render()`; avoid reading or mutating it directly.
91
+ - In contexts without a render container, `ctx.element` is `undefined`; ensure a container exists or pass `container` to `ctx.render()`.
92
+ - ElementProxy’s `innerHTML`/`outerHTML` are sanitized with DOMPurify, but prefer `ctx.render()` for all rendering.
99
93
 
100
94
  ## Related
101
95
 
102
- - [ctx.render](./render.md): Rendering content into a container
103
- - [ctx.view](./view.md): Current view controller
104
- - [ctx.modal](./modal.md): Shortcut API for modals
96
+ - [ctx.render](./render.md): render into container
97
+ - [ctx.view](./view.md): current view controller
98
+ - [ctx.modal](./modal.md): modal APIs
@@ -1,96 +1,94 @@
1
1
  # ctx.exitAll()
2
2
 
3
- Terminates the current event flow and all subsequent event flows triggered in the same event dispatch. It is commonly used when all event flows under the current event need to be aborted immediately due to a global error or permission validation failure.
3
+ Stops the current event flow and all **subsequent** event flows that were triggered in the same event dispatch. Use when a global error or permission check requires stopping every flow for that event.
4
4
 
5
5
  ## Use Cases
6
6
 
7
- `ctx.exitAll()` is generally used in JS-executable contexts where it is necessary to **simultaneously abort the current event flow and subsequent event flows triggered by that event**:
7
+ Use `ctx.exitAll()` in JS-capable contexts when you need to **stop both the current flow and any later flows for the same event**:
8
8
 
9
9
  | Scenario | Description |
10
- |------|------|
11
- | **Event Flow** | Main event flow validation fails (e.g., insufficient permissions), requiring the termination of the main flow and any subsequent flows under the same event that have not yet executed. |
12
- | **Linkage Rules** | When linkage validation fails, the current linkage and subsequent linkages triggered by the same event must be terminated. |
13
- | **Action Events** | Pre-action validation fails (e.g., permission check before deletion), requiring the prevention of the main action and subsequent steps. |
10
+ |----------|-------------|
11
+ | **Event flow** | Main flow fails (e.g. no permission); stop it and any subsequent flows for that event |
12
+ | **Linkage rules** | When linkage validation fails and you want to stop current and subsequent linkage |
13
+ | **Action events** | Pre-action check fails (e.g. delete permission); block the action and later steps |
14
14
 
15
- > Difference from `ctx.exit()`: `ctx.exit()` only terminates the current event flow; `ctx.exitAll()` terminates the current event flow and any **unexecuted** subsequent event flows in the same event dispatch.
15
+ > Difference from `ctx.exit()`: `ctx.exit()` only stops the current flow; `ctx.exitAll()` also stops **subsequent** flows for that event.
16
16
 
17
- ## Type Definition
17
+ ## Type
18
18
 
19
19
  ```ts
20
20
  exitAll(): never;
21
21
  ```
22
22
 
23
- Calling `ctx.exitAll()` throws an internal `FlowExitAllException`, which is caught by the FlowEngine to stop the current event flow instance and subsequent event flows under the same event. Once called, the remaining statements in the current JS code will not be executed.
23
+ Calling `ctx.exitAll()` throws an internal `FlowExitAllException`, which the engine uses to stop the current flow instance and subsequent flows for the same event. The rest of the current JS does not run.
24
24
 
25
25
  ## Comparison with ctx.exit()
26
26
 
27
27
  | Method | Scope |
28
- |------|----------|
29
- | `ctx.exit()` | Only terminates the current event flow; subsequent event flows are unaffected. |
30
- | `ctx.exitAll()` | Terminates the current event flow and aborts subsequent event flows executed **sequentially** under the same event. |
28
+ |--------|--------|
29
+ | `ctx.exit()` | Stops only the current flow; later flows still run |
30
+ | `ctx.exitAll()` | Stops the current flow and **subsequent** flows for the same event |
31
31
 
32
- ## Execution Mode
32
+ ## Execution mode
33
33
 
34
- - **Sequential Execution**: Event flows under the same event are executed in order. After any event flow calls `ctx.exitAll()`, subsequent event flows will not execute.
35
- - **Parallel Execution**: Event flows under the same event are executed in parallel. Calling `ctx.exitAll()` in one event flow will not interrupt other concurrent event flows (as they are independent).
34
+ - **Sequential**: flows for the same event run one after another; after any flow calls `ctx.exitAll()`, later flows do not run.
35
+ - **Parallel**: flows run in parallel; one flow calling `ctx.exitAll()` does not stop other already-running flows.
36
36
 
37
37
  ## Examples
38
38
 
39
- ### Terminate all event flows when permission validation fails
39
+ ### Stop all flows on permission failure
40
40
 
41
41
  ```ts
42
- // Abort the main event flow and subsequent event flows when permissions are insufficient
43
42
  if (!hasPermission(ctx)) {
44
- ctx.notification.error({ message: 'No operation permission' });
43
+ ctx.notification.error({ message: 'No permission' });
45
44
  ctx.exitAll();
46
45
  }
47
46
  ```
48
47
 
49
- ### Terminate when global pre-validation fails
48
+ ### Stop on global pre-check failure
50
49
 
51
50
  ```ts
52
- // Example: If associated data is found to be non-deletable before deletion, prevent the main event flow and subsequent actions
53
51
  const canDelete = await checkDeletable(ctx.model?.getValue?.());
54
52
  if (!canDelete) {
55
- ctx.message.error('Cannot delete: associated data exists');
53
+ ctx.message.error('Cannot delete: related data exists');
56
54
  ctx.exitAll();
57
55
  }
58
56
  ```
59
57
 
60
- ### Choosing between ctx.exit() and ctx.exitAll()
58
+ ### When to use ctx.exit() vs ctx.exitAll()
61
59
 
62
60
  ```ts
63
- // Only the current event flow needs to exit -> Use ctx.exit()
61
+ // Only this flow ctx.exit()
64
62
  if (!params.valid) {
65
- ctx.message.error('Invalid parameters');
66
- ctx.exit(); // Subsequent event flows are unaffected
63
+ ctx.message.error('Invalid params');
64
+ ctx.exit();
67
65
  }
68
66
 
69
- // Need to terminate all subsequent event flows under the current event -> Use ctx.exitAll()
67
+ // This and all subsequent flows ctx.exitAll()
70
68
  if (!ctx.model?.context?.getPermission?.()) {
71
- ctx.notification.warning({ message: 'Insufficient permissions' });
72
- ctx.exitAll(); // Both the main event flow and subsequent event flows under the same event are terminated
69
+ ctx.notification.warning({ message: 'No permission' });
70
+ ctx.exitAll();
73
71
  }
74
72
  ```
75
73
 
76
- ### Prompt before terminating
74
+ ### Message then exit
77
75
 
78
76
  ```ts
79
77
  if (!isValidInput(ctx.form?.getValues?.())) {
80
- ctx.message.warning('Please correct the errors in the form first');
78
+ ctx.message.warning('Please fix form errors first');
81
79
  ctx.exitAll();
82
80
  }
83
81
  ```
84
82
 
85
83
  ## Notes
86
84
 
87
- - After calling `ctx.exitAll()`, subsequent code in the current JS will not execute. It is recommended to explain the reason to the user via `ctx.message`, `ctx.notification`, or a modal before calling it.
88
- - Business code usually does not need to catch `FlowExitAllException`; let the FlowEngine handle it.
89
- - If you only need to stop the current event flow without affecting subsequent ones, use `ctx.exit()`.
90
- - In parallel mode, `ctx.exitAll()` only terminates the current event flow and does not interrupt other concurrent event flows.
85
+ - After `ctx.exitAll()`, the rest of the current JS does not run; explain to the user with `ctx.message`, `ctx.notification`, or a dialog before calling.
86
+ - You usually do not need to catch `FlowExitAllException`; the engine handles it.
87
+ - To stop only the current flow, use `ctx.exit()`.
88
+ - In parallel mode, `ctx.exitAll()` only stops the current flow; it does not cancel other concurrent flows.
91
89
 
92
90
  ## Related
93
91
 
94
- - [ctx.exit()](./exit.md): Terminates only the current event flow
95
- - [ctx.message](./message.md): Message prompts
96
- - [ctx.modal](./modal.md): Confirmation modal
92
+ - [ctx.exit()](./exit.md): stop only the current flow
93
+ - [ctx.message](./message.md): message API
94
+ - [ctx.modal](./modal.md): confirm dialog
@@ -1,89 +1,86 @@
1
1
  # ctx.exit()
2
2
 
3
- Terminates the execution of the current event flow; subsequent steps will not run. It is commonly used when business conditions are not met, the user cancels, or an irrecoverable error occurs.
3
+ Stops the current event flow; later steps in that flow do not run. Often used when business conditions fail, the user cancels, or an unrecoverable error occurs.
4
4
 
5
5
  ## Use Cases
6
6
 
7
- `ctx.exit()` is generally used in the following contexts where JS can be executed:
7
+ `ctx.exit()` is used in contexts that execute JS, such as:
8
8
 
9
9
  | Scenario | Description |
10
- |------|------|
11
- | **Event Flow** | In event flows triggered by form submissions, button clicks, etc., terminates subsequent steps when conditions are not met. |
12
- | **Linkage Rules** | In field linkages, filter linkages, etc., terminates the current event flow when validation fails or execution needs to be skipped. |
13
- | **Action Events** | In custom actions (e.g., delete confirmation, pre-save validation), exits when the user cancels or validation fails. |
10
+ |----------|-------------|
11
+ | **Event flow** | In flows triggered by form submit, button click, etc., stop when conditions are not met |
12
+ | **Linkage rules** | Field or filter linkage; stop when validation fails or execution should be skipped |
13
+ | **Action events** | In custom actions (e.g. delete confirm, pre-save validation), exit when user cancels or validation fails |
14
14
 
15
- > Difference from `ctx.exitAll()`: `ctx.exit()` only terminates the current event flow; other event flows under the same event are not affected. `ctx.exitAll()` terminates the current event flow as well as any subsequent event flows under the same event that have not yet been executed.
15
+ > Difference from `ctx.exitAll()`: `ctx.exit()` only stops the **current** event flow; other flows for the same event still run. `ctx.exitAll()` also stops **subsequent** flows for that event.
16
16
 
17
- ## Type Definition
17
+ ## Type
18
18
 
19
19
  ```ts
20
20
  exit(): never;
21
21
  ```
22
22
 
23
- Calling `ctx.exit()` throws an internal `FlowExitException`, which is caught by the FlowEngine to stop the current event flow execution. Once called, the remaining statements in the current JS code will not execute.
23
+ Calling `ctx.exit()` throws an internal `FlowExitException`, which the event flow engine catches and uses to stop the current flow. Once called, the rest of the current JS does not run.
24
24
 
25
25
  ## Comparison with ctx.exitAll()
26
26
 
27
- | Method | Scope of Effect |
28
- |------|----------|
29
- | `ctx.exit()` | Terminates only the current event flow; subsequent event flows are unaffected. |
30
- | `ctx.exitAll()` | Terminates the current event flow and aborts subsequent event flows under the same event that are set to **execute sequentially**. |
27
+ | Method | Scope |
28
+ |--------|--------|
29
+ | `ctx.exit()` | Stops only the current event flow; others unaffected |
30
+ | `ctx.exitAll()` | Stops the current flow and **subsequent** flows for the same event |
31
31
 
32
32
  ## Examples
33
33
 
34
- ### Exit on User Cancellation
34
+ ### Exit on user cancel
35
35
 
36
36
  ```ts
37
- // In a confirmation modal, terminate the event flow if the user clicks cancel
38
37
  if (!confirmed) {
39
- ctx.message.info('Operation cancelled');
38
+ ctx.message.info('Cancelled');
40
39
  ctx.exit();
41
40
  }
42
41
  ```
43
42
 
44
- ### Exit on Parameter Validation Failure
43
+ ### Exit on validation failure
45
44
 
46
45
  ```ts
47
- // Prompt and terminate when validation fails
48
46
  if (!params.value || params.value.length < 3) {
49
- ctx.message.error('Invalid parameters, length must be at least 3');
47
+ ctx.message.error('Invalid: length must be at least 3');
50
48
  ctx.exit();
51
49
  }
52
50
  ```
53
51
 
54
- ### Exit When Business Conditions Are Not Met
52
+ ### Exit when business condition fails
55
53
 
56
54
  ```ts
57
- // Terminate if conditions are not met; subsequent steps will not execute
58
55
  const record = ctx.model?.getValue?.();
59
56
  if (!record || record.status !== 'draft') {
60
- ctx.notification.warning({ message: 'Only drafts can be submitted' });
57
+ ctx.notification.warning({ message: 'Only draft can be submitted' });
61
58
  ctx.exit();
62
59
  }
63
60
  ```
64
61
 
65
- ### Choosing Between ctx.exit() and ctx.exitAll()
62
+ ### When to use ctx.exit() vs ctx.exitAll()
66
63
 
67
64
  ```ts
68
- // Only the current event flow needs to exit Use ctx.exit()
65
+ // Only this flow should stop → ctx.exit()
69
66
  if (!params.valid) {
70
- ctx.message.error('Invalid parameters');
71
- ctx.exit(); // Other event flows are unaffected
67
+ ctx.message.error('Invalid params');
68
+ ctx.exit();
72
69
  }
73
70
 
74
- // Need to terminate all subsequent event flows under the current event → Use ctx.exitAll()
71
+ // Stop this and all subsequent flows for this event → ctx.exitAll()
75
72
  if (!ctx.model?.context?.getPermission?.()) {
76
- ctx.notification.warning({ message: 'Insufficient permissions' });
77
- ctx.exitAll(); // Both the current event flow and subsequent event flows under the same event are terminated
73
+ ctx.notification.warning({ message: 'No permission' });
74
+ ctx.exitAll();
78
75
  }
79
76
  ```
80
77
 
81
- ### Exit Based on User Choice After Modal Confirmation
78
+ ### Exit after modal confirm
82
79
 
83
80
  ```ts
84
81
  const ok = await ctx.modal?.confirm?.({
85
- title: 'Confirm Delete',
86
- content: 'This action cannot be undone. Do you want to continue?',
82
+ title: 'Confirm delete',
83
+ content: 'Cannot be recovered. Continue?',
87
84
  });
88
85
  if (!ok) {
89
86
  ctx.message.info('Cancelled');
@@ -93,12 +90,12 @@ if (!ok) {
93
90
 
94
91
  ## Notes
95
92
 
96
- - After calling `ctx.exit()`, subsequent code in the current JS will not execute; it is recommended to explain the reason to the user via `ctx.message`, `ctx.notification`, or a modal before calling it.
97
- - There is usually no need to catch `FlowExitException` in business code; let the FlowEngine handle it.
98
- - If you need to terminate all subsequent event flows under the current event, use `ctx.exitAll()`.
93
+ - After `ctx.exit()`, the rest of the current JS does not run; use `ctx.message`, `ctx.notification`, or a dialog before calling to explain why.
94
+ - You usually do not need to catch `FlowExitException`; the event flow engine handles it.
95
+ - To stop all subsequent flows for the same event, use `ctx.exitAll()`.
99
96
 
100
97
  ## Related
101
98
 
102
- - [ctx.exitAll()](./exit-all.md): Terminates the current event flow and subsequent event flows under the same event.
103
- - [ctx.message](./message.md): Message prompts.
104
- - [ctx.modal](./modal.md): Confirmation modals.
99
+ - [ctx.exitAll()](./exit-all.md): stop current and subsequent flows for the event
100
+ - [ctx.message](./message.md): message API
101
+ - [ctx.modal](./modal.md): confirm dialog