@nocobase/plugin-flow-engine 2.1.0-alpha.6 → 2.1.0-alpha.8

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 (53) hide show
  1. package/dist/ai/docs/runjs/context/block-model.md +35 -35
  2. package/dist/ai/docs/runjs/context/collection-field.md +53 -51
  3. package/dist/ai/docs/runjs/context/collection.md +39 -39
  4. package/dist/ai/docs/runjs/context/data-source-manager.md +40 -30
  5. package/dist/ai/docs/runjs/context/data-source.md +52 -44
  6. package/dist/ai/docs/runjs/context/element.md +44 -38
  7. package/dist/ai/docs/runjs/context/exit-all.md +37 -35
  8. package/dist/ai/docs/runjs/context/exit.md +38 -35
  9. package/dist/ai/docs/runjs/context/filter-manager.md +36 -30
  10. package/dist/ai/docs/runjs/context/form.md +57 -57
  11. package/dist/ai/docs/runjs/context/get-model.md +22 -21
  12. package/dist/ai/docs/runjs/context/get-value.md +20 -19
  13. package/dist/ai/docs/runjs/context/get-var.md +61 -55
  14. package/dist/ai/docs/runjs/context/i18n.md +17 -14
  15. package/dist/ai/docs/runjs/context/import-async.md +333 -45
  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 +34 -31
  19. package/dist/ai/docs/runjs/context/logger.md +41 -40
  20. package/dist/ai/docs/runjs/context/make-resource.md +27 -26
  21. package/dist/ai/docs/runjs/context/message.md +42 -41
  22. package/dist/ai/docs/runjs/context/modal.md +44 -44
  23. package/dist/ai/docs/runjs/context/model.md +36 -33
  24. package/dist/ai/docs/runjs/context/notification.md +41 -40
  25. package/dist/ai/docs/runjs/context/off.md +14 -14
  26. package/dist/ai/docs/runjs/context/on.md +30 -29
  27. package/dist/ai/docs/runjs/context/open-view.md +40 -40
  28. package/dist/ai/docs/runjs/context/render.md +37 -32
  29. package/dist/ai/docs/runjs/context/request.md +46 -45
  30. package/dist/ai/docs/runjs/context/require-async.md +28 -25
  31. package/dist/ai/docs/runjs/context/resource.md +34 -34
  32. package/dist/ai/docs/runjs/context/route.md +36 -34
  33. package/dist/ai/docs/runjs/context/router.md +43 -31
  34. package/dist/ai/docs/runjs/context/set-value.md +18 -17
  35. package/dist/ai/docs/runjs/context/sql.md +7 -15
  36. package/dist/ai/docs/runjs/context/t.md +20 -17
  37. package/dist/ai/docs/runjs/context/view.md +49 -46
  38. package/dist/ai/docs/runjs/document.md +1 -0
  39. package/dist/ai/docs/runjs/import-modules.md +32 -32
  40. package/dist/ai/docs/runjs/index.md +13 -13
  41. package/dist/ai/docs/runjs/jsx.md +19 -19
  42. package/dist/ai/docs/runjs/model/form-block-model.md +1 -3
  43. package/dist/ai/docs/runjs/render.md +15 -15
  44. package/dist/ai/docs/runjs/resource/api-resource.md +53 -53
  45. package/dist/ai/docs/runjs/resource/multi-record-resource.md +64 -64
  46. package/dist/ai/docs/runjs/resource/single-record-resource.md +55 -55
  47. package/dist/ai/docs/runjs/resource/sql-resource.md +57 -57
  48. package/dist/ai/docs/runjs/window.md +5 -5
  49. package/dist/externalVersion.js +10 -10
  50. package/dist/node_modules/ses/package.json +1 -1
  51. package/dist/node_modules/zod/package.json +1 -1
  52. package/dist/server/collections/flowsql.js +1 -0
  53. package/package.json +2 -2
@@ -1,83 +1,83 @@
1
1
  # SingleRecordResource
2
2
 
3
- Resource for **single records**: data is one object; supports get by primary key, create/update (save), and destroy. Use for detail, form, and other "single record" scenarios. Unlike [MultiRecordResource](./multi-record-resource.md), SingleRecordResource's `getData()` returns a single object; use `setFilterByTk(id)` for primary key; `save()` auto-calls create or update based on `isNewRecord`.
3
+ A Resource oriented towards a **single record**: data is a single object, supporting retrieval by primary key, creation/updating (save), and deletion. It is suitable for "single record" scenarios such as details and forms. Unlike [MultiRecordResource](./multi-record-resource.md), the `getData()` method of `SingleRecordResource` returns a single object. You specify the primary key via `setFilterByTk(id)`, and `save()` will automatically call `create` or `update` based on the `isNewRecord` state.
4
4
 
5
5
  **Inheritance**: FlowResource → APIResource → BaseRecordResource → SingleRecordResource.
6
6
 
7
- **Create with**: `ctx.makeResource('SingleRecordResource')` or `ctx.initResource('SingleRecordResource')`. Before use call `setResourceName('collectionName')`; for operations by primary key call `setFilterByTk(id)`; RunJS injects `ctx.api`.
7
+ **Creation**: `ctx.makeResource('SingleRecordResource')` or `ctx.initResource('SingleRecordResource')`. You must call `setResourceName('collectionName')` before use. When performing operations by primary key, call `setFilterByTk(id)`. In RunJS, `ctx.api` is injected by the runtime environment.
8
8
 
9
9
  ---
10
10
 
11
- ## Use cases
11
+ ## Use Scenarios
12
12
 
13
13
  | Scenario | Description |
14
- |----------|-------------|
15
- | **Detail block** | Detail block uses SingleRecordResource by default; loads single record by primary key |
16
- | **Form block** | Create/edit forms use SingleRecordResource; `save()` auto-distinguishes create vs update |
17
- | **JSBlock detail** | Load single user, order, etc. in JSBlock and render custom UI |
18
- | **Association resources** | Load associated single record with `users.profile`; requires `setSourceId(parentRecordId)` |
14
+ |------|------|
15
+ | **Details Block** | The Details block uses `SingleRecordResource` by default to load a single record by its primary key. |
16
+ | **Form Block** | Create/Edit forms use `SingleRecordResource`, where `save()` automatically distinguishes between `create` and `update`. |
17
+ | **JSBlock Details** | Load a single user, order, etc., in a JSBlock and customize the display. |
18
+ | **Association Resources** | Load associated single records using the format `users.profile`, requiring `setSourceId(parentRecordID)`. |
19
19
 
