@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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@msbci/form-server",
3
- "version": "1.3.2",
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
- "dependencies": {
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
+ }
@@ -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
+ }