@msbci/form-server 1.3.2 → 1.3.4
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/LICENSE.md +7 -7
- package/README.md +213 -213
- package/dist/index.cjs +1 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +65 -55
- package/dist/index.d.ts +65 -55
- package/dist/index.mjs +1 -2
- package/dist/index.mjs.map +1 -1
- package/package.json +18 -18
- package/src/prisma/schema.prisma +286 -286
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@msbci/form-server",
|
|
3
|
-
"version": "1.3.
|
|
3
|
+
"version": "1.3.4",
|
|
4
4
|
"description": "Form server — REST API with Prisma, multi-tenant, multi-database",
|
|
5
5
|
"main": "./dist/index.cjs",
|
|
6
6
|
"module": "./dist/index.mjs",
|
|
@@ -21,6 +21,21 @@
|
|
|
21
21
|
"publishConfig": {
|
|
22
22
|
"access": "public"
|
|
23
23
|
},
|
|
24
|
+
"dependencies": {
|
|
25
|
+
"@prisma/client": "^6.2.0",
|
|
26
|
+
"zod": "^3.24.0",
|
|
27
|
+
"@msbci/form-core": "1.3.3"
|
|
28
|
+
},
|
|
29
|
+
"devDependencies": {
|
|
30
|
+
"@types/node": "^20.0.0",
|
|
31
|
+
"@vitest/coverage-v8": "^2.1.0",
|
|
32
|
+
"prisma": "^6.2.0",
|
|
33
|
+
"tsup": "^8.3.0",
|
|
34
|
+
"typescript": "^5.7.0",
|
|
35
|
+
"vitest": "^2.1.0"
|
|
36
|
+
},
|
|
37
|
+
"sideEffects": false,
|
|
38
|
+
"license": "SEE LICENSE IN LICENSE.md",
|
|
24
39
|
"scripts": {
|
|
25
40
|
"prisma:generate": "prisma generate --schema=src/prisma/schema.prisma",
|
|
26
41
|
"prisma:sync": "prisma db push --schema=src/prisma/schema.prisma --skip-generate --accept-data-loss",
|
|
@@ -38,20 +53,5 @@
|
|
|
38
53
|
"db:generate": "prisma generate --schema=src/prisma/schema.prisma",
|
|
39
54
|
"db:migrate": "prisma migrate dev --schema=src/prisma/schema.prisma",
|
|
40
55
|
"db:push": "prisma db push --schema=src/prisma/schema.prisma"
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
"@msbci/form-core": "workspace:*",
|
|
44
|
-
"@prisma/client": "^6.2.0",
|
|
45
|
-
"zod": "^3.24.0"
|
|
46
|
-
},
|
|
47
|
-
"devDependencies": {
|
|
48
|
-
"@types/node": "^20.0.0",
|
|
49
|
-
"@vitest/coverage-v8": "^2.1.0",
|
|
50
|
-
"prisma": "^6.2.0",
|
|
51
|
-
"tsup": "^8.3.0",
|
|
52
|
-
"typescript": "^5.7.0",
|
|
53
|
-
"vitest": "^2.1.0"
|
|
54
|
-
},
|
|
55
|
-
"sideEffects": false,
|
|
56
|
-
"license": "SEE LICENSE IN LICENSE.md"
|
|
57
|
-
}
|
|
56
|
+
}
|
|
57
|
+
}
|
package/src/prisma/schema.prisma
CHANGED
|
@@ -1,286 +1,286 @@
|
|
|
1
|
-
// @msbci/form-server — Prisma schema
|
|
2
|
-
// Supports PostgreSQL and SQLite providers
|
|
3
|
-
// Hierarchy: FormDefinition → FormPage[] → (FormVariable[] + FormRoster[])
|
|
4
|
-
// FormRoster → FormVariable[] (via rosterId FK, NOT parentId)
|
|
5
|
-
|
|
6
|
-
generator client {
|
|
7
|
-
provider = "prisma-client-js"
|
|
8
|
-
output = "../../generated/prisma"
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
datasource db {
|
|
12
|
-
provider = "sqlite"
|
|
13
|
-
url = env("DATABASE_URL")
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
// ─── Form Type Classification ─────────────────────────────
|
|
17
|
-
|
|
18
|
-
model FormType {
|
|
19
|
-
id String @id @default(cuid())
|
|
20
|
-
code String @unique
|
|
21
|
-
name String
|
|
22
|
-
description String?
|
|
23
|
-
metadata String? // JSON
|
|
24
|
-
createdAt DateTime @default(now())
|
|
25
|
-
updatedAt DateTime @updatedAt
|
|
26
|
-
|
|
27
|
-
forms FormDefinition[]
|
|
28
|
-
|
|
29
|
-
@@map("form_types")
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
// ─── Form Definition ──────────────────────────────────────
|
|
33
|
-
|
|
34
|
-
model FormDefinition {
|
|
35
|
-
id String @id @default(cuid())
|
|
36
|
-
code String
|
|
37
|
-
name String
|
|
38
|
-
description String?
|
|
39
|
-
version String @default("1.0.0")
|
|
40
|
-
isPublished Boolean @default(false)
|
|
41
|
-
tenantId String?
|
|
42
|
-
formTypeId String?
|
|
43
|
-
metadata String? // JSON
|
|
44
|
-
createdAt DateTime @default(now())
|
|
45
|
-
updatedAt DateTime @updatedAt
|
|
46
|
-
createdBy String?
|
|
47
|
-
updatedBy String?
|
|
48
|
-
|
|
49
|
-
formType FormType? @relation(fields: [formTypeId], references: [id])
|
|
50
|
-
scopes FormDefinitionScope[]
|
|
51
|
-
pages FormPage[]
|
|
52
|
-
submissions FormSubmission[]
|
|
53
|
-
|
|
54
|
-
@@unique([code, version, tenantId])
|
|
55
|
-
@@index([tenantId])
|
|
56
|
-
@@index([formTypeId])
|
|
57
|
-
@@map("form_definitions")
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
// Pivot table — one form can reference many scopes (priority = order).
|
|
61
|
-
model FormDefinitionScope {
|
|
62
|
-
formId String
|
|
63
|
-
scopeId String
|
|
64
|
-
order Int @default(0)
|
|
65
|
-
|
|
66
|
-
form FormDefinition @relation(fields: [formId], references: [id], onDelete: Cascade)
|
|
67
|
-
scope Scope @relation(fields: [scopeId], references: [id], onDelete: Cascade)
|
|
68
|
-
|
|
69
|
-
@@id([formId, scopeId])
|
|
70
|
-
@@index([formId, order])
|
|
71
|
-
@@index([scopeId])
|
|
72
|
-
@@map("form_definition_scopes")
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
// ─── Form Page (navigation unit) ──────────────────────────
|
|
76
|
-
|
|
77
|
-
model FormPage {
|
|
78
|
-
id String @id @default(cuid())
|
|
79
|
-
code String
|
|
80
|
-
name String
|
|
81
|
-
order Int
|
|
82
|
-
isRepeatable Boolean @default(false)
|
|
83
|
-
repeatMinInstances Int?
|
|
84
|
-
repeatMaxInstances Int?
|
|
85
|
-
repeatControlVarCode String?
|
|
86
|
-
repeatInstanceLabel String?
|
|
87
|
-
conditions String? // JSON: IConditionRule[]
|
|
88
|
-
metadata String? // JSON
|
|
89
|
-
createdAt DateTime @default(now())
|
|
90
|
-
updatedAt DateTime @updatedAt
|
|
91
|
-
|
|
92
|
-
formId String
|
|
93
|
-
form FormDefinition @relation(fields: [formId], references: [id], onDelete: Cascade)
|
|
94
|
-
|
|
95
|
-
// Composition: a page owns variables AND rosters
|
|
96
|
-
variables FormVariable[] @relation("PageVariables")
|
|
97
|
-
rosters FormRoster[]
|
|
98
|
-
|
|
99
|
-
@@unique([formId, code])
|
|
100
|
-
@@index([formId])
|
|
101
|
-
@@map("form_pages")
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
// ─── Form Roster (sub-component of a page) ────────────────
|
|
105
|
-
|
|
106
|
-
model FormRoster {
|
|
107
|
-
id String @id @default(cuid())
|
|
108
|
-
code String
|
|
109
|
-
name String
|
|
110
|
-
rosterType String // 'check' | 'list' | 'collection' | 'collection_extend'
|
|
111
|
-
order Int
|
|
112
|
-
pilotVariableCode String?
|
|
113
|
-
options String? // JSON: IVariableOption[]
|
|
114
|
-
conditions String? // JSON: IConditionRule[]
|
|
115
|
-
metadata String? // JSON
|
|
116
|
-
createdAt DateTime @default(now())
|
|
117
|
-
updatedAt DateTime @updatedAt
|
|
118
|
-
|
|
119
|
-
pageId String
|
|
120
|
-
page FormPage @relation(fields: [pageId], references: [id], onDelete: Cascade)
|
|
121
|
-
|
|
122
|
-
// Composition: a roster owns its variables
|
|
123
|
-
variables FormVariable[] @relation("RosterVariables")
|
|
124
|
-
|
|
125
|
-
@@unique([pageId, code])
|
|
126
|
-
@@index([pageId])
|
|
127
|
-
@@map("form_rosters")
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
// ─── Form Variable (field) ────────────────────────────────
|
|
131
|
-
|
|
132
|
-
model FormVariable {
|
|
133
|
-
id String @id @default(cuid())
|
|
134
|
-
code String
|
|
135
|
-
name String
|
|
136
|
-
type String // VariableType enum as string
|
|
137
|
-
order Int
|
|
138
|
-
isRequired Boolean @default(false)
|
|
139
|
-
isReadonly Boolean @default(false)
|
|
140
|
-
isHidden Boolean @default(false)
|
|
141
|
-
defaultValue String?
|
|
142
|
-
placeholder String?
|
|
143
|
-
description String?
|
|
144
|
-
options String? // JSON: IVariableOption[]
|
|
145
|
-
validationRules String? // JSON: IValidationRule[]
|
|
146
|
-
conditions String? // JSON: IConditionRule[]
|
|
147
|
-
expression String? // For calculated fields
|
|
148
|
-
dataSourceId String?
|
|
149
|
-
dataSourceDependencies String? // JSON: Record<string, string>
|
|
150
|
-
style String? // JSON: IComponentStyle
|
|
151
|
-
metadata String? // JSON
|
|
152
|
-
createdAt DateTime @default(now())
|
|
153
|
-
updatedAt DateTime @updatedAt
|
|
154
|
-
|
|
155
|
-
// A variable belongs to EITHER a page or a roster (not both)
|
|
156
|
-
pageId String?
|
|
157
|
-
page FormPage? @relation("PageVariables", fields: [pageId], references: [id], onDelete: Cascade)
|
|
158
|
-
rosterId String?
|
|
159
|
-
roster FormRoster? @relation("RosterVariables", fields: [rosterId], references: [id], onDelete: Cascade)
|
|
160
|
-
|
|
161
|
-
// Optional link to a reusable VariableTemplate (Option B — resolved
|
|
162
|
-
// in-memory at load time). Local overrides live in `templateOverrides`.
|
|
163
|
-
templateId String?
|
|
164
|
-
template VariableTemplate? @relation(fields: [templateId], references: [id])
|
|
165
|
-
templateOverrides String? // JSON: Partial<IVariableTemplateOverrides>
|
|
166
|
-
|
|
167
|
-
@@index([pageId])
|
|
168
|
-
@@index([rosterId])
|
|
169
|
-
@@index([templateId])
|
|
170
|
-
@@map("form_variables")
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// ─── Scope ────────────────────────────────────────────────
|
|
174
|
-
|
|
175
|
-
model Scope {
|
|
176
|
-
id String @id @default(cuid())
|
|
177
|
-
code String
|
|
178
|
-
name String // JSON LocalizedString or plain string
|
|
179
|
-
description String? // JSON LocalizedString or plain string
|
|
180
|
-
tenantId String @default("default")
|
|
181
|
-
metadata String? // JSON
|
|
182
|
-
// Encrypted scope-level headers shared by all DataSourceConfig in the
|
|
183
|
-
// scope. Format produced by utils/encryption.ts. NULL when unset.
|
|
184
|
-
headers String?
|
|
185
|
-
createdAt DateTime @default(now())
|
|
186
|
-
updatedAt DateTime @updatedAt
|
|
187
|
-
createdBy String?
|
|
188
|
-
updatedBy String?
|
|
189
|
-
|
|
190
|
-
forms FormDefinitionScope[]
|
|
191
|
-
templates VariableTemplate[]
|
|
192
|
-
dataSources DataSourceConfig[]
|
|
193
|
-
|
|
194
|
-
@@unique([code, tenantId])
|
|
195
|
-
@@index([tenantId])
|
|
196
|
-
@@map("scopes")
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// ─── Data Source Config (admin-managed REST sources) ──────
|
|
200
|
-
|
|
201
|
-
model DataSourceConfig {
|
|
202
|
-
id String @id @default(cuid())
|
|
203
|
-
code String
|
|
204
|
-
name String // JSON LocalizedString
|
|
205
|
-
scopeId String
|
|
206
|
-
url String
|
|
207
|
-
method String @default("GET")
|
|
208
|
-
queryParam String? @default("q")
|
|
209
|
-
valueField String
|
|
210
|
-
labelField String
|
|
211
|
-
headersOverride String? // JSON encrypted (utils/encryption.ts)
|
|
212
|
-
dependencies String? // JSON Record<string,string> (urlParam → varCode)
|
|
213
|
-
metadata String? // JSON
|
|
214
|
-
createdAt DateTime @default(now())
|
|
215
|
-
updatedAt DateTime @updatedAt
|
|
216
|
-
createdBy String?
|
|
217
|
-
updatedBy String?
|
|
218
|
-
|
|
219
|
-
scope Scope @relation(fields: [scopeId], references: [id], onDelete: Cascade)
|
|
220
|
-
|
|
221
|
-
@@unique([code, scopeId])
|
|
222
|
-
@@index([scopeId])
|
|
223
|
-
@@map("data_source_configs")
|
|
224
|
-
}
|
|
225
|
-
|
|
226
|
-
// ─── Variable Template ────────────────────────────────────
|
|
227
|
-
|
|
228
|
-
model VariableTemplate {
|
|
229
|
-
id String @id @default(cuid())
|
|
230
|
-
code String
|
|
231
|
-
name String // JSON LocalizedString or plain string
|
|
232
|
-
scopeId String
|
|
233
|
-
tenantId String @default("default")
|
|
234
|
-
|
|
235
|
-
// Overridable fields (mirrors IFormVariable, minus instance-only ones)
|
|
236
|
-
variableType String
|
|
237
|
-
description String? // JSON LocalizedString or plain string
|
|
238
|
-
placeholder String? // JSON LocalizedString or plain string
|
|
239
|
-
isRequired Boolean @default(false)
|
|
240
|
-
isReadonly Boolean @default(false)
|
|
241
|
-
isHidden Boolean @default(false)
|
|
242
|
-
options String? // JSON: IVariableOption[]
|
|
243
|
-
validationRules String? // JSON: IValidationRule[]
|
|
244
|
-
conditions String? // JSON: IConditionRule[]
|
|
245
|
-
expression String?
|
|
246
|
-
dataSourceId String?
|
|
247
|
-
dataSourceDependencies String? // JSON: Record<string, string>
|
|
248
|
-
style String? // JSON: IComponentStyle
|
|
249
|
-
metadata String? // JSON
|
|
250
|
-
|
|
251
|
-
createdAt DateTime @default(now())
|
|
252
|
-
updatedAt DateTime @updatedAt
|
|
253
|
-
createdBy String?
|
|
254
|
-
updatedBy String?
|
|
255
|
-
|
|
256
|
-
scope Scope @relation(fields: [scopeId], references: [id])
|
|
257
|
-
variables FormVariable[]
|
|
258
|
-
|
|
259
|
-
@@unique([code, scopeId])
|
|
260
|
-
@@index([scopeId])
|
|
261
|
-
@@index([tenantId])
|
|
262
|
-
@@map("variable_templates")
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
// ─── Form Submission ──────────────────────────────────────
|
|
266
|
-
|
|
267
|
-
model FormSubmission {
|
|
268
|
-
id String @id @default(cuid())
|
|
269
|
-
formId String
|
|
270
|
-
tenantId String?
|
|
271
|
-
status String @default("draft") // draft, submitted, approved, rejected, completed
|
|
272
|
-
data String // JSON: Record<string, IFieldResponse>
|
|
273
|
-
submittedBy String?
|
|
274
|
-
metadata String? // JSON
|
|
275
|
-
createdAt DateTime @default(now())
|
|
276
|
-
updatedAt DateTime @updatedAt
|
|
277
|
-
createdBy String?
|
|
278
|
-
updatedBy String?
|
|
279
|
-
|
|
280
|
-
form FormDefinition @relation(fields: [formId], references: [id], onDelete: Cascade)
|
|
281
|
-
|
|
282
|
-
@@index([formId])
|
|
283
|
-
@@index([tenantId])
|
|
284
|
-
@@index([status])
|
|
285
|
-
@@map("form_submissions")
|
|
286
|
-
}
|
|
1
|
+
// @msbci/form-server — Prisma schema
|
|
2
|
+
// Supports PostgreSQL and SQLite providers
|
|
3
|
+
// Hierarchy: FormDefinition → FormPage[] → (FormVariable[] + FormRoster[])
|
|
4
|
+
// FormRoster → FormVariable[] (via rosterId FK, NOT parentId)
|
|
5
|
+
|
|
6
|
+
generator client {
|
|
7
|
+
provider = "prisma-client-js"
|
|
8
|
+
output = "../../generated/prisma"
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
datasource db {
|
|
12
|
+
provider = "sqlite"
|
|
13
|
+
url = env("DATABASE_URL")
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// ─── Form Type Classification ─────────────────────────────
|
|
17
|
+
|
|
18
|
+
model FormType {
|
|
19
|
+
id String @id @default(cuid())
|
|
20
|
+
code String @unique
|
|
21
|
+
name String
|
|
22
|
+
description String?
|
|
23
|
+
metadata String? // JSON
|
|
24
|
+
createdAt DateTime @default(now())
|
|
25
|
+
updatedAt DateTime @updatedAt
|
|
26
|
+
|
|
27
|
+
forms FormDefinition[]
|
|
28
|
+
|
|
29
|
+
@@map("form_types")
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// ─── Form Definition ──────────────────────────────────────
|
|
33
|
+
|
|
34
|
+
model FormDefinition {
|
|
35
|
+
id String @id @default(cuid())
|
|
36
|
+
code String
|
|
37
|
+
name String
|
|
38
|
+
description String?
|
|
39
|
+
version String @default("1.0.0")
|
|
40
|
+
isPublished Boolean @default(false)
|
|
41
|
+
tenantId String?
|
|
42
|
+
formTypeId String?
|
|
43
|
+
metadata String? // JSON
|
|
44
|
+
createdAt DateTime @default(now())
|
|
45
|
+
updatedAt DateTime @updatedAt
|
|
46
|
+
createdBy String?
|
|
47
|
+
updatedBy String?
|
|
48
|
+
|
|
49
|
+
formType FormType? @relation(fields: [formTypeId], references: [id])
|
|
50
|
+
scopes FormDefinitionScope[]
|
|
51
|
+
pages FormPage[]
|
|
52
|
+
submissions FormSubmission[]
|
|
53
|
+
|
|
54
|
+
@@unique([code, version, tenantId])
|
|
55
|
+
@@index([tenantId])
|
|
56
|
+
@@index([formTypeId])
|
|
57
|
+
@@map("form_definitions")
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Pivot table — one form can reference many scopes (priority = order).
|
|
61
|
+
model FormDefinitionScope {
|
|
62
|
+
formId String
|
|
63
|
+
scopeId String
|
|
64
|
+
order Int @default(0)
|
|
65
|
+
|
|
66
|
+
form FormDefinition @relation(fields: [formId], references: [id], onDelete: Cascade)
|
|
67
|
+
scope Scope @relation(fields: [scopeId], references: [id], onDelete: Cascade)
|
|
68
|
+
|
|
69
|
+
@@id([formId, scopeId])
|
|
70
|
+
@@index([formId, order])
|
|
71
|
+
@@index([scopeId])
|
|
72
|
+
@@map("form_definition_scopes")
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// ─── Form Page (navigation unit) ──────────────────────────
|
|
76
|
+
|
|
77
|
+
model FormPage {
|
|
78
|
+
id String @id @default(cuid())
|
|
79
|
+
code String
|
|
80
|
+
name String
|
|
81
|
+
order Int
|
|
82
|
+
isRepeatable Boolean @default(false)
|
|
83
|
+
repeatMinInstances Int?
|
|
84
|
+
repeatMaxInstances Int?
|
|
85
|
+
repeatControlVarCode String?
|
|
86
|
+
repeatInstanceLabel String?
|
|
87
|
+
conditions String? // JSON: IConditionRule[]
|
|
88
|
+
metadata String? // JSON
|
|
89
|
+
createdAt DateTime @default(now())
|
|
90
|
+
updatedAt DateTime @updatedAt
|
|
91
|
+
|
|
92
|
+
formId String
|
|
93
|
+
form FormDefinition @relation(fields: [formId], references: [id], onDelete: Cascade)
|
|
94
|
+
|
|
95
|
+
// Composition: a page owns variables AND rosters
|
|
96
|
+
variables FormVariable[] @relation("PageVariables")
|
|
97
|
+
rosters FormRoster[]
|
|
98
|
+
|
|
99
|
+
@@unique([formId, code])
|
|
100
|
+
@@index([formId])
|
|
101
|
+
@@map("form_pages")
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// ─── Form Roster (sub-component of a page) ────────────────
|
|
105
|
+
|
|
106
|
+
model FormRoster {
|
|
107
|
+
id String @id @default(cuid())
|
|
108
|
+
code String
|
|
109
|
+
name String
|
|
110
|
+
rosterType String // 'check' | 'list' | 'collection' | 'collection_extend'
|
|
111
|
+
order Int
|
|
112
|
+
pilotVariableCode String?
|
|
113
|
+
options String? // JSON: IVariableOption[]
|
|
114
|
+
conditions String? // JSON: IConditionRule[]
|
|
115
|
+
metadata String? // JSON
|
|
116
|
+
createdAt DateTime @default(now())
|
|
117
|
+
updatedAt DateTime @updatedAt
|
|
118
|
+
|
|
119
|
+
pageId String
|
|
120
|
+
page FormPage @relation(fields: [pageId], references: [id], onDelete: Cascade)
|
|
121
|
+
|
|
122
|
+
// Composition: a roster owns its variables
|
|
123
|
+
variables FormVariable[] @relation("RosterVariables")
|
|
124
|
+
|
|
125
|
+
@@unique([pageId, code])
|
|
126
|
+
@@index([pageId])
|
|
127
|
+
@@map("form_rosters")
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ─── Form Variable (field) ────────────────────────────────
|
|
131
|
+
|
|
132
|
+
model FormVariable {
|
|
133
|
+
id String @id @default(cuid())
|
|
134
|
+
code String
|
|
135
|
+
name String
|
|
136
|
+
type String // VariableType enum as string
|
|
137
|
+
order Int
|
|
138
|
+
isRequired Boolean @default(false)
|
|
139
|
+
isReadonly Boolean @default(false)
|
|
140
|
+
isHidden Boolean @default(false)
|
|
141
|
+
defaultValue String?
|
|
142
|
+
placeholder String?
|
|
143
|
+
description String?
|
|
144
|
+
options String? // JSON: IVariableOption[]
|
|
145
|
+
validationRules String? // JSON: IValidationRule[]
|
|
146
|
+
conditions String? // JSON: IConditionRule[]
|
|
147
|
+
expression String? // For calculated fields
|
|
148
|
+
dataSourceId String?
|
|
149
|
+
dataSourceDependencies String? // JSON: Record<string, string>
|
|
150
|
+
style String? // JSON: IComponentStyle
|
|
151
|
+
metadata String? // JSON
|
|
152
|
+
createdAt DateTime @default(now())
|
|
153
|
+
updatedAt DateTime @updatedAt
|
|
154
|
+
|
|
155
|
+
// A variable belongs to EITHER a page or a roster (not both)
|
|
156
|
+
pageId String?
|
|
157
|
+
page FormPage? @relation("PageVariables", fields: [pageId], references: [id], onDelete: Cascade)
|
|
158
|
+
rosterId String?
|
|
159
|
+
roster FormRoster? @relation("RosterVariables", fields: [rosterId], references: [id], onDelete: Cascade)
|
|
160
|
+
|
|
161
|
+
// Optional link to a reusable VariableTemplate (Option B — resolved
|
|
162
|
+
// in-memory at load time). Local overrides live in `templateOverrides`.
|
|
163
|
+
templateId String?
|
|
164
|
+
template VariableTemplate? @relation(fields: [templateId], references: [id])
|
|
165
|
+
templateOverrides String? // JSON: Partial<IVariableTemplateOverrides>
|
|
166
|
+
|
|
167
|
+
@@index([pageId])
|
|
168
|
+
@@index([rosterId])
|
|
169
|
+
@@index([templateId])
|
|
170
|
+
@@map("form_variables")
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// ─── Scope ────────────────────────────────────────────────
|
|
174
|
+
|
|
175
|
+
model Scope {
|
|
176
|
+
id String @id @default(cuid())
|
|
177
|
+
code String
|
|
178
|
+
name String // JSON LocalizedString or plain string
|
|
179
|
+
description String? // JSON LocalizedString or plain string
|
|
180
|
+
tenantId String @default("default")
|
|
181
|
+
metadata String? // JSON
|
|
182
|
+
// Encrypted scope-level headers shared by all DataSourceConfig in the
|
|
183
|
+
// scope. Format produced by utils/encryption.ts. NULL when unset.
|
|
184
|
+
headers String?
|
|
185
|
+
createdAt DateTime @default(now())
|
|
186
|
+
updatedAt DateTime @updatedAt
|
|
187
|
+
createdBy String?
|
|
188
|
+
updatedBy String?
|
|
189
|
+
|
|
190
|
+
forms FormDefinitionScope[]
|
|
191
|
+
templates VariableTemplate[]
|
|
192
|
+
dataSources DataSourceConfig[]
|
|
193
|
+
|
|
194
|
+
@@unique([code, tenantId])
|
|
195
|
+
@@index([tenantId])
|
|
196
|
+
@@map("scopes")
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// ─── Data Source Config (admin-managed REST sources) ──────
|
|
200
|
+
|
|
201
|
+
model DataSourceConfig {
|
|
202
|
+
id String @id @default(cuid())
|
|
203
|
+
code String
|
|
204
|
+
name String // JSON LocalizedString
|
|
205
|
+
scopeId String
|
|
206
|
+
url String
|
|
207
|
+
method String @default("GET")
|
|
208
|
+
queryParam String? @default("q")
|
|
209
|
+
valueField String
|
|
210
|
+
labelField String
|
|
211
|
+
headersOverride String? // JSON encrypted (utils/encryption.ts)
|
|
212
|
+
dependencies String? // JSON Record<string,string> (urlParam → varCode)
|
|
213
|
+
metadata String? // JSON
|
|
214
|
+
createdAt DateTime @default(now())
|
|
215
|
+
updatedAt DateTime @updatedAt
|
|
216
|
+
createdBy String?
|
|
217
|
+
updatedBy String?
|
|
218
|
+
|
|
219
|
+
scope Scope @relation(fields: [scopeId], references: [id], onDelete: Cascade)
|
|
220
|
+
|
|
221
|
+
@@unique([code, scopeId])
|
|
222
|
+
@@index([scopeId])
|
|
223
|
+
@@map("data_source_configs")
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
// ─── Variable Template ────────────────────────────────────
|
|
227
|
+
|
|
228
|
+
model VariableTemplate {
|
|
229
|
+
id String @id @default(cuid())
|
|
230
|
+
code String
|
|
231
|
+
name String // JSON LocalizedString or plain string
|
|
232
|
+
scopeId String
|
|
233
|
+
tenantId String @default("default")
|
|
234
|
+
|
|
235
|
+
// Overridable fields (mirrors IFormVariable, minus instance-only ones)
|
|
236
|
+
variableType String
|
|
237
|
+
description String? // JSON LocalizedString or plain string
|
|
238
|
+
placeholder String? // JSON LocalizedString or plain string
|
|
239
|
+
isRequired Boolean @default(false)
|
|
240
|
+
isReadonly Boolean @default(false)
|
|
241
|
+
isHidden Boolean @default(false)
|
|
242
|
+
options String? // JSON: IVariableOption[]
|
|
243
|
+
validationRules String? // JSON: IValidationRule[]
|
|
244
|
+
conditions String? // JSON: IConditionRule[]
|
|
245
|
+
expression String?
|
|
246
|
+
dataSourceId String?
|
|
247
|
+
dataSourceDependencies String? // JSON: Record<string, string>
|
|
248
|
+
style String? // JSON: IComponentStyle
|
|
249
|
+
metadata String? // JSON
|
|
250
|
+
|
|
251
|
+
createdAt DateTime @default(now())
|
|
252
|
+
updatedAt DateTime @updatedAt
|
|
253
|
+
createdBy String?
|
|
254
|
+
updatedBy String?
|
|
255
|
+
|
|
256
|
+
scope Scope @relation(fields: [scopeId], references: [id])
|
|
257
|
+
variables FormVariable[]
|
|
258
|
+
|
|
259
|
+
@@unique([code, scopeId])
|
|
260
|
+
@@index([scopeId])
|
|
261
|
+
@@index([tenantId])
|
|
262
|
+
@@map("variable_templates")
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// ─── Form Submission ──────────────────────────────────────
|
|
266
|
+
|
|
267
|
+
model FormSubmission {
|
|
268
|
+
id String @id @default(cuid())
|
|
269
|
+
formId String
|
|
270
|
+
tenantId String?
|
|
271
|
+
status String @default("draft") // draft, submitted, approved, rejected, completed
|
|
272
|
+
data String // JSON: Record<string, IFieldResponse>
|
|
273
|
+
submittedBy String?
|
|
274
|
+
metadata String? // JSON
|
|
275
|
+
createdAt DateTime @default(now())
|
|
276
|
+
updatedAt DateTime @updatedAt
|
|
277
|
+
createdBy String?
|
|
278
|
+
updatedBy String?
|
|
279
|
+
|
|
280
|
+
form FormDefinition @relation(fields: [formId], references: [id], onDelete: Cascade)
|
|
281
|
+
|
|
282
|
+
@@index([formId])
|
|
283
|
+
@@index([tenantId])
|
|
284
|
+
@@index([status])
|
|
285
|
+
@@map("form_submissions")
|
|
286
|
+
}
|