@fui-org/fui-cli 1.3.2 → 2.1.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.
Files changed (115) hide show
  1. package/README.md +21 -3
  2. package/dist/fui-cx180e19.js +379 -0
  3. package/dist/fui.js +1 -1
  4. package/package.json +3 -6
  5. package/skills/fui/SKILL.md +9 -41
  6. package/skills/fui-skill/SKILL.md +95 -225
  7. package/skills/fui-skill/assets/projectdefaultstyle-3.0.css +555 -0
  8. package/skills/fui-skill/assets/projectdefaultstyle.css +207 -235
  9. package/skills/fui-skill/references/INDEX.md +105 -137
  10. package/skills/fui-skill/references/advanced-techniques.md +76 -68
  11. package/skills/fui-skill/references/coding-standards.md +56 -56
  12. package/skills/fui-skill/references/component-design.md +166 -173
  13. package/skills/fui-skill/references/component-quickref.md +61 -60
  14. package/skills/fui-skill/references/component-table.md +128 -117
  15. package/skills/fui-skill/references/components-dialog.md +55 -56
  16. package/skills/fui-skill/references/components-display.md +24 -30
  17. package/skills/fui-skill/references/components-echart.md +186 -261
  18. package/skills/fui-skill/references/components-input.md +72 -96
  19. package/skills/fui-skill/references/controls-patterns.md +196 -342
  20. package/skills/fui-skill/references/controls-styling-vocabulary.md +130 -97
  21. package/skills/fui-skill/references/db-table-design.md +24 -28
  22. package/skills/fui-skill/references/db-workflow.md +191 -390
  23. package/skills/fui-skill/references/default-function.md +169 -128
  24. package/skills/fui-skill/references/design-modes.md +35 -63
  25. package/skills/fui-skill/references/echart-templates.md +204 -196
  26. package/skills/fui-skill/references/fastproject.md +62 -60
  27. package/skills/fui-skill/references/fsheet.md +109 -124
  28. package/skills/fui-skill/references/fullstack-workflow.md +90 -128
  29. package/skills/fui-skill/references/module-data-patterns.md +31 -40
  30. package/skills/fui-skill/references/module-json-anatomy.md +47 -52
  31. package/skills/fui-skill/references/module-structure.md +80 -196
  32. package/skills/fui-skill/references/new-session.md +49 -51
  33. package/skills/fui-skill/references/pdfmake.md +17 -17
  34. package/skills/fui-skill/references/permission-system.md +89 -108
  35. package/skills/fui-skill/references/platform-architecture.md +128 -153
  36. package/skills/fui-skill/references/project-config.md +102 -134
  37. package/skills/fui-skill/references/project-provisioning.md +139 -244
  38. package/skills/fui-skill/references/script-map.md +208 -242
  39. package/skills/fui-skill/references/sql-clr-functions.md +98 -97
  40. package/skills/fui-skill/references/system-design.md +63 -88
  41. package/skills/fui-skill/references/tapi-file-api.md +46 -52
  42. package/skills/fui-skill/references/tapi-permission-patterns.md +51 -53
  43. package/skills/fui-skill/references/tapi-reference.md +132 -207
  44. package/skills/fui-skill/references/tools-registry.md +84 -460
  45. package/skills/fui-skill/references/ui-crosswindow-patterns.md +79 -75
  46. package/skills/fui-skill/references/ui-dialog-patterns.md +98 -72
  47. package/skills/fui-skill/references/ui-layout-patterns.md +26 -26
  48. package/skills/fui-skill/references/ui-patterns.md +71 -83
  49. package/skills/fui-skill/references/ui-screenshot-review.md +63 -62
  50. package/skills/fui-skill/references/ui-table-cell-patterns.md +61 -59
  51. package/skills/fui-skill/references/ui-templates.md +16 -23
  52. package/skills/fui-skill/references/verification.md +236 -246
  53. package/skills/fui-skill/references/watcher-patterns.md +30 -63
  54. package/skills/fui-skill/references/websocket-realtime.md +83 -66
  55. package/skills/fui-skill/scripts/component-3.0.js +298 -131
  56. package/skills/fui-skill/scripts/component.js +277 -271
  57. package/skills/fui-skill/scripts/componentTable-3.0.js +182 -53
  58. package/skills/fui-skill/scripts/componentTable.js +171 -49
  59. package/skills/fui-skill/scripts/defaultfunction-3.0.js +88 -3
  60. package/skills/fui-skill/scripts/defaultfunction.js +88 -3
  61. package/skills/fui-skill/scripts/fsheet.js +38 -0
  62. package/skills/fui-target/.claude-plugin/plugin.json +6 -0
  63. package/skills/fui-target/hooks/hooks.json +1 -0
  64. package/skills/fui-target/hooks/register.tsx +71 -0
  65. package/skills/fui-target/types/index.d.ts +7 -0
  66. package/dist/fui-y8an39cn.js +0 -420
  67. package/skills/fui-skill/README.md +0 -112
  68. package/skills/fui-skill/metadata.json +0 -75
  69. package/skills/fui-skill-cli/SKILL.md +0 -139
  70. package/skills/fui-skill-cli/references/INDEX.md +0 -110
  71. package/skills/fui-skill-cli/references/advanced-techniques.md +0 -168
  72. package/skills/fui-skill-cli/references/coding-standards.md +0 -112
  73. package/skills/fui-skill-cli/references/component-design.md +0 -448
  74. package/skills/fui-skill-cli/references/component-quickref.md +0 -78
  75. package/skills/fui-skill-cli/references/component-table.md +0 -248
  76. package/skills/fui-skill-cli/references/components-dialog.md +0 -191
  77. package/skills/fui-skill-cli/references/components-display.md +0 -141
  78. package/skills/fui-skill-cli/references/components-echart.md +0 -316
  79. package/skills/fui-skill-cli/references/components-input.md +0 -335
  80. package/skills/fui-skill-cli/references/controls-patterns.md +0 -701
  81. package/skills/fui-skill-cli/references/controls-styling-vocabulary.md +0 -137
  82. package/skills/fui-skill-cli/references/db-table-design.md +0 -73
  83. package/skills/fui-skill-cli/references/db-workflow.md +0 -288
  84. package/skills/fui-skill-cli/references/default-function.md +0 -425
  85. package/skills/fui-skill-cli/references/design-modes.md +0 -57
  86. package/skills/fui-skill-cli/references/echart-templates.md +0 -489
  87. package/skills/fui-skill-cli/references/fastproject.md +0 -99
  88. package/skills/fui-skill-cli/references/fsheet.md +0 -203
  89. package/skills/fui-skill-cli/references/fullstack-workflow.md +0 -313
  90. package/skills/fui-skill-cli/references/module-data-patterns.md +0 -117
  91. package/skills/fui-skill-cli/references/module-json-anatomy.md +0 -132
  92. package/skills/fui-skill-cli/references/module-structure.md +0 -141
  93. package/skills/fui-skill-cli/references/new-session.md +0 -85
  94. package/skills/fui-skill-cli/references/pdfmake.md +0 -60
  95. package/skills/fui-skill-cli/references/permission-system.md +0 -150
  96. package/skills/fui-skill-cli/references/platform-architecture.md +0 -269
  97. package/skills/fui-skill-cli/references/project-config.md +0 -303
  98. package/skills/fui-skill-cli/references/project-provisioning.md +0 -278
  99. package/skills/fui-skill-cli/references/script-map.md +0 -262
  100. package/skills/fui-skill-cli/references/sql-clr-functions.md +0 -225
  101. package/skills/fui-skill-cli/references/system-design.md +0 -89
  102. package/skills/fui-skill-cli/references/tapi-file-api.md +0 -185
  103. package/skills/fui-skill-cli/references/tapi-permission-patterns.md +0 -156
  104. package/skills/fui-skill-cli/references/tapi-reference.md +0 -474
  105. package/skills/fui-skill-cli/references/tools-registry.md +0 -84
  106. package/skills/fui-skill-cli/references/ui-crosswindow-patterns.md +0 -321
  107. package/skills/fui-skill-cli/references/ui-dialog-patterns.md +0 -255
  108. package/skills/fui-skill-cli/references/ui-layout-patterns.md +0 -176
  109. package/skills/fui-skill-cli/references/ui-patterns.md +0 -303
  110. package/skills/fui-skill-cli/references/ui-screenshot-review.md +0 -95
  111. package/skills/fui-skill-cli/references/ui-table-cell-patterns.md +0 -318
  112. package/skills/fui-skill-cli/references/ui-templates.md +0 -22
  113. package/skills/fui-skill-cli/references/verification.md +0 -236
  114. package/skills/fui-skill-cli/references/watcher-patterns.md +0 -163
  115. 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`.