20
20
  ---
21
21
 
22
- ## Data format
22
+ ## Data Format
23
23
 
24
- - `getData()` returns a **single record object**, i.e. the get API `data` field
25
- - `getMeta()` returns metadata (if any)
24
+ - `getData()` returns a **single record object**, which corresponds to the `data` field of the `get` API response.
25
+ - `getMeta()` returns metadata (if available).
26
26
 
27
27
  ---
28
28
 
29
- ## Resource name and primary key
29
+ ## Resource Name and Primary Key
30
30
 
31
31
  | Method | Description |
32
- |--------|-------------|
33
- | `setResourceName(name)` / `getResourceName()` | Resource name, e.g. `'users'`, `'users.profile'` (association) |
34
- | `setSourceId(id)` / `getSourceId()` | Parent record id for association resources (e.g. `users.profile` needs users primary key) |
35
- | `setDataSourceKey(key)` / `getDataSourceKey()` | Data source key (for multiple data sources) |
36
- | `setFilterByTk(tk)` / `getFilterByTk()` | Current record primary key; after set, `isNewRecord` is false |
32
+ |------|------|
33
+ | `setResourceName(name)` / `getResourceName()` | Resource name, e.g., `'users'`, `'users.profile'` (association resource). |
34
+ | `setSourceId(id)` / `getSourceId()` | The parent record ID for association resources (e.g., `users.profile` requires the primary key of the `users` record). |
35
+ | `setDataSourceKey(key)` / `getDataSourceKey()` | Data source identifier (used in multi-data source environments). |
36
+ | `setFilterByTk(tk)` / `getFilterByTk()` | The primary key of the current record; once set, `isNewRecord` becomes `false`. |
37
37
 
38
38
  ---
39
39
 
40
40
  ## State
41
41
 
42
42
  | Property/Method | Description |
43
- |-----------------|-------------|
44
- | `isNewRecord` | Whether in "create" state (true when filterByTk not set or just created) |
43
+ |----------|------|
44
+ | `isNewRecord` | Whether it is in a "New" state (true if `filterByTk` is not set or if it was just created). |
45
45
 
46
46
  ---
47
47
 
48
- ## Request params (filter / fields)
48
+ ## Request Parameters (Filter / Fields)
49
49
 
50
50
  | Method | Description |
51
- |--------|-------------|
52
- | `setFilter(filter)` / `getFilter()` | Filter (when not new) |
53
- | `setFields(fields)` / `getFields()` | Requested fields |
54
- | `setAppends(appends)` / `getAppends()` / `addAppends` / `removeAppends` | Association expansion |
51
+ |------|------|
52
+ | `setFilter(filter)` / `getFilter()` | Filter (available when not in "New" state). |
53
+ | `setFields(fields)` / `getFields()` | Requested fields. |
54
+ | `setAppends(appends)` / `getAppends()` / `addAppends` / `removeAppends` | Association loading (appends). |
55
55
 
56
56
  ---
57
57
 
58
58
  ## CRUD
59
59
 
60
60
  | Method | Description |
61
- |--------|-------------|
62
- | `refresh()` | Request get with current `filterByTk`; update `getData()`. No request when in new state. |
63
- | `save(data, options?)` | Create when new, otherwise update; optional `{ refresh: false }` to skip auto refresh |
64
- | `destroy(options?)` | Delete by current `filterByTk` and clear local data |
65
- | `runAction(actionName, options)` | Call any resource action |
61
+ |------|------|
62
+ | `refresh()` | Requests `get` based on the current `filterByTk` and updates `getData()`; does nothing in "New" state. |
63
+ | `save(data, options?)` | Calls `create` when in "New" state, otherwise calls `update`; optional `{ refresh: false }` prevents automatic refreshing. |
64
+ | `destroy(options?)` | Deletes the record based on the current `filterByTk` and clears local data. |
65
+ | `runAction(actionName, options)` | Calls any resource action. |
66
66
 
67
67
  ---
68
68
 
69
- ## Config and events
69
+ ## Configuration and Events
70
70
 
71
71
  | Method | Description |
72
- |--------|-------------|
73
- | `setSaveActionOptions(options)` | Request config for save |
74
- | `on('refresh', fn)` / `on('saved', fn)` | Fired when refresh completes or after save |
72
+ |------|------|
73
+ | `setSaveActionOptions(options)` | Request configuration for the `save` action. |
74
+ | `on('refresh', fn)` / `on('saved', fn)` | Triggered after refresh is complete or after saving. |
75
75
 
76
76
  ---
77
77
 
78
78
  ## Examples
79
79
 
80
- ### Basic get and update
80
+ ### Basic Retrieval and Update
81
81
 
82
82
  ```js
83
83
  ctx.initResource('SingleRecordResource');
@@ -87,27 +87,27 @@ await ctx.resource.refresh();
87
87
  const user = ctx.resource.getData();
88
88
 
89
89
  // Update
90
- await ctx.resource.save({ name: 'Jane' });
90
+ await ctx.resource.save({ name: 'John Doe' });
91
91
  ```
92
92
 
93
- ### Create record
93
+ ### Create New Record
94
94
 
95
95
  ```js
96
96
  const newRes = ctx.makeResource('SingleRecordResource');
97
97
  newRes.setResourceName('users');
98
- await newRes.save({ name: 'Bob', email: 'bob@example.com' });
98
+ await newRes.save({ name: 'Jane Smith', email: 'janesmith@example.com' });
99
99
  ```
100
100
 
101
- ### Delete record
101
+ ### Delete Record
102
102
 
103
103
  ```js
104
104
  ctx.resource.setResourceName('users');
105
105
  ctx.resource.setFilterByTk(1);
106
106
  await ctx.resource.destroy();
107
- // After destroy, getData() is null
107
+ // After destroy, getData() returns null
108
108
  ```
109
109
 
110
- ### Association expansion and fields
110
+ ### Association Loading and Fields
111
111
 
