@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,137 +0,0 @@
|
|
|
1
|
-
# Controls Styling — Approved Layout Vocabulary (use only this)
|
|
2
|
-
|
|
3
|
-
> Owns: **approved class/prop/style set for `controls` and `.vue`, and presentation priority order**. Aesthetic mode + `border-radius` limits: [design-modes.md](design-modes.md).
|
|
4
|
-
|
|
5
|
-
**Rule #1: do NOT add `style` or `class` to "beautify" UI.** Use only the vocabulary below (extracted from 78 real `module.json` files across 5 projects: contest-score, security-manager, fp, lhu-test, lhu-lib). If the user didn't ask for a specific effect/spacing/color → **add nothing**. FUI layout (grid + Vuetify + project theme) is already consistent.
|
|
6
|
-
|
|
7
|
-
> Stats: of 1,284 control objects only ~12% use `attr.style` (almost only for `width`), and **zero custom classes** — 100% standard Vuetify utilities. Common AI mistake: adding `style="padding/margin/border/box-shadow/border-radius/background"` and invented classes → **don't.**
|
|
8
|
-
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
## Principles
|
|
12
|
-
|
|
13
|
-
1. **Default: no style, no class.** Set only `el`, `attr` (v-model/label/:items/:action…), `w`, and `col` when splitting columns.
|
|
14
|
-
2. Spacing/alignment → **Vuetify utility classes** from the tables below, NOT `style`.
|
|
15
|
-
3. `style` only for **fixed `width`** of a filter field (`style: "width:200px"`) — never padding/margin/border/color/background.
|
|
16
|
-
4. Color: component prop (`color="primary"`) or class `primary--text`/`error--text` — no `style="color:#..."`.
|
|
17
|
-
5. **Never** add `border`, `border-radius`, `box-shadow`, `background`, `padding`, custom classes unless the user explicitly asks.
|
|
18
|
-
6. **Compact padding — default `pa-2`** (or `pa-1`/`pa-0`). **NO large padding** (`pa-4`, `pa-6`, `pa-8`...) — wastes screen space. Margin likewise: prefer `-1`/`-2`, avoid `-6`/`-8`.
|
|
19
|
-
7. **When the user _does_ ask for specific presentation — follow this priority**, moving down only when the previous level can't do it:
|
|
20
|
-
`component prop` (`color`, `outlined`, `dense`, `elevation`) → `Vuetify utility class` (`pa-*`, `ma-*`, `d-flex`, `text-*`, `primary--text`) → `mw-*` for width → custom class → inline `style` (**last**).
|
|
21
|
-
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## 1. Container / row `prop` (grid wrapper)
|
|
25
|
-
|
|
26
|
-
Outer container and each row use only these tokens (by real frequency):
|
|
27
|
-
|
|
28
|
-
| Token | Purpose | Frequency |
|
|
29
|
-
| ------------------------------------------------ | --------------------------------------------------------------------- | --------- |
|
|
30
|
-
| `grid-list-md` | Standard column gap (container) | very high |
|
|
31
|
-
| `fluid` | Full-width container | high |
|
|
32
|
-
| `row` | Marks a row | very high |
|
|
33
|
-
| `align-center` | **Vertically center** controls in a row, esp. different types/heights | high |
|
|
34
|
-
| `justify-center` | Horizontal centering | very high |
|
|
35
|
-
| `justify-left` / `justify-end` / `justify-start` | Left / right align | medium |
|
|
36
|
-
| `text-center` / `text-left` | Text align | medium |
|
|
37
|
-
| `mw-800` `mw-1000` `mw-1200` `mw-1400` | **Limit content width** (FUI class) — centered form/data-entry pages | medium |
|
|
38
|
-
| `hidden-container` | Wraps dialogs (v-dialog/f-dialog) — takes no layout space | dialogs |
|
|
39
|
-
| `grid-list-lg` | Wider gap than grid-list-md | low |
|
|
40
|
-
| `pa-0` / `py-0` | Remove container padding to touch edges | low |
|
|
41
|
-
| `page-container` / `page-navigation` | Sticky filter-bar layout (see ui-layout-patterns.md) | rare |
|
|
42
|
-
|
|
43
|
-
> **Default formula**: container `"fluid grid-list-md"`, each row `"row"`. Rows mixing control types/heights: `"row wrap align-center"` for a shared vertical axis; `justify-center` is horizontal only. Form pages: add `mw-1000`/`mw-1200`.
|
|
44
|
-
|
|
45
|
-
## 2. `col` (grid column wrapping a control)
|
|
46
|
-
|
|
47
|
-
`col` only for width splitting or aligning/shrinking the column:
|
|
48
|
-
|
|
49
|
-
| Token | Purpose |
|
|
50
|
-
| ----------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
51
|
-
| `shrink` | **Fixed-width filter field** (doesn't grow) — most common. **Required whenever `w` is px**; write `"class": "shrink"`, NOT `"shrink": true` (inert on V3) |
|
|
52
|
-
| `text-end` / `text-start` / `text-center` | Align content in column |
|
|
53
|
-
| `pa-0` | Remove column padding |
|
|
54
|
-
| `align-self-center` | Vertical centering |
|
|
55
|
-
|
|
56
|
-
Short string `"text-end"` or object `{ "class": "shrink" }`. Add `"v-if": "..."` to `col` to show/hide the whole column by right/condition.
|
|
57
|
-
|
|
58
|
-
> Prefer `align-center` on the row to align the whole row. Use `align-self-center` on `col` only when a single control needs fixing. Never compensate vertical offset with margin or inline style.
|
|
59
|
-
|
|
60
|
-
## 3. `attr.class` (on the control itself)
|
|
61
|
-
|
|
62
|
-
Vuetify utility classes only:
|
|
63
|
-
|
|
64
|
-
| Group | Tokens |
|
|
65
|
-
| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
66
|
-
| Margin | `mt-1 mt-2 mt-3` · `mb-1 mb-2 mb-4` · `my-2` · `ml-1 ml-2` · `mr-1 mr-2` |
|
|
67
|
-
| Padding | `pa-0 pa-2` · `pt-3` · `py-1` — **avoid `pa-4/6/8`** |
|
|
68
|
-
| Flex | `d-flex` · `flex-column` · `align-center` · `justify-center` · `justify-end` · `flex-grow-0` · `flex-wrap` · `flex-md-grow-0` |
|
|
69
|
-
| Text | `text-center` · `text-left` · `text-right` |
|
|
70
|
-
| Size / weight | `text-h6` · `subtitle-1` · `body-2` · `caption` · `font-weight-bold` · `font-weight-medium` |
|
|
71
|
-
| Text color (V2) | `primary--text` · `error--text` · `grey--text` · `white--text` — **FUI V2 (Vuetify 1.5) only** (`--text` suffix) |
|
|
72
|
-
| Text color (V3) | `text-primary` · `text-error` · `text-grey` · `text-white` — **Vuetify 3** `text-{color}`. Wrong version = no effect, no error |
|
|
73
|
-
| Background | prop `color="primary"`, or Vuetify bg classes `primary` · `grey lighten-4` |
|
|
74
|
-
| Rounding | `rounded` · `rounded-lg` · `rounded-0` |
|
|
75
|
-
| Shadow / flat | prop `elevation="0"` / `flat` / `outlined` on `v-card`/`v-btn` |
|
|
76
|
-
| Breakpoint visibility | `d-none d-md-flex`... |
|
|
77
|
-
| Size | component props (`max-width`, `width`, `dense`, `small`, `x-large`) — no `style="width:..."` unless fixed px needed. Icons: keep default size, **don't add `small`/`:small`** |
|
|
78
|
-
|
|
79
|
-
### Icon size
|
|
80
|
-
|
|
81
|
-
- Icons use the component/theme default size.
|
|
82
|
-
- **Don't set `small` or `:small`** on `v-icon`, icon buttons, or buttons with icons just to look "compact".
|
|
83
|
-
- Shrink only when the user explicitly asks or a specialised component/pattern prescribes it; then set the prop on exactly that component — don't shrink the whole button unintentionally.
|
|
84
|
-
|
|
85
|
-
**Before adding a class → check the table above.** Define a custom class only for what Vuetify lacks: complex grid-template, animation, pseudo-element (`::before`), specific child selectors. Put it in `header.html`, clearly prefixed, **minimal count** — don't recreate card/badge/spacing Vuetify already has.
|
|
86
|
-
|
|
87
|
-
> `flex-md-grow-0` + `col: { class: "shrink" }` + `style: "width:200px"` = **fixed-width filter field** — standard toolbar pattern ([ui-patterns.md](ui-patterns.md) §4). The only valid place for `style` (width only).
|
|
88
|
-
|
|
89
|
-
---
|
|
90
|
-
|
|
91
|
-
## 4. Width: `w` (NOT style/class)
|
|
92
|
-
|
|
93
|
-
| `w` | Meaning |
|
|
94
|
-
| -------------------- | -------------------------------------------------------------------------------------- |
|
|
95
|
-
| `1`–`12` | Grid columns (12 = full row) |
|
|
96
|
-
| `>= 25` (e.g. `250`) | Fixed px width — **requires `col: { "class": "shrink" }`**, otherwise px has no effect |
|
|
97
|
-
| `13`–`24` | **Don't use** — dead zone: V2 yields px, V3 yields a non-existent class |
|
|
98
|
-
| `""` (empty) | Size to content |
|
|
99
|
-
|
|
100
|
-
Always split columns with `w` — no `style="width:..%"`, no invented `col-6`.
|
|
101
|
-
|
|
102
|
-
Measurements and reasons: [controls-patterns.md](controls-patterns.md) §Pixel `w`.
|
|
103
|
-
|
|
104
|
-
---
|
|
105
|
-
|
|
106
|
-
## 5. RIGHT / WRONG
|
|
107
|
-
|
|
108
|
-
```json
|
|
109
|
-
// ✅ ĐÚNG — gọn, dùng w + prop chuẩn, không style thừa
|
|
110
|
-
{ "el": "v-text-field", "w": 6, "attr": { "v-model": "hoTen", "label": "Họ tên" } }
|
|
111
|
-
|
|
112
|
-
// ❌ SAI — style/class tự chế không cần thiết
|
|
113
|
-
{ "el": "v-text-field", "w": 6, "attr": {
|
|
114
|
-
"v-model": "hoTen", "label": "Họ tên",
|
|
115
|
-
"style": "padding:8px; border:1px solid #ddd; border-radius:8px; margin-bottom:12px",
|
|
116
|
-
"class": "my-custom-input rounded-lg shadow" } }
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
```json
|
|
120
|
-
// ✅ ĐÚNG — card mặc định của Vuetify, không tự style
|
|
121
|
-
{ "el": "v-card", "attr": { "class": "pa-2" }, "innerHTML": [ ... ] }
|
|
122
|
-
|
|
123
|
-
// ❌ SAI — tự vẽ lại card
|
|
124
|
-
{ "el": "v-card", "attr": { "style": "background:#fff; box-shadow:0 4px 12px rgba(0,0,0,.1); border-radius:16px; padding:24px" } }
|
|
125
|
-
```
|
|
126
|
-
|
|
127
|
-
---
|
|
128
|
-
|
|
129
|
-
## 6. When style/class IS allowed
|
|
130
|
-
|
|
131
|
-
Only when the user **explicitly requests** specific presentation (e.g. "grey background for this block", "limit width to 800px", "this text red"). Even then:
|
|
132
|
-
|
|
133
|
-
- Prop → Vuetify utility class → `mw-*` for width → `style` last.
|
|
134
|
-
- `border-radius` on request: obey limits in [design-modes.md](design-modes.md) (large frame ≤12px, medium ≤8px, small ≤6px).
|
|
135
|
-
- No `<style>` in `.vue`; CSS goes in `header.html`.
|
|
136
|
-
|
|
137
|
-
> **About to type `style` or name a new class → stop and ask "did the user request this?". If not → drop it.**
|
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
# Table Design Conventions
|
|
2
|
-
|
|
3
|
-
> Owns: **table design rules: naming, PK/FK, audit columns, data types**. Connection/SP workflow: [db-workflow.md](db-workflow.md). Load when designing a new schema.
|
|
4
|
-
|
|
5
|
-
> **DDL — structure changes OK, data loss not:** `ALTER TABLE ... ADD` (column/constraint) and `DROP CONSTRAINT` run directly via fui. `ALTER COLUMN` (type change) runs but **needs `--confirm-write`** — narrowing numeric/time precision silently loses data. `CREATE TABLE`, `DROP COLUMN`, `DROP TABLE` are **hard-blocked**; the developer runs them. Conventions below are documentation — present DDL to the user for approval before running.
|
|
6
|
-
>
|
|
7
|
-
> DB connection, dbToken, schema, SP workflow: [db-workflow.md](db-workflow.md). Multi-table/multi-module app design: [system-design.md](system-design.md).
|
|
8
|
-
|
|
9
|
-
---
|
|
10
|
-
|
|
11
|
-
## Table names
|
|
12
|
-
|
|
13
|
-
| Group | Rule | Example |
|
|
14
|
-
| -------------------------------- | ------------------------- | ------------------------------------------ |
|
|
15
|
-
| System / auxiliary lookup tables | Lowercase, no prefix | `syslog`, `syslogtype`, `syspermission` |
|
|
16
|
-
| Business / main entity tables | `tbl` prefix + PascalCase | `tblUsers`, `tblDepartments`, `tblSession` |
|
|
17
|
-
|
|
18
|
-
**Primary key:** `[EntityName]ID`
|
|
19
|
-
|
|
20
|
-
| Table | PK |
|
|
21
|
-
| ---------------- | -------------- |
|
|
22
|
-
| `tblUsers` | `UserID` |
|
|
23
|
-
| `tblDepartments` | `DepartmentID` |
|
|
24
|
-
| `tblSession` | `SessionID` |
|
|
25
|
-
|
|
26
|
-
> FK in a child table uses the same name as the parent PK — `UserID`, never `CreatorID` or `OwnerID`.
|
|
27
|
-
|
|
28
|
-
---
|
|
29
|
-
|
|
30
|
-
## Timestamp columns
|
|
31
|
-
|
|
32
|
-
Every table should have at least one timestamp:
|
|
33
|
-
|
|
34
|
-
```sql
|
|
35
|
-
[CreateTime] [datetime] DEFAULT (getdate())
|
|
36
|
-
[UpdateTime] [datetime] DEFAULT (getdate())
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
- Type `datetime`; `DEFAULT (getdate())` — SQL Server **fills it** on INSERT, no need to pass from code.
|
|
40
|
-
- `CreateTime` for write-once tables; `UpdateTime` for frequently updated ones; both when created vs last-modified must differ.
|
|
41
|
-
|
|
42
|
-
---
|
|
43
|
-
|
|
44
|
-
## User tracking columns
|
|
45
|
-
|
|
46
|
-
```sql
|
|
47
|
-
[CreateUser] [char](9) NULL
|
|
48
|
-
[UpdateUser] [char](9) NULL
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
- Type `char(9)` or `varchar(20)` — **match the type of `UserID` in `tblUsers`**.
|
|
52
|
-
- **No DEFAULT** — the app must pass the logged-in `UserID`. SQL Server can't know the FUI/tAPI user; code is responsible.
|
|
53
|
-
- In SPs: receive via `@sys_UserID` (tAPI auto-injects), store into `[CreateUser]` / `[UpdateUser]`.
|
|
54
|
-
|
|
55
|
-
```sql
|
|
56
|
-
CREATE PROCEDURE spAPI_EntityInsert
|
|
57
|
-
@Name nvarchar(100),
|
|
58
|
-
@sys_UserID int -- tAPI auto-inject UserID
|
|
59
|
-
AS
|
|
60
|
-
INSERT INTO tblEntity (Name, CreateUser, CreateTime)
|
|
61
|
-
VALUES (@Name, @sys_UserID, DEFAULT)
|
|
62
|
-
```
|
|
63
|
-
|
|
64
|
-
---
|
|
65
|
-
|
|
66
|
-
## Audit column template — paste into new tables
|
|
67
|
-
|
|
68
|
-
```sql
|
|
69
|
-
[CreateUser] [char](9) NULL,
|
|
70
|
-
[CreateTime] [datetime] DEFAULT (getdate()),
|
|
71
|
-
[UpdateUser] [char](9) NULL,
|
|
72
|
-
[UpdateTime] [datetime] DEFAULT (getdate()),
|
|
73
|
-
```
|
|
@@ -1,288 +0,0 @@
|
|
|
1
|
-
# DB Connection Workflow
|
|
2
|
-
|
|
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
|
-
|
|
5
|
-
## 1. Storage layout
|
|
6
|
-
|
|
7
|
-
One `_db/` subfolder PER connection; a project may call several DBs, each via its alias (`apiName`):
|
|
8
|
-
|
|
9
|
-
```
|
|
10
|
-
{FUI_MCP_WORKDIR}/{projectId}/
|
|
11
|
-
└── _db/
|
|
12
|
-
├── _connections.json ← all connections + default
|
|
13
|
-
├── rights.json ← rights cache from "acc", keyed by alias
|
|
14
|
-
├── {alias}/ ← alias = apiName = first segment of "API": "/{alias}/Ten"
|
|
15
|
-
│ ├── schema.json ← schema cache
|
|
16
|
-
│ └── {name}.sql ← SPs (NO "sp/" level)
|
|
17
|
-
└── {other-alias}/…
|
|
18
|
-
```
|
|
19
|
-
|
|
20
|
-
- Alias links everything: `"API": "/fee/HocPhi_Select"` → apiName `fee` → `_db/fee/`.
|
|
21
|
-
- Every DB command takes `--db <alias>` or `--db <project>/<alias>`. Omitted → inferred from the object; if not inferable, fui returns a MENU of aliases — pick one, re-run. Never guess.
|
|
22
|
-
- Overwritten/deleted files go to `{FUI_MCP_WORKDIR}/_history/`, same path shape; all versions of a file sit together. Never auto-cleaned (user deletes manually):
|
|
23
|
-
|
|
24
|
-
```
|
|
25
|
-
{FUI_MCP_WORKDIR}/_history/{projectId}/_db/{alias}/{name}_{timestamp}.sql
|
|
26
|
-
{FUI_MCP_WORKDIR}/_history/{projectId}/_db/{alias}/{name}_{timestamp}_deleted.sql ← DROPped SP
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
`_db/_connections.json`:
|
|
30
|
-
|
|
31
|
-
```json
|
|
32
|
-
{
|
|
33
|
-
"default": "acc",
|
|
34
|
-
"connections": {
|
|
35
|
-
"acc": {
|
|
36
|
-
"apiDomain": "api.example3.vn",
|
|
37
|
-
"sqlServer": "192.0.2.101",
|
|
38
|
-
"database": "AccountUser",
|
|
39
|
-
"dbToken": "<base64-encoded connection string>",
|
|
40
|
-
"userToken": "<bearer token — optional>"
|
|
41
|
-
},
|
|
42
|
-
"Dashboard": { "apiDomain": "api.example3.vn", "…": "…" }
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
```
|
|
46
|
-
|
|
47
|
-
`default` applies only to reads without `--db`. Writes (`fui query` with a write, `fui exec`, `fui db token-rebuild`) never use it — `--db` required.
|
|
48
|
-
|
|
49
|
-
| Field | Req | Meaning |
|
|
50
|
-
| ----------- | --- | -------------------------------------------------------- |
|
|
51
|
-
| key | ✅ | alias/apiName = `_db/{alias}/` = `"/{alias}/Ten"` |
|
|
52
|
-
| `apiDomain` | ✅ | Host only, NO alias, NO trailing `/` (`api.example3.vn`) |
|
|
53
|
-
| `sqlServer` | ❌* | Needed for `fui db token-rebuild` |
|
|
54
|
-
| `database` | ❌* | Needed for `fui db token-rebuild` |
|
|
55
|
-
| `dbToken` | ✅ | Base64 SQL Server connection string |
|
|
56
|
-
| `userToken` | ❌ | Bearer to test `spAPI_*` after deploy |
|
|
57
|
-
|
|
58
|
-
*Pass on `fui db add` so rebuild needs no re-asking.
|
|
59
|
-
|
|
60
|
-
> **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`.
|
|
61
|
-
|
|
62
|
-
## 2. Finding connection info
|
|
63
|
-
|
|
64
|
-
### 2a. From project.json
|
|
65
|
-
|
|
66
|
-
```json
|
|
67
|
-
"data": {
|
|
68
|
-
"apiDomain": "https://tapi.example.vn/acc/",
|
|
69
|
-
...
|
|
70
|
-
}
|
|
71
|
-
```
|
|
72
|
-
|
|
73
|
-
→ `apiDomain` = `tapi.example.vn`, `apiName` = `acc` (first path segment). Multi-domain projects:
|
|
74
|
-
|
|
75
|
-
```json
|
|
76
|
-
"domainSetting": {
|
|
77
|
-
"sec.example.vn": {
|
|
78
|
-
"apiDomain": "https://tapi.example.vn/acc/"
|
|
79
|
-
},
|
|
80
|
-
"sec.example3.vn": {
|
|
81
|
-
"apiDomain": "https://api.example3.vn/acc/"
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
```
|
|
85
|
-
|
|
86
|
-
→ Ask the user which domain to use.
|
|
87
|
-
|
|
88
|
-
### 2b. Alias known, no dbToken → `fui db alias list` + `fui db add-by-name`
|
|
89
|
-
|
|
90
|
-
Never extract UID/PWD by hand (PowerShell etc.) — exposes credentials.
|
|
91
|
-
|
|
92
|
-
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).
|
|
93
|
-
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/{alias}/`. Never prints dbToken/UID/PWD.
|
|
94
|
-
|
|
95
|
-
- Several different logins in workspace → menu; pass `--borrow-from <projectId>/<alias>`. Same login across one group's connections is not ambiguous.
|
|
96
|
-
- "apiName not found" = alias doesn't exist OR you're not granted it. Don't assume a typo; run `fui db alias list`.
|
|
97
|
-
- 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`.
|
|
98
|
-
|
|
99
|
-
> ⚠️ `Password` in `SM_Modules_ManagerSelect` is a tAPI internal hash, not the SQL password — unusable for dbToken. fui never prints it.
|
|
100
|
-
|
|
101
|
-
### 2c. First connection for a new project
|
|
102
|
-
|
|
103
|
-
> 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`).
|
|
104
|
-
|
|
105
|
-
```
|
|
106
|
-
1. fui project sync -p <projectId> → local project.json (apiDomain source)
|
|
107
|
-
2. fui use -p <projectId> → project implied afterwards
|
|
108
|
-
3. fui db alias list → aliases you may manage
|
|
109
|
-
4. fui db add-by-name <apiName> → lookup + token + test + save + schema (do NOT run fui schema pull after)
|
|
110
|
-
5. Module uses other aliases? Repeat 4 per alias. Added connections do NOT become default (use --default).
|
|
111
|
-
```
|
|
112
|
-
|
|
113
|
-
Already have a dbToken → skip 3–4, use `fui db add`.
|
|
114
|
-
|
|
115
|
-
## 3. Building a dbToken
|
|
116
|
-
|
|
117
|
-
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:
|
|
118
|
-
|
|
119
|
-
```
|
|
120
|
-
Server={sqlServer};Database={database};UID={uid};PWD={pwd};Encrypt=True;TrustServerCertificate=True;
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
```js
|
|
124
|
-
Buffer.from(
|
|
125
|
-
"Server=192.0.2.101;Database=AccountUser;UID=sa;PWD=MyPass;Encrypt=True;TrustServerCertificate=True;",
|
|
126
|
-
).toString("base64");
|
|
127
|
-
```
|
|
128
|
-
|
|
129
|
-
```powershell
|
|
130
|
-
[Convert]::ToBase64String([System.Text.Encoding]::UTF8.GetBytes("Server=192.0.2.101;Database=AccountUser;UID=sa;PWD=MyPass;Encrypt=True;TrustServerCertificate=True;"))
|
|
131
|
-
```
|
|
132
|
-
|
|
133
|
-
Pass secrets only via stdin (`-`) or `--*-env VAR`.
|
|
134
|
-
|
|
135
|
-
## 4. `fui db add`
|
|
136
|
-
|
|
137
|
-
- Saved to `{FUI_MCP_WORKDIR}/{projectId}/_db/_connections.json` under `apiName`. projectId ≠ apiName; a project can have many apiNames — never derive one from the other.
|
|
138
|
-
- **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.
|
|
139
|
-
|
|
140
|
-
```
|
|
141
|
-
fui db add <alias> -p <project> --token - --api-domain host --sql-server host --database name [--user-token-env VAR] [--default]
|
|
142
|
-
→ schema auto-fetched to _db/{alias}/schema.json; do NOT run fui schema pull after
|
|
143
|
-
```
|
|
144
|
-
|
|
145
|
-
- Always pass `--sql-server` + `--database` (enables `fui db token-rebuild`).
|
|
146
|
-
- Multi-DB: each distinct `"/{alias}/…"` in `module.json` needs its own `fui db add`; 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.
|
|
147
|
-
- First connection stays `default`; change with `--default`.
|
|
148
|
-
|
|
149
|
-
## 5. Password change — `fui db token-rebuild`
|
|
150
|
-
|
|
151
|
-
UID/PWD changed, Server/Database unchanged:
|
|
152
|
-
|
|
153
|
-
1. `fui db list -p <projectId>` — confirm the connection has `sqlServer` and `database` (missing → full `fui db add` instead).
|
|
154
|
-
2. `fui db token-rebuild --db <alias> --uid <login> --pwd -` — rebuilds, tests, saves.
|
|
155
|
-
|
|
156
|
-
`--db` REQUIRED with >1 connection (overwrites credentials; wrong guess clobbers another DB's token).
|
|
157
|
-
|
|
158
|
-
## 6. userToken
|
|
159
|
-
|
|
160
|
-
- `userToken` = user's Bearer token to call `spAPI_*` after deploy as a real user; `dbToken` = direct SQL Server connection.
|
|
161
|
-
|
|
162
|
-
```
|
|
163
|
-
dbToken → SQL Server connection to run schema/SP
|
|
164
|
-
userToken → call tAPI REST API as an end-user (test spAPI_*)
|
|
165
|
-
```
|
|
166
|
-
|
|
167
|
-
- Shareable across projects with the same `GroupName` in `_projectInfo.json` (`{ "GroupName": "GroupA" }`): `fui db user-token --db <alias> --from <project/alias>` — no re-login. `fui db user-token` with no source lists workspace tokens.
|
|
168
|
-
- Stored PER CONNECTION in `_connections.json`. Multi-DB → one token per connection; pass `--db <alias>` (omitted → default).
|
|
169
|
-
- `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.
|
|
170
|
-
- Not set at `fui db add` → `fui db user-token --db <alias> --token -`.
|
|
171
|
-
|
|
172
|
-
## 6a. Domain SSO — same parent domain: token works, don't ask
|
|
173
|
-
|
|
174
|
-
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`.
|
|
175
|
-
|
|
176
|
-
- 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.
|
|
177
|
-
- Scanning the workspace for tokens (`fui db user-token` without a token) is valid and recommended.
|
|
178
|
-
|
|
179
|
-
| Case | Action |
|
|
180
|
-
| ------------------------------------------------- | -------------------------------------------- |
|
|
181
|
-
| Same parent domain | Use now, no asking/testing |
|
|
182
|
-
| Different parent domain (`*.dhlh.vn`, `*.fap.vn`) | Token invalid — need that domain's token |
|
|
183
|
-
| `domainSetting` hosts on different parent domains | Each parent domain is its own SSO zone (§2a) |
|
|
184
|
-
|
|
185
|
-
> `GroupName` is admin grouping; the parent domain decides acceptance. If they differ, trust the domain.
|
|
186
|
-
|
|
187
|
-
## 7. Schema refresh
|
|
188
|
-
|
|
189
|
-
| When | Command |
|
|
190
|
-
| --------------------------------------------------------------- | ------------------------------ |
|
|
191
|
-
| After `fui db add` | Not needed |
|
|
192
|
-
| User asks / table or SP created, renamed, dropped / cache stale | `fui schema pull --db <alias>` |
|
|
193
|
-
|
|
194
|
-
Read cache (no DB call): `fui schema [--db <alias>] [--type Table|View|API|"API File"|Procedure|Function] [--search text]`.
|
|
195
|
-
|
|
196
|
-
- Each connection has its own `schema.json`; both commands act on one connection. Pulling one alias doesn't refresh others — check `fui db list`, pull each. Object missing in `fui schema` usually = wrong connection.
|
|
197
|
-
- `fui schema pull` also reloads every `_db/{alias}/{name}.sql`; local copies differing from server go to `_history/` first. Don't trust local files as latest before a pull.
|
|
198
|
-
|
|
199
|
-
Orphans: `fui db add`/`fui schema pull` scan actual `.sql` files in that connection's `_db/{alias}/` only:
|
|
200
|
-
|
|
201
|
-
| Group | Condition | Behavior |
|
|
202
|
-
| ----------------- | --------------- | -------------------------------------------------------------------------------------------------------------- |
|
|
203
|
-
| Alive | in NEW schema | keep, reload body |
|
|
204
|
-
| Dropped on server | in OLD, not NEW | archive to `_history/{projectId}/_db/{alias}/{name}_{timestamp}_deleted.sql`, remove locally |
|
|
205
|
-
| Local only | in neither | listed, NOT deleted (likely unsaved draft from `fui sp save`); clean with `fui schema pull --prune-local-only` |
|
|
206
|
-
|
|
207
|
-
Prints `📋 Archived orphaned local SP file(s)...` when archiving. Name match is case-insensitive.
|
|
208
|
-
|
|
209
|
-
## 8. SP workflow
|
|
210
|
-
|
|
211
|
-
```
|
|
212
|
-
1. fui sp list → all connections, SPs tagged by alias
|
|
213
|
-
2. fui sp get <name> → fetch definition → _db/{alias}/{name}.sql
|
|
214
|
-
3. edit _db/{alias}/{name}.sql
|
|
215
|
-
4. fui sp save <name> -f file.sql → local only, not deployed
|
|
216
|
-
5. fui sp deploy <name> → server's RUNNING version saved to _history/ first (rollback copy);
|
|
217
|
-
spAPI_*/spAPIFILE_* → auto /help clears tAPI cache once
|
|
218
|
-
(failure ignored, doesn't block, don't retry)
|
|
219
|
-
6. fui sp help <name> → REQUIRED if the SP was ALTERed outside fui sp deploy
|
|
220
|
-
(e.g. ALTER PROCEDURE via fui exec — no auto-clear).
|
|
221
|
-
Also shows input params before wiring IN/OUT in module.json.
|
|
222
|
-
Calls ONCE on the standard URL; failure = one info line.
|
|
223
|
-
Do NOT try URL variants.
|
|
224
|
-
7. fui sp verify <name> [--params …] → STATIC contract check (read or write API); calls NO endpoint.
|
|
225
|
-
Reads real SP body → response shape, error contract, read/write,
|
|
226
|
-
apiMocks snippet for fui module simulate. REQUIRED before writing
|
|
227
|
-
apiMocks for an existing SP — never invent structure;
|
|
228
|
-
fui module simulate warns on unverified mocks matching real SPs.
|
|
229
|
-
```
|
|
230
|
-
|
|
231
|
-
- `--db` omitted → inferred from SP name (schema + local `.sql` per connection). One match → silent; zero or several (same name in two DBs) → alias menu, pick and re-run, don't guess.
|
|
232
|
-
- `fui sp save` for a brand-new SP can't infer: multi-connection projects must pass `--db` on first save.
|
|
233
|
-
|
|
234
|
-
> `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`.
|
|
235
|
-
|
|
236
|
-
**Rollback:** read `{FUI_MCP_WORKDIR}/_history/{projectId}/_db/{alias}/{name}_{timestamp}.sql` → `fui sp save <name> -f <old file>` → `fui sp deploy <name>`.
|
|
237
|
-
|
|
238
|
-
## 8a. Linked Server — `spIO_IN_` / `spIO_OUT_`
|
|
239
|
-
|
|
240
|
-
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:
|
|
241
|
-
|
|
242
|
-
```sql
|
|
243
|
-
EXEC XDATA23.Calendar2015.dbo.spIO_IN_DeleteMonHocInfo @MonHocID, @ErrorDKMH OUTPUT
|
|
244
|
-
-- ^^^^^^^^^^^^^^^^^^^^^^^^^ ← 4 parts: linked-server.database.schema.sp-name
|
|
245
|
-
```
|
|
246
|
-
|
|
247
|
-
| Prefix | Direction | Use |
|
|
248
|
-
| ----------- | ----------------- | --------------------------------------------------------- |
|
|
249
|
-
| `spIO_IN_` | Into current DB | Receives commands from an external DB, acts on current DB |
|
|
250
|
-
| `spIO_OUT_` | Out of current DB | Provides data for an external DB to call |
|
|
251
|
-
|
|
252
|
-
- These are boundary SPs, NOT tAPI endpoints (despite `spIO_`). Never wire into `"API":` in module.json.
|
|
253
|
-
- New SPs acting across a linked server MUST use the prefix matching data direction.
|
|
254
|
-
- `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 alias.
|
|
255
|
-
|
|
256
|
-
## 9. List connections
|
|
257
|
-
|
|
258
|
-
`fui db list -p <projectId>` — every connection: alias, `apiDomain`, `sqlServer`, `database`, `_db/{alias}/`, 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.
|
|
259
|
-
|
|
260
|
-
## 10. Cheat sheet
|
|
261
|
-
|
|
262
|
-
| Situation | Command |
|
|
263
|
-
| ------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
|
|
264
|
-
| DB doesn't exist (from scratch) | [project-provisioning.md](project-provisioning.md): 2 permission gates → CREATE DATABASE → 2 accounts → `fui db alias new` |
|
|
265
|
-
| Check `CREATE DATABASE`/`CREATE LOGIN` rights | [project-provisioning.md](project-provisioning.md) §Step 0 — `IS_SRVROLEMEMBER` + `HAS_PERMS_BY_NAME`, read-only |
|
|
266
|
-
| DB exists, no alias in `acc` | `fui db alias new` ([project-provisioning.md](project-provisioning.md) §Step 5) |
|
|
267
|
-
| First connect, have dbToken | `fui db add` |
|
|
268
|
-
| Alias only, no dbToken | `fui db alias list` → `fui db add-by-name` |
|
|
269
|
-
| Which DBs am I granted | `fui db alias list` |
|
|
270
|
-
| Another DB (new alias) | `fui db add-by-name` again |
|
|
271
|
-
| Connections + default | `fui db list` |
|
|
272
|
-
| UID/PWD changed | `fui db token-rebuild` (`--db` if several) |
|
|
273
|
-
| Set userToken | `fui db user-token` (`--db` if several) |
|
|
274
|
-
| List tables/SPs | `fui sp list` |
|
|
275
|
-
| Get SP body | `fui sp get` |
|
|
276
|
-
| Refresh / read schema | `fui schema pull` / `fui schema` |
|
|
277
|
-
| Save SQL locally | `fui sp save` |
|
|
278
|
-
| Deploy (auto cache clear for spAPI__/spAPIFILE__) | `fui sp deploy` |
|
|
279
|
-
| API input params before wiring | `fui sp help` |
|
|
280
|
-
| Clear tAPI cache after ALTER via `fui exec` | `fui sp help` (required) |
|
|
281
|
-
| Static check of deployed API | `fui sp verify` |
|
|
282
|
-
| Drop / rename SP | `fui sp delete` / `fui sp rename` |
|
|
283
|
-
| SQLServer + DatabaseName of an alias | `fui db alias list --search <text>` |
|
|
284
|
-
| dbToken via borrowed UID/PWD | `fui db add-by-name` — never decode by hand in PowerShell |
|
|
285
|
-
|
|
286
|
-
## 11. Table design
|
|
287
|
-
|
|
288
|
-
Naming, primary keys, timestamps, audit columns: [db-table-design.md](db-table-design.md) — load when designing a schema.
|