@fui-org/fui-cli 1.3.1 → 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.
Files changed (111) hide show
  1. package/README.md +19 -3
  2. package/dist/fui-bmg5pnmq.js +379 -0
  3. package/dist/fui.js +1 -1
  4. package/package.json +7 -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/dist/fui-x7kph78r.js +0 -420
  63. package/skills/fui-skill/README.md +0 -112
  64. package/skills/fui-skill/metadata.json +0 -75
  65. package/skills/fui-skill-cli/SKILL.md +0 -139
  66. package/skills/fui-skill-cli/references/INDEX.md +0 -110
  67. package/skills/fui-skill-cli/references/advanced-techniques.md +0 -168
  68. package/skills/fui-skill-cli/references/coding-standards.md +0 -112
  69. package/skills/fui-skill-cli/references/component-design.md +0 -448
  70. package/skills/fui-skill-cli/references/component-quickref.md +0 -78
  71. package/skills/fui-skill-cli/references/component-table.md +0 -248
  72. package/skills/fui-skill-cli/references/components-dialog.md +0 -191
  73. package/skills/fui-skill-cli/references/components-display.md +0 -141
  74. package/skills/fui-skill-cli/references/components-echart.md +0 -316
  75. package/skills/fui-skill-cli/references/components-input.md +0 -335
  76. package/skills/fui-skill-cli/references/controls-patterns.md +0 -701
  77. package/skills/fui-skill-cli/references/controls-styling-vocabulary.md +0 -137
  78. package/skills/fui-skill-cli/references/db-table-design.md +0 -73
  79. package/skills/fui-skill-cli/references/db-workflow.md +0 -288
  80. package/skills/fui-skill-cli/references/default-function.md +0 -425
  81. package/skills/fui-skill-cli/references/design-modes.md +0 -57
  82. package/skills/fui-skill-cli/references/echart-templates.md +0 -489
  83. package/skills/fui-skill-cli/references/fastproject.md +0 -99
  84. package/skills/fui-skill-cli/references/fsheet.md +0 -203
  85. package/skills/fui-skill-cli/references/fullstack-workflow.md +0 -313
  86. package/skills/fui-skill-cli/references/module-data-patterns.md +0 -117
  87. package/skills/fui-skill-cli/references/module-json-anatomy.md +0 -132
  88. package/skills/fui-skill-cli/references/module-structure.md +0 -141
  89. package/skills/fui-skill-cli/references/new-session.md +0 -85
  90. package/skills/fui-skill-cli/references/pdfmake.md +0 -60
  91. package/skills/fui-skill-cli/references/permission-system.md +0 -150
  92. package/skills/fui-skill-cli/references/platform-architecture.md +0 -269
  93. package/skills/fui-skill-cli/references/project-config.md +0 -303
  94. package/skills/fui-skill-cli/references/project-provisioning.md +0 -278
  95. package/skills/fui-skill-cli/references/script-map.md +0 -262
  96. package/skills/fui-skill-cli/references/sql-clr-functions.md +0 -225
  97. package/skills/fui-skill-cli/references/system-design.md +0 -89
  98. package/skills/fui-skill-cli/references/tapi-file-api.md +0 -185
  99. package/skills/fui-skill-cli/references/tapi-permission-patterns.md +0 -156
  100. package/skills/fui-skill-cli/references/tapi-reference.md +0 -474
  101. package/skills/fui-skill-cli/references/tools-registry.md +0 -84
  102. package/skills/fui-skill-cli/references/ui-crosswindow-patterns.md +0 -321
  103. package/skills/fui-skill-cli/references/ui-dialog-patterns.md +0 -255
  104. package/skills/fui-skill-cli/references/ui-layout-patterns.md +0 -176
  105. package/skills/fui-skill-cli/references/ui-patterns.md +0 -303
  106. package/skills/fui-skill-cli/references/ui-screenshot-review.md +0 -95
  107. package/skills/fui-skill-cli/references/ui-table-cell-patterns.md +0 -318
  108. package/skills/fui-skill-cli/references/ui-templates.md +0 -22
  109. package/skills/fui-skill-cli/references/verification.md +0 -236
  110. package/skills/fui-skill-cli/references/watcher-patterns.md +0 -163
  111. package/skills/fui-skill-cli/references/websocket-realtime.md +0 -271