112
112
  ```js
113
113
  ctx.resource.setResourceName('users');
@@ -118,25 +118,25 @@ await ctx.resource.refresh();
118
118
  const user = ctx.resource.getData();
119
119
  ```
120
120
 
121
- ### Association resource (e.g. users.profile)
121
+ ### Association Resources (e.g., users.profile)
122
122
 
123
123
  ```js
124
124
  const res = ctx.makeResource('SingleRecordResource');
125
125
  res.setResourceName('users.profile');
126
126
  res.setSourceId(ctx.record?.id); // Parent record primary key
127
- res.setFilterByTk(profileId); // Can omit filterByTk if profile is hasOne
127
+ res.setFilterByTk(profileId); // filterByTk can be omitted if profile is a hasOne relationship
128
128
  await res.refresh();
129
129
  const profile = res.getData();
130
130
  ```
131
131
 
132
- ### save without auto refresh
132
+ ### Save Without Auto-Refresh
133
133
 
134
134
  ```js
135
135
  await ctx.resource.save({ status: 'active' }, { refresh: false });
136
- // After save, no refresh; getData() keeps previous value
136
+ // getData() retains the old value as refresh is not triggered after saving
137
137
  ```
138
138
 
139
- ### Listen to refresh / saved events
139
+ ### Listening to refresh / saved Events
140
140
 
141
141
  ```js
142
142
  ctx.resource?.on?.('refresh', () => {
@@ -144,7 +144,7 @@ ctx.resource?.on?.('refresh', () => {
144
144
  ctx.render(<div>User: {data?.nickname}</div>);
145
145
  });
146
146
  ctx.resource?.on?.('saved', (savedData) => {
147
- ctx.message.success('Saved');
147
+ ctx.message.success('Saved successfully');
148
148
  });
149
149
  await ctx.resource?.refresh?.();
150
150
  ```
@@ -153,17 +153,17 @@ await ctx.resource?.refresh?.();
153
153
 
154
154
  ## Notes
155
155
 
156
- - **setResourceName required**: Must call `setResourceName('collectionName')` before use; otherwise request URL cannot be built.
157
- - **filterByTk and isNewRecord**: When `setFilterByTk` is not set, `isNewRecord` is true; `refresh()` does not send request; `save()` does create.
158
- - **Association resources**: When resource name is `parent.child` (e.g. `users.profile`), call `setSourceId(parentPrimaryKey)` first.
159
- - **getData is object**: Single record API returns `data` as record object; `getData()` returns that object; after `destroy()` it is null.
156
+ - **setResourceName is Required**: You must call `setResourceName('collectionName')` before use, otherwise the request URL cannot be constructed.
157
+ - **filterByTk and isNewRecord**: If `setFilterByTk` is not called, `isNewRecord` is `true`, and `refresh()` will not initiate a request; `save()` will execute a `create` action.
158
+ - **Association Resources**: When the resource name is in `parent.child` format (e.g., `users.profile`), you must call `setSourceId(parentPrimaryKey)` first.
159
+ - **getData Returns an Object**: The `data` returned by single-record APIs is a record object; `getData()` returns this object directly. It becomes `null` after `destroy()`.
160
160
 
161
161
  ---
162
162
 
163
163
  ## Related
164
164
 
165
- - [ctx.resource](../context/resource.md) - Resource instance in current context
166
- - [ctx.initResource()](../context/init-resource.md) - Initialize and bind to ctx.resource
167
- - [ctx.makeResource()](../context/make-resource.md) - Create resource instance without binding
168
- - [APIResource](./api-resource.md) - Generic API resource, request by URL
169
- - [MultiRecordResource](./multi-record-resource.md) - For data tables/lists, CRUD, pagination
165
+ - [ctx.resource](../context/resource.md) - The resource instance in the current context
166
+ - [ctx.initResource()](../context/init-resource.md) - Initialize and bind to `ctx.resource`
167
+ - [ctx.makeResource()](../context/make-resource.md) - Create a new resource instance without binding
168
+ - [APIResource](./api-resource.md) - General API resource requested by URL
169
+ - [MultiRecordResource](./multi-record-resource.md) - Oriented towards collections/lists, supporting CRUD and pagination
@@ -1,95 +1,95 @@
1
1
  # SQLResource
2
2
 
3
- Resource that runs queries via **saved SQL config** or **dynamic SQL**; data comes from `flowSql:run` / `flowSql:runById`, etc. Use for reports, stats, custom SQL lists. Unlike [MultiRecordResource](./multi-record-resource.md), SQLResource does not depend on data tables and runs SQL directly; supports pagination, parameter binding, template variables (`{{ctx.xxx}}`), and result type control.
3
+ A Resource for executing queries based on **saved SQL configurations** or **dynamic SQL**, with data sourced from interfaces such as `flowSql:run` / `flowSql:runById`. It is suitable for reports, statistics, custom SQL lists, and other scenarios. Unlike [MultiRecordResource](./multi-record-resource.md), SQLResource does not depend on collections; it executes SQL queries directly and supports pagination, parameter binding, template variables (`{{ctx.xxx}}`), and result type control.
4
4
 
5
5
  **Inheritance**: FlowResource → APIResource → BaseRecordResource → SQLResource.
6
6
 
7
- **Create with**: `ctx.makeResource('SQLResource')` or `ctx.initResource('SQLResource')`. For saved-config execution call `setFilterByTk(uid)` (SQL template uid); for debugging use `setDebug(true)` + `setSQL(sql)` to run SQL directly; RunJS injects `ctx.api`.
7
+ **Creation**: `ctx.makeResource('SQLResource')` or `ctx.initResource('SQLResource')`. To execute based on a saved configuration, use `setFilterByTk(uid)` (the UID of the SQL template). For debugging, use `setDebug(true)` + `setSQL(sql)` to execute SQL directly. In RunJS, `ctx.api` is injected by the runtime environment.
8
8
 
9
9
  ---
10
10
 
11
- ## Use cases
11
+ ## Use Cases
12
12
 
13
13
  | Scenario | Description |
