@fui-org/fui-cli 1.3.2 → 2.0.0
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/README.md +19 -3
- package/dist/fui-bmg5pnmq.js +379 -0
- package/dist/fui.js +1 -1
- package/package.json +3 -6
- package/skills/fui/SKILL.md +9 -41
- package/skills/fui-skill/SKILL.md +95 -225
- package/skills/fui-skill/assets/projectdefaultstyle-3.0.css +555 -0
- package/skills/fui-skill/assets/projectdefaultstyle.css +207 -235
- package/skills/fui-skill/references/INDEX.md +105 -137
- package/skills/fui-skill/references/advanced-techniques.md +76 -68
- package/skills/fui-skill/references/coding-standards.md +56 -56
- package/skills/fui-skill/references/component-design.md +166 -173
- package/skills/fui-skill/references/component-quickref.md +61 -60
- package/skills/fui-skill/references/component-table.md +128 -117
- package/skills/fui-skill/references/components-dialog.md +55 -56
- package/skills/fui-skill/references/components-display.md +24 -30
- package/skills/fui-skill/references/components-echart.md +186 -261
- package/skills/fui-skill/references/components-input.md +72 -96
- package/skills/fui-skill/references/controls-patterns.md +196 -342
- package/skills/fui-skill/references/controls-styling-vocabulary.md +130 -97
- package/skills/fui-skill/references/db-table-design.md +24 -28
- package/skills/fui-skill/references/db-workflow.md +191 -390
- package/skills/fui-skill/references/default-function.md +169 -128
- package/skills/fui-skill/references/design-modes.md +35 -63
- package/skills/fui-skill/references/echart-templates.md +204 -196
- package/skills/fui-skill/references/fastproject.md +62 -60
- package/skills/fui-skill/references/fsheet.md +109 -124
- package/skills/fui-skill/references/fullstack-workflow.md +90 -128
- package/skills/fui-skill/references/module-data-patterns.md +31 -40
- package/skills/fui-skill/references/module-json-anatomy.md +47 -52
- package/skills/fui-skill/references/module-structure.md +80 -196
- package/skills/fui-skill/references/new-session.md +49 -51
- package/skills/fui-skill/references/pdfmake.md +17 -17
- package/skills/fui-skill/references/permission-system.md +89 -108
- package/skills/fui-skill/references/platform-architecture.md +128 -153
- package/skills/fui-skill/references/project-config.md +102 -134
- package/skills/fui-skill/references/project-provisioning.md +139 -244
- package/skills/fui-skill/references/script-map.md +208 -242
- package/skills/fui-skill/references/sql-clr-functions.md +98 -97
- package/skills/fui-skill/references/system-design.md +63 -88
- package/skills/fui-skill/references/tapi-file-api.md +46 -52
- package/skills/fui-skill/references/tapi-permission-patterns.md +51 -53
- package/skills/fui-skill/references/tapi-reference.md +132 -207
- package/skills/fui-skill/references/tools-registry.md +84 -460
- package/skills/fui-skill/references/ui-crosswindow-patterns.md +79 -75
- package/skills/fui-skill/references/ui-dialog-patterns.md +98 -72
- package/skills/fui-skill/references/ui-layout-patterns.md +26 -26
- package/skills/fui-skill/references/ui-patterns.md +71 -83
- package/skills/fui-skill/references/ui-screenshot-review.md +63 -62
- package/skills/fui-skill/references/ui-table-cell-patterns.md +61 -59
- package/skills/fui-skill/references/ui-templates.md +16 -23
- package/skills/fui-skill/references/verification.md +236 -246
- package/skills/fui-skill/references/watcher-patterns.md +30 -63
- package/skills/fui-skill/references/websocket-realtime.md +83 -66
- package/skills/fui-skill/scripts/component-3.0.js +298 -131
- package/skills/fui-skill/scripts/component.js +277 -271
- package/skills/fui-skill/scripts/componentTable-3.0.js +182 -53
- package/skills/fui-skill/scripts/componentTable.js +171 -49
- package/skills/fui-skill/scripts/defaultfunction-3.0.js +88 -3
- package/skills/fui-skill/scripts/defaultfunction.js +88 -3
- package/skills/fui-skill/scripts/fsheet.js +38 -0
- package/dist/fui-y8an39cn.js +0 -420
- package/skills/fui-skill/README.md +0 -112
- package/skills/fui-skill/metadata.json +0 -75
- package/skills/fui-skill-cli/SKILL.md +0 -139
- package/skills/fui-skill-cli/references/INDEX.md +0 -110
- package/skills/fui-skill-cli/references/advanced-techniques.md +0 -168
- package/skills/fui-skill-cli/references/coding-standards.md +0 -112
- package/skills/fui-skill-cli/references/component-design.md +0 -448
- package/skills/fui-skill-cli/references/component-quickref.md +0 -78
- package/skills/fui-skill-cli/references/component-table.md +0 -248
- package/skills/fui-skill-cli/references/components-dialog.md +0 -191
- package/skills/fui-skill-cli/references/components-display.md +0 -141
- package/skills/fui-skill-cli/references/components-echart.md +0 -316
- package/skills/fui-skill-cli/references/components-input.md +0 -335
- package/skills/fui-skill-cli/references/controls-patterns.md +0 -701
- package/skills/fui-skill-cli/references/controls-styling-vocabulary.md +0 -137
- package/skills/fui-skill-cli/references/db-table-design.md +0 -73
- package/skills/fui-skill-cli/references/db-workflow.md +0 -288
- package/skills/fui-skill-cli/references/default-function.md +0 -425
- package/skills/fui-skill-cli/references/design-modes.md +0 -57
- package/skills/fui-skill-cli/references/echart-templates.md +0 -489
- package/skills/fui-skill-cli/references/fastproject.md +0 -99
- package/skills/fui-skill-cli/references/fsheet.md +0 -203
- package/skills/fui-skill-cli/references/fullstack-workflow.md +0 -313
- package/skills/fui-skill-cli/references/module-data-patterns.md +0 -117
- package/skills/fui-skill-cli/references/module-json-anatomy.md +0 -132
- package/skills/fui-skill-cli/references/module-structure.md +0 -141
- package/skills/fui-skill-cli/references/new-session.md +0 -85
- package/skills/fui-skill-cli/references/pdfmake.md +0 -60
- package/skills/fui-skill-cli/references/permission-system.md +0 -150
- package/skills/fui-skill-cli/references/platform-architecture.md +0 -269
- package/skills/fui-skill-cli/references/project-config.md +0 -303
- package/skills/fui-skill-cli/references/project-provisioning.md +0 -278
- package/skills/fui-skill-cli/references/script-map.md +0 -262
- package/skills/fui-skill-cli/references/sql-clr-functions.md +0 -225
- package/skills/fui-skill-cli/references/system-design.md +0 -89
- package/skills/fui-skill-cli/references/tapi-file-api.md +0 -185
- package/skills/fui-skill-cli/references/tapi-permission-patterns.md +0 -156
- package/skills/fui-skill-cli/references/tapi-reference.md +0 -474
- package/skills/fui-skill-cli/references/tools-registry.md +0 -84
- package/skills/fui-skill-cli/references/ui-crosswindow-patterns.md +0 -321
- package/skills/fui-skill-cli/references/ui-dialog-patterns.md +0 -255
- package/skills/fui-skill-cli/references/ui-layout-patterns.md +0 -176
- package/skills/fui-skill-cli/references/ui-patterns.md +0 -303
- package/skills/fui-skill-cli/references/ui-screenshot-review.md +0 -95
- package/skills/fui-skill-cli/references/ui-table-cell-patterns.md +0 -318
- package/skills/fui-skill-cli/references/ui-templates.md +0 -22
- package/skills/fui-skill-cli/references/verification.md +0 -236
- package/skills/fui-skill-cli/references/watcher-patterns.md +0 -163
- package/skills/fui-skill-cli/references/websocket-realtime.md +0 -271
|
@@ -1,474 +0,0 @@
|
|
|
1
|
-
# tAPI Reference — Transparent Query API (Core)
|
|
2
|
-
|
|
3
|
-
> Owns: **tAPI conventions: SP naming (`spAPI_*`/`spAPI_AUTH_*`/`spAPIFILE_*`), params, URL, response contract, `/help` route**. Deploy workflow: [db-workflow.md](db-workflow.md).
|
|
4
|
-
|
|
5
|
-
tAPI auto-generates APIs from SQL SPs; the SP name sets URL, auth type and access (no controllers/routes). Accepts **GET and POST** — don't specify a method in the SP; module.json picks it. Load as needed:
|
|
6
|
-
|
|
7
|
-
| Topic | File |
|
|
8
|
-
| ------------------------------------------------------------------------------- | ---------------------------------------------------------- |
|
|
9
|
-
| Permission checks in SP body (5 patterns, `@sys_SystemRight`, `getSystemRight`) | [tapi-permission-patterns.md](tapi-permission-patterns.md) |
|
|
10
|
-
| File API — GET/UPLOAD, `spAPIFILE_`, `fileContent`, `tblFileData` | [tapi-file-api.md](tapi-file-api.md) |
|
|
11
|
-
|
|
12
|
-
> Image processing, outbound HTTP, email, server file I/O, regex → first check for an existing **SQL CLR function** (`httpCall`, `sendMail`, `ImageResize`, `FileWriter`, `RegexMatch`...): [sql-clr-functions.md](sql-clr-functions.md).
|
|
13
|
-
|
|
14
|
-
## 1. SP naming
|
|
15
|
-
|
|
16
|
-
```
|
|
17
|
-
spAPI_[AUTH_]FunctionName
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
| Part | Required | Meaning |
|
|
21
|
-
| -------------- | -------- | ---------------------------------------------------------------- |
|
|
22
|
-
| `spAPI_` | ✅ | Marks SP as API-callable. Missing → API cannot call it |
|
|
23
|
-
| `AUTH_` | ❌ | No auth required. Omitted → valid token mandatory |
|
|
24
|
-
| `FunctionName` | ✅ | API function name used in URL, e.g. `MessageHome`, `UserSetting` |
|
|
25
|
-
|
|
26
|
-
```sql
|
|
27
|
-
spAPI_MessageHome -- có auth
|
|
28
|
-
spAPI_AUTH_SelectChat -- không cần auth
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
File API:
|
|
32
|
-
|
|
33
|
-
```
|
|
34
|
-
spAPIFILE_Document -- SP để GET file
|
|
35
|
-
spAPIFILE_UPLOAD_Document -- SP để nhận file upload
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
Details: [tapi-file-api.md](tapi-file-api.md).
|
|
39
|
-
|
|
40
|
-
---
|
|
41
|
-
|
|
42
|
-
## 2. SP parameters
|
|
43
|
-
|
|
44
|
-
### `@url1_`, `@url2_`, `@url3_`... — route params
|
|
45
|
-
|
|
46
|
-
Taken from URL segments in order:
|
|
47
|
-
|
|
48
|
-
```
|
|
49
|
-
https://api.domain.vn/app/FunctionName/value1/value2
|
|
50
|
-
```
|
|
51
|
-
|
|
52
|
-
```sql
|
|
53
|
-
@url1_GroupID varchar(50), -- nhận "value1"
|
|
54
|
-
@url2_Mode varchar(50), -- nhận "value2"
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
### `@sys_` — system params (injected by tAPI, never sent by client)
|
|
58
|
-
|
|
59
|
-
| Param | Type | Meaning |
|
|
60
|
-
| -------------------------- | ------------- | ------------------------------------------------------------------------------------------------------------ |
|
|
61
|
-
| `@sys_UserID` | varchar(9) | Authenticated user ID |
|
|
62
|
-
| `@sys_UserName` | varchar(50) | Login name |
|
|
63
|
-
| `@sys_GroupID` | int | User's group |
|
|
64
|
-
| `@sys_DepartmentID` | varchar(9) | Department ID |
|
|
65
|
-
| `@sys_SystemRight` | int | Tiered right (1=low, 9=high) |
|
|
66
|
-
| `@sys_FunctionRight` | varchar(2000) | Function rights as `[AD][RPT][MGR]` |
|
|
67
|
-
| `@sys_SessionID` | varchar(50) | Auth session ID |
|
|
68
|
-
| `@sys_RawData` | nvarchar(max) | Full client JSON body |
|
|
69
|
-
| `@sys_header_{HeaderName}` | varchar(n) | **A family, not one fixed name** — reads any HTTP header; `NULL` if client didn't send it. Naming rule below |
|
|
70
|
-
|
|
71
|
-
> **CRITICAL — never put `@sys_` in module.json `IN`.** tAPI fills all `@sys_*` from the session; client values are **ignored or overwritten**.
|
|
72
|
-
>
|
|
73
|
-
> ```json
|
|
74
|
-
> // ❌ SAI — không đưa sys_ vào IN
|
|
75
|
-
> "IN": { "ModuleID": "sModuleID", "sys_UserID": "vueData.user.UserID" }
|
|
76
|
-
>
|
|
77
|
-
> // ✅ ĐÚNG — chỉ truyền custom params
|
|
78
|
-
> "IN": { "ModuleID": "sModuleID" }
|
|
79
|
-
> ```
|
|
80
|
-
|
|
81
|
-
#### `@sys_header_*` — read HTTP headers: replace each `-` with `_`
|
|
82
|
-
|
|
83
|
-
Works for **any** header. `-` is invalid in SQL Server param names, so the literal name won't compile:
|
|
84
|
-
|
|
85
|
-
```sql
|
|
86
|
-
-- ❌ SAI — lỗi cú pháp ngay lúc CREATE PROCEDURE, không phải lỗi runtime
|
|
87
|
-
@sys_header_User-Agent varchar(500)
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
- **No quoting works**: `@[sys_header_User-Agent]` and `@"sys_header_User-Agent"` are both invalid. Renaming is the **only** way.
|
|
91
|
-
- **Each `-` → one `_`.** 1-to-1: don't drop characters, change case, or merge segments.
|
|
92
|
-
|
|
93
|
-
| HTTP header | SP param |
|
|
94
|
-
| ------------------ | ---------------------------------------- |
|
|
95
|
-
| `User-Agent` | `@sys_header_User_Agent` |
|
|
96
|
-
| `Sec-Ch-Ua-Mobile` | `@sys_header_Sec_Ch_Ua_Mobile` |
|
|
97
|
-
| `X-Forwarded-For` | `@sys_header_X_Forwarded_For` |
|
|
98
|
-
| `Accept-Language` | `@sys_header_Accept_Language` |
|
|
99
|
-
| `Cookie` | `@sys_header_Cookie` — no `-`, unchanged |
|
|
100
|
-
|
|
101
|
-
- Reverse (reading an existing SP): drop `@sys_header_`, turn remaining `_` into `-` — `@sys_header_Accept_Language` → `Accept-Language`.
|
|
102
|
-
- Matching is **case-insensitive** (prefix and name): `@sys_header_User_Agent`, `@sys_Header_User_Agent`, `@sys_header_USER_AGENT` are the same header (so `@sys_Header_RequestID` works). Still use standard casing (`User-Agent`, not `USER_AGENT`). Only `_` for `-` is mandatory.
|
|
103
|
-
|
|
104
|
-
```sql
|
|
105
|
-
CREATE PROCEDURE spAPI_AuditLog_Insert
|
|
106
|
-
@Action nvarchar(100),
|
|
107
|
-
@sys_UserID varchar(9),
|
|
108
|
-
@sys_header_User_Agent nvarchar(500),
|
|
109
|
-
@sys_header_X_Forwarded_For varchar(200)
|
|
110
|
-
AS
|
|
111
|
-
BEGIN
|
|
112
|
-
-- ISNULL vì client không gửi header thì tham số là NULL, không phải chuỗi rỗng
|
|
113
|
-
INSERT INTO tblAuditLog (Action, UserID, UserAgent, ClientIP, CreateTime)
|
|
114
|
-
VALUES (@Action, @sys_UserID,
|
|
115
|
-
ISNULL(@sys_header_User_Agent, N'(không có)'),
|
|
116
|
-
ISNULL(@sys_header_X_Forwarded_For, ''),
|
|
117
|
-
GETDATE());
|
|
118
|
-
END
|
|
119
|
-
```
|
|
120
|
-
|
|
121
|
-
- **Still `@sys_*`:** auto-filled, **not** in `IN`, **no default** (`= null` is a hard error; `fui sp deploy` blocks it, see below).
|
|
122
|
-
- **Missing header → `NULL`** (not `''`) — normal, e.g. script/server-to-server calls often lack `User-Agent`. Wrap in `ISNULL(...)` at use: comparisons give UNKNOWN (`WHERE @sys_header_User_Agent <> 'bot'` **drops** the row), and `+` concatenation gives `NULL` (blanks the whole log string).
|
|
123
|
-
- **Untrusted (client-supplied, spoofable).** Log/stats only, never authorization; take rights from `@sys_UserID`/`@sys_SystemRight` (from the verified token).
|
|
124
|
-
|
|
125
|
-
Check the name tAPI sees: `fui sp help <name>` (§3.1).
|
|
126
|
-
|
|
127
|
-
### Custom params — business params
|
|
128
|
-
|
|
129
|
-
Param name = JSON body field name:
|
|
130
|
-
|
|
131
|
-
```sql
|
|
132
|
-
@StudentID varchar(9),
|
|
133
|
-
@SemesterID int,
|
|
134
|
-
@Keyword nvarchar(200)
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
#### Param binding is LENIENT — never errors
|
|
138
|
-
|
|
139
|
-
- Body **lacks** a key → param gets **`NULL`**. Body has an **extra** key → **silently ignored**.
|
|
140
|
-
- A typo in `IN` (`StudentId` vs `StudentID`) → SP gets `NULL`, empty/wrong data, HTTP 200. Most common silent wiring bug.
|
|
141
|
-
- **Renaming/removing an SP param is a contract change with NO signal**: old modules keep sending old keys. Audit callers or compare with `fui sp help <name>` (§3.1).
|
|
142
|
-
- **`NULL` follows T-SQL rules** (`<>` → UNKNOWN drops rows; `+` → `NULL`): wrap possibly-absent params in `ISNULL(...)` at use.
|
|
143
|
-
|
|
144
|
-
> **CRITICAL — no default value on any param** (`= value` or `= null`, including `@sys_*`). tAPI **always passes every param** (`NULL` if not sent), so `@HeID int = 99` silently gives `NULL`, not `99`. `fui sp deploy` hard-blocks it for `spAPI_*`/`spAPIFILE_*` (`detectDefaultApiParams()` in `src/tools/db.ts`); `fui sp verify` warns earlier. Set defaults **in the body**: `SET @HeID = ISNULL(@HeID, 99)`.
|
|
145
|
-
>
|
|
146
|
-
> ```sql
|
|
147
|
-
> -- ❌ SAI
|
|
148
|
-
> CREATE PROCEDURE spAPI_TS_Report
|
|
149
|
-
> @HeID int = 99,
|
|
150
|
-
> @NamHoc int = 2024,
|
|
151
|
-
> @sys_UserID varchar(9) = null,
|
|
152
|
-
> @sys_SystemRight int
|
|
153
|
-
>
|
|
154
|
-
> -- ✅ ĐÚNG
|
|
155
|
-
> CREATE PROCEDURE spAPI_TS_Report
|
|
156
|
-
> @HeID int,
|
|
157
|
-
> @NamHoc int,
|
|
158
|
-
> @sys_UserID varchar(9),
|
|
159
|
-
> @sys_SystemRight int
|
|
160
|
-
> ```
|
|
161
|
-
|
|
162
|
-
Client sends: `POST /app/FunctionName` with body `{ "StudentID": "SV001", "SemesterID": 1 }`
|
|
163
|
-
|
|
164
|
-
---
|
|
165
|
-
|
|
166
|
-
## 3. API URL
|
|
167
|
-
|
|
168
|
-
```
|
|
169
|
-
{domain}/{apiName}/{FunctionName}/{url1}/{url2}...
|
|
170
|
-
{domain}/{apiName}/auth/{FunctionName}/{url1}/{url2}...
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
| Part | Meaning |
|
|
174
|
-
| ----------------- | --------------------------------------------------------------------------------------------------------------- |
|
|
175
|
-
| `domain` | API domain, e.g. `https://api.example.vn` |
|
|
176
|
-
| `apiName` | App apiName: `me`, `congvan`, `calen`... — also the **DB connection alias** in the workspace (`_db/{apiName}/`) |
|
|
177
|
-
| `auth` | Add when SP has `AUTH_` (no token) |
|
|
178
|
-
| `FunctionName` | SP name after the prefix |
|
|
179
|
-
| `url1`, `url2`... | Route params for `@url1_`, `@url2_` |
|
|
180
|
-
|
|
181
|
-
**A project can have MANY `apiName`s** (one DB alias each). `"API": "/{alias}/Ten"` in module.json names the SP's database; fui uses that alias for `_db/{alias}/` and as `--db` of DB commands ([db-workflow.md](db-workflow.md) §1, §4).
|
|
182
|
-
|
|
183
|
-
```
|
|
184
|
-
SP: spAPI_AUTH_Select_Chat
|
|
185
|
-
URL: https://api.example.vn/me/auth/Select_Chat
|
|
186
|
-
|
|
187
|
-
SP: spAPI_GetStudentList
|
|
188
|
-
URL: https://api.example.vn/me/GetStudentList
|
|
189
|
-
|
|
190
|
-
SP: spAPI_GetStudentDetail (@url1_StudentID)
|
|
191
|
-
URL: https://api.example.vn/me/GetStudentDetail/SV001
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
> **CRITICAL — common bug: missing `/` between `domain` and `apiName`.** `domain` NEVER ends with `/`; insert exactly ONE `/` before `apiName`.
|
|
195
|
-
>
|
|
196
|
-
> ```
|
|
197
|
-
> domain=tapi.lhu.edu.vn, apiName=ts, function=TS_Report_HeXetTuyenSelectAll
|
|
198
|
-
>
|
|
199
|
-
> ❌ SAI (thiếu /, "ts" bị nuốt vào domain): https://tapi.lhu.edu.vnts/TS_Report_HeXetTuyenSelectAll
|
|
200
|
-
> ✅ ĐÚNG: https://tapi.lhu.edu.vn/ts/TS_Report_HeXetTuyenSelectAll
|
|
201
|
-
> ```
|
|
202
|
-
>
|
|
203
|
-
> **Don't build URLs by hand/memory** — copy the `Wiring URL: ...` line from `fui sp verify` (or `fui sp help`) verbatim.
|
|
204
|
-
|
|
205
|
-
### 3.1 Param cache & `/help` route
|
|
206
|
-
|
|
207
|
-
tAPI **caches each function's param signature** after the first call. After ALTERing a `spAPI_*`/`spAPIFILE_*` SP's params (add/remove/rename/retype), the live endpoint keeps the **old** signature until cleared. Route = API URL with `/help` right after domain:
|
|
208
|
-
|
|
209
|
-
```
|
|
210
|
-
{domain}/help/{apiName}/{FunctionName} ← xoá cache + trả về tham số của hàm
|
|
211
|
-
{domain}/help/{apiName}/auth/{FunctionName}
|
|
212
|
-
```
|
|
213
|
-
|
|
214
|
-
It **(a) clears the cache** and **(b) returns the input params** (useful before wiring `IN`).
|
|
215
|
-
|
|
216
|
-
**Mandatory after every SP ALTER/UPDATE** (else old signature → param errors even with a correct SP):
|
|
217
|
-
|
|
218
|
-
- `fui sp deploy` auto-calls `/help` **once, standard URL; ignore failure** (SP is already deployed).
|
|
219
|
-
- `ALTER PROCEDURE` via `fui exec`: **no auto-clear → run `fui sp help` manually** right after. The only manual case.
|
|
220
|
-
- **`/help` errors → STOP, no URL variants.** `/auth/` or not follows from the SP name; retrying changes nothing. Re-run `fui sp help` only if the live endpoint truly still takes old params.
|
|
221
|
-
|
|
222
|
-
---
|
|
223
|
-
|
|
224
|
-
## 4. Response format
|
|
225
|
-
|
|
226
|
-
### 4.1 One SELECT → array
|
|
227
|
-
|
|
228
|
-
```sql
|
|
229
|
-
SELECT StudentID, FullName, GPA FROM tblStudent WHERE ClassID = @ClassID
|
|
230
|
-
```
|
|
231
|
-
|
|
232
|
-
```json
|
|
233
|
-
{
|
|
234
|
-
"data": [
|
|
235
|
-
{ "StudentID": "SV001", "FullName": "Nguyen Van A", "GPA": 3.5 },
|
|
236
|
-
{ "StudentID": "SV002", "FullName": "Tran Thi B", "GPA": 3.2 }
|
|
237
|
-
]
|
|
238
|
-
}
|
|
239
|
-
```
|
|
240
|
-
|
|
241
|
-
### 4.2 Multiple SELECTs → array of arrays
|
|
242
|
-
|
|
243
|
-
Each `SELECT` becomes one sub-array in `data`:
|
|
244
|
-
|
|
245
|
-
```sql
|
|
246
|
-
SELECT TotalCount = COUNT(*) FROM tblStudent WHERE ClassID = @ClassID
|
|
247
|
-
SELECT StudentID, FullName FROM tblStudent WHERE ClassID = @ClassID
|
|
248
|
-
```
|
|
249
|
-
|
|
250
|
-
```json
|
|
251
|
-
{
|
|
252
|
-
"data": [
|
|
253
|
-
[{ "TotalCount": 42 }],
|
|
254
|
-
[
|
|
255
|
-
{ "StudentID": "SV001", "FullName": "Nguyen Van A" },
|
|
256
|
-
{ "StudentID": "SV002", "FullName": "Tran Thi B" }
|
|
257
|
-
]
|
|
258
|
-
]
|
|
259
|
-
}
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
In module.json, read sub-arrays by index:
|
|
263
|
-
|
|
264
|
-
```json
|
|
265
|
-
"OUT": "studentList",
|
|
266
|
-
"CALLBACK": { "EXE": "vueData.total = vueData.studentList[0][0].TotalCount; vueData.students = vueData.studentList[1]" }
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
### 4.3 `convert_to_object` — row → object
|
|
270
|
-
|
|
271
|
-
Returns an object instead of an array. **Many SELECTs** may use it; all merge into one response object.
|
|
272
|
-
|
|
273
|
-
> ⚠️ When a SELECT has `convert_to_object` **and** a `json_data` column with a JSON string, it must return **exactly 1 row**. More than 1 → tAPI returns `{}`.
|
|
274
|
-
|
|
275
|
-
- `convert_to_object = 'key'` → nested object under that key
|
|
276
|
-
- `convert_to_object = ''` → merged into root
|
|
277
|
-
|
|
278
|
-
**Ex 1 — named key + root merge:**
|
|
279
|
-
|
|
280
|
-
```sql
|
|
281
|
-
SELECT convert_to_object = 'sinhvien',
|
|
282
|
-
sys_SystemRight = @sys_SystemRight,
|
|
283
|
-
sys_FunctionRight = @sys_FunctionRight
|
|
284
|
-
|
|
285
|
-
SELECT convert_to_object = '',
|
|
286
|
-
ngaythang = GETDATE(), count = 10
|
|
287
|
-
```
|
|
288
|
-
|
|
289
|
-
```json
|
|
290
|
-
{
|
|
291
|
-
"sinhvien": {
|
|
292
|
-
"sys_SystemRight": 9,
|
|
293
|
-
"sys_FunctionRight": "[11][3]"
|
|
294
|
-
},
|
|
295
|
-
"ngaythang": "2018-09-11T11:20:47.397",
|
|
296
|
-
"count": 10
|
|
297
|
-
}
|
|
298
|
-
```
|
|
299
|
-
|
|
300
|
-
**Ex 2 — `json_data` overrides same-name fields** (parsed and merged after SQL columns, so `json_data` wins, e.g. `ProjectName`):
|
|
301
|
-
|
|
302
|
-
```sql
|
|
303
|
-
SELECT convert_to_object = '',
|
|
304
|
-
ProjectName = N'abc',
|
|
305
|
-
stt = 123,
|
|
306
|
-
json_data = '{"ProjectName":"T-A-P-I","menu":[{"name":"Croatia","link":"vn"},{"name":"England","link":"/tuyensinh"}]}'
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
```json
|
|
310
|
-
{
|
|
311
|
-
"ProjectName": "T-A-P-I",
|
|
312
|
-
"stt": 123,
|
|
313
|
-
"menu": [
|
|
314
|
-
{ "name": "Croatia", "link": "vn" },
|
|
315
|
-
{ "name": "England", "link": "/tuyensinh" }
|
|
316
|
-
]
|
|
317
|
-
}
|
|
318
|
-
```
|
|
319
|
-
|
|
320
|
-
**Ex 3 — multiple `convert_to_object = ''` SELECTs all merge into root:**
|
|
321
|
-
|
|
322
|
-
```sql
|
|
323
|
-
SELECT convert_to_object = '',
|
|
324
|
-
ProjectName = N'abc', stt = 123,
|
|
325
|
-
json_data = '{"ProjectName":"T-A-P-I","menu":[{"name":"Croatia","link":"vn"},{"name":"England","link":"/tuyensinh"}]}'
|
|
326
|
-
|
|
327
|
-
SELECT convert_to_object = '',
|
|
328
|
-
TruyVan2 = N'Dữ liệu của truy vấn 2',
|
|
329
|
-
json_data = '{"TruyVan2_json_string": 99}'
|
|
330
|
-
```
|
|
331
|
-
|
|
332
|
-
```json
|
|
333
|
-
{
|
|
334
|
-
"ProjectName": "T-A-P-I",
|
|
335
|
-
"stt": 123,
|
|
336
|
-
"menu": [
|
|
337
|
-
{ "name": "Croatia", "link": "vn" },
|
|
338
|
-
{ "name": "England", "link": "/tuyensinh" }
|
|
339
|
-
],
|
|
340
|
-
"TruyVan2": "Dữ liệu của truy vấn 2",
|
|
341
|
-
"TruyVan2_json_string": 99
|
|
342
|
-
}
|
|
343
|
-
```
|
|
344
|
-
|
|
345
|
-
### 4.4 `[json_data:FieldName]` — JSON string column → object
|
|
346
|
-
|
|
347
|
-
Return a JSON-string column as an object:
|
|
348
|
-
|
|
349
|
-
```sql
|
|
350
|
-
SELECT PartID, PartName, [json_data:FileInfo] = FileInfo
|
|
351
|
-
FROM tblPart WHERE PartID = @url1_PartID
|
|
352
|
-
```
|
|
353
|
-
|
|
354
|
-
tAPI parses it into a nested object:
|
|
355
|
-
|
|
356
|
-
```json
|
|
357
|
-
{
|
|
358
|
-
"PartID": "P001",
|
|
359
|
-
"PartName": "Tài liệu",
|
|
360
|
-
"FileInfo": { "fileName": "doc.pdf", "size": 1024 }
|
|
361
|
-
}
|
|
362
|
-
```
|
|
363
|
-
|
|
364
|
-
DB column stays a string. Name after `:` = response field; after `=` = real column.
|
|
365
|
-
|
|
366
|
-
---
|
|
367
|
-
|
|
368
|
-
## 5. Error handling in SP
|
|
369
|
-
|
|
370
|
-
All errors use `RAISERROR` with severity **16**.
|
|
371
|
-
|
|
372
|
-
### Normal errors (validation, data constraints)
|
|
373
|
-
|
|
374
|
-
```sql
|
|
375
|
-
RAISERROR(N'Dữ liệu không hợp lệ', 16, 1)
|
|
376
|
-
RETURN
|
|
377
|
-
```
|
|
378
|
-
|
|
379
|
-
```json
|
|
380
|
-
{ "Message": "Dữ liệu không hợp lệ" }
|
|
381
|
-
```
|
|
382
|
-
|
|
383
|
-
### Unauthorized — prefix `[Unauthorized]` → HTTP 401
|
|
384
|
-
|
|
385
|
-
```sql
|
|
386
|
-
IF @sys_SystemRight < 2
|
|
387
|
-
BEGIN
|
|
388
|
-
RAISERROR(N'[Unauthorized]Bạn không có quyền trên chức năng này.', 16, 1)
|
|
389
|
-
RETURN
|
|
390
|
-
END
|
|
391
|
-
```
|
|
392
|
-
|
|
393
|
-
```json
|
|
394
|
-
{ "Message": "Bạn không có quyền trên chức năng này." }
|
|
395
|
-
```
|
|
396
|
-
|
|
397
|
-
**Mandatory:**
|
|
398
|
-
|
|
399
|
-
- Always severity `16` — never `11`, `14` or anything else.
|
|
400
|
-
- Always `RETURN` right after `RAISERROR`.
|
|
401
|
-
- `N` prefix required for Vietnamese Unicode.
|
|
402
|
-
- **Every permission error (missing `SystemRight`/`FunctionRight`) must start with `[Unauthorized]`** → HTTP `401` instead of `200`/`500`; client `errorMess()` (`fastproject.js`) redirects to login if message contains "token", else shows a permission error. tAPI strips the prefix from `Message`. Validation errors **don't** use it.
|
|
403
|
-
|
|
404
|
-
> Detailed permission checks (5 patterns, `getSystemRight`, check order, message conventions): [tapi-permission-patterns.md](tapi-permission-patterns.md).
|
|
405
|
-
|
|
406
|
-
---
|
|
407
|
-
|
|
408
|
-
## 6. SP design rules
|
|
409
|
-
|
|
410
|
-
### Naming
|
|
411
|
-
|
|
412
|
-
```
|
|
413
|
-
spAPI_{Entity}{Action}
|
|
414
|
-
```
|
|
415
|
-
|
|
416
|
-
| Action | Meaning |
|
|
417
|
-
| ------------------- | ----------------------- |
|
|
418
|
-
| `Select` / `List` | List query |
|
|
419
|
-
| `Get` | One record's detail |
|
|
420
|
-
| `Insert` / `Add` | Create |
|
|
421
|
-
| `Update` / `Edit` | Update |
|
|
422
|
-
| `Delete` / `Remove` | Delete |
|
|
423
|
-
| `AUTH_Select` | Public query (no token) |
|
|
424
|
-
|
|
425
|
-
```sql
|
|
426
|
-
spAPI_StudentList -- GET danh sách sinh viên
|
|
427
|
-
spAPI_StudentGet -- GET chi tiết (url1 = StudentID)
|
|
428
|
-
spAPI_StudentInsert -- POST thêm mới
|
|
429
|
-
spAPI_StudentUpdate -- POST cập nhật
|
|
430
|
-
spAPI_StudentDelete -- POST xoá (url1 = StudentID)
|
|
431
|
-
spAPI_AUTH_CourseList -- Danh sách môn học công khai
|
|
432
|
-
```
|
|
433
|
-
|
|
434
|
-
### Wiring in FUI module.json
|
|
435
|
-
|
|
436
|
-
```json
|
|
437
|
-
"fetchStudents": {
|
|
438
|
-
"API": "/me/StudentList",
|
|
439
|
-
"IN": { "Keyword": "vueData.keyword", "ClassID": "vueData.selectedClass" },
|
|
440
|
-
"OUT": "studentList"
|
|
441
|
-
},
|
|
442
|
-
"addStudent": {
|
|
443
|
-
"API": "/me/StudentInsert",
|
|
444
|
-
"IN": {
|
|
445
|
-
"StudentID": "vueData.form.StudentID",
|
|
446
|
-
"FullName": "vueData.form.FullName",
|
|
447
|
-
"ClassID": "vueData.form.ClassID"
|
|
448
|
-
},
|
|
449
|
-
"CALLBACK": [ { "CALL": "vueData.fetchStudents" }, { "MESS": "Đã thêm thành công" } ]
|
|
450
|
-
},
|
|
451
|
-
"deleteStudent": {
|
|
452
|
-
"API": "/me/StudentDelete/`{{vueData.selectedID}}",
|
|
453
|
-
"CONFIRM": "Bạn có chắc muốn xoá?",
|
|
454
|
-
"CALLBACK": { "CALL": "vueData.fetchStudents" }
|
|
455
|
-
}
|
|
456
|
-
```
|
|
457
|
-
|
|
458
|
-
---
|
|
459
|
-
|
|
460
|
-
## 7. SP design checklist
|
|
461
|
-
|
|
462
|
-
1. `spAPI_` prefix mandatory — missing means API can't call it.
|
|
463
|
-
2. Add `AUTH_` for public endpoints (login page, lookup data).
|
|
464
|
-
3. Always include `@sys_UserID` in SPs that write data (audit trail).
|
|
465
|
-
4. No `SELECT *` — list columns.
|
|
466
|
-
5. Check permissions at SP start if needed, with `RAISERROR` + `RETURN` — see [tapi-permission-patterns.md](tapi-permission-patterns.md).
|
|
467
|
-
6. Multiple SELECTs → client reads by index `data[0]`, `data[1]`.
|
|
468
|
-
7. Single record → use `convert_to_object` instead of `data[0][0]`.
|
|
469
|
-
8. **No `GRANT EXECUTE` in the .sql file** — the SP body runs to end of batch and tAPI has no `GO` support, so a GRANT after `END` is **swallowed into the SP body** (runs every call, grants nothing, no error). `fui sp deploy` grants and confirms via `sys.database_permissions` — read its `✓`/`❗` line ([verification.md](verification.md#security)).
|
|
470
|
-
9. **Never put `sys_*` params in module.json `IN`** — tAPI injects them.
|
|
471
|
-
9b. **Headers** → `@sys_header_{HeaderName}`, **each `-` → `_`**; `-` is a syntax error, brackets don't help (§2). Log only, never gate permissions.
|
|
472
|
-
9c. **Binding never errors** (missing → `NULL`, extra → ignored): check `IN` names with `fui sp help`. `DEFAULT` is useless; use `SET @x = ISNULL(@x, <giá trị>)`.
|
|
473
|
-
10. **File GET/UPLOAD**: prefix `spAPIFILE_`, binary column alias `fileContent`, params `@sys_FileContent`/`@sys_FileName`, standard table `tblFileData` — see [tapi-file-api.md](tapi-file-api.md). Don't infer from training data.
|
|
474
|
-
11. **Any ALTER/UPDATE of a deployed SP** (params, logic, anything) → **MUST clear tAPI cache** via `fui sp help` (§3.1). `fui sp deploy` does it (once; ignore failure); only ALTER via `fui exec` needs it manually.
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
# fui commands — safety registry
|
|
2
|
-
|
|
3
|
-
Risk per command. `R` reads only (touches no byte on disk); `M` writes the server or the local workspace (a local refresh overwrites files; the old copy goes to `_history/` first).
|
|
4
|
-
|
|
5
|
-
- ✅ Safe: run freely.
|
|
6
|
-
- ⚠️ Confirm: summarize for the user and wait for OK.
|
|
7
|
-
- 🔴 Destructive: full summary, then an explicit yes from the user.
|
|
8
|
-
|
|
9
|
-
Full syntax: `fui <command> --help`. The fui skill (`fui skill`) has the Fui MCP tool → command map.
|
|
10
|
-
|
|
11
|
-
## Commands
|
|
12
|
-
|
|
13
|
-
| Command | R/M | Risk |
|
|
14
|
-
| ------------------------------------------------------------------------------------------- | ----- | ---- |
|
|
15
|
-
| `use`, `use --clear`, `resolve` | M / R | ✅ |
|
|
16
|
-
| `project list` | R | ✅ |
|
|
17
|
-
| `project sync` | M | ✅ |
|
|
18
|
-
| `project new`, `project update`, `project publish-config` | M | ⚠️ |
|
|
19
|
-
| `user search`, `user list` | R | ✅ |
|
|
20
|
-
| `user add`, `user set` | M | ⚠️ |
|
|
21
|
-
| `user remove` | M | 🔴 |
|
|
22
|
-
| `module list`, `module validate`, `module outline`, `module simulate`, `module preview` | R | ✅ |
|
|
23
|
-
| `module get`, `module get-ui`, `module get-html` | M | ✅ |
|
|
24
|
-
| `module new`, `module update` | M | ⚠️ |
|
|
25
|
-
| `module publish json`, `module publish html`, `module publish script`, `module publish css` | M | ⚠️ |
|
|
26
|
-
| `module delete` | M | 🔴 |
|
|
27
|
-
| `component get`, `component list` | M | ✅ |
|
|
28
|
-
| `component preview` | R | ✅ |
|
|
29
|
-
| `component new`, `component update` | M | ⚠️ |
|
|
30
|
-
| `component delete` | M | 🔴 |
|
|
31
|
-
| `import list`, `import get` | R | ✅ |
|
|
32
|
-
| `import new`, `import update`, `import upload` | M | ⚠️ |
|
|
33
|
-
| `import delete` | M | 🔴 |
|
|
34
|
-
| `db list`, `db alias list` | R | ✅ |
|
|
35
|
-
| `db add`, `db add-by-name`, `db user-token` | M | ✅ |
|
|
36
|
-
| `db alias new`, `db token-rebuild` | M | ⚠️ |
|
|
37
|
-
| `schema`, `sp list`, `sp help`, `sp verify` | R | ✅ |
|
|
38
|
-
| `schema pull`, `sp get` | M | ✅ |
|
|
39
|
-
| `query` | R/M | ⚠️ |
|
|
40
|
-
| `sp save`, `sp rename` | M | ⚠️ |
|
|
41
|
-
| `exec` | R/M | 🔴 |
|
|
42
|
-
| `sp deploy`, `sp delete` | M | 🔴 |
|
|
43
|
-
| `right system list`, `right function list` | R | ✅ |
|
|
44
|
-
| `right system new/update`, `right function new/update` | M | ⚠️ |
|
|
45
|
-
| `right system delete`, `right function delete` | M | 🔴 |
|
|
46
|
-
| `skill get`, `skill ref`, `design list`, `design read`, `library`, `log read` | R | ✅ |
|
|
47
|
-
| `skill sync`, `log clear` | M | ✅ |
|
|
48
|
-
|
|
49
|
-
## Refresh scope
|
|
50
|
-
|
|
51
|
-
Each refresh overwrites every file in its scope without asking (old copies go to `_history/`):
|
|
52
|
-
|
|
53
|
-
| Files | Refreshed by |
|
|
54
|
-
| ------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------- |
|
|
55
|
-
| `module.json`, `header.html`, `body.html`, `script.js`, `_moduleInfo.json`, module-scope `uc-*.vue`, module imports | `fui module get` |
|
|
56
|
-
| project-scope `uc-*.vue` (`{projectId}/components/`) | `fui component get`, or `fui project sync` for all |
|
|
57
|
-
| `project.json`, `_projectInfo.json`, `_modules.json`, `imports/*` | `fui project sync` |
|
|
58
|
-
| `_db/{alias}/schema.json` and all `_db/{alias}/*.sql` of one connection | `fui schema pull` |
|
|
59
|
-
|
|
60
|
-
## Publish: which command for which file
|
|
61
|
-
|
|
62
|
-
- Before publishing module.json: `fui module validate`, fix every error. For complex runtime logic (action chains, watch cascades, dialog flows) also `fui module simulate` the main flow.
|
|
63
|
-
- Only `module.json` → `fui module publish json` (no preview needed).
|
|
64
|
-
- `header.html` / `body.html` / title (with or without module.json) → `fui module preview`, user approves, then `fui module publish html --approval <token>`. It pushes module.json too.
|
|
65
|
-
- `script.js` (also to clear it) → `fui module publish script`. `module publish json` does not push it.
|
|
66
|
-
- `style.css` (also to clear it) → `fui module publish css`.
|
|
67
|
-
- `uc-*.vue` → `fui component new <name>` the first time, `fui component update <name>` after; scope comes from `-m`; `<style scoped>` is sent as ComCSS.
|
|
68
|
-
- Several files changed → one command per file, in turn. `fui file push <path...>` routes each path to its publisher; `fui file status` lists what is still unpublished (a local ledger; it never blocks a publish).
|
|
69
|
-
|
|
70
|
-
## Database rules (enforced in code)
|
|
71
|
-
|
|
72
|
-
- `query` / `exec`: summarize what the SQL does and what data it touches, and wait for the user. Writes (INSERT, UPDATE…SET, DELETE, MERGE, TRUNCATE, ALTER COLUMN) exit 3 until `--confirm-write`, added only after the user approved that exact write.
|
|
73
|
-
- Always blocked, no flag unlocks them: `DROP TABLE`, `ALTER TABLE … DROP COLUMN`/`SWITCH`, `DELETE`/`UPDATE` without `WHERE` in `exec`. Show the SQL for the user to run by hand. `ALTER TABLE … ADD` and `DROP CONSTRAINT` are free.
|
|
74
|
-
- Never call a live API SP or run sub-queries "to test" it: read its body (`fui sp get`) and reason, or `fui sp verify <name|Fn>` (reads the definition; `--check-grant` also reads permissions).
|
|
75
|
-
- `apiMocks` for an SP that exists must come from `fui sp verify`, never guessed.
|
|
76
|
-
- `fui sp deploy`: archives the live body to `_history/`, fixes CREATE/ALTER, grants EXECUTE to `[public]` on new procedures, clears the tAPI cache once. After an `ALTER PROCEDURE` through `exec`, run `fui sp help <name>` to clear the cache yourself, or tAPI keeps the old signature.
|
|
77
|
-
- Never write `GRANT` into the `.sql` file: tAPI sends one batch without `GO`, so it would become part of the procedure body.
|
|
78
|
-
- `fui db add` stores the connection in `{projectId}/_db/_connections.json` under the alias; if the project is unclear, ask the user.
|
|
79
|
-
- Secrets only via stdin (`-`) or `--*-env VAR`; never print `_db/_connections.json` or `_db/config.json`.
|
|
80
|
-
|
|
81
|
-
## Concurrency
|
|
82
|
-
|
|
83
|
-
- Read-only commands can run in parallel.
|
|
84
|
-
- Never in parallel: any 🔴 command, `module publish html` with anything else, two `sp deploy`.
|