@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,91 +1,84 @@
|
|
|
1
1
|
# DB Connection Workflow
|
|
2
2
|
|
|
3
|
-
>
|
|
3
|
+
> Owns: DB connections, dbToken, schema cache, SP workflow, rollback. Per-command risk/guards: [tools-registry.md](tools-registry.md); SP checklist: [verification.md](verification.md). Flags: `fui <command> --help`.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## 1. Storage layout
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
## 1. Thông tin kết nối lưu ở đâu
|
|
10
|
-
|
|
11
|
-
Mỗi project có thư mục `_db/` riêng, **bên trong là một thư mục con cho MỖI kết nối** — một project
|
|
12
|
-
FUI gọi được nhiều database cùng lúc, mỗi cái qua một alias (`apiName`) riêng:
|
|
7
|
+
One `_db/` subfolder PER connection. The folder name is a short, readable `connectionName` chosen by the user/AI; `apiName` is only the tAPI route alias and **may repeat across zones**.
|
|
13
8
|
|
|
14
9
|
```
|
|
15
|
-
{
|
|
10
|
+
{workspace}/{projectId}/
|
|
16
11
|
└── _db/
|
|
17
|
-
├── _connections.json ←
|
|
18
|
-
├── rights.json ← cache
|
|
19
|
-
├── {
|
|
20
|
-
│ ├── schema.json ←
|
|
21
|
-
│ └── {name}.sql ←
|
|
22
|
-
└── {
|
|
12
|
+
├── _connections.json ← all connections + default
|
|
13
|
+
├── rights.json ← rights cache from "acc", keyed by alias
|
|
14
|
+
├── {connectionName}/ ← key in "connections" = folder name
|
|
15
|
+
│ ├── schema.json ← schema cache
|
|
16
|
+
│ └── {name}.sql ← SPs (NO "sp/" level)
|
|
17
|
+
└── {other-connectionName}/…
|
|
23
18
|
```
|
|
24
19
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
Bản cũ **không** nằm cạnh bản hiện tại: mọi thứ sắp bị ghi đè/xoá đi về một kho chung
|
|
33
|
-
`{FUI_MCP_WORKDIR}/_history/`, giữ nguyên hình dạng đường dẫn gốc:
|
|
20
|
+
- Three identifiers, three jobs:
|
|
21
|
+
- `apiName`: the alias in `/{apiName}/...` URLs; may repeat across zones.
|
|
22
|
+
- `connectionName`: the key in `connections` and the folder name; pick something memorable (`docs`, `docs_lhbs`).
|
|
23
|
+
- `sqlServer + database`: the physical database; fui uses it to recognize a connection it already has, never as a folder name.
|
|
24
|
+
- Every DB command takes `--db <connectionName>` or `--db <project>/<connectionName>`; a unique apiName also works. Omitted → inferred from the object; if not inferable, or an alias exists in several zones, fui returns a MENU of connectionName + apiName + SQLServer/database — pick one, re-run. Never guess.
|
|
25
|
+
- Overwritten/deleted files go to `{workspace}/_history/`, same path shape; all versions of a file sit together. Never auto-cleaned (user deletes manually):
|
|
34
26
|
|
|
35
27
|
```
|
|
36
|
-
{
|
|
37
|
-
{
|
|
28
|
+
{workspace}/_history/{projectId}/_db/{connectionName}/{name}_{timestamp}.sql
|
|
29
|
+
{workspace}/_history/{projectId}/_db/{connectionName}/{name}_{timestamp}_deleted.sql ← DROPped SP
|
|
38
30
|
```
|
|
39
31
|
|
|
40
|
-
|
|
41
|
-
một file nằm cạnh nhau (tìm theo tên file, không phải theo thời điểm). Kho này **không bao giờ tự
|
|
42
|
-
dọn** — user tự xoá tay khi thấy đủ.
|
|
43
|
-
|
|
44
|
-
**Cấu trúc `_db/_connections.json`:**
|
|
32
|
+
`_db/_connections.json`:
|
|
45
33
|
|
|
46
34
|
```json
|
|
47
35
|
{
|
|
48
|
-
"
|
|
36
|
+
"version": 2,
|
|
37
|
+
"default": "docs",
|
|
49
38
|
"connections": {
|
|
50
|
-
"
|
|
51
|
-
"
|
|
52
|
-
"
|
|
53
|
-
"
|
|
54
|
-
"
|
|
55
|
-
"
|
|
39
|
+
"docs": {
|
|
40
|
+
"apiName": "docs",
|
|
41
|
+
"apiDomain": "tapi.lhu.edu.vn",
|
|
42
|
+
"sqlServer": "172.0.0.24",
|
|
43
|
+
"database": "QLCongVan",
|
|
44
|
+
"dbToken": "<base64-encoded connection string>",
|
|
45
|
+
"userToken": "<bearer token — optional>"
|
|
56
46
|
},
|
|
57
|
-
"
|
|
47
|
+
"docs_lhbs": {
|
|
48
|
+
"apiName": "docs",
|
|
49
|
+
"apiDomain": "tapi.lhbs.vn",
|
|
50
|
+
"sqlServer": "192.168.100.23",
|
|
51
|
+
"database": "QLCongVan",
|
|
52
|
+
"dbToken": "<base64>"
|
|
53
|
+
}
|
|
58
54
|
}
|
|
59
55
|
}
|
|
60
56
|
```
|
|
61
57
|
|
|
62
|
-
`default`
|
|
63
|
-
`db_sql_execute_nonquery`, `db_token_rebuild`) không bao giờ tự dùng mặc định — phải nêu rõ `db`.
|
|
58
|
+
`default` applies only to reads without `--db`. Writes (`fui query` with a write, `fui exec`, `fui db token-rebuild`) never use it — `--db` required.
|
|
64
59
|
|
|
65
|
-
| Field
|
|
66
|
-
|
|
67
|
-
|
|
|
68
|
-
|
|
|
69
|
-
| `
|
|
70
|
-
| `
|
|
71
|
-
| `
|
|
72
|
-
| `
|
|
60
|
+
| Field | Req | Meaning |
|
|
61
|
+
| ----------- | --- | ------------------------------------------------------------------ |
|
|
62
|
+
| `version` | ✅ | Always `2` for this layout |
|
|
63
|
+
| key | ✅ | `connectionName`, also the folder name (`docs`, `docs_lhbs`) |
|
|
64
|
+
| `apiName` | ✅ | tAPI alias in `"API": "/{apiName}/Ten"`; may repeat across zones |
|
|
65
|
+
| `apiDomain` | ✅ | Host only, NO alias, NO trailing `/` (`api.example3.vn`) |
|
|
66
|
+
| `sqlServer` | ✅ | SQL Server host; with `database`, identifies the physical database |
|
|
67
|
+
| `database` | ✅ | Database name; with `sqlServer`, prevents duplicate connections |
|
|
68
|
+
| `dbToken` | ✅ | Base64 SQL Server connection string |
|
|
69
|
+
| `userToken` | ❌ | Bearer to test `spAPI_*` after deploy |
|
|
73
70
|
|
|
74
|
-
|
|
71
|
+
Without `--sql-server`/`--database`, `fui db add` reads both from the connection string in the token.
|
|
75
72
|
|
|
76
|
-
|
|
77
|
-
> - `_db/_connections.json` (MCP, bảng trên) → **host trần**, không alias, không `/` cuối: `api.example3.vn`.
|
|
78
|
-
> - `project.json`'s `data.apiDomain` (runtime FUI, mục 2a bên dưới) → **base URL đầy đủ** đã kèm sẵn `apiName` + `/` cuối: `https://tapi.example.vn/acc/`.
|
|
79
|
-
>
|
|
80
|
-
> Ghép URL thủ công bằng cách lấy `_db/_connections.json`'s `apiDomain` (host trần) rồi nối thẳng `apiName` vào — **không chèn `/`** — là lỗi hay gặp nhất khi tự gõ tay: `tapi.lhu.edu.vn` + `ts` → `tapi.lhu.edu.vnts` (sai, "ts" bị nuốt vào domain) thay vì `tapi.lhu.edu.vn/ts` (đúng). Xem thêm ví dụ đối chiếu ❌/✅ ở [tapi-reference.md](tapi-reference.md) §3. Cách an toàn nhất: đừng tự ghép — copy nguyên văn dòng `Wiring URL` từ `db_sp_verify`/`db_sp_help`.
|
|
73
|
+
**Naming:** pass `--name <connectionName>` for a specific name. Omitted, fui suggests `apiName` first; if taken, adds the zone from `apiDomain` (`docs` → `docs_lhbs`); still taken, adds the database and a number. Names take letters, digits, `.`, `_`, `-` and are lowercased. The same server + database added again keeps its existing name.
|
|
81
74
|
|
|
82
|
-
|
|
75
|
+
**v1 compatibility, no silent moves:** an old record without `apiName` reads as `apiName = connectionName = key`. fui never renames old SQL folders. A new connection can take its own name, so an alias repeated across zones can sit next to the old record.
|
|
83
76
|
|
|
84
|
-
|
|
77
|
+
> **CRITICAL — `apiDomain` has two meanings:** `_connections.json` → bare host (`api.example3.vn`); `project.json` `data.apiDomain` → full base URL with apiName + trailing `/` (`https://tapi.example.vn/acc/`). Top bug: bare host + apiName without `/` → `tapi.lhu.edu.vnts` instead of `tapi.lhu.edu.vn/ts`. See [tapi-reference.md](tapi-reference.md) §3. Don't build URLs; copy the `Wiring URL` line from `fui sp verify`/`fui sp help`.
|
|
85
78
|
|
|
86
|
-
|
|
79
|
+
## 2. Finding connection info
|
|
87
80
|
|
|
88
|
-
|
|
81
|
+
### 2a. From project.json
|
|
89
82
|
|
|
90
83
|
```json
|
|
91
84
|
"data": {
|
|
@@ -94,11 +87,7 @@ dọn** — user tự xoá tay khi thấy đủ.
|
|
|
94
87
|
}
|
|
95
88
|
```
|
|
96
89
|
|
|
97
|
-
|
|
98
|
-
- **`apiDomain`** → `tapi.example.vn`
|
|
99
|
-
- **`apiName`** → `acc` (phần path đầu tiên sau domain)
|
|
100
|
-
|
|
101
|
-
Một số project có nhiều domain, mỗi domain dùng một tAPI server riêng:
|
|
90
|
+
→ `apiDomain` = `tapi.example.vn`, `apiName` = `acc` (first path segment). Multi-domain projects:
|
|
102
91
|
|
|
103
92
|
```json
|
|
104
93
|
"domainSetting": {
|
|
@@ -111,394 +100,206 @@ Một số project có nhiều domain, mỗi domain dùng một tAPI server riê
|
|
|
111
100
|
}
|
|
112
101
|
```
|
|
113
102
|
|
|
114
|
-
→
|
|
103
|
+
→ Ask the user which domain to use.
|
|
115
104
|
|
|
116
|
-
### 2b.
|
|
105
|
+
### 2b. Alias known, no dbToken → `fui db alias list` + `fui db add-by-name`
|
|
117
106
|
|
|
118
|
-
|
|
119
|
-
chỉ biết `apiName` thì **đừng đi tra tay bằng PowerShell** (moi UID/PWD ra command line là phơi
|
|
120
|
-
credential, và cả quy trình đó nay đã có tool):
|
|
107
|
+
Never extract UID/PWD by hand (PowerShell etc.) — exposes credentials.
|
|
121
108
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
db_alias_list()
|
|
125
|
-
```
|
|
126
|
-
**Không cần tham số nào.** `SM_Modules_ManagerSelect` không nhận tham số: tAPI bơm `@sys_UserID` từ
|
|
127
|
-
Bearer token ở phía server, nên danh sách trả về **đã lọc sẵn theo quyền quản lý của chính bạn**.
|
|
128
|
-
Trả về bảng `APIName | SQLServer | DatabaseName | ModuleName | Enable`. Danh sách dài thì thêm
|
|
129
|
-
`search` để lọc phía client (khớp `APIName`/`DatabaseName`/`ModuleName`, không phân biệt hoa-thường).
|
|
109
|
+
1. `fui db alias list` — no args: tAPI injects `@sys_UserID` from the Bearer token, so `SM_Modules_ManagerSelect` returns only DBs you're granted. Columns `APIName | SQLServer | DatabaseName | ModuleName | Enable`; `--search` filters client-side (APIName/DatabaseName/ModuleName, case-insensitive).
|
|
110
|
+
2. `fui db add-by-name <apiName>` — looks up SQLServer/DatabaseName on acc → borrows the UID/PWD pair of an existing connection → builds dbToken → tests `SELECT 1` before saving anything → saves + fetches schema to `_db/{connectionName}/`. Never prints dbToken/UID/PWD.
|
|
130
111
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
```
|
|
135
|
-
Tool làm trọn gói: tra `SQLServer`/`DatabaseName` từ acc → **mượn cặp UID/PWD** của một kết nối bạn đã
|
|
136
|
-
có → dựng `dbToken` → **test `SELECT 1` trước khi lưu bất cứ thứ gì** → `saveConnection` +
|
|
137
|
-
fetch schema về `_db/{alias}/`. Báo cáo giống hệt `db_connect`. **Không bao giờ in dbToken/UID/PWD.**
|
|
112
|
+
- Several different logins in workspace → menu; pass `--borrow-from <projectId>/<connectionName>`. Same login across one group's connections is not ambiguous.
|
|
113
|
+
- "apiName not found" = alias doesn't exist OR you're not granted it. Don't assume a typo; run `fui db alias list`.
|
|
114
|
+
- Project with no connections works: apiDomain from local `project.json`, userToken borrowed from another project on the same domain (auto only if exactly one candidate, else menu). Else pass `--api-domain` + `--user-token-env VAR`.
|
|
138
115
|
|
|
139
|
-
|
|
140
|
-
làm tay cũ. Workspace có nhiều login **khác nhau** → tool trả **menu** để bạn chọn, không đoán; nêu rõ
|
|
141
|
-
bằng `borrowCredentialsFrom: "{projectId}/{alias}"`. (Một login xuất hiện ở nhiều kết nối cùng group
|
|
142
|
-
là chuyện thường và **không** bị coi là nhập nhằng.)
|
|
116
|
+
> ⚠️ `Password` in `SM_Modules_ManagerSelect` is a tAPI internal hash, not the SQL password — unusable for dbToken. fui never prints it.
|
|
143
117
|
|
|
144
|
-
|
|
145
|
-
quản lý nó. Đừng vội kết luận là gõ sai tên: chạy `db_alias_list()` xem mình thực sự có gì.
|
|
118
|
+
### 2c. First connection for a new project
|
|
146
119
|
|
|
147
|
-
|
|
148
|
-
`project.json` local, `userToken` mượn từ kết nối của project khác cùng domain — chỉ tự chọn khi có
|
|
149
|
-
đúng một ứng viên, nhiều thì trả menu. Bí quá thì truyền thẳng `apiDomain` + `userToken`.
|
|
150
|
-
|
|
151
|
-
> ⚠️ Field `Password` trong response của `SM_Modules_ManagerSelect` là **hash nội bộ của tAPI**, không
|
|
152
|
-
> phải SQL Server password thực — không dùng được để build dbToken. Tool **không in field này ra**.
|
|
153
|
-
|
|
154
|
-
### 2c. Workflow đầy đủ — kết nối DB lần đầu cho project mới
|
|
155
|
-
|
|
156
|
-
> Mục này giả định database **đã tồn tại và đã được đăng ký alias** trong `acc`. Chưa có (dựng dự án
|
|
157
|
-
> từ số 0) → làm [project-provisioning.md](project-provisioning.md) trước: tạo DB, hai tài khoản SQL,
|
|
158
|
-
> rồi `db_alias_new` để có alias — xong mới quay lại đây.
|
|
120
|
+
> Requires the DB to exist and be registered as an alias in `acc`. Otherwise do [project-provisioning.md](project-provisioning.md) first (DB, two SQL accounts, `fui db alias new`).
|
|
159
121
|
|
|
160
122
|
```
|
|
161
|
-
1.
|
|
162
|
-
2.
|
|
163
|
-
3.
|
|
164
|
-
4.
|
|
165
|
-
|
|
166
|
-
5. [Module gọi thêm alias khác?] lặp bước 4 cho từng alias còn thiếu.
|
|
167
|
-
Kết nối thêm KHÔNG tự giành `default` — muốn đổi thì `makeDefault: true`.
|
|
123
|
+
1. fui project sync -p <projectId> → local project.json (apiDomain source)
|
|
124
|
+
2. fui use -p <projectId> → project implied afterwards
|
|
125
|
+
3. fui db alias list → aliases you may manage
|
|
126
|
+
4. fui db add-by-name <apiName> → lookup + token + test + save + schema (do NOT run fui schema pull after)
|
|
127
|
+
5. Module uses other aliases? Repeat 4 per alias. Added connections do NOT become default (use --default).
|
|
168
128
|
```
|
|
169
129
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
---
|
|
173
|
-
|
|
174
|
-
## 3. Build dbToken
|
|
130
|
+
Already have a dbToken → skip 3–4, use `fui db add`.
|
|
175
131
|
|
|
176
|
-
|
|
177
|
-
> một kết nối đã có thì dùng `db_connect_by_name` (§2b) — nó dựng token giúp, và không in ra plain text.
|
|
132
|
+
## 3. Building a dbToken
|
|
178
133
|
|
|
179
|
-
`
|
|
134
|
+
Only if you hold UID/PWD and want `fui db add`; to borrow credentials use `fui db add-by-name` (no plain text). dbToken = base64 of:
|
|
180
135
|
|
|
181
136
|
```
|
|
182
137
|
Server={sqlServer};Database={database};UID={uid};PWD={pwd};Encrypt=True;TrustServerCertificate=True;
|
|
183
138
|
```
|
|
184
139
|
|
|
185
|
-
**Build bằng JavaScript:**
|
|
186
140
|
```js
|
|
187
|
-
Buffer.from(
|
|
141
|
+
Buffer.from(
|
|
142
|
+
"Server=192.0.2.101;Database=AccountUser;UID=sa;PWD=MyPass;Encrypt=True;TrustServerCertificate=True;",
|
|
143
|
+
).toString("base64");
|
|
188
144
|
```
|
|
189
145
|
|
|
190
|
-
**Build bằng PowerShell:**
|
|
191
146
|
```powershell
|
|
192
147
|
[Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("Server=192.0.2.101;Database=AccountUser;UID=sa;PWD=MyPass;Encrypt=True;TrustServerCertificate=True;"))
|
|
193
148
|
```
|
|
194
149
|
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
## 4. Workflow kết nối lần đầu
|
|
198
|
-
|
|
199
|
-
### Xác định projectId trước khi kết nối
|
|
200
|
-
|
|
201
|
-
Thông tin kết nối DB được lưu vào `{FUI_MCP_WORKDIR}/{projectId}/_db/_connections.json`, dưới khoá
|
|
202
|
-
`apiName`. **Một project có thể có nhiều apiName** — `projectId` và `apiName` là hai thứ khác nhau,
|
|
203
|
-
đừng suy cái này ra cái kia.
|
|
204
|
-
|
|
205
|
-
**Quy tắc bắt buộc:** Nếu user không chỉ rõ projectId, hoặc alias/database chưa rõ thuộc project nào → **phải hỏi xác nhận** trước khi gọi `db_connect`:
|
|
206
|
-
|
|
207
|
-
> _"Thông tin kết nối DB này sẽ được lưu vào project nào? (projectId)"_
|
|
208
|
-
|
|
209
|
-
Không tự đoán projectId rồi gọi luôn — lưu sai project sẽ khiến schema/SP bị đặt nhầm chỗ và khó tìm lại.
|
|
210
|
-
|
|
211
|
-
```
|
|
212
|
-
db_connect(apiDomain, dbToken, apiName, [sqlServer, database, userToken])
|
|
213
|
-
→ schema tự động được fetch và lưu vào _db/{alias}/schema.json
|
|
214
|
-
→ KHÔNG gọi db_schema_get thêm sau bước này
|
|
215
|
-
```
|
|
216
|
-
|
|
217
|
-
### Project gọi nhiều database → gọi `db_connect` NHIỀU LẦN
|
|
218
|
-
|
|
219
|
-
Mở `module.json` và quét mọi `"API": "/{alias}/…"`: **mỗi alias khác nhau là một kết nối cần có**.
|
|
220
|
-
Gọi `db_connect` lần lượt cho từng alias — lần sau **không đụng** gì tới kết nối đã có, mỗi cái nằm
|
|
221
|
-
trong thư mục `_db/{alias}/` của riêng nó.
|
|
222
|
-
|
|
223
|
-
Thiếu một alias thì mọi lời gọi thuộc alias đó **không được kiểm gì cả**: `module_validate` không có
|
|
224
|
-
schema để đối chiếu tên SP, `db_sp_verify`/`db_sp_get` không tìm thấy SP, và `db_sp_deploy` không có
|
|
225
|
-
đường nào tới đúng database đó.
|
|
226
|
-
|
|
227
|
-
Kết nối **thêm vào không tự giành mặc định** — kết nối đầu tiên vẫn là `default`. Muốn đổi thì
|
|
228
|
-
`db_connect({ …, makeDefault: true })`.
|
|
229
|
-
|
|
230
|
-
**Tham số đầy đủ nên truyền:**
|
|
231
|
-
|
|
232
|
-
```json
|
|
233
|
-
{
|
|
234
|
-
"projectId": "my-project",
|
|
235
|
-
"apiDomain": "tapi.example.vn",
|
|
236
|
-
"apiName": "acc",
|
|
237
|
-
"sqlServer": "192.0.2.101",
|
|
238
|
-
"database": "MyDatabase",
|
|
239
|
-
"dbToken": "<base64>",
|
|
240
|
-
"userToken": "<bearer token nếu có>"
|
|
241
|
-
}
|
|
242
|
-
```
|
|
243
|
-
|
|
244
|
-
Truyền `sqlServer` + `database` ngay từ đầu để sau này dùng được `db_token_rebuild` mà không cần hỏi lại.
|
|
245
|
-
|
|
246
|
-
---
|
|
247
|
-
|
|
248
|
-
## 5. Khi đổi mật khẩu — db_token_rebuild
|
|
249
|
-
|
|
250
|
-
Khi UID hoặc PWD thay đổi nhưng Server và Database vẫn giữ nguyên:
|
|
251
|
-
|
|
252
|
-
**Bước 1:** Xác nhận kết nối cần sửa đã có `sqlServer` và `database`
|
|
253
|
-
```
|
|
254
|
-
db_config_read(projectId)
|
|
255
|
-
```
|
|
256
|
-
|
|
257
|
-
**Bước 2:** Rebuild token — server tự lấy `sqlServer`/`database` từ kết nối đó, chỉ cần truyền thông tin thay đổi
|
|
258
|
-
```
|
|
259
|
-
db_token_rebuild({ projectId, db, uid, password })
|
|
260
|
-
```
|
|
261
|
-
|
|
262
|
-
Tool sẽ tự build lại `dbToken`, test kết nối, và lưu. Nếu `sqlServer`/`database` chưa có → phải dùng `db_connect` đầy đủ thay thế.
|
|
263
|
-
|
|
264
|
-
**`db` là BẮT BUỘC khi project có nhiều hơn một kết nối** — đây là thao tác ghi đè credential, đoán
|
|
265
|
-
sai thì ghi token của DB này đè lên DB kia. Một kết nối duy nhất thì bỏ trống được.
|
|
266
|
-
|
|
267
|
-
---
|
|
150
|
+
Pass secrets only via stdin (`-`) or `--*-env VAR`.
|
|
268
151
|
|
|
269
|
-
##
|
|
152
|
+
## 4. `fui db add`
|
|
270
153
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
`userToken` là **Bearer token của người dùng** — dùng để gọi các `spAPI_*` endpoint sau khi deploy, nhằm test API như một user thực. Khác với `dbToken` là kết nối trực tiếp vào SQL Server.
|
|
154
|
+
- Saved to `{workspace}/{projectId}/_db/_connections.json` under `apiName`. projectId ≠ apiName; a project can have many apiNames — never derive one from the other.
|
|
155
|
+
- **Mandatory:** projectId not stated, or alias's project unclear → ask _"Which project should this DB connection be saved to? (projectId)"_ before `fui db add`. Wrong project misplaces schema/SPs.
|
|
274
156
|
|
|
275
157
|
```
|
|
276
|
-
|
|
277
|
-
|
|
158
|
+
fui db add <apiName> -p <project> --token - --api-domain host [--name connectionName] [--sql-server host --database name] [--user-token-env VAR] [--default]
|
|
159
|
+
→ schema auto-fetched to _db/{connectionName}/schema.json; do NOT run fui schema pull after
|
|
278
160
|
```
|
|
279
161
|
|
|
280
|
-
|
|
162
|
+
- Always pass `--sql-server` + `--database` (enables `fui db token-rebuild`).
|
|
163
|
+
- Multi-DB: scan every `"/{alias}/…"` in `module.json` and match it against the current zone/apiDomain. One alias can map to databases in several zones; each physical database gets its own `fui db add` and its own `_db/{connectionName}/`; later adds don't touch existing ones. A missing alias gets no checks: `fui module validate` can't match SP names, `fui sp verify`/`fui sp get` can't find SPs, `fui sp deploy` can't reach the DB.
|
|
164
|
+
- First connection stays `default`; change with `--default`.
|
|
281
165
|
|
|
282
|
-
|
|
166
|
+
## 5. Password change — `fui db token-rebuild`
|
|
283
167
|
|
|
284
|
-
|
|
285
|
-
{ "GroupName": "GroupA" }
|
|
286
|
-
```
|
|
168
|
+
UID/PWD changed, Server/Database unchanged:
|
|
287
169
|
|
|
288
|
-
|
|
170
|
+
1. `fui db list -p <projectId>` — confirm the connection has `sqlServer` and `database` (missing → full `fui db add` instead).
|
|
171
|
+
2. `fui db token-rebuild --db <connectionName> --uid <login> --pwd -` — rebuilds, tests, saves.
|
|
289
172
|
|
|
290
|
-
|
|
291
|
-
db_user_token_set({ projectId, db, userToken })
|
|
292
|
-
```
|
|
173
|
+
`--db` REQUIRED with >1 connection (overwrites credentials; wrong guess clobbers another DB's token).
|
|
293
174
|
|
|
294
|
-
|
|
175
|
+
## 6. userToken
|
|
295
176
|
|
|
296
|
-
|
|
177
|
+
- `userToken` = user's Bearer token to call `spAPI_*` after deploy as a real user; `dbToken` = direct SQL Server connection.
|
|
297
178
|
|
|
298
|
-
`userToken` nằm trong mục của một alias trong `_db/_connections.json`, không phải một giá trị chung
|
|
299
|
-
của project. Project nhiều database thì mỗi kết nối cần token riêng — truyền `db: "<alias>"` để nói
|
|
300
|
-
rõ set vào kết nối nào; bỏ trống thì vào kết nối mặc định.
|
|
301
|
-
|
|
302
|
-
Điều này quan trọng với `right_*`: nhóm tool quyền gọi alias `acc` bằng `userToken` lấy từ **kết nối
|
|
303
|
-
khớp `apiName` đang thao tác** (không khớp thì kết nối mặc định) — thiếu token ở đúng kết nối đó thì
|
|
304
|
-
tool quyền không chạy được dù kết nối khác đã có token.
|
|
305
|
-
|
|
306
|
-
### Set userToken sau khi kết nối
|
|
307
|
-
|
|
308
|
-
Nếu chưa có lúc `db_connect`, set riêng sau:
|
|
309
179
|
```
|
|
310
|
-
|
|
180
|
+
dbToken → SQL Server connection to run schema/SP
|
|
181
|
+
userToken → call tAPI REST API as an end-user (test spAPI_*)
|
|
311
182
|
```
|
|
312
183
|
|
|
313
|
-
|
|
184
|
+
- Shareable across projects with the same `GroupName` in `_projectInfo.json` (`{ "GroupName": "GroupA" }`): `fui db user-token --db <connectionName> --from <project/connectionName>` — no re-login. `fui db user-token` with no source lists workspace tokens.
|
|
185
|
+
- Stored PER CONNECTION in `_connections.json`. Multi-DB → one token per connection; pass `--db <connectionName>` (omitted → default).
|
|
186
|
+
- `fui right …` calls `acc` with the userToken of the connection matching the current apiName (else default); missing there → rights commands fail even if other connections have tokens.
|
|
187
|
+
- Not set at `fui db add` → `fui db user-token --db <connectionName> --token -`.
|
|
314
188
|
|
|
315
|
-
## 6a. SSO
|
|
189
|
+
## 6a. Domain SSO — same parent domain: token works, don't ask
|
|
316
190
|
|
|
317
|
-
|
|
318
|
-
API nằm dưới cùng một domain cha (ví dụ mọi host `*.lhu.edu.vn`: `tapi.lhu.edu.vn`, `api.lhu.edu.vn`,
|
|
319
|
-
`capnhatluong.lhu.edu.vn`…) **chấp nhận cùng một `userToken`**.
|
|
191
|
+
SSO is by parent domain: all APIs under e.g. `*.lhu.edu.vn` (`tapi.lhu.edu.vn`, `api.lhu.edu.vn`, `capnhatluong.lhu.edu.vn`…) accept the same `userToken`.
|
|
320
192
|
|
|
321
|
-
|
|
193
|
+
- Have a token for that parent domain → use it for other projects/aliases there. Do NOT ask the user, do NOT test-call to "verify", do NOT make them log in.
|
|
194
|
+
- Scanning the workspace for tokens (`fui db user-token` without a token) is valid and recommended.
|
|
322
195
|
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
196
|
+
| Case | Action |
|
|
197
|
+
| ------------------------------------------------- | -------------------------------------------- |
|
|
198
|
+
| Same parent domain | Use now, no asking/testing |
|
|
199
|
+
| Different parent domain (`*.dhlh.vn`, `*.fap.vn`) | Token invalid — need that domain's token |
|
|
200
|
+
| `domainSetting` hosts on different parent domains | Each parent domain is its own SSO zone (§2a) |
|
|
328
201
|
|
|
329
|
-
|
|
202
|
+
> `GroupName` is admin grouping; the parent domain decides acceptance. If they differ, trust the domain.
|
|
330
203
|
|
|
331
|
-
|
|
332
|
-
|---|---|
|
|
333
|
-
| Cùng domain cha (`*.lhu.edu.vn` → `*.lhu.edu.vn`) | **Dùng ngay**, không hỏi, không thử |
|
|
334
|
-
| Khác domain cha (`*.lhu.edu.vn` → `*.dhlh.vn`, `*.fap.vn`) | Token **không** áp dụng — cần token riêng của domain kia |
|
|
335
|
-
| Project nhiều domain (`domainSetting` có nhiều host khác domain cha nhau) | Mỗi domain cha là một vùng SSO riêng — xem `domainSetting` trong `project.json` (mục 2a) để biết đang đứng ở vùng nào |
|
|
204
|
+
## 7. Schema refresh
|
|
336
205
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
206
|
+
| When | Command |
|
|
207
|
+
| --------------------------------------------------------------- | --------------------------------------- |
|
|
208
|
+
| After `fui db add` | Not needed |
|
|
209
|
+
| User asks / table or SP created, renamed, dropped / cache stale | `fui schema pull --db <connectionName>` |
|
|
340
210
|
|
|
341
|
-
|
|
211
|
+
Read cache (no DB call): `fui schema [--db <connectionName>] [--type Table|View|API|"API File"|Procedure|Function] [--search text]`.
|
|
342
212
|
|
|
343
|
-
|
|
213
|
+
- Each connection has its own `schema.json`; both commands act on one connection. Pulling one connection doesn't refresh others — check `fui db list`, pull each. Object missing in `fui schema` usually = wrong connection.
|
|
214
|
+
- `fui schema pull` also reloads every `_db/{connectionName}/{name}.sql`; local copies differing from server go to `_history/` first. Don't trust local files as latest before a pull.
|
|
344
215
|
|
|
345
|
-
|
|
346
|
-
|---|---|
|
|
347
|
-
| Sau `db_connect` | **Không cần** — schema đã tự fetch |
|
|
348
|
-
| User yêu cầu refresh | `db_schema_get({ projectId, db })` |
|
|
349
|
-
| Vừa tạo/đổi tên/xóa table hoặc SP | `db_schema_get({ projectId, db })` |
|
|
350
|
-
| Schema local trông cũ/thiếu | `db_schema_get({ projectId, db })` |
|
|
216
|
+
Orphans: `fui db add`/`fui schema pull` scan actual `.sql` files in that connection's `_db/{connectionName}/` only:
|
|
351
217
|
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
**Mỗi kết nối có schema riêng** (`_db/{alias}/schema.json`) và cả hai tool này thao tác trên **đúng
|
|
359
|
-
một** kết nối. Project nhiều database thì `db_schema_get` một alias **không** làm mới alias còn lại —
|
|
360
|
-
tra `db_config_read` xem có bao nhiêu kết nối rồi refresh từng cái. Không thấy một bảng/SP trong
|
|
361
|
-
`db_schema_read` thường không phải "chưa có" mà là **đang đọc nhầm kết nối**.
|
|
362
|
-
|
|
363
|
-
**Cũng tải lại thân SP:** `db_schema_get` làm mới **mọi thứ kết nối đó đang giữ** — `schema.json` lẫn
|
|
364
|
-
từng file `_db/{alias}/{name}.sql`. Bản `.sql` local khác server được chép vào `_history/` trước rồi
|
|
365
|
-
mới ghi đè, nên không mất; nhưng đừng coi file local là bản mới nhất nếu chưa refresh.
|
|
366
|
-
|
|
367
|
-
**Tự dọn SP/function mồ côi khi refresh:** `db_connect`/`db_schema_get` quét **các file `.sql` thật
|
|
368
|
-
trong `_db/{alias}/`** rồi xếp làm ba nhóm — chỉ trong phạm vi kết nối đó, không nhìn sang alias khác:
|
|
369
|
-
|
|
370
|
-
| Nhóm | Điều kiện | Hành vi |
|
|
371
|
-
|---|---|---|
|
|
372
|
-
| Còn sống | tên có trong schema MỚI | giữ + tải lại thân từ server |
|
|
373
|
-
| Đã xóa trên server | có ở schema CŨ, mất ở schema MỚI | **archive** vào `_history/{projectId}/_db/{alias}/{name}_{thời điểm}_deleted.sql` rồi xóa khỏi `_db/{alias}/` |
|
|
374
|
-
| Chỉ có ở local | không có ở cả hai | **chỉ liệt kê, không xóa** — nhiều khả năng là SP đang soạn qua `db_sp_save` chưa deploy. Muốn dọn: `db_schema_get({ pruneLocalOnly: true })` |
|
|
218
|
+
| Group | Condition | Behavior |
|
|
219
|
+
| ----------------- | --------------- | -------------------------------------------------------------------------------------------------------------- |
|
|
220
|
+
| Alive | in NEW schema | keep, reload body |
|
|
221
|
+
| Dropped on server | in OLD, not NEW | archive to `_history/{projectId}/_db/{connectionName}/{name}_{timestamp}_deleted.sql`, remove locally |
|
|
222
|
+
| Local only | in neither | listed, NOT deleted (likely unsaved draft from `fui sp save`); clean with `fui schema pull --prune-local-only` |
|
|
375
223
|
|
|
376
|
-
|
|
377
|
-
file(s)...` nếu có. So tên **không phân biệt hoa-thường** (SQL Server không phân biệt, file có thể lệch case).
|
|
224
|
+
Prints `📋 Archived orphaned local SP file(s)...` when archiving. Name match is case-insensitive.
|
|
378
225
|
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
## 8. Workflow làm việc với SP
|
|
226
|
+
## 8. SP workflow
|
|
382
227
|
|
|
383
228
|
```
|
|
384
|
-
1.
|
|
385
|
-
2.
|
|
386
|
-
3.
|
|
387
|
-
4.
|
|
388
|
-
5.
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
một dòng thông tin — ĐỪNG thử URL biến thể khác
|
|
402
|
-
7. db_sp_verify(name, params) → kiểm chứng TĨNH contract API vừa deploy (đọc hay ghi đều
|
|
403
|
-
qua tool này) — KHÔNG gọi endpoint nào, chỉ đọc thân SP
|
|
404
|
-
thật và suy luận response shape, contract lỗi, phân loại
|
|
405
|
-
đọc/ghi, sinh sẵn snippet apiMocks cho module_simulate.
|
|
406
|
-
BẮT BUỘC chạy trước khi viết apiMocks cho một SP đã tồn
|
|
407
|
-
tại — tự bịa cấu trúc là sai, module_simulate sẽ cảnh báo
|
|
408
|
-
nếu phát hiện mock khớp SP thật mà chưa được verify.
|
|
229
|
+
1. fui sp list → all connections, SPs tagged by connection
|
|
230
|
+
2. fui sp get <name> → fetch definition → _db/{connectionName}/{name}.sql
|
|
231
|
+
3. edit _db/{connectionName}/{name}.sql
|
|
232
|
+
4. fui sp save <name> -f file.sql → local only, not deployed
|
|
233
|
+
5. fui sp deploy <name> → server's RUNNING version saved to _history/ first (rollback copy);
|
|
234
|
+
spAPI_*/spAPIFILE_* → auto /help clears tAPI cache once
|
|
235
|
+
(failure ignored, doesn't block, don't retry)
|
|
236
|
+
6. fui sp help <name> → REQUIRED if the SP was ALTERed outside fui sp deploy
|
|
237
|
+
(e.g. ALTER PROCEDURE via fui exec — no auto-clear).
|
|
238
|
+
Also shows input params before wiring IN/OUT in module.json.
|
|
239
|
+
Calls ONCE on the standard URL; failure = one info line.
|
|
240
|
+
Do NOT try URL variants.
|
|
241
|
+
7. fui sp verify <name> [--params …] → STATIC contract check (read or write API); calls NO endpoint.
|
|
242
|
+
Reads real SP body → response shape, error contract, read/write,
|
|
243
|
+
apiMocks snippet for fui module simulate. REQUIRED before writing
|
|
244
|
+
apiMocks for an existing SP — never invent structure;
|
|
245
|
+
fui module simulate warns on unverified mocks matching real SPs.
|
|
409
246
|
```
|
|
410
247
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
**không** kết nối nào hoặc **nhiều hơn một** (SP trùng tên ở hai DB) thì tool trả về **menu các alias**,
|
|
414
|
-
chọn một cái rồi gọi lại — đừng đoán. Riêng `db_sp_save` với SP **mới hoàn toàn** thì chưa có gì để
|
|
415
|
-
suy: project nhiều kết nối phải nêu `db` ngay từ lần lưu đầu.
|
|
416
|
-
|
|
417
|
-
> Cách suy luận của `db_sp_verify` (đọc thân SP thật, không đoán theo tên, lỗi cứng khi không đọc
|
|
418
|
-
> được thân SP) và cách kiểm tra API ghi bằng module_simulate: xem
|
|
419
|
-
> [tools-registry.md](tools-registry.md#quy-tắc-bắt-buộc-cho-db-tools). Các guard `DROP`/`ALTER
|
|
420
|
-
> TABLE`, `DELETE`/`UPDATE` không `WHERE` đều enforce ở code level, không bypass được; lệnh ghi qua
|
|
421
|
-
> `db_sql_execute`/`db_sql_execute_nonquery` cần `confirmWrite: true`.
|
|
248
|
+
- `--db` omitted → inferred from SP name (schema + local `.sql` per connection). One match → silent; zero or several (same name in two DBs) → connection menu, pick and re-run, don't guess.
|
|
249
|
+
- `fui sp save` for a brand-new SP can't infer: multi-connection projects must pass `--db` on first save.
|
|
422
250
|
|
|
423
|
-
|
|
424
|
-
1. Đọc file trong `{FUI_MCP_WORKDIR}/_history/{projectId}/_db/{alias}/{name}_{thời điểm}.sql`
|
|
425
|
-
2. `db_sp_save(name, oldSql)` — ghi lại bản cũ vào local
|
|
426
|
-
3. `db_sp_deploy(name)` — deploy lại
|
|
251
|
+
> `fui sp verify` reads the real body, not the name; hard error if unreadable. Write-API testing with `fui module simulate`: [tools-registry.md](tools-registry.md). Guards on `DROP`/`ALTER TABLE`, `DELETE`/`UPDATE` without `WHERE` are enforced in code, no bypass. Writes via `fui query`/`fui exec` need `--confirm-write`.
|
|
427
252
|
|
|
428
|
-
|
|
253
|
+
**Rollback:** read `{workspace}/_history/{projectId}/_db/{connectionName}/{name}_{timestamp}.sql` → `fui sp save <name> -f <old file>` → `fui sp deploy <name>`.
|
|
429
254
|
|
|
430
|
-
## 8a. Linked Server —
|
|
255
|
+
## 8a. Linked Server — `spIO_IN_` / `spIO_OUT_`
|
|
431
256
|
|
|
432
|
-
|
|
257
|
+
Linked servers exist, but for security you can NOT query another DB's tables through them — only call a predefined SP on the other side:
|
|
433
258
|
|
|
434
|
-
**Cú pháp gọi qua Linked Server trong thân SP:**
|
|
435
259
|
```sql
|
|
436
260
|
EXEC XDATA23.Calendar2015.dbo.spIO_IN_DeleteMonHocInfo @MonHocID, @ErrorDKMH OUTPUT
|
|
437
|
-
-- ^^^^^^^^^^^^^^^^^^^^^^^^^ ← 4
|
|
438
|
-
```
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
|
475
|
-
|
|
476
|
-
|
|
|
477
|
-
|
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
| Project gọi thêm một database nữa (alias khác) | `db_connect_by_name` lần nữa với `apiName` mới |
|
|
483
|
-
| Xem project đang có những kết nối nào, alias nào default | `db_config_read` |
|
|
484
|
-
| Đổi UID/PWD, server/database giữ nguyên | `db_token_rebuild` (nêu `db` nếu nhiều kết nối) |
|
|
485
|
-
| Set userToken sau khi connect | `db_user_token_set` (nêu `db` nếu nhiều kết nối) |
|
|
486
|
-
| Xem danh sách tables/SPs | `db_sp_list` |
|
|
487
|
-
| Lấy nội dung SP từ DB | `db_sp_get` |
|
|
488
|
-
| Refresh schema từ DB thực | `db_schema_get` |
|
|
489
|
-
| Đọc schema đã cache | `db_schema_read` |
|
|
490
|
-
| Lưu SQL chỉnh sửa vào local | `db_sp_save` |
|
|
491
|
-
| Deploy SP lên DB (tự xoá cache tAPI nếu là spAPI_*/spAPIFILE_*) | `db_sp_deploy` |
|
|
492
|
-
| Xem tham số đầu vào của API đã deploy (trước khi wire vào module.json) | `db_sp_help` |
|
|
493
|
-
| Xoá cache tAPI thủ công sau khi ALTER qua `db_sql_execute_nonquery` (đường đó không có auto-clear) | `db_sp_help` **(bắt buộc)** |
|
|
494
|
-
| Kiểm chứng tĩnh API vừa deploy (trước khi wire vào UI, không gọi sống) | `db_sp_verify` |
|
|
495
|
-
| Xóa SP khỏi DB | `db_sp_delete` |
|
|
496
|
-
| Đổi tên SP | `db_sp_rename` |
|
|
497
|
-
| Tìm SQLServer + DatabaseName của alias | `db_alias_list({ search })` (xem mục 2b) |
|
|
498
|
-
| Build dbToken bằng cách mượn UID/PWD của kết nối sẵn có | `db_connect_by_name` làm luôn (xem mục 2b) — **đừng decode tay bằng PowerShell** |
|
|
499
|
-
|
|
500
|
-
---
|
|
501
|
-
|
|
502
|
-
## 11. Quy tắc thiết kế bảng
|
|
503
|
-
|
|
504
|
-
Quy ước đặt tên bảng, khóa chính, trường timestamp và cột audit đã tách sang **[db-table-design.md](db-table-design.md)** — load file đó khi thiết kế schema mới.
|
|
261
|
+
-- ^^^^^^^^^^^^^^^^^^^^^^^^^ ← 4 parts: linked-server.database.schema.sp-name
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
| Prefix | Direction | Use |
|
|
265
|
+
| ----------- | ----------------- | --------------------------------------------------------- |
|
|
266
|
+
| `spIO_IN_` | Into current DB | Receives commands from an external DB, acts on current DB |
|
|
267
|
+
| `spIO_OUT_` | Out of current DB | Provides data for an external DB to call |
|
|
268
|
+
|
|
269
|
+
- These are boundary SPs, NOT tAPI endpoints (despite `spIO_`). Never wire into `"API":` in module.json.
|
|
270
|
+
- New SPs acting across a linked server MUST use the prefix matching data direction.
|
|
271
|
+
- `fui sp deploy` can't deploy them to the other DB; they run on the current DB and `EXEC` across. Deploy to the owning DB's connection.
|
|
272
|
+
|
|
273
|
+
## 9. List connections
|
|
274
|
+
|
|
275
|
+
`fui db list -p <projectId>` — every connection: connectionName (`db`), `apiName`, `apiDomain`, `sqlServer`, `database`, `_db/{connectionName}/`, dbToken/userToken present or not (never values), which is `default`. Run first when unsure which `--db` to use. Also lists `_db/` folders with no connection (leftovers, nothing reads them) — delete manually when sure.
|
|
276
|
+
|
|
277
|
+
## 10. Cheat sheet
|
|
278
|
+
|
|
279
|
+
| Situation | Command |
|
|
280
|
+
| ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
|
|
281
|
+
| DB doesn't exist (from scratch) | [project-provisioning.md](project-provisioning.md): 2 permission gates → CREATE DATABASE → 2 accounts → `fui db alias new` |
|
|
282
|
+
| Check `CREATE DATABASE`/`CREATE LOGIN` rights | [project-provisioning.md](project-provisioning.md) §Step 0 — `IS_SRVROLEMEMBER` + `HAS_PERMS_BY_NAME`, read-only |
|
|
283
|
+
| DB exists, no alias in `acc` | `fui db alias new` ([project-provisioning.md](project-provisioning.md) §Step 5) |
|
|
284
|
+
| First connect, have dbToken | `fui db add` |
|
|
285
|
+
| Alias only, no dbToken | `fui db alias list` → `fui db add-by-name` |
|
|
286
|
+
| Which DBs am I granted | `fui db alias list` |
|
|
287
|
+
| Another DB (new alias) | `fui db add-by-name` again |
|
|
288
|
+
| Connections + default | `fui db list` |
|
|
289
|
+
| UID/PWD changed | `fui db token-rebuild` (`--db` if several) |
|
|
290
|
+
| Set userToken | `fui db user-token` (`--db` if several) |
|
|
291
|
+
| List tables/SPs | `fui sp list` |
|
|
292
|
+
| Get SP body | `fui sp get` |
|
|
293
|
+
| Refresh / read schema | `fui schema pull` / `fui schema` |
|
|
294
|
+
| Save SQL locally | `fui sp save` |
|
|
295
|
+
| Deploy (auto cache clear for spAPI__/spAPIFILE__) | `fui sp deploy` |
|
|
296
|
+
| API input params before wiring | `fui sp help` |
|
|
297
|
+
| Clear tAPI cache after ALTER via `fui exec` | `fui sp help` (required) |
|
|
298
|
+
| Static check of deployed API | `fui sp verify` |
|
|
299
|
+
| Drop / rename SP | `fui sp delete` / `fui sp rename` |
|
|
300
|
+
| SQLServer + DatabaseName of an alias | `fui db alias list --search <text>` |
|
|
301
|
+
| dbToken via borrowed UID/PWD | `fui db add-by-name` — never decode by hand in PowerShell |
|
|
302
|
+
|
|
303
|
+
## 11. Table design
|
|
304
|
+
|
|
305
|
+
Naming, primary keys, timestamps, audit columns: [db-table-design.md](db-table-design.md) — load when designing a schema.
|