14
- |----------|-------------|
15
- | **Reports / stats** | Complex aggregations, cross-table queries, custom metrics |
16
- | **JSBlock custom list** | Use SQL for special filter, sort, or join; render custom UI |
17
- | **Chart block** | Save SQL template to drive chart data source; supports pagination |
18
- | **vs ctx.sql** | Use SQLResource when you need pagination, events, or reactive data; use `ctx.sql.run()` / `ctx.sql.runById()` for simple one-off queries |
14
+ |------|------|
15
+ | **Reports / Statistics** | Complex aggregations, cross-table queries, and custom statistical metrics. |
16
+ | **JSBlock Custom Lists** | Implementing special filtering, sorting, or associations using SQL with custom rendering. |
17
+ | **Chart Blocks** | Driving chart data sources with saved SQL templates, supporting pagination. |
18
+ | **Choosing between SQLResource and ctx.sql** | Use SQLResource when pagination, events, or reactive data are required; use `ctx.sql.run()` / `ctx.sql.runById()` for simple one-off queries. |
19
19
 
20
20
  ---
21
21
 
22
- ## Data format
22
+ ## Data Format
23
23
 
24
24
  - `getData()` returns different formats based on `setSQLType()`:
25
- - `selectRows` (default): **array**, multiple rows
26
- - `selectRow`: **single object**
27
- - `selectVar`: **scalar value** (e.g. COUNT, SUM)
28
- - `getMeta()` returns pagination meta: `page`, `pageSize`, `count`, `totalPage`, etc.
25
+ - `selectRows` (default): **Array**, multiple row results.
26
+ - `selectRow`: **Single object**.
27
+ - `selectVar`: **Scalar value** (e.g., COUNT, SUM).
28
+ - `getMeta()` returns metadata such as pagination: `page`, `pageSize`, `count`, `totalPage`, etc.
29
29
 
30
30
  ---
31
31
 
32
- ## SQL config and execution mode
32
+ ## SQL Configuration and Execution Modes
33
33
 
34
34
  | Method | Description |
35
- |--------|-------------|
36
- | `setFilterByTk(uid)` | SQL template uid to run (for runById; must be saved first) |
37
- | `setSQL(sql)` | Raw SQL (only in debug mode `setDebug(true)` for runBySQL) |
38
- | `setSQLType(type)` | Result type: `'selectVar'` / `'selectRow'` / `'selectRows'` |
39
- | `setDebug(enabled)` | When true, refresh uses `runBySQL()`; otherwise `runById()` |
40
- | `run()` | Calls `runBySQL()` or `runById()` depending on debug |
41
- | `runBySQL()` | Run current `setSQL` SQL (requires setDebug(true)) |
42
- | `runById()` | Run saved SQL template by current uid |
35
+ |------|------|
36
+ | `setFilterByTk(uid)` | Sets the UID of the SQL template to execute (corresponds to `runById`; must be saved in the admin interface first). |
37
+ | `setSQL(sql)` | Sets the raw SQL (used for `runBySQL` only when debug mode `setDebug(true)` is enabled). |
38
+ | `setSQLType(type)` | Result type: `'selectVar'` / `'selectRow'` / `'selectRows'`. |
39
+ | `setDebug(enabled)` | When set to `true`, `refresh` calls `runBySQL()`; otherwise, it calls `runById()`. |
40
+ | `run()` | Calls `runBySQL()` or `runById()` based on the debug state. |
41
+ | `runBySQL()` | Executes using the SQL defined in `setSQL` (requires `setDebug(true)`). |
42
+ | `runById()` | Executes the saved SQL template using the current UID. |
43
43
 
44
44
  ---
45
45
 
46
- ## Params and context
46
+ ## Parameters and Context
47
47
 
48
48
  | Method | Description |
49
- |--------|-------------|
50
- | `setBind(bind)` | Bound variables; object with `:name`, array with `?` |
51
- | `setLiquidContext(ctx)` | Template context (Liquid) for `{{ctx.xxx}}` |
52
- | `setFilter(filter)` | Extra filter (passed in request data) |
53
- | `setDataSourceKey(key)` | Data source key (for multiple data sources) |
49
+ |------|------|
50
+ | `setBind(bind)` | Binds variables. Use an object for `:name` placeholders or an array for `?` placeholders. |
51
+ | `setLiquidContext(ctx)` | Template context (Liquid), used to parse `{{ctx.xxx}}`. |
52
+ | `setFilter(filter)` | Additional filter conditions (passed into the request data). |
53
+ | `setDataSourceKey(key)` | Data source identifier (used for multi-data source environments). |
54
54
 
55
55
  ---
56
56
 
57
57
  ## Pagination
58
58
 
59
59
  | Method | Description |
60
- |--------|-------------|
61
- | `setPage(page)` / `getPage()` | Current page (default 1) |
62
- | `setPageSize(size)` / `getPageSize()` | Page size (default 20) |
63
- | `next()` / `previous()` / `goto(page)` | Change page and trigger refresh |
60
+ |------|------|
61
+ | `setPage(page)` / `getPage()` | Current page (default is 1). |
62
+ | `setPageSize(size)` / `getPageSize()` | Items per page (default is 20). |
63
+ | `next()` / `previous()` / `goto(page)` | Navigates pages and triggers `refresh`. |
64
64
 
65
- Use `{{ctx.limit}}` and `{{ctx.offset}}` in SQL for pagination; SQLResource injects `limit` and `offset` into context.
65
+ In SQL, you can use `{{ctx.limit}}` and `{{ctx.offset}}` to reference pagination parameters. SQLResource injects `limit` and `offset` into the context automatically.
66
66
 
67
67
  ---
68
68
 
69
- ## Data fetch and events
69
+ ## Data Fetching and Events
70
70
 
71
71
  | Method | Description |
72
- |--------|-------------|
73
- | `refresh()` | Run SQL (runById or runBySQL); write result to `setData(data)` and update meta; emit `'refresh'` |
74
- | `runAction(actionName, options)` | Call underlying APIs (e.g. `getBind`, `run`, `runById`) |
75
- | `on('refresh', fn)` / `on('loading', fn)` | Fired when refresh completes or loading starts |
72
+ |------|------|
73
+ | `refresh()` | Executes the SQL (`runById` or `runBySQL`), writes the result to `setData(data)`, updates meta, and triggers the `'refresh'` event. |
74
+ | `runAction(actionName, options)` | Calls underlying actions (e.g., `getBind`, `run`, `runById`). |
75
+ | `on('refresh', fn)` / `on('loading', fn)` | Triggered when refreshing is complete or when loading starts. |
76
76
 
