@flusys/nestjs-form-builder 9.1.0 → 9.1.2
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 +28 -0
- package/config/message-keys.d.ts +1 -0
- package/dtos/form.dto.d.ts +5 -4
- package/entities/form.entity.d.ts +2 -1
- package/fesm/432.js +270 -302
- package/fesm/720.js +39 -17
- package/fesm/config/index.js +2 -1
- package/fesm/docs/index.js +1 -1
- package/fesm/dtos/index.js +47 -18
- package/fesm/entities/index.js +3 -3
- package/fesm/index.js +10 -6
- package/interfaces/form.interface.d.ts +2 -2
- package/package.json +5 -5
- package/services/form-result.service.d.ts +5 -3
- package/services/form.service.d.ts +7 -4
- package/utils/computed-field.utils.d.ts +13 -37
- package/utils/permission.utils.d.ts +3 -3
package/README.md
CHANGED
|
@@ -145,6 +145,23 @@ TypeOrmModule.forRoot({
|
|
|
145
145
|
|
|
146
146
|
The service selects the correct entity automatically at request time — no manual switching needed.
|
|
147
147
|
|
|
148
|
+
### ACTION_GROUP permission rule
|
|
149
|
+
|
|
150
|
+
An `ACTION_GROUP` form stores `permissionLogic` — an `ILogicNode` AND / OR tree from `@flusys/nestjs-shared/interfaces` (up to `MAX_PERMISSION_LOGIC_DEPTH` nested groups and `MAX_PERMISSION_LOGIC_CODES` codes), validated with `permissionLogicProblem()` from `@flusys/nestjs-shared/utils`:
|
|
151
|
+
|
|
152
|
+
```typescript
|
|
153
|
+
{
|
|
154
|
+
type: 'group',
|
|
155
|
+
operator: 'AND',
|
|
156
|
+
children: [
|
|
157
|
+
{ type: 'action', actionId: 'hr.survey.submit' },
|
|
158
|
+
{ type: 'group', operator: 'OR', children: [{ type: 'action', actionId: 'hr.manager' }, { type: 'action', actionId: 'hr.admin' }] },
|
|
159
|
+
],
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Fetching (`form/authenticated/:id`) and submitting check it with `evaluatePermissionLogic()` against the user's codes from `loadPermissionCodes()` (`PERMISSION_RESOLVER`, else `SharedPermissionCacheService`); when the codes cannot be read, access fails closed (403 `form.permission.check.failed`). A form with no rule is open to any logged-in user.
|
|
164
|
+
|
|
148
165
|
---
|
|
149
166
|
|
|
150
167
|
## 3. EMAIL_VERIFIED Access Type
|
|
@@ -189,6 +206,17 @@ FormBuilderModule.forRoot({
|
|
|
189
206
|
|
|
190
207
|
---
|
|
191
208
|
|
|
209
|
+
## 4. Computed Fields
|
|
210
|
+
|
|
211
|
+
`schema.settings.computedFields[]` are calculated on final submission (not drafts) and stored under `data._computed[key]`. Each field has ordered `rules` - `{ condition?, value }`, first match wins, else `defaultValue` - where `value` is an [Expression](../nestjs-shared/README.md#10-expressions) and `condition` an expression condition group. Combinations (regex extract, then join with another field, then upper-case; inline if / else) are just nested expressions.
|
|
212
|
+
|
|
213
|
+
- References: a field id, a field `name` (what templates use, `{{ email }}`), or `computed.<key>` for a computed field defined **earlier**.
|
|
214
|
+
- `valueType` (`number` | `string` | `boolean`) casts the result; a rule that fails at run time falls back to `defaultValue` instead of failing the submission.
|
|
215
|
+
- Saving a form validates its computed fields (`findComputedFieldIssue`): key format and uniqueness, shape, unknown references or functions, argument counts, literal regex patterns. A problem is a 400 with `form.invalid.computed.field` and `{ field, code, ... }`.
|
|
216
|
+
- **Breaking (v9):** the old rule shape (`computation: { type: 'direct' | 'field_reference' | 'arithmetic', config }` with `{ fieldId, comparison }` conditions) is not read or converted. A form saved with it computes only `defaultValue` on submit and is refused on save until its computed fields are rebuilt in the builder.
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
192
220
|
## License
|
|
193
221
|
|
|
194
222
|
MIT © FLUSYS
|
package/config/message-keys.d.ts
CHANGED
|
@@ -15,6 +15,7 @@ export declare const FORM_MESSAGES: {
|
|
|
15
15
|
readonly OTP_EXPIRED: "form.email.otp.expired";
|
|
16
16
|
readonly OTP_TOO_MANY_ATTEMPTS: "form.email.otp.too.many.attempts";
|
|
17
17
|
readonly OTP_VERIFIED: "form.email.otp.verified";
|
|
18
|
+
readonly INVALID_COMPUTED_FIELD: "form.invalid.computed.field";
|
|
18
19
|
};
|
|
19
20
|
export declare const FORM_RESULT_MESSAGES: {
|
|
20
21
|
readonly GET_ALL_SUCCESS: "form.result.get.all.success";
|
package/dtos/form.dto.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { IdentityResponseDto } from '@flusys/nestjs-shared/dtos';
|
|
2
|
+
import { type ILogicNode } from '@flusys/nestjs-shared/interfaces';
|
|
2
3
|
import { FormAccessType } from '../enums/form-access-type.enum.js';
|
|
3
4
|
export declare class CreateFormDto {
|
|
4
5
|
name: string;
|
|
@@ -6,7 +7,7 @@ export declare class CreateFormDto {
|
|
|
6
7
|
slug?: string;
|
|
7
8
|
schema: Record<string, unknown>;
|
|
8
9
|
accessType?: FormAccessType;
|
|
9
|
-
|
|
10
|
+
permissionLogic?: ILogicNode | null;
|
|
10
11
|
tags?: string[];
|
|
11
12
|
companyId?: string;
|
|
12
13
|
isActive?: boolean;
|
|
@@ -23,15 +24,15 @@ export declare class FormResponseDto extends IdentityResponseDto {
|
|
|
23
24
|
schema: Record<string, unknown>;
|
|
24
25
|
schemaVersion: number;
|
|
25
26
|
accessType: FormAccessType;
|
|
26
|
-
|
|
27
|
+
permissionLogic: ILogicNode | null;
|
|
27
28
|
tags: string[] | null;
|
|
28
29
|
companyId: string | null;
|
|
29
30
|
isActive: boolean;
|
|
30
31
|
}
|
|
31
|
-
declare const PublicFormResponseDto_base: import("@nestjs/common").Type<Pick<FormResponseDto, "
|
|
32
|
+
declare const PublicFormResponseDto_base: import("@nestjs/common").Type<Pick<FormResponseDto, "name" | "description" | "schema" | "id" | "schemaVersion">>;
|
|
32
33
|
export declare class PublicFormResponseDto extends PublicFormResponseDto_base {
|
|
33
34
|
}
|
|
34
|
-
declare const FormAccessInfoResponseDto_base: import("@nestjs/common").Type<Pick<FormResponseDto, "
|
|
35
|
+
declare const FormAccessInfoResponseDto_base: import("@nestjs/common").Type<Pick<FormResponseDto, "name" | "description" | "accessType" | "permissionLogic" | "isActive" | "id">>;
|
|
35
36
|
export declare class FormAccessInfoResponseDto extends FormAccessInfoResponseDto_base {
|
|
36
37
|
}
|
|
37
38
|
export declare class EmailVerifiedFormResponseDto extends PublicFormResponseDto {
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Identity } from '@flusys/nestjs-shared/entities';
|
|
2
|
+
import { type ILogicNode } from '@flusys/nestjs-shared/interfaces';
|
|
2
3
|
import { FormAccessType } from '../enums/form-access-type.enum.js';
|
|
3
4
|
export declare class Form extends Identity {
|
|
4
5
|
name: string;
|
|
@@ -7,7 +8,7 @@ export declare class Form extends Identity {
|
|
|
7
8
|
schema: Record<string, unknown>;
|
|
8
9
|
schemaVersion: number;
|
|
9
10
|
accessType: FormAccessType;
|
|
10
|
-
|
|
11
|
+
permissionLogic: ILogicNode | null;
|
|
11
12
|
tags: string[] | null;
|
|
12
13
|
isActive: boolean;
|
|
13
14
|
}
|