@@ -1,278 +0,0 @@
1
- # Provisioning a New FUI Project
2
-
3
- > Owns: **new-project infrastructure — SQL Server database, two SQL accounts (execute-only app vs db_owner dev), `acc` alias, FUI project, project admin rights**. Connection/schema/SP: [db-workflow.md](db-workflow.md); multi-module design: [system-design.md](system-design.md); table naming: [db-table-design.md](db-table-design.md); end-user rights: [permission-system.md](permission-system.md). Flags: `fui <command> --help`.
4
-
5
- Use for **"new project"** / **"new DB + FUI project"**, or [system-design.md](system-design.md) Step 0 → _"build from scratch"_. Comes **before** all of `system-design.md`.
6
-
7
- **Do Step 0, then Steps 1–6 in order, skipping none** unless the user says otherwise. Two permission gates in two systems must both pass before anything is created.
8
-
9
- ---
10
-
11
- ## 🛑 Step 0 — Check BOTH gates first
12
-
13
- | Gate | Needs | Check with |
14
- | ------------------------ | --------------------------------- | -------------------------- |
15
- | **A. FUI platform** | `SystemRight >= 3` on system `fp` | `fui project new` (Step 1) |
16
- | **B. Target SQL Server** | create database + create login | read-only `SELECT` below |
17
-
18
- **Check B BEFORE A.** B has no side effects; A only answers by actually creating the project. Reverse order ⇒ orphan FUI project if the DB can't be created. Late discovery leaves garbage fui can't clean up.
19
-
20
- ### Gate B — target SQL Server
21
-
22
- `CREATE DATABASE`/`CREATE LOGIN` are server-level; a normal dev account (`db_owner` on some DBs) can't. Run with `fui query` on a connection **to the exact target server** (`fui db alias list` shows alias → server):
23
-
24
- ```sql
25
- SELECT SUSER_NAME() AS LoginHienTai,
26
- IS_SRVROLEMEMBER('sysadmin') AS sysadmin,
27
- IS_SRVROLEMEMBER('dbcreator') AS dbcreator,
28
- IS_SRVROLEMEMBER('securityadmin') AS securityadmin,
29
- HAS_PERMS_BY_NAME(NULL, NULL, 'CREATE ANY DATABASE') AS taoDuocDB,
30
- HAS_PERMS_BY_NAME(NULL, NULL, 'ALTER ANY LOGIN') AS taoDuocLogin;
31
- ```
32
-
33
- Pass: `sysadmin = 1`, **or** `taoDuocDB = 1` **and** `taoDuocLogin = 1`.
34
-
35
- - `sa` not required — `dbcreator` + `securityadmin` also pass. Don't block a valid setup with "needs `sa`".
36
- - Need BOTH: `dbcreator` alone creates the DB but not the Step 3 login ⇒ fails midway.
37
- - `IS_SRVROLEMEMBER` returns `NULL` (not `0`) for a bad role name/invalid login ⇒ **unknown**, ask the user.
38
- - A connection borrowed from a sibling project may point at another server ⇒ green for the wrong server.
39
- - ⚠️ `HAS_PERMS_BY_NAME` answers only for the _connected principal_ — correct here. Never use it for another principal (e.g. `[public]` `EXECUTE`): always green for `db_owner`. Read `sys.database_permissions` instead.
40
-
41
- Fails ⇒ **stop; user must request rights on that server**. Never run `CREATE DATABASE` to probe; never grant `db_datareader` to the app account to avoid creating a login.
42
-
43
- ### Gate A — FUI platform
44
-
45
- Creating a project needs **`SystemRight >= 3`** on `fp`, enforced server-side in `spAPI_FUI_Dev_ProjectEdit` (direct API calls can't bypass):
46
-
47
- ```sql
48
- if @jID is null -- không có id ⇒ đang TẠO MỚI
49
- Begin
50
- if @sys_SystemRight < 3
51
- RAISERROR(N'Bạn không có quyền tạo dự án', 16, 1)
52
- ```
53
-
54
- **No right ⇒ STOP, report, do nothing else.** Project goes before the DB because `INSERT INTO tblA_Project` needs only `ProjectID`/`ProjectName`/`GroupName`/`Framework`/`pDomain`/`Router` — no database. DB-first then rejection leaves a real DB, two SQL logins and an orphan `acc` record; fui hard-blocks `DROP DATABASE`, so cleanup is manual. `fui project new` _is_ the gate A check (no extra call); rejected ⇒ nothing created (if B was checked first).
55
-
56
- | Operation | SP | Condition |
57
- | ----------------------------------------------------- | --------------------------------------------------------- | ------------------------------------------ |
58
- | **Create** project (`fui project new`) | `spAPI_FUI_Dev_ProjectEdit` (empty `id`) | `SystemRight >= 3` |
59
- | **Edit** project (`fui project update`) | `spAPI_FUI_Dev_ProjectEdit` (with `id`) | `SystemRight >= 2` **and** `UserRight > 2` |
60
- | Publish `project.json` (`fui project publish-config`) | `spAPI_FUI_Dev_EditorUpdate` (`Mode = 'project'`) | `SystemRight >= 2` **and** `UserRight > 2` |
61
- | Create/edit/publish **module** | `spAPI_FUI_Dev_ModuleEdit` · `spAPI_FUI_Dev_EditorUpdate` | `SystemRight >= 2` **and** `UserRight > 1` |
62
-
63
- `SystemRight` (whole `fp`) is necessary, `UserRight` (that project) sufficient — ANDed. Only _create_ skips `UserRight` (no `tblA_UserProject` row yet).
64
-
65
- > ⚠️ `pDomain` is checked **before** the permission gate (`CheckDomain`): a duplicate domain gives a domain error, not a permission error. Don't go request rights over it.
66
-
67
- ---
68
-
69
- ## Index — phases of a new project
70
-
71
- This file owns **phase 1 only**.
72
-
73
- | # | Phase | Owner | Do |
74
- | ----- | ------------------------- | -------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------- |
75
- | 0 | Clarify scope | [system-design.md](system-design.md) §Step 0 | Users, process, main entities |
76
- | **1** | **Infrastructure ← HERE** | **this file** | 2 gates → `fui project new` → DB + 2 SQL accounts + `acc` alias → admin rights |
77
- | 2 | Split into modules | [system-design.md](system-design.md) §Step 1 | Module list, access roles |
78
- | 3 | Schema | [db-table-design.md](db-table-design.md) | Naming, PK/FK, audit columns. `CREATE TABLE` **run by the developer** |
79
- | 4 | **End-user** rights | [permission-system.md](permission-system.md) + [system-design.md](system-design.md) §Step 4b | `fui right system new` / `fui right function new` — BEFORE any module gates on them |
80
- | 5 | Runtime config | [project-config.md](project-config.md) | `project.json`: menu, menuLeft, navigation, domainSetting |
81
- | 6 | First module | `fui module new` → [fullstack-workflow.md](fullstack-workflow.md) | 6-step UI-first flow |
82
-
83
- Not in this file (don't look or copy here): table naming · menus · end-user rights · SP writing ([tapi-reference.md](tapi-reference.md)) · daily connection/schema/SP ([db-workflow.md](db-workflow.md)).
84
-
85
- ---
86
-
87
- ## 🔴 Two permission planes — don't mix
88
-
89
- | | `SystemRight` (system `acc`) | `UserRight` (`tblA_UserProject`) |
90
- | --------- | ------------------------------------------------------------------ | --------------------------------------- |
91
- | Scope | **System-wide** — one number per user per app | **Per project** |
92
- | Answers | "What can this user do in app X?" | "What can this user do with project Y?" |
93
- | Stored in | `acc.tblSysRight` + `acc` assignment tables | `tblA_UserProject` (FUI platform DB) |
94
- | Commands | `fui right ...` (8) → [permission-system.md](permission-system.md) | `fui user ...` (5) → Step 6 |
95
-
96
- Mixing them = granting in the wrong place, then "granted but no effect". The FUI IDE _is itself a FUI app_ (project `fp`), so `SystemRight` on `fp` = developer rights in the IDE:
97
-
98
- - `SystemRight` on `fp` = **may create projects** (≥ 3); necessary for every edit.
99
- - `UserRight` on project Y = **may touch Y**; sufficient.
100
- - ANDed: `UserRight = 3` with `SystemRight = 1` can't edit anything.
101
-
102
- `SystemRight`/`FunctionRight` on **your business project** (not `fp`) are end-user rights — later, per [system-design.md](system-design.md) Step 4b.
103
-
104
- ---
105
-
106
- ## Step 1 — Create the FUI project (gate A, before the DB)
107
-
108
- ```
109
- fui project new --data '{
110
- "ProjectID": "...", "ProjectName": "...", "GroupName": "...", "Framework": "V3",
111
- "pDomain": "...",
112
- "Router": ""
113
- }'
114
- ```
115
-
116
- `pDomain` optional (project's own domain); `Router` optional, default `""`.
117
-
118
- - **Only these SIX fields are read** from `@jsonObj`.
119
- - 🔴 **`title`/`login`/`apiDomain`/`fileDomain`/`userInfo`/`menu` are silently IGNORED.** The SP writes `projectData` from a hardcoded constant:
120
- ```sql
121
- declare @jProjectdata nvarchar(1000) = '{"title":"","apiDomain":"","login":"","menu":[]}'
122
- ```
123
- API still returns ✅, project created, config lost — silent failure.
124
- - Runtime config: edit `{projectId}/project.json` then `fui project publish-config` ([project-config.md](project-config.md)) — the **only** way `menu`/`apiDomain`/`login` get in.
125
- - `projectData` must be **FLAT** — not wrapped in `"data"`.
126
- - **`Framework`: `V3` for new projects** unless the user has a reason (usually matching older projects in the group). Expensive to change: decides import layer, component vocabulary, grid syntax — V2 = Vuetify 1.5 (`v-container/v-layout/v-flex`), V3 = Vuetify 3 (`v-container/v-row/v-col`), and `w` px thresholds differ. Most skill module.json examples are **V2**; for V3 cross-check [controls-patterns.md](controls-patterns.md) §6 (V2/V3 diff owner). State the choice to the user; never implicit.
127
-
128
- **Only the caller gets `UserRight = 3` on the new project** (SP `INSERT INTO tblA_UserProject ... 3`) — hence Step 6.
129
-
130
- Rejected with `Bạn không có quyền tạo dự án` ⇒ **stop; user must request `SystemRight >= 3` on `fp`**. Nothing created yet — keep it so.
131
-
132
- ---
133
-
134
- ## Step 2 — Create the database
135
-
136
- > Prerequisite: gate B green. Never run `CREATE DATABASE` to probe.
137
-
138
- **Query where the server keeps other DB files; never hardcode paths** (wrong guess = misplaced files, unnoticed until backup):
139
-
140
- ```sql
141
- SELECT DISTINCT LEFT(physical_name, LEN(physical_name) - CHARINDEX('\', REVERSE(physical_name)))
142
- FROM sys.master_files WHERE database_id > 4;
143
- ```
144
-
145
- `database_id > 4` skips `master`/`model`/`msdb`/`tempdb` (install dir). Typical: `C:\Application\Database\`. Follow it:
146
-
147
- ```sql
148
- CREATE DATABASE [TenDB]
149
- ON PRIMARY (NAME = N'TenDB', FILENAME = N'C:\Application\Database\TenDB.mdf')
150
- LOG ON (NAME = N'TenDB_log', FILENAME = N'C:\Application\Database\TenDB_log.ldf');
151
- ```
152
-
153
- Chicken-and-egg: the new DB has no connection — borrow an **existing connection on the same server** (`fui db alias list`, then `fui db add-by-name <apiName>`) and run `fui exec "<sql>" --confirm-write`.
154
-
155
- ---
156
-
157
- ## Step 3 — APP account (execute-only)
158
-
159
- Login **named after the DB**, strong random password:
160
-
161
- ```bash
162
- openssl rand -base64 12
163
- ```
164
-
165
- ```sql
166
- CREATE LOGIN [TenDB] WITH PASSWORD = N'<mật khẩu vừa sinh>',
167
- DEFAULT_DATABASE = [TenDB], CHECK_POLICY = ON;
168
- USE [TenDB];
169
- CREATE USER [TenDB] FOR LOGIN [TenDB];
170
- GRANT EXECUTE ON SCHEMA::dbo TO [TenDB];
171
- ```
172
-
173
- **Only `public` + `GRANT EXECUTE ON SCHEMA::dbo`. NO `db_datareader`, NO `db_datawriter`, NO table grants.** tAPI only runs SPs; new SPs fall under `SCHEMA::dbo` automatically. Table rights don't help the app — they only open direct table access to an abused call.
174
-
175
- The **only** account loaded into `acc` (Step 5).
176
-
177
- ---
178
-
179
- ## Step 4 — DEV account (db_owner)
180
-
181
- **Default: reuse the existing shared dev login** (e.g. `xTuan`) — just add it to the new DB:
182
-
183
- ```sql
184
- USE [TenDB];
185
- CREATE USER [xTuan] FOR LOGIN [xTuan];
186
- ALTER ROLE db_owner ADD MEMBER [xTuan];
187
- ```
188
-
189
- **NO new `CREATE LOGIN`** unless the user asks for a project-specific dev account — each extra login is another password, while the shared one exists in every sibling DB and is the credential `fui db add-by-name` borrows.
190
-
191
- ---
192
-
193
- ## Step 5 — Register the DB as a tAPI alias
194
-
195
- ```
196
- fui db alias new tenalias \
197
- --module-name "Tên hệ thống" \
198
- --sql-server "..." \
199
- --database TenDB \
200
- --username TenDB \
201
- --password-env TENDB_PASSWORD
202
- ```
203
-
204
- `tenalias` → module.json calls `"/tenalias/TenAPI"`. Password only via `--password -` (stdin) or `--password-env VAR`.
205
-
206
- fui calls `SM_Modules_Update` **twice**: `UpdateConnection=0` creates the record, `UpdateConnection=1` sets the connection (record must exist first).
207
-
208
- - 🔴 **Credentials = Step 3 APP account, NEVER the dev account.** Dev account ⇒ every app API call runs as `db_owner`, with no visible error.
209
- - New `ModuleID` = `MAX(ModuleID)+1` over **all** `acc.tblModules` ⇒ needs an `acc` connection (`fui db add-by-name acc`). Can't use `fui db alias list`: it lists only modules **you** manage; MAX over a subset may collide.
210
- - Existing alias ⇒ hard error, no overwrite.
211
-
212
- Then `fui db add-by-name tenalias` works — [db-workflow.md](db-workflow.md) §2b.
213
-
214
- ---
215
-
216
- ## Step 6 — Grant project admin to others
217
-
218
- Order is **mandatory**:
219
-
220
- ```
221
- 1. fui user list → who has rights now
222
- 2. fui user search "tên/username" → get the real UserID
223
- 3. fui user add DEV001 --right 3
224
- ```
225
-
226
- **`fui user add`/`set`/`remove` take only the exact `UserID`** — a structural identity gate: you must run `fui user search` and see `UserID | Username | Họ tên`. **Show that table and let the user pick before granting** — duplicate names are common; a wrong Admin grant can't be undone in one call.
227
-
228
- | Level | Meaning |
229
- | ----- | -------------------------------------------------------------------------------------- |
230
- | 1 | View only |
231
- | 2 | Develop |
232
- | 3 | **Admin** — needed to manage the project (`fui project publish-config` requires `> 2`) |
233
-
234
- - Create and edit are separate: `fui user add` hard-errors if rights exist (use `set`), and vice versa. No silent upsert.
235
- - Revoke = `fui user remove` — 🔴 summarize the consequence, wait for confirmation.
236
- - **Rights are ALWAYS project-level.** The SP has `@MID` and IDE module `fp/permission` passes it, but the body never reads it — all filtering is by `ProjectID`. Don't infer a module scope.
237
-
238
- **For YOU to grant** (`spAPI_FUI_Dev_UserRight_Update`): `SystemRight >= 2` **and** (`UserRight > 2` on the project **or** `SystemRight >= 4`) — `SystemRight >= 4` grants on any project. _Listing_ (`fui user list`): `SystemRight >= 2` and (`UserRight > 1` or `SystemRight >= 3`).
239
-
240
- ---
241
-
242
- ## After infrastructure
243
-
244
- Step 6 ends **phase 1 only**: the project is empty, runtime config still SP-seeded empty strings, no tables/modules/right codes. Don't report "done"; don't jump into module.json.
245
-
246
- 1. `fui project sync` + `fui use <projectId>` — pull into workspace, set as target.
247
- 2. **Runtime config (mandatory)**: edit `{projectId}/project.json` (`apiDomain` → new alias, `title`, `login`, `menu`), then `fui project publish-config` — [project-config.md](project-config.md). Skipped ⇒ the project can't call any API.
248
- 3. `fui db add-by-name <apiName>` ([db-workflow.md](db-workflow.md) §2c) — also **proves** Steps 3 and 5 (app account + `acc` record OK).
249
- 4. Resume [system-design.md](system-design.md) at **Step 1**, following the index.
250
-
251
- Only **one** simple module ⇒ skip `system-design.md`: `fui module new` → [fullstack-workflow.md](fullstack-workflow.md).
252
-
253
- ---
254
-
255
- ## Checklist
256
-
257
- - [ ] Gate B: read-only `SELECT` on the **target server** — `sysadmin = 1`, or `CREATE ANY DATABASE` **and** `ALTER ANY LOGIN` = 1
258
- - [ ] Gate A: `fui project new` ran BEFORE the DB and succeeded — else stop, no DB
259
- - [ ] `projectData` FLAT, **only 6 fields**; `Framework` agreed with user
260
- - [ ] Physical folder from `sys.master_files`, not hardcoded; `CREATE DATABASE` `FILENAME` follows it
261
- - [ ] App account: login = DB name, random password, **only** `GRANT EXECUTE ON SCHEMA::dbo`
262
- - [ ] Dev account: **shared login reused**, only `CREATE USER` + `db_owner`
263
- - [ ] `fui db alias new` loaded the **app account**
264
- - [ ] `fui db add-by-name <apiName>` works
265
- - [ ] `fui user list` shows exactly the right people
266
- - [ ] `fui project sync` + `fui use` + **`fui project publish-config`** done
267
- - [ ] Told the user **what phase 2 is**
268
- - [ ] **Security check**: as the app account, `SELECT TOP 1 * FROM <any table>` is **denied** and `EXEC` of an SP works — otherwise the `GRANT` is unverified
269
-
270
- ---
271
-
272
- ## Three common misreadings
273
-
274
- **Server-level DDL ≠ business-schema DDL.** `CREATE DATABASE` / `CREATE LOGIN` / `GRANT` run via `fui exec "<sql>" --confirm-write`. The _"`CREATE TABLE`/`ALTER TABLE` run by the developer"_ rule ([system-design.md](system-design.md) Step 2) still stands for the **business schema** only — no conflict.
275
-
276
- **The app password is in the transcript verbatim** (Step 3 `CREATE LOGIN` goes through the fui command) — treat the provisioning transcript as sensitive. From Step 5 on nothing prints it (`fui db alias new`/`fui db alias list` omit `Password`).
277
-
278
- **Step 6 `UserRight` ≠ `SystemRight` on the business project.** `UserRight=3` grants **nothing** in the running app, and vice versa.
@@ -1,262 +0,0 @@
1
- # FUI Script Map
2
-
3
- > Owns: **bundled libraries (§0) and the FUI script source map — which function lives in which file/line**. Function usage: [default-function.md](default-function.md). Read framework sources with `fui library <name>`.
4
-
5
- > **File by framework** — check `_moduleInfo.json.Framework` (`"V2"` or `"V3"`):
6
- >
7
- > | Content | V2 file | V3 file |
8
- > | --------------------------------------------- | -------------------------------- | -------------------------------- |
9
- > | Core engine (action, API, layout) | `scripts/fastproject.js` | `scripts/fastproject-3.0.js` |
10
- > | Utilities (router, export, auth, WS) | `scripts/defaultfunction.js` | `scripts/defaultfunction-3.0.js` |
11
- > | Component registry (`f-*`, dialog, editor...) | `scripts/component.js` | `scripts/component-3.0.js` |
12
- > | Table system (`f-table`, `t-*`) | `scripts/componentTable.js` | `scripts/componentTable-3.0.js` |
13
- > | Chart (`f-echart`) | `scripts/fechart.js` | `scripts/fechart.js` |
14
- > | Input sheet (`f-sheet`) | `scripts/fsheet.js` (shared, §5) | `scripts/fsheet.js` (shared, §5) |
15
-
16
- FUI conventions:
17
-
18
- - Metadata is `module.json` (not `controls.json`).
19
- - Call action logic via `CALL(vueData.actionName)` or the Action Protocol.
20
- - `controls` layout is always `container > rows > cols`.
21
- - JSON events use `v-on:...` (not `@...`).
22
- - Literal forcing (`` ` `` or `'...'`) is for Action `IN` mapping, not normal static component props.
23
-
24
- ## 0) Bundled libraries (FUI V2)
25
-
26
- Auto-loaded into **every** module — no import needed; use them instead of equivalents. **Never add a CDN** for any of them — re-adding causes conflicts.
27
-
28
- > ⛔ **Applies ONLY to `HTMLOnly=false`.** `HTMLOnly: true` modules get nothing preloaded (no Vue, Vuetify, jQuery, lodash, MDI, `projectdefaultstyle.css`); there CDNs are **required**: see [module-structure.md §HTMLOnly=true: KHÔNG có thư viện nào được nhúng sẵn](module-structure.md).
29
-
30
- CSS: Roboto · Material Design Icons (`mdi-*`) · Vuetify · vue-toast-notification · jquery-confirm · FUI projectdefaultstyle.css
31
-
32
- | Global | Library | Use |
33
- | ---------------------------- | ---------------------- | -------------------------------------------- |
34
- | `$`, `jQuery` | jQuery 3.6.0 | DOM, AJAX |
35
- | `$.confirm()` / `$.dialog()` | jquery-confirm | Styled dialogs (instead of `window.confirm`) |
36
- | `_` | Lodash 4.17 | Array/object utils |
37
- | `moment` | Moment.js (vi) | Dates, Vietnamese locale preset |
38
- | `numeral` | Numeral.js | Number/currency format |
39
- | `Vue.$toast` | vue-toast-notification | Toasts |
40
-
41
- FUI JS (loaded after the above): `defaultfunction.js` (`jsonToExcel`, `pushRouter`, `openWindow`, `CALL`, `confirm`, `showMessage`, ...) · `component.js` (all `f-*`: `f-table`, `f-form`, `f-echart`, ...) · `componentTable.js` (table helpers) · `fastproject.js` (bootstrapper).
42
-
43
- ```js
44
- // Toast thông báo
45
- Vue.$toast.success("Lưu thành công", { position: "top" });
46
- Vue.$toast.error("Có lỗi xảy ra", { position: "top" });
47
-
48
- // Dialog xác nhận (FUI wrapper — dùng hàm confirm() từ defaultfunction.js)
49
- confirm({
50
- title: "Xác nhận xóa",
51
- message: "Bạn có chắc muốn xóa không?",
52
- action: function () {
53
- /* xử lý khi OK */
54
- },
55
- });
56
-
57
- // Dialog thông báo (FUI wrapper)
58
- showMessage({ title: "Thông báo", message: "Đã lưu thành công" });
59
-
60
- // Lodash — dùng trong script.js / vueData
61
- _.find(vueData.list, { id: 5 });
62
- _.groupBy(vueData.data, "loai");
63
- _.sumBy(items, "soLuong");
64
- _.cloneDeep(vueData.formData);
65
- _.debounce(fn, 300);
66
-
67
- // Moment — format ngày
68
- moment(val).format("DD/MM/YYYY");
69
- moment(val).format("DD/MM/YYYY HH:mm");
70
- moment().subtract(7, "days").format("YYYY-MM-DD");
71
-
72
- // Numeral — format số
73
- numeral(value).format("0,0"); // 1,234,567
74
- numeral(value).format("0,0.0"); // 1,234,567.8
75
- numeral(_.sumBy(items, key)).format("0,0"); // tổng cột trong bảng
76
- ```
77
-
78
- > `f-*` needing extra JS/CSS: [component-quickref.md](component-quickref.md) §Components needing JS/CSS imports.
79
-
80
- ## 1) scripts/fastproject.js — V3: fastproject-3.0.js
81
-
82
- Core engine: init module, build DOM from `module.json.controls`, run actions, map data, call APIs.
83
-
84
- Init: `$(document).ready` → `loadModuleInfo()` (merge config, read URL/user info) → `createModuleDom()` (`runAction($moduleUI.data)` + render controls) → `createWatch()` (watchers from `$moduleUI.watch`) → Vue mounts.
85
-
86
- | Line | Function | Purpose |
87
- | ---: | ---------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
88
- | 65 | `buildParamURL()` | Query string → `vueData` |
89
- | 77 | `loadModuleInfo()` | Load project/module config, user info |
90
- | 122 | `createModuleDom()` | Main layout, render controls, init watch |
91
- | 210 | `buildModuleUI(controlsList, target)` | Recursive UI from JSON controls |
92
- | 233 | `buildControl(controlsList, flex, target)` | One control: attr/event/import |
93
- | 299 | `addImport(importArr)` | Load control script/css deps |
94
- | 310 | `createWatch_Data(obj)` | Init watch data |
95
- | 320 | `createWatch(obj)` | Attach watchers from `watch` |
96
- | 345 | `buildVisualValForObj(controlAttr, target)` | Bind dynamic values into attrs |
97
- | 373 | `runAction(obj, includeData)` | Action engine (object/array) |
98
- | 407 | `vueAction(objAction, includeData, callBack)` | One action (IF/API/CALL/EXE/...) |
99
- | 485 | `mapData(map, target, src, includeData)` | Map data between objects |
100
- | 527 | `defProp(obj)` | Normalize object props for context |
101
- | 537 | `bindData(obj)` | Resolve dynamic string/object |
102
- | 542 | `getVueData(key, src)` | Value by path (`vueData.x.y`, `item.x`, template...). Literal forcing is for `IN` mapping; static props without `:` are already plain strings. |
103
- | 578 | `setValue(target, key, value, srcData, index)` | Set by path on object/window |
104
- | 612 | `bindDataToString(str, data)` | Resolve template string |
105
- | 619 | `templateCompiled(str, data)` | Compile lodash-style template |
106
- | 624 | `getWindowData(value)` | Read window/iframe context |
107
- | 638 | `setWindowData(key, value)` | Write window/iframe context |
108
- | 657 | `runFunction(obj, callback)` | Call declared JS function |
109
- | 665 | `tableActionEvent(ctrl)` | Table/control action events |
110
- | 687 | `callAPI(objApi, callBack, includeData)` | API call (`IN/OUT/CALLBACK`) |
111
- | 743 | `loginFUN()` | Login/redirect |
112
- | 761 | `errorMess(code, message)` | Standard error display |
113
-
114
- ## 2) scripts/defaultfunction.js — V3: defaultfunction-3.0.js
115
-
116
- Shared utilities (router, messaging, transform, AJAX, export, auth, websocket).
117
-
118
- | Line | Function | Purpose |
119
- | ---: | ------------------------------------------------------ | ------------------------------------- |
120
- | 35 | `extractHostname(url)` | Hostname |
121
- | 53 | `getDomainWithoutSubdomain(url)` | Root domain |
122
- | 62 | `loadScripts(scriptsArray, callbackFunc)` | Load scripts, then callback |
123
- | 75 | `pushRouter(router)` | Push browser history |
124
- | 82 | `CALL(obj, includeData)` | Alias of `runAction(...)` |
125
- | 86 | `windowSendMessage(window, cmd, data)` | `postMessage` to parent/window/iframe |
126
- | 100 | `appCommand(cmdData)` | Command to native wrapper (RN/WebKit) |
127
- | 106 | `buildHeader(obj, mapCol)` | Table headers from data/column map |
128
- | 130 | `fillData(obj)` | Map source → destination |
129
- | 162 | `groupBy(arrayObj, groupField, sumArr)` | Group + sum columns |
130
- | 188 | `chartDataBuild(obj)` | Generic chart data |
131
- | 219 | `chartQABuild(obj)` | QA/report chart data |
132
- | 239 | `confirm(obj)` | Confirm dialog |
133
- | 259 | `showMessage(obj)` | Message dialog/toast |
134
- | 283 | `rightTest(rightObject)` | Check user rights |
135
- | 301 | `openWindow(obj)` | FUI popup/dialog window |
136
- | 326 | `redirect(obj, query)` | Navigate by URL/config |
137
- | 339 | `reload()` | Reload page |
138
- | 343 | `findInArray(obj)` | Find by value condition |
139
- | 348 | `fixURL(url)` | Normalize URL (prepend API domain) |
140
- | 354 | `stringAttrToJson(str, removeVueEvent)` | HTML attr string → JSON |
141
- | 371 | `json_data_parse(obj, level)` | Parse `json_data:` fields recursively |
142
- | 407 | `ajaxCALL(URL, DATA, callBack, errorCallBack, header)` | AJAX POST |
143
- | 449 | `capacityText(numb)` | Bytes → KB/MB |
144
- | 454 | `generateID()` | Random ID |
145
- | 467 | `printPDF(obj)` | PDF via `pdfMake` |
146
- | 499 | `colorLib(color)` | Color utils |
147
- | 645 | `transparentize(value, opacity)` | Alpha color |
148
- | 650 | `jsonToExcel(Obj)` | JSON → Excel |
149
- | 746 | `copyToClipboard(textToCopy)` | Clipboard |
150
- | 770 | `fileNameClear(fname)` | Sanitize file name |
151
- | 775 | `hashCode(s)` | String hash |
152
- | 785 | `getCookie(cname)` | Read cookie |
153
- | 800 | `setCookie(name, value, days, domain)` | Set cookie |
154
- | 814 | `logout(cookiesName, domain, url)` | Clear cookies, logout/redirect |
155
- | 827 | `webSocketJoinGroup(groupObj, timeout, callBackFunc)` | Join WS group |
156
- | 851 | `webSocketConnection(wsURL, WS, wsState)` | Create/keep WS connection |
157
- | 892 | `webSocket_Send(obj)` | Send over WS |
158
-
159
- > **Real-time (SignalR)** — required imports, `data[]` group declaration, send/receive, full `module.json`: [websocket-realtime.md](websocket-realtime.md).
160
-
161
- ## 3) scripts/component.js — V3: component-3.0.js
162
-
163
- Base `f-*` and business components. Also holds `defaultControlAttr` (default attrs per `el`). Many need external imports (CKEditor, pdfMake, cropper, chart, ...).
164
-
165
- | Line | Component | Purpose |
166
- | ---: | ----------------- | -------------------------------------------------------------------------------------------------------------------------------------- |
167
- | 304 | `f-label` | Formatted label/text |
168
- | 319 | `f-box` | Simple box/card |
169
- | 377 | `f-header` | Light section header |
170
- | 386 | `f-title` | Title |
171
- | 395 | `f-radiobox` | Radio group |
172
- | 425 | `f-menu` | Menu/navigation |
173
- | 472 | `f-search` | Search input |
174
- | 536 | `f-button` | Button |
175
- | 607 | `f-slider` | Slider |
176
- | 618 | `f-file-upload` | File upload |
177
- | 768 | `f-qrcode` | QR render |
178
- | 843 | `f-qrcode-reader` | QR scan |
179
- | 914 | `f-image-update` | Crop/rotate/upload image dialog |
180
- | 1161 | `f-date` | Date picker |
181
- | 1434 | `f-time` | Time picker |
182
- | 1639 | `f-time-counter` | Counter/countdown/clock |
183
- | 1775 | `fp-profile` | Header profile menu |
184
- | 2020 | `header-bar` | Main header bar |
185
- | 2277 | `f-chart` | Legacy Chart.js (props `data`/`type`/`options`). Use `f-echart` — [components-echart.md](components-echart.md) |
186
- | 2389 | `f-window` | Dynamic window/dialog host |
187
- | 2453 | `f-editor` | WYSIWYG (CKEditor) |
188
- | 2591 | `f-editor-dialog` | Fullscreen editor dialog |
189
- | 2687 | `f-dialog` | Dialog built from `controls` |
190
- | 2899 | `f-pdfmake` | PDF viewer via `printPDF` |
191
- | 2934 | `f-excel-reader` | Excel/CSV → object array: sheet pick, skip N rows, key names, size limit; XLSX lazy-loaded. [components-input.md](components-input.md) |
192
-
193
- ## 4) scripts/componentTable.js — V3: componentTable-3.0.js (§4b)
194
-
195
- | Line | Component | Purpose |
196
- | ---: | ------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
197
- | 1 | `f-table` | The only data table (CRUD and readonly): search, select, CRUD (`update-api`, `update-form`), export, auto headers when `headers` omitted, sum row/line via `sumFormat` (object/string), `:height` |
198
- | 416 | `t-html` | HTML cell |
199
- | 420 | `t-label` | Text cell |
200
- | 424 | `t-num` | Number cell |
201
- | 442 | `t-time` | Time cell |
202
- | 452 | `t-boolean` | Bool icon/color |
203
- | 473 | `t-check` | Checkbox cell |
204
- | 501 | `t-text` | Inline text input |
205
- | 523 | `t-select` | Inline select |
206
- | 544 | `t-combobox` | Inline combobox |
207
- | 616 | `t-menu` | Action menu cell |
208
- | 654 | `t-link` | Link / open-dialog cell |
209
- | 678 | `t-button` | Action button cell |
210
-
211
- **`f-table` `:height`** — computed `heightNum`/`tableHeight` + `updateFillHeight()`: empty = grows with rows; `<=0` = measures real `getBoundingClientRect()`, fills to screen bottom leaving `abs(n)` px (`window.resize` listener); `>0` = fixed px.
212
-
213
- ## 4b) scripts/componentTable-3.0.js
214
-
215
- **V3** (Vue 3 + Vuetify 3) of the same components, PascalCase names (`FTable`, `THtml`, `TNum`, ...). Module framework (`_moduleInfo.json`) picks the file.
216
-
217
- When editing **both** files:
218
-
219
- - Lifecycle: V3 `beforeUnmount` (components declare both to run on V2 and V3).
220
- - Classes: V3 `text-primary` / `text-subtitle-1` / `text-caption` vs V2 `primary--text` / `subtitle-1` / `caption`; `v-btn outlined` (V2) → `variant="outlined"` (V3).
221
- - `v-data-table` scroll wrapper: V2 `.v-data-table__wrapper`, V3 `.v-table__wrapper`.
222
- - Names bound directly in a V3 template **must not start with `_`** (proxy `has` trap) — use a suffix, e.g. `hideDefaultFooter_cacl`.
223
- - `f-table` `headers`: V2 `{ text, value }`, V3 `{ title, key }`; slot `body.append` gets `{ headers }` (V2) / `{ columns }` (V3).
224
-
225
- Verify V3: `node test/v3-table-harness.mjs [sum|fill|auto]` — real V3 framework from `https://fui.vn` in headless chromium with **local `componentTable-3.0.js` swapped in**; APIs blocked + mocked. Prints JS errors/`[Vue warn]`, real height, sum row, AG Grid cells; screenshots `test/v3-{mode}.png`.
226
-
227
- ## 5) scripts/fsheet.js — shared V2 + V3
228
-
229
- Whole `f-sheet` in **one file** for V2 and V3 (declares both `beforeDestroy` and `beforeUnmount`); not split by framework.
230
-
231
- Required imports (from `component.js` `defaultControlAttr["f-sheet"].import`), **in this order**:
232
-
233
- ```
234
- /include/ag-grid/ag-grid-community.min.js
235
- /include/ag-grid/fsheet.js
236
- ```
237
-
238
- | Content | Notes |
239
- | -------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
240
- | `Vue.component('FSheet', {...})` | Main component — props/columns/API: [fsheet.md](fsheet.md) |
241
- | 4 cell renderers (`fsHtmlCellRenderer`/`fsLinkCellRenderer`/`fsButtonCellRenderer`/`fsMenuCellRenderer`) | = `f-table`'s `t-html`/`t-link`/`t-button`/`t-menu` — [fsheet.md](fsheet.md) |
242
- | Custom range selection + fill handle + TSV clipboard | AG Grid Community lacks Cell Selection (Enterprise), so f-sheet drives it and applies AG Grid classes (`.ag-cell-range-*`, `.ag-selection-fill-*`, `.ag-fill-handle`) |
243
-
244
- `:height` has the same 3 modes (auto-grow / fill to bottom / fixed px) — [fsheet.md](fsheet.md) §`:height`.
245
-
246
- Verify `fsheet.js`: `fui component preview` (isolated `f-sheet` with sample data, no push) or `fui module simulate --render` (in a real module) — both real browser, no extra harness.
247
-
248
- ## 6) Lookup by task
249
-
250
- > Files listed are V2; for **V3** use the matching `-3.0` file.
251
-
252
- | Task | Open first | Look at |
253
- | ------------------------------------------- | --------------------------------------- | ----------------------------------------------------------------------------------------- |
254
- | Layout renders wrong | `fastproject.js` | `buildModuleUI`, `buildControl`, `bindData` |
255
- | Action not running / wrong branch | `fastproject.js` | `runAction`, `vueAction`, `mapData`, `getVueData` |
256
- | API returns no `OUT` | `fastproject.js` + `defaultfunction.js` | `callAPI`, `fixURL`, `ajaxCALL` |
257
- | Table Add/Edit/Delete fails | `componentTable.js` | `f-table` + `update-api`, `update-form` |
258
- | Dynamic dialog not binding | `component.js` | `f-dialog`, `buildModuleUI` (fastproject) |
259
- | Image upload/crop/save | `component.js` | `f-image-update` |
260
- | Excel/PDF export | `defaultfunction.js` + `component.js` | `jsonToExcel`, `printPDF`, `f-pdfmake`, `f-excel-reader` |
261
- | Login/rights/menu | `fastproject.js` + `defaultfunction.js` | `loadModuleInfo`, `loginFUN`, `rightTest` |
262
- | `f-sheet` missing / "FSheet is not defined" | `fsheet.js` (shared V2+V3) | Missing import — [component-quickref.md](component-quickref.md) or [fsheet.md](fsheet.md) |