77
77
  ---
78
78
 
79
79
  ## Examples
80
80
 
81
- ### Run by saved template (runById)
81
+ ### Executing via Saved Template (runById)
82
82
 
83
83
  ```js
84
84
  ctx.initResource('SQLResource');
85
- ctx.resource.setFilterByTk('active-users-report'); // Saved SQL template uid
85
+ ctx.resource.setFilterByTk('active-users-report'); // UID of the saved SQL template
86
86
  ctx.resource.setBind({ status: 'active' });
87
87
  await ctx.resource.refresh();
88
88
  const data = ctx.resource.getData();
89
89
  const meta = ctx.resource.getMeta(); // page, pageSize, count, etc.
90
90
  ```
91
91
 
92
- ### Debug mode: run SQL directly (runBySQL)
92
+ ### Debug Mode: Executing SQL Directly (runBySQL)
93
93
 
94
94
  ```js
95
95
  const res = ctx.makeResource('SQLResource');
@@ -100,20 +100,20 @@ await res.refresh();
100
100
  const data = res.getData();
101
101
  ```
102
102
 
103
- ### Pagination and navigation
103
+ ### Pagination and Navigation
104
104
 
105
105
  ```js
106
106
  ctx.resource.setFilterByTk('user-list-sql');
107
107
  ctx.resource.setPageSize(20);
108
108
  await ctx.resource.refresh();
109
109
 
110
- // Navigate pages
110
+ // Navigation
111
111
  await ctx.resource.next();
112
112
  await ctx.resource.previous();
113
113
  await ctx.resource.goto(3);
114
114
  ```
115
115
 
116
- ### Result types
116
+ ### Result Types
117
117
 
118
118
  ```js
119
119
  // Multiple rows (default)
@@ -124,12 +124,12 @@ const rows = ctx.resource.getData(); // [{...}, {...}]
124
124
  ctx.resource.setSQLType('selectRow');
125
125
  const row = ctx.resource.getData(); // {...}
126
126
 
127
- // Single value (e.g. COUNT)
127
+ // Single value (e.g., COUNT)
128
128
  ctx.resource.setSQLType('selectVar');
129
129
  const total = ctx.resource.getData(); // 42
130
130
  ```
131
131
 
132
- ### Use template variables
132
+ ### Using Template Variables
133
133
 
134
134
  ```js
135
135
  ctx.defineProperty('minId', { get: () => 10 });
@@ -139,7 +139,7 @@ res.setSQL('SELECT * FROM users WHERE id > {{ctx.minId}} LIMIT {{ctx.limit}}');
139
139
  await res.refresh();
140
140
  ```
141
141
 
142
- ### Listen to refresh event
142
+ ### Listening to the refresh Event
143
143
 
