@flusys/nestjs-form-builder 4.1.1 → 5.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 CHANGED
@@ -1,68 +1,9 @@
1
1
  # @flusys/nestjs-form-builder
2
2
 
3
- > Dynamic form management for NestJS — JSON schema definitions, schema versioning, access control (PUBLIC/AUTHENTICATED/ACTION_GROUP), draft submissions, and a server-side computed fields engine.
3
+ Dynamic form management for NestJS — JSON schema storage, schema versioning, access control (PUBLIC / AUTHENTICATED / ACTION_GROUP), draft submissions, and a server-side computed fields engine.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/@flusys/nestjs-form-builder.svg)](https://www.npmjs.com/package/@flusys/nestjs-form-builder)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
- [![NestJS](https://img.shields.io/badge/NestJS-11.x-red.svg)](https://nestjs.com/)
8
- [![TypeScript](https://img.shields.io/badge/TypeScript-5.x-blue.svg)](https://www.typescriptlang.org/)
9
- [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D18.x-green.svg)](https://nodejs.org/)
10
-
11
- ---
12
-
13
- ## Table of Contents
14
-
15
- - [Overview](#overview)
16
- - [Features](#features)
17
- - [Compatibility](#compatibility)
18
- - [Installation](#installation)
19
- - [Quick Start](#quick-start)
20
- - [Module Registration](#module-registration)
21
- - [forRoot (Sync)](#forroot-sync)
22
- - [forRootAsync (Factory)](#forrootasync-factory)
23
- - [Configuration Reference](#configuration-reference)
24
- - [Feature Toggles](#feature-toggles)
25
- - [API Endpoints](#api-endpoints)
26
- - [Entities](#entities)
27
- - [Access Control](#access-control)
28
- - [Schema Versioning](#schema-versioning)
29
- - [Draft Support](#draft-support)
30
- - [Computed Fields Engine](#computed-fields-engine)
31
- - [Exported Services](#exported-services)
32
- - [Programmatic Usage](#programmatic-usage)
33
- - [Troubleshooting](#troubleshooting)
34
- - [License](#license)
35
-
36
- ---
37
-
38
- ## Overview
39
-
40
- `@flusys/nestjs-form-builder` provides a complete dynamic form system where form structures are stored as JSON in the database. New forms can be created without any code changes. The module handles schema versioning (submissions snapshot the schema they were submitted against), per-form access control, draft submissions, and server-side computed field evaluation.
41
-
42
- ---
43
-
44
- ## Features
45
-
46
- - **Database-driven forms** — JSON schema stored in PostgreSQL; no code changes for new forms
47
- - **Schema versioning** — Schema version auto-increments on change; each submission captures the version it used
48
- - **Access types** — `PUBLIC` (no auth), `AUTHENTICATED` (any logged-in user), `ACTION_GROUP` (IAM permission-based)
49
- - **Draft submissions** — Users can save partial form data and finalize later
50
- - **Computed fields engine** — Server-side arithmetic computed from submission data using rules and conditions
51
- - **Slug-based lookup** — Forms accessible by a URL-friendly slug
52
- - **Company scoping** — Optional `companyId` isolation via `FormWithCompany` entity
53
- - **Multi-tenant** — Per-tenant DataSource isolation
54
-
55
- ---
56
-
57
- ## Compatibility
58
-
59
- | Package | Version |
60
- |---------|---------|
61
- | `@flusys/nestjs-core` | `^4.0.0` |
62
- | `@flusys/nestjs-shared` | `^4.0.0` |
63
- | `@nestjs/core` | `^11.0.0` |
64
- | `typeorm` | `^0.3.0` |
65
- | Node.js | `>= 18.x` |
66
7
 
67
8
  ---
68
9
 
@@ -74,377 +15,139 @@ npm install @flusys/nestjs-form-builder @flusys/nestjs-shared @flusys/nestjs-cor
74
15
 
75
16
  ---
76
17
 
77
- ## Quick Start
18
+ ## 1. Module Registration
19
+
20
+ ### forRoot (sync)
78
21
 
79
- ### Minimal Setup (Single Database)
22
+ #### Mode 1: Single Database
80
23
 
81
24
  ```typescript
82
- import { Module } from '@nestjs/common';
83
25
  import { FormBuilderModule } from '@flusys/nestjs-form-builder';
84
26
 
85
- @Module({
86
- imports: [
87
- FormBuilderModule.forRoot({
88
- global: true,
89
- includeController: true,
90
- bootstrapAppConfig: {
91
- databaseMode: 'single',
92
- enableCompanyFeature: false,
93
- },
94
- config: {
95
- defaultDatabaseConfig: {
96
- type: 'postgres',
97
- host: process.env.DB_HOST,
98
- port: Number(process.env.DB_PORT ?? 5432),
99
- username: process.env.DB_USER,
100
- password: process.env.DB_PASSWORD,
101
- database: process.env.DB_NAME,
102
- },
103
- },
104
- }),
105
- ],
106
- })
107
- export class AppModule {}
27
+ FormBuilderModule.forRoot({
28
+ global: true,
29
+ includeController: true,
30
+ bootstrapAppConfig: {
31
+ databaseMode: 'single',
32
+ enableCompanyFeature: false,
33
+ },
34
+ config: {
35
+ defaultDatabaseConfig: {
36
+ type: 'mysql',
37
+ host: process.env.DB_HOST,
38
+ port: Number(process.env.DB_PORT ?? 3306),
39
+ username: process.env.DB_USER,
40
+ password: process.env.DB_PASSWORD,
41
+ database: process.env.DB_NAME,
42
+ },
43
+ },
44
+ });
108
45
  ```
109
46
 
110
- After startup, create forms via `POST /form-builder/form/insert` and collect submissions via `POST /form-builder/result/insert`.
111
-
112
- ---
113
-
114
- ## Module Registration
115
-
116
- ### forRoot (Sync)
47
+ #### Mode 2: Multi-Tenant
117
48
 
118
49
  ```typescript
119
50
  FormBuilderModule.forRoot({
120
- global?: boolean;
121
- includeController?: boolean; // Default: true
122
- bootstrapAppConfig?: {
123
- databaseMode: 'single' | 'multi-tenant';
124
- enableCompanyFeature: boolean; // true = FormWithCompany entity
125
- };
126
- config?: IFormBuilderConfig;
127
- })
51
+ global: true,
52
+ includeController: true,
53
+ bootstrapAppConfig: {
54
+ databaseMode: 'multi-tenant',
55
+ enableCompanyFeature: true,
56
+ },
57
+ config: {
58
+ tenantDefaultDatabaseConfig: {
59
+ type: 'mysql',
60
+ host: process.env.TENANT_DB_HOST,
61
+ port: Number(process.env.TENANT_DB_PORT ?? 3306),
62
+ username: process.env.TENANT_DB_USER,
63
+ password: process.env.TENANT_DB_PASSWORD,
64
+ database: process.env.TENANT_DB_NAME,
65
+ },
66
+ tenants: [
67
+ { id: 'tenant-a', database: 'tenant_a_db' },
68
+ { id: 'tenant-b', database: 'tenant_b_db' },
69
+ ],
70
+ },
71
+ });
128
72
  ```
129
73
 
130
- ### forRootAsync (Factory)
74
+ ### forRootAsync (factory — recommended)
131
75
 
132
76
  ```typescript
133
- import { ConfigService } from '@nestjs/config';
77
+ import { ConfigModule, ConfigService } from '@nestjs/config';
78
+ import { FormBuilderModule, ITenantDatabaseConfig } from '@flusys/nestjs-form-builder';
134
79
 
80
+ // Single database
135
81
  FormBuilderModule.forRootAsync({
136
82
  global: true,
137
- includeController: true,
138
83
  bootstrapAppConfig: {
139
84
  databaseMode: 'single',
140
85
  enableCompanyFeature: true,
141
86
  },
142
87
  imports: [ConfigModule],
143
- useFactory: (configService: ConfigService) => ({
88
+ useFactory: (cfg: ConfigService) => ({
144
89
  defaultDatabaseConfig: {
145
- type: 'postgres',
146
- host: configService.get('DB_HOST'),
147
- port: configService.get<number>('DB_PORT'),
148
- username: configService.get('DB_USER'),
149
- password: configService.get('DB_PASSWORD'),
150
- database: configService.get('DB_NAME'),
90
+ type: 'mysql',
91
+ host: cfg.get('DB_HOST'),
92
+ port: cfg.get<number>('DB_PORT'),
93
+ username: cfg.get('DB_USER'),
94
+ password: cfg.get('DB_PASSWORD'),
95
+ database: cfg.get('DB_NAME'),
151
96
  },
152
97
  }),
153
98
  inject: [ConfigService],
154
- })
155
- ```
156
-
157
- **Exported services** (available for injection after registration):
158
- - `FormBuilderConfigService`
159
- - `FormBuilderDataSourceProvider`
160
- - `FormService`
161
- - `FormResultService`
162
-
163
- ---
164
-
165
- ## Configuration Reference
99
+ });
166
100
 
167
- ```typescript
168
- interface IFormBuilderConfig extends IDataSourceServiceOptions {
169
- // No form-builder-specific runtime config.
170
- // IDataSourceServiceOptions provides:
171
- // defaultDatabaseConfig?: IDatabaseConfig
172
- // tenantDefaultDatabaseConfig?: IDatabaseConfig
173
- // tenants?: ITenantDatabaseConfig[]
174
- }
101
+ // Multi-tenant
102
+ FormBuilderModule.forRootAsync({
103
+ global: true,
104
+ bootstrapAppConfig: {
105
+ databaseMode: 'multi-tenant',
106
+ enableCompanyFeature: true,
107
+ },
108
+ imports: [ConfigModule],
109
+ useFactory: (cfg: ConfigService) => ({
110
+ tenantDefaultDatabaseConfig: {
111
+ type: 'mysql',
112
+ host: cfg.get('TENANT_DB_HOST'),
113
+ port: cfg.get<number>('TENANT_DB_PORT'),
114
+ username: cfg.get('TENANT_DB_USER'),
115
+ password: cfg.get('TENANT_DB_PASSWORD'),
116
+ database: cfg.get('TENANT_DB_NAME'),
117
+ },
118
+ tenants: cfg.get<ITenantDatabaseConfig[]>('TENANTS'),
119
+ }),
120
+ inject: [ConfigService],
121
+ });
175
122
  ```
176
123
 
177
- Bootstrap configuration:
178
-
179
- | Field | Type | Default | Effect |
180
- |-------|------|---------|--------|
181
- | `databaseMode` | `'single' \| 'multi-tenant'` | `'single'` | Controls DataSource resolution per request |
182
- | `enableCompanyFeature` | `boolean` | `false` | Uses `FormWithCompany` entity when `true` |
183
-
184
- ---
185
-
186
- ## Feature Toggles
187
-
188
- | Feature | Config | Default | Effect |
189
- |---------|--------|---------|--------|
190
- | Company scoping | `enableCompanyFeature: true` | `false` | All queries filtered by `companyId` from JWT; uses `FormWithCompany` entity |
191
- | Multi-tenant | `databaseMode: 'multi-tenant'` | `'single'` | Per-tenant DataSource connections |
192
-
193
- ---
194
-
195
- ## API Endpoints
196
-
197
- All endpoints use **POST**. Authentication depends on the form's `accessType`.
198
-
199
- ### Forms — `POST /form-builder/form/*`
200
-
201
- | Endpoint | Auth | Description |
202
- |----------|------|-------------|
203
- | `POST /form-builder/form/insert` | `form.create` | Create a new form with JSON schema |
204
- | `POST /form-builder/form/get-all` | `form.read` | List all forms (admin) |
205
- | `POST /form-builder/form/get/:id` | `form.read` | Get form by ID |
206
- | `POST /form-builder/form/get-by-slug/:slug` | Varies* | Get form by URL slug |
207
- | `POST /form-builder/form/update` | `form.update` | Update form (increments schema version if schema changes) |
208
- | `POST /form-builder/form/delete` | `form.delete` | Delete form |
209
- | `POST /form-builder/form/publish` | `form.update` | Publish draft form |
210
- | `POST /form-builder/form/unpublish` | `form.update` | Unpublish form |
211
-
212
- *`get-by-slug` respects the form's `accessType` — PUBLIC forms are accessible without auth.
213
-
214
- ### Form Results (Submissions) — `POST /form-builder/result/*`
215
-
216
- | Endpoint | Auth | Description |
217
- |----------|------|-------------|
218
- | `POST /form-builder/result/insert` | Varies* | Submit a form result |
219
- | `POST /form-builder/result/get-all` | `form-result.read` | List all submissions |
220
- | `POST /form-builder/result/get/:id` | `form-result.read` | Get submission by ID |
221
- | `POST /form-builder/result/update` | `form-result.update` | Update a submission |
222
- | `POST /form-builder/result/delete` | `form-result.delete` | Delete a submission |
223
- | `POST /form-builder/result/save-draft` | Varies* | Save a partial draft submission |
224
- | `POST /form-builder/result/finalize` | Varies* | Convert draft to final submission |
225
- | `POST /form-builder/result/get-my-results` | JWT | Get current user's own submissions |
226
-
227
- *Depends on the form's `accessType`.
124
+ **Exported services** (available for injection after registration):
125
+ `FormService`, `FormResultService`, `FormBuilderConfigService`, `FormBuilderDataSourceProvider`
228
126
 
229
127
  ---
230
128
 
231
- ## Entities
232
-
233
- ### Core Entities (always registered)
234
-
235
- | Entity | Table | Description |
236
- |--------|-------|-------------|
237
- | `Form` | `form_builder_form` | Form definition with JSON schema, access type, version |
238
- | `FormResult` | `form_builder_result` | Submission data + schema version snapshot |
239
-
240
- ### Company Feature Entities (`enableCompanyFeature: true`)
241
-
242
- | Entity | Table | Description |
243
- |--------|-------|-------------|
244
- | `FormWithCompany` | `form_builder_form` | Same as Form + `companyId` |
129
+ ## 2. Entities
245
130
 
246
131
  ```typescript
247
- import { FormBuilderModule } from '@flusys/nestjs-form-builder';
132
+ import { getFormBuilderEntitiesByConfig } from '@flusys/nestjs-form-builder/entities';
248
133
 
249
134
  TypeOrmModule.forRoot({
250
135
  entities: [
251
- ...FormBuilderModule.getEntities({ enableCompanyFeature: true }),
136
+ ...getFormBuilderEntitiesByConfig(false), // match enableCompanyFeature in bootstrapAppConfig
252
137
  ],
253
- })
138
+ });
254
139
  ```
255
140
 
256
- ---
257
-
258
- ## Access Control
259
-
260
- Each form has an `accessType` field that controls who can access it:
261
-
262
- | Access Type | Description |
263
- |-------------|-------------|
264
- | `PUBLIC` | No authentication required. Anyone can view and submit. |
265
- | `AUTHENTICATED` | Requires valid JWT token. Any logged-in user can submit. |
266
- | `ACTION_GROUP` | Requires a specific IAM action permission (from `nestjs-iam`). |
141
+ | `enableCompanyFeature` | Entities registered |
142
+ | ---------------------- | ------------------------------- |
143
+ | `false` | `Form`, `FormResult` |
144
+ | `true` | `FormWithCompany`, `FormResult` |
267
145
 
268
- **Creating a form with access control:**
269
-
270
- ```json
271
- POST /form-builder/form/insert
272
- {
273
- "name": "Employee Survey",
274
- "slug": "employee-survey",
275
- "accessType": "AUTHENTICATED",
276
- "schema": { /* JSON schema */ },
277
- "isPublished": true
278
- }
279
- ```
280
-
281
- **ACTION_GROUP form:**
282
-
283
- ```json
284
- {
285
- "name": "Finance Report",
286
- "slug": "finance-report",
287
- "accessType": "ACTION_GROUP",
288
- "requiredAction": "finance.submit-report",
289
- "schema": { /* JSON schema */ }
290
- }
291
- ```
146
+ The service selects the correct entity automatically at request time — no manual switching needed.
292
147
 
293
148
  ---
294
149
 
295
- ## Schema Versioning
296
-
297
- When you update a form's `schema` field, the `schemaVersion` counter is automatically incremented. Every form submission stores the `schemaVersion` at the time of submission.
298
-
299
- This allows:
300
- - Viewing historical submissions against the exact schema that was active
301
- - Running analytics on form data across schema versions
302
- - Preventing schema changes from breaking existing submission records
303
-
304
- ```json
305
- // Version 1 schema
306
- { "fields": [{ "name": "firstName", "type": "text" }] }
307
-
308
- // After update (version 2) - new field added
309
- { "fields": [{ "name": "firstName", "type": "text" }, { "name": "lastName", "type": "text" }] }
310
- ```
311
-
312
- Historical submissions still reference `schemaVersion: 1` so you know they were submitted before the `lastName` field existed.
313
-
314
- ---
315
-
316
- ## Draft Support
317
-
318
- Users can save partial form data as a draft and finalize later:
319
-
320
- ```json
321
- // Save draft (no validation on all required fields)
322
- POST /form-builder/result/save-draft
323
- {
324
- "formId": "uuid",
325
- "data": { "firstName": "John" }
326
- }
327
-
328
- // Finalize (validates all required fields)
329
- POST /form-builder/result/finalize
330
- {
331
- "draftId": "uuid",
332
- "data": { "firstName": "John", "lastName": "Doe" }
333
- }
334
- ```
335
-
336
- Draft submissions have `isDraft: true`. Finalized submissions have `isDraft: false`. Users can retrieve their own drafts via `POST /form-builder/result/get-my-results`.
337
-
338
- ---
339
-
340
- ## Computed Fields Engine
341
-
342
- Server-side computed fields are calculated from submission data using declarative rules:
343
-
344
- ```json
345
- POST /form-builder/form/insert
346
- {
347
- "name": "Loan Calculator",
348
- "schema": {
349
- "fields": [
350
- { "name": "principal", "type": "number", "label": "Loan Amount" },
351
- { "name": "rate", "type": "number", "label": "Interest Rate (%)" },
352
- { "name": "years", "type": "number", "label": "Term (Years)" }
353
- ],
354
- "computedFields": [
355
- {
356
- "name": "monthlyPayment",
357
- "label": "Monthly Payment",
358
- "expression": "(principal * (rate / 1200)) / (1 - Math.pow(1 + rate / 1200, -years * 12))",
359
- "dependsOn": ["principal", "rate", "years"]
360
- },
361
- {
362
- "name": "totalPayment",
363
- "label": "Total Payment",
364
- "expression": "monthlyPayment * years * 12",
365
- "dependsOn": ["monthlyPayment", "years"]
366
- }
367
- ]
368
- }
369
- }
370
- ```
371
-
372
- Computed values are evaluated server-side at submission time and stored with the result.
373
-
374
- ---
375
-
376
- ## Exported Services
377
-
378
- | Service | Description |
379
- |---------|-------------|
380
- | `FormService` | Form CRUD, slug lookup, publish/unpublish |
381
- | `FormResultService` | Submission CRUD, draft management, computed field evaluation |
382
- | `FormBuilderConfigService` | Exposes runtime config and feature flags |
383
- | `FormBuilderDataSourceProvider` | Dynamic DataSource resolution per request |
384
-
385
- ---
386
-
387
- ## Programmatic Usage
388
-
389
- ```typescript
390
- import { FormService, FormResultService } from '@flusys/nestjs-form-builder';
391
-
392
- @Injectable()
393
- export class SurveyService {
394
- constructor(
395
- @Inject(FormService) private readonly formService: FormService,
396
- @Inject(FormResultService) private readonly resultService: FormResultService,
397
- ) {}
398
-
399
- async getPublicForm(slug: string) {
400
- return this.formService.getBySlug(slug);
401
- }
402
-
403
- async submitForm(formId: string, data: Record<string, any>, userId: string) {
404
- return this.resultService.submit({ formId, data, userId });
405
- }
406
-
407
- async getFormResults(formId: string) {
408
- return this.resultService.getAll({ filter: { formId } }, null);
409
- }
410
- }
411
- ```
412
-
413
- ---
414
-
415
- ## Troubleshooting
416
-
417
- **`Form not found` for a public form**
418
-
419
- Check that the form is published (`isPublished: true`). Unpublished forms are not returned by the public API.
420
-
421
- ---
422
-
423
- **Draft finalization fails validation**
424
-
425
- The `finalize` endpoint applies full schema validation. Ensure all required fields in the form schema are present in the submitted data.
426
-
427
- ---
428
-
429
- **Computed fields not appearing in submission**
430
-
431
- Computed fields are evaluated at submission time. Check that `dependsOn` field names exactly match the form field `name` values (case-sensitive).
432
-
433
- ---
434
-
435
- **`No metadata for entity`**
436
-
437
- Register entities in your `TypeOrmModule`:
438
- ```typescript
439
- entities: [...FormBuilderModule.getEntities({ enableCompanyFeature: false })]
440
- ```
441
-
442
- ---
443
150
 
444
151
  ## License
445
152
 
446
153
  MIT © FLUSYS
447
-
448
- ---
449
-
450
- > Part of the **FLUSYS** framework — a full-stack monorepo powering Angular 21 + NestJS 11 applications.
@@ -10,9 +10,6 @@ function _export(target, all) {
10
10
  });
11
11
  }
12
12
  _export(exports, {
13
- get FORM_BUILDER_MODULE_MESSAGES () {
14
- return FORM_BUILDER_MODULE_MESSAGES;
15
- },
16
13
  get FORM_MESSAGES () {
17
14
  return FORM_MESSAGES;
18
15
  },
@@ -21,42 +18,21 @@ _export(exports, {
21
18
  }
22
19
  });
23
20
  const FORM_MESSAGES = {
24
- CREATE_SUCCESS: 'form.create.success',
25
- CREATE_MANY_SUCCESS: 'form.create.many.success',
26
- GET_SUCCESS: 'form.get.success',
27
- GET_ALL_SUCCESS: 'form.get.all.success',
28
- UPDATE_SUCCESS: 'form.update.success',
29
- UPDATE_MANY_SUCCESS: 'form.update.many.success',
30
- DELETE_SUCCESS: 'form.delete.success',
31
- RESTORE_SUCCESS: 'form.restore.success',
32
21
  NOT_FOUND: 'form.not.found',
33
- SCHEMA_SUCCESS: 'form.schema.success',
34
- PUBLISH_SUCCESS: 'form.publish.success',
35
- UNPUBLISH_SUCCESS: 'form.unpublish.success',
36
- DUPLICATE_SUCCESS: 'form.duplicate.success',
37
22
  NOT_PUBLIC: 'form.not.public',
38
23
  AUTH_REQUIRED: 'form.auth.required',
39
24
  ACCESS_DENIED: 'form.access.denied',
40
25
  INVALID_ACCESS_TYPE: 'form.invalid.access.type',
41
- PERMISSION_CHECK_FAILED: 'form.permission.check.failed'
26
+ PERMISSION_CHECK_FAILED: 'form.permission.check.failed',
27
+ GET_SUCCESS: 'form.get.success',
28
+ GET_ACCESS_INFO_SUCCESS: 'form.get.access.info.success'
42
29
  };
43
30
  const FORM_RESULT_MESSAGES = {
44
- CREATE_SUCCESS: 'form.result.create.success',
45
- CREATE_MANY_SUCCESS: 'form.result.create.many.success',
46
- GET_SUCCESS: 'form.result.get.success',
47
31
  GET_ALL_SUCCESS: 'form.result.get.all.success',
48
- UPDATE_SUCCESS: 'form.result.update.success',
49
- UPDATE_MANY_SUCCESS: 'form.result.update.many.success',
50
- DELETE_SUCCESS: 'form.result.delete.success',
51
- RESTORE_SUCCESS: 'form.result.restore.success',
52
32
  NOT_FOUND: 'form.result.not.found',
53
- SUBMIT_SUCCESS: 'form.result.submit.success',
54
- EXPORT_SUCCESS: 'form.result.export.success',
55
- STATS_SUCCESS: 'form.result.stats.success',
56
33
  HAS_SUBMITTED_SUCCESS: 'form.result.has.submitted.success',
57
- HAS_NOT_SUBMITTED_SUCCESS: 'form.result.has.not.submitted.success'
58
- };
59
- const FORM_BUILDER_MODULE_MESSAGES = {
60
- FORM: FORM_MESSAGES,
61
- FORM_RESULT: FORM_RESULT_MESSAGES
34
+ HAS_NOT_SUBMITTED_SUCCESS: 'form.result.has.not.submitted.success',
35
+ SUBMIT_SUCCESS: 'form.result.submit.success',
36
+ DRAFT_GET_SUCCESS: 'form.result.draft.get.success',
37
+ DRAFT_UPDATE_SUCCESS: 'form.result.draft.update.success'
62
38
  };
@@ -9,12 +9,12 @@ Object.defineProperty(exports, "FormResultController", {
9
9
  }
10
10
  });
11
11
  const _classes = require("@flusys/nestjs-shared/classes");
12
- const _config = require("../config");
13
12
  const _decorators = require("@flusys/nestjs-shared/decorators");
14
13
  const _guards = require("@flusys/nestjs-shared/guards");
15
14
  const _interfaces = require("@flusys/nestjs-shared/interfaces");
16
15
  const _common = require("@nestjs/common");
17
16
  const _swagger = require("@nestjs/swagger");
17
+ const _config = require("../config");
18
18
  const _dtos = require("../dtos");
19
19
  const _formresultservice = require("../services/form-result.service");
20
20
  function _define_property(obj, key, value) {
@@ -45,7 +45,7 @@ function _ts_param(paramIndex, decorator) {
45
45
  };
46
46
  }
47
47
  let FormResultController = class FormResultController extends (0, _classes.createApiController)(_dtos.CreateFormResultDto, _dtos.UpdateFormResultDto, _dtos.FormResultResponseDto, {
48
- entityName: 'formResult',
48
+ entityName: 'form.result',
49
49
  security: {
50
50
  insert: {
51
51
  level: 'permission',
@@ -95,24 +95,41 @@ let FormResultController = class FormResultController extends (0, _classes.creat
95
95
  /**
96
96
  * Submit form with authentication
97
97
  */ async submitForm(dto, user) {
98
- return this.formResultService.submitForm(dto, user, false);
98
+ const data = await this.formResultService.submitForm(dto, user, false);
99
+ return {
100
+ success: true,
101
+ message: 'Form submitted successfully',
102
+ messageKey: _config.FORM_RESULT_MESSAGES.SUBMIT_SUCCESS,
103
+ data
104
+ };
99
105
  }
100
- /**
101
- * Submit public form (no authentication required)
102
- * Only works for forms with accessType = 'public'
103
- */ async submitPublicForm(dto) {
104
- return this.formResultService.submitForm(dto, null, true);
106
+ async submitPublicForm(dto) {
107
+ const data = await this.formResultService.submitForm(dto, null, true);
108
+ return {
109
+ success: true,
110
+ message: 'Form submitted successfully',
111
+ messageKey: _config.FORM_RESULT_MESSAGES.SUBMIT_SUCCESS,
112
+ data
113
+ };
105
114
  }
106
115
  // Draft Endpoints
107
- /**
108
- * Get current user's draft for a form
109
- */ async getMyDraft(dto, user) {
110
- return this.formResultService.getMyDraft(dto.formId, user);
116
+ async getMyDraft(dto, user) {
117
+ const data = await this.formResultService.getMyDraft(dto.formId, user);
118
+ return {
119
+ success: true,
120
+ message: 'Draft retrieved',
121
+ messageKey: _config.FORM_RESULT_MESSAGES.DRAFT_GET_SUCCESS,
122
+ data
123
+ };
111
124
  }
112
- /**
113
- * Update existing draft or convert to final submission
114
- */ async updateDraft(dto, user) {
115
- return this.formResultService.updateDraft(dto.draftId, dto, user);
125
+ async updateDraft(dto, user) {
126
+ const data = await this.formResultService.updateDraft(dto.draftId, dto, user);
127
+ return {
128
+ success: true,
129
+ message: 'Draft updated successfully',
130
+ messageKey: _config.FORM_RESULT_MESSAGES.DRAFT_UPDATE_SUCCESS,
131
+ data
132
+ };
116
133
  }
117
134
  // Query Endpoints
118
135
  /**