144
144
  ```js
145
145
  ctx.resource?.on?.('refresh', () => {
@@ -153,18 +153,18 @@ await ctx.resource?.refresh?.();
153
153
 
154
154
  ## Notes
155
155
 
156
- - **runById requires saved template**: `setFilterByTk(uid)` uid must be a saved SQL template ID; save via `ctx.sql.save({ uid, sql })`.
157
- - **Debug mode needs permission**: `setDebug(true)` uses `flowSql:run`; requires SQL config permission. `runById` only needs login.
158
- - **refresh debounce**: Multiple `refresh()` calls in the same event loop only run the last one to avoid duplicate requests.
159
- - **Parameter binding prevents injection**: Use `setBind()` with `:name` / `?` placeholders; avoid string concatenation to prevent SQL injection.
156
+ - **runById requires saving the template first**: The UID used in `setFilterByTk(uid)` must be a SQL template ID already saved in the admin interface. You can save it via `ctx.sql.save({ uid, sql })`.
157
+ - **Debug mode requires permissions**: `setDebug(true)` uses `flowSql:run`, which requires the current role to have SQL configuration permissions. `runById` only requires the user to be logged in.
158
+ - **Refresh Debouncing**: Multiple calls to `refresh()` within the same event loop will only execute the last one to avoid redundant requests.
159
+ - **Parameter Binding for Injection Prevention**: Use `setBind()` with `:name` or `?` placeholders instead of string concatenation to prevent SQL injection.
160
160
 
161
161
  ---
162
162
 
163
163
  ## Related
164
164
 
165
- - [ctx.sql](../context/sql.md) - SQL execution and management; `ctx.sql.runById` for simple one-off queries
166
- - [ctx.resource](../context/resource.md) - Resource instance in current context
167
- - [ctx.initResource()](../context/init-resource.md) - Initialize and bind to ctx.resource
168
- - [ctx.makeResource()](../context/make-resource.md) - Create resource instance without binding
169
- - [APIResource](./api-resource.md) - Generic API resource
170
- - [MultiRecordResource](./multi-record-resource.md) - For data tables/lists
165
+ - [ctx.sql](../context/sql.md) - SQL execution and management; `ctx.sql.runById` is suitable for simple one-off queries.
166
+ - [ctx.resource](../context/resource.md) - The resource instance in the current context.
167
+ - [ctx.initResource()](../context/init-resource.md) - Initializes and binds to `ctx.resource`.
168
+ - [ctx.makeResource()](../context/make-resource.md) - Creates a new resource instance without binding.
169
+ - [APIResource](./api-resource.md) - General API resource.
170
+ - [MultiRecordResource](./multi-record-resource.md) - Designed for collections and lists.
@@ -1,6 +1,6 @@
1
1
  # window
2
2
 
3
- The following are available on `window`:
3
+ The following properties can be accessed directly via `window`:
4
4
 
5
5
  * `setTimeout` / `clearTimeout`
6
6
  * `setInterval` / `clearInterval`
@@ -9,12 +9,12 @@ The following are available on `window`:
9
9
  * `Date`
10
10
  * `FormData`
11
11
  * `addEventListener`
12
- * `open` (only `http:`, `https:`, or `about:blank` allowed)
13
- * `location` (read-only, safe navigation)
12
+ * `open` (Only `http:`, `https:`, or `about:blank` are allowed)
13
+ * `location` (Read-only, supports secure navigation)
14
14
  * `navigator`
15
15
 
16
- Only basic, safe DOM query and creation are supported:
16
+ Only basic and secure DOM query and creation capabilities are supported:
17
17
 
18
18
  * `createElement(tagName)`
19
19
  * `querySelector(selectors)`
20
- * `querySelectorAll(selectors)`
20
+ * `querySelectorAll(selectors)`
@@ -8,15 +8,15 @@
8
8
  */
9
9
 
10
10
  module.exports = {
11
- "@nocobase/client": "2.1.0-alpha.6",
11
+ "@nocobase/client": "2.1.0-alpha.8",
12
12
  "lodash": "4.17.21",
13
- "@nocobase/database": "2.1.0-alpha.6",
14
- "@nocobase/data-source-manager": "2.1.0-alpha.6",
15
- "@nocobase/resourcer": "2.1.0-alpha.6",
16
- "@nocobase/server": "2.1.0-alpha.6",
17
- "@nocobase/utils": "2.1.0-alpha.6",
18
- "@nocobase/cache": "2.1.0-alpha.6",
19
- "@nocobase/plugin-localization": "2.1.0-alpha.6",
20
- "@nocobase/ai": "2.1.0-alpha.6",
21
- "@nocobase/actions": "2.1.0-alpha.6"
13
+ "@nocobase/database": "2.1.0-alpha.8",
14
+ "@nocobase/data-source-manager": "2.1.0-alpha.8",
15
+ "@nocobase/resourcer": "2.1.0-alpha.8",
16
+ "@nocobase/server": "2.1.0-alpha.8",
17
+ "@nocobase/utils": "2.1.0-alpha.8",
18
+ "@nocobase/cache": "2.1.0-alpha.8",
19
+ "@nocobase/plugin-localization": "2.1.0-alpha.8",
20
+ "@nocobase/ai": "2.1.0-alpha.8",
21
+ "@nocobase/actions": "2.1.0-alpha.8"
22
22
  };
@@ -1 +1 @@
1
- {"name":"ses","version":"1.14.0","description":"Hardened JavaScript for Fearless Cooperation","keywords":["lockdown","harden","Compartment","assert","security","confinement","isolation","object capabilities","ocaps","secure execution","third-party code","prototype pollution","supply-chain attack","plugin"],"author":"Agoric","license":"Apache-2.0","homepage":"https://github.com/Agoric/SES-shim/tree/master/packages/ses#readme","repository":{"type":"git","url":"git+https://github.com/endojs/endo.git","directory":"packages/ses"},"bugs":{"url":"https://github.com/endojs/endo/issues"},"type":"module","main":"./dist/ses.cjs","module":"./index.js","unpkg":"./dist/ses.umd.js","types":"./types.d.ts","exports":{".":{"import":{"types":"./types.d.ts","xs":"./src-xs/index.js","default":"./index.js"},"require":{"types":"./dist/types.d.cts","default":"./dist/ses.cjs"}},"./lockdown":{"import":{"types":"./types.d.ts","default":"./index.js"},"require":{"types":"./dist/types.d.cts","default":"./dist/ses.cjs"}},"./hermes":{"require":{"types":"./dist/types.d.cts","default":"./dist/ses-hermes.cjs"}},"./tools.js":"./tools.js","./assert-shim.js":"./assert-shim.js","./lockdown-shim.js":{"xs":"./src-xs/lockdown-shim.js","default":"./lockdown-shim.js"},"./compartment-shim.js":{"xs":"./src-xs/compartment-shim.js","default":"./compartment-shim.js"},"./console-shim.js":"./console-shim.js","./package.json":"./package.json"},"scripts":{"build:vanilla":"node scripts/bundle.js","build:hermes":"node scripts/bundle.js hermes","build":"yarn build:vanilla && yarn build:hermes","clean":"rm -rf dist","cover":"c8 ava","demo":"python3 -m http.server","lint":"yarn lint:types && yarn lint:eslint","lint-fix":"eslint --fix .","lint:eslint":"eslint .","lint:types":"tsc","prepare":"npm run clean && npm run build","qt":"ava","test":"tsd && ava","test:hermes":"./scripts/hermes-test.sh","test:xs":"xst dist/ses.umd.js test/_lockdown-safe.js && node scripts/generate-test-xs.js && xst tmp/test-xs.js && rm -rf tmp","postpack":"git clean -fX \"*.d.ts*\" \"*.d.cts*\" \"*.d.mts*\" \"*.tsbuildinfo\""},"dependencies":{"@endo/cache-map":"^1.1.0","@endo/env-options":"^1.1.11","@endo/immutable-arraybuffer":"^1.1.2"},"devDependencies":{"@babel/generator":"^7.26.3","@babel/parser":"~7.26.2","@babel/traverse":"~7.25.9","@babel/types":"~7.26.0","@endo/compartment-mapper":"^1.6.3","@endo/module-source":"^1.3.3","@endo/test262-runner":"^0.1.48","@types/babel__traverse":"^7.20.5","ava":"^6.1.3","babel-eslint":"^10.1.0","c8":"^7.14.0","core-js":"^3.31.0","eslint":"^8.57.1","eslint-config-airbnb-base":"^15.0.0","eslint-config-prettier":"^9.1.0","eslint-plugin-eslint-comments":"^3.2.0","eslint-plugin-import":"^2.31.0","hermes-engine-cli":"^0.12.0","prettier":"^3.5.3","terser":"^5.16.6","tsd":"^0.31.2","typescript":"~5.8.3"},"files":["./*.d.ts","./*.js","./*.map","LICENSE*","SECURITY*","dist","lib","src","tools"],"publishConfig":{"access":"public"},"eslintConfig":{"extends":["plugin:@endo/ses"]},"ava":{"files":["test/**/*.test.*"],"timeout":"2m"},"typeCoverage":{"atLeast":81.17},"gitHead":"9815aea9541f241389d2135c6097a7442bdffa17","_lastModified":"2026-02-24T16:06:30.228Z"}
1
+ {"name":"ses","version":"1.14.0","description":"Hardened JavaScript for Fearless Cooperation","keywords":["lockdown","harden","Compartment","assert","security","confinement","isolation","object capabilities","ocaps","secure execution","third-party code","prototype pollution","supply-chain attack","plugin"],"author":"Agoric","license":"Apache-2.0","homepage":"https://github.com/Agoric/SES-shim/tree/master/packages/ses#readme","repository":{"type":"git","url":"git+https://github.com/endojs/endo.git","directory":"packages/ses"},"bugs":{"url":"https://github.com/endojs/endo/issues"},"type":"module","main":"./dist/ses.cjs","module":"./index.js","unpkg":"./dist/ses.umd.js","types":"./types.d.ts","exports":{".":{"import":{"types":"./types.d.ts","xs":"./src-xs/index.js","default":"./index.js"},"require":{"types":"./dist/types.d.cts","default":"./dist/ses.cjs"}},"./lockdown":{"import":{"types":"./types.d.ts","default":"./index.js"},"require":{"types":"./dist/types.d.cts","default":"./dist/ses.cjs"}},"./hermes":{"require":{"types":"./dist/types.d.cts","default":"./dist/ses-hermes.cjs"}},"./tools.js":"./tools.js","./assert-shim.js":"./assert-shim.js","./lockdown-shim.js":{"xs":"./src-xs/lockdown-shim.js","default":"./lockdown-shim.js"},"./compartment-shim.js":{"xs":"./src-xs/compartment-shim.js","default":"./compartment-shim.js"},"./console-shim.js":"./console-shim.js","./package.json":"./package.json"},"scripts":{"build:vanilla":"node scripts/bundle.js","build:hermes":"node scripts/bundle.js hermes","build":"yarn build:vanilla && yarn build:hermes","clean":"rm -rf dist","cover":"c8 ava","demo":"python3 -m http.server","lint":"yarn lint:types && yarn lint:eslint","lint-fix":"eslint --fix .","lint:eslint":"eslint .","lint:types":"tsc","prepare":"npm run clean && npm run build","qt":"ava","test":"tsd && ava","test:hermes":"./scripts/hermes-test.sh","test:xs":"xst dist/ses.umd.js test/_lockdown-safe.js && node scripts/generate-test-xs.js && xst tmp/test-xs.js && rm -rf tmp","postpack":"git clean -fX \"*.d.ts*\" \"*.d.cts*\" \"*.d.mts*\" \"*.tsbuildinfo\""},"dependencies":{"@endo/cache-map":"^1.1.0","@endo/env-options":"^1.1.11","@endo/immutable-arraybuffer":"^1.1.2"},"devDependencies":{"@babel/generator":"^7.26.3","@babel/parser":"~7.26.2","@babel/traverse":"~7.25.9","@babel/types":"~7.26.0","@endo/compartment-mapper":"^1.6.3","@endo/module-source":"^1.3.3","@endo/test262-runner":"^0.1.48","@types/babel__traverse":"^7.20.5","ava":"^6.1.3","babel-eslint":"^10.1.0","c8":"^7.14.0","core-js":"^3.31.0","eslint":"^8.57.1","eslint-config-airbnb-base":"^15.0.0","eslint-config-prettier":"^9.1.0","eslint-plugin-eslint-comments":"^3.2.0","eslint-plugin-import":"^2.31.0","hermes-engine-cli":"^0.12.0","prettier":"^3.5.3","terser":"^5.16.6","tsd":"^0.31.2","typescript":"~5.8.3"},"files":["./*.d.ts","./*.js","./*.map","LICENSE*","SECURITY*","dist","lib","src","tools"],"publishConfig":{"access":"public"},"eslintConfig":{"extends":["plugin:@endo/ses"]},"ava":{"files":["test/**/*.test.*"],"timeout":"2m"},"typeCoverage":{"atLeast":81.17},"gitHead":"9815aea9541f241389d2135c6097a7442bdffa17","_lastModified":"2026-03-12T00:54:45.690Z"}
@@ -1 +1 @@
1
- {"name":"zod","version":"4.3.5","type":"module","license":"MIT","author":"Colin McDonnell <zod@colinhacks.com>","description":"TypeScript-first schema declaration and validation library with static type inference","homepage":"https://zod.dev","llms":"https://zod.dev/llms.txt","llmsFull":"https://zod.dev/llms-full.txt","mcpServer":"https://mcp.inkeep.com/zod/mcp","funding":"https://github.com/sponsors/colinhacks","sideEffects":false,"files":["src","**/*.js","**/*.mjs","**/*.cjs","**/*.d.ts","**/*.d.mts","**/*.d.cts","**/package.json"],"keywords":["typescript","schema","validation","type","inference"],"main":"./index.cjs","types":"./index.d.cts","module":"./index.js","zshy":{"exports":{"./package.json":"./package.json",".":"./src/index.ts","./mini":"./src/mini/index.ts","./locales":"./src/locales/index.ts","./v3":"./src/v3/index.ts","./v4":"./src/v4/index.ts","./v4-mini":"./src/v4-mini/index.ts","./v4/mini":"./src/v4/mini/index.ts","./v4/core":"./src/v4/core/index.ts","./v4/locales":"./src/v4/locales/index.ts","./v4/locales/*":"./src/v4/locales/*"},"conditions":{"@zod/source":"src"}},"exports":{"./package.json":"./package.json",".":{"@zod/source":"./src/index.ts","types":"./index.d.cts","import":"./index.js","require":"./index.cjs"},"./mini":{"@zod/source":"./src/mini/index.ts","types":"./mini/index.d.cts","import":"./mini/index.js","require":"./mini/index.cjs"},"./locales":{"@zod/source":"./src/locales/index.ts","types":"./locales/index.d.cts","import":"./locales/index.js","require":"./locales/index.cjs"},"./v3":{"@zod/source":"./src/v3/index.ts","types":"./v3/index.d.cts","import":"./v3/index.js","require":"./v3/index.cjs"},"./v4":{"@zod/source":"./src/v4/index.ts","types":"./v4/index.d.cts","import":"./v4/index.js","require":"./v4/index.cjs"},"./v4-mini":{"@zod/source":"./src/v4-mini/index.ts","types":"./v4-mini/index.d.cts","import":"./v4-mini/index.js","require":"./v4-mini/index.cjs"},"./v4/mini":{"@zod/source":"./src/v4/mini/index.ts","types":"./v4/mini/index.d.cts","import":"./v4/mini/index.js","require":"./v4/mini/index.cjs"},"./v4/core":{"@zod/source":"./src/v4/core/index.ts","types":"./v4/core/index.d.cts","import":"./v4/core/index.js","require":"./v4/core/index.cjs"},"./v4/locales":{"@zod/source":"./src/v4/locales/index.ts","types":"./v4/locales/index.d.cts","import":"./v4/locales/index.js","require":"./v4/locales/index.cjs"},"./v4/locales/*":{"@zod/source":"./src/v4/locales/*","types":"./v4/locales/*","import":"./v4/locales/*","require":"./v4/locales/*"}},"repository":{"type":"git","url":"git+https://github.com/colinhacks/zod.git"},"bugs":{"url":"https://github.com/colinhacks/zod/issues"},"support":{"backing":{"npm-funding":true}},"scripts":{"clean":"git clean -xdf . -e node_modules","build":"zshy --project tsconfig.build.json","postbuild":"tsx ../../scripts/write-stub-package-jsons.ts && pnpm biome check --write .","test:watch":"pnpm vitest","test":"pnpm vitest run","prepublishOnly":"tsx ../../scripts/check-versions.ts"},"_lastModified":"2026-02-24T16:06:29.729Z"}
1
+ {"name":"zod","version":"4.3.5","type":"module","license":"MIT","author":"Colin McDonnell <zod@colinhacks.com>","description":"TypeScript-first schema declaration and validation library with static type inference","homepage":"https://zod.dev","llms":"https://zod.dev/llms.txt","llmsFull":"https://zod.dev/llms-full.txt","mcpServer":"https://mcp.inkeep.com/zod/mcp","funding":"https://github.com/sponsors/colinhacks","sideEffects":false,"files":["src","**/*.js","**/*.mjs","**/*.cjs","**/*.d.ts","**/*.d.mts","**/*.d.cts","**/package.json"],"keywords":["typescript","schema","validation","type","inference"],"main":"./index.cjs","types":"./index.d.cts","module":"./index.js","zshy":{"exports":{"./package.json":"./package.json",".":"./src/index.ts","./mini":"./src/mini/index.ts","./locales":"./src/locales/index.ts","./v3":"./src/v3/index.ts","./v4":"./src/v4/index.ts","./v4-mini":"./src/v4-mini/index.ts","./v4/mini":"./src/v4/mini/index.ts","./v4/core":"./src/v4/core/index.ts","./v4/locales":"./src/v4/locales/index.ts","./v4/locales/*":"./src/v4/locales/*"},"conditions":{"@zod/source":"src"}},"exports":{"./package.json":"./package.json",".":{"@zod/source":"./src/index.ts","types":"./index.d.cts","import":"./index.js","require":"./index.cjs"},"./mini":{"@zod/source":"./src/mini/index.ts","types":"./mini/index.d.cts","import":"./mini/index.js","require":"./mini/index.cjs"},"./locales":{"@zod/source":"./src/locales/index.ts","types":"./locales/index.d.cts","import":"./locales/index.js","require":"./locales/index.cjs"},"./v3":{"@zod/source":"./src/v3/index.ts","types":"./v3/index.d.cts","import":"./v3/index.js","require":"./v3/index.cjs"},"./v4":{"@zod/source":"./src/v4/index.ts","types":"./v4/index.d.cts","import":"./v4/index.js","require":"./v4/index.cjs"},"./v4-mini":{"@zod/source":"./src/v4-mini/index.ts","types":"./v4-mini/index.d.cts","import":"./v4-mini/index.js","require":"./v4-mini/index.cjs"},"./v4/mini":{"@zod/source":"./src/v4/mini/index.ts","types":"./v4/mini/index.d.cts","import":"./v4/mini/index.js","require":"./v4/mini/index.cjs"},"./v4/core":{"@zod/source":"./src/v4/core/index.ts","types":"./v4/core/index.d.cts","import":"./v4/core/index.js","require":"./v4/core/index.cjs"},"./v4/locales":{"@zod/source":"./src/v4/locales/index.ts","types":"./v4/locales/index.d.cts","import":"./v4/locales/index.js","require":"./v4/locales/index.cjs"},"./v4/locales/*":{"@zod/source":"./src/v4/locales/*","types":"./v4/locales/*","import":"./v4/locales/*","require":"./v4/locales/*"}},"repository":{"type":"git","url":"git+https://github.com/colinhacks/zod.git"},"bugs":{"url":"https://github.com/colinhacks/zod/issues"},"support":{"backing":{"npm-funding":true}},"scripts":{"clean":"git clean -xdf . -e node_modules","build":"zshy --project tsconfig.build.json","postbuild":"tsx ../../scripts/write-stub-package-jsons.ts && pnpm biome check --write .","test:watch":"pnpm vitest","test":"pnpm vitest run","prepublishOnly":"tsx ../../scripts/check-versions.ts"},"_lastModified":"2026-03-12T00:54:45.189Z"}
@@ -32,6 +32,7 @@ module.exports = __toCommonJS(flowsql_exports);
32
32
  var import_database = require("@nocobase/database");
33
33
  var flowsql_default = (0, import_database.defineCollection)({
34
34
  name: "flowSql",
35
+ filterTargetKey: "uid",
35
36
  migrationRules: ["overwrite", "schema-only"],
36
37
  fields: [
37
38
  {
package/package.json CHANGED
@@ -4,7 +4,7 @@
4
4
  "displayName.zh-CN": "前端流引擎",
5
5
  "description": "",
6
6
  "description.zh-CN": "",
7
- "version": "2.1.0-alpha.6",
7
+ "version": "2.1.0-alpha.8",
8
8
  "main": "./dist/server/index.js",
9
9
  "license": "Apache-2.0",
10
10
  "devDependencies": {
@@ -24,5 +24,5 @@
24
24
  "@nocobase/test": "2.x",
25
25
  "@nocobase/utils": "2.x"
26
26
  },
27
- "gitHead": "189dc0eb7683a8330db1e4c5fd46ee871b8b4e1f"
27
+ "gitHead": "eda3bfb9df40d4394905e178f1c5331adbec4e76"
28
28
  }