@flusys/nestjs-entity-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 +59 -26
- package/config/entity-builder.constants.d.ts +2 -0
- package/config/message-keys.d.ts +96 -12
- package/controllers/definition-bundle.controller.d.ts +15 -0
- package/controllers/flow-definition.controller.d.ts +7 -1
- package/controllers/index.d.ts +1 -1
- package/dtos/definition-bundle.dto.d.ts +57 -0
- package/dtos/flow.dto.d.ts +12 -20
- package/dtos/index.d.ts +1 -0
- package/entities/flow-definition.entity.d.ts +3 -9
- package/entities/flow-execution.entity.d.ts +3 -0
- package/entities/flow-version.entity.d.ts +10 -0
- package/entities/index.d.ts +3 -3
- package/fesm/21.js +101 -16
- package/fesm/458.js +695 -0
- package/fesm/{996.js → 677.js} +1582 -1047
- package/fesm/794.js +135 -240
- package/fesm/{489.js → 857.js} +216 -289
- package/fesm/{719.js → 870.js} +1955 -220
- package/fesm/{362.js → 897.js} +566 -2
- package/fesm/{606.js → 946.js} +564 -290
- package/fesm/config/index.js +15 -2
- package/fesm/controllers/index.js +9 -9
- package/fesm/docs/index.js +7 -4
- package/fesm/dtos/index.js +451 -256
- package/fesm/entities/index.js +58 -3
- package/fesm/guards/index.js +101 -22
- package/fesm/index.js +444 -948
- package/fesm/interfaces/index.js +92 -4
- package/fesm/modules/index.js +10 -628
- package/fesm/rule-engine/index.js +12 -3
- package/fesm/services/index.js +97 -27
- package/flow-engine/flow-api-key.d.ts +3 -7
- package/flow-engine/flow-graph.validator.d.ts +4 -2
- package/flow-engine/flow-permission-logic.d.ts +2 -0
- package/flow-engine/flow-run.types.d.ts +17 -8
- package/flow-engine/flow.types.d.ts +107 -15
- package/guards/designer-writable.interceptor.d.ts +12 -0
- package/guards/index.d.ts +1 -0
- package/interfaces/definition-bundle.interface.d.ts +111 -0
- package/interfaces/entity-builder-module.interface.d.ts +6 -0
- package/interfaces/flow-definition.interface.d.ts +13 -9
- package/interfaces/generic-record.interface.d.ts +11 -1
- package/interfaces/index.d.ts +1 -0
- package/package.json +5 -6
- package/rule-engine/rule-engine.service.d.ts +3 -1
- package/rule-engine/rule-permission.d.ts +3 -7
- package/rule-engine/rule-regex.d.ts +0 -2
- package/rule-engine/rule-values.d.ts +4 -1
- package/rule-engine/rule.interface.d.ts +2 -3
- package/services/definition-bundle.diff.d.ts +62 -0
- package/services/definition-bundle.file.d.ts +7 -0
- package/services/definition-bundle.service.d.ts +32 -0
- package/services/entity-builder-config.service.d.ts +2 -0
- package/services/entity-flow-scaffold.d.ts +1 -1
- package/services/flow-definition.service.d.ts +25 -12
- package/services/flow-execution.service.d.ts +7 -0
- package/services/flow-executor.service.d.ts +8 -8
- package/services/generic-entity.service.d.ts +5 -1
- package/services/index.d.ts +3 -1
- package/services/schema-evolution.service.d.ts +3 -1
- package/services/schema-sync.service.d.ts +5 -1
- package/controllers/flow-api-key.controller.d.ts +0 -14
- package/entities/flow-api-key.entity.d.ts +0 -10
- package/services/flow-api-key.service.d.ts +0 -31
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { type IMessageRef } from '@flusys/nestjs-shared/interfaces';
|
|
2
|
+
import { type EntityStatus } from '../enums/entity-status.enum.js';
|
|
3
|
+
import { type FieldType } from '../enums/field-type.enum.js';
|
|
4
|
+
import { type IFlowSnapshot } from './flow-definition.interface.js';
|
|
5
|
+
import { type ISchemaChangePlan } from '../services/schema-change.types.js';
|
|
6
|
+
export declare const DEFINITION_BUNDLE_FORMAT = "flusys.entity-builder.bundle";
|
|
7
|
+
export declare const DEFINITION_BUNDLE_VERSION = 1;
|
|
8
|
+
export interface IBundleField {
|
|
9
|
+
id: string;
|
|
10
|
+
code: string;
|
|
11
|
+
label: string;
|
|
12
|
+
fieldType: FieldType;
|
|
13
|
+
nullable: boolean;
|
|
14
|
+
unique: boolean;
|
|
15
|
+
isIndexed: boolean;
|
|
16
|
+
defaultValue: unknown;
|
|
17
|
+
validationRules: Record<string, unknown> | null;
|
|
18
|
+
selectOptions: unknown[] | null;
|
|
19
|
+
relationTarget: string | null;
|
|
20
|
+
order: number;
|
|
21
|
+
uiConfig: Record<string, unknown> | null;
|
|
22
|
+
isSearchable: boolean;
|
|
23
|
+
deprecated: boolean;
|
|
24
|
+
}
|
|
25
|
+
export interface IBundleEntity {
|
|
26
|
+
id: string;
|
|
27
|
+
code: string;
|
|
28
|
+
label: string;
|
|
29
|
+
description: string | null;
|
|
30
|
+
status: EntityStatus;
|
|
31
|
+
isSoftDeleteEnabled: boolean;
|
|
32
|
+
isAuditEnabled: boolean;
|
|
33
|
+
uiConfig: Record<string, unknown> | null;
|
|
34
|
+
fields: IBundleField[];
|
|
35
|
+
}
|
|
36
|
+
export type IBundleFlow = IFlowSnapshot;
|
|
37
|
+
export interface IDefinitionBundle {
|
|
38
|
+
format: typeof DEFINITION_BUNDLE_FORMAT;
|
|
39
|
+
version: typeof DEFINITION_BUNDLE_VERSION;
|
|
40
|
+
entities: IBundleEntity[];
|
|
41
|
+
flows: IBundleFlow[];
|
|
42
|
+
}
|
|
43
|
+
export interface IImportBundleRequest {
|
|
44
|
+
bundle: IDefinitionBundle;
|
|
45
|
+
deprecateMissingFields?: boolean;
|
|
46
|
+
confirm?: boolean;
|
|
47
|
+
expectedChecksum?: string;
|
|
48
|
+
expectedPlanChecksum?: string;
|
|
49
|
+
}
|
|
50
|
+
export interface IBundleExport {
|
|
51
|
+
bundle: IDefinitionBundle;
|
|
52
|
+
checksum: string;
|
|
53
|
+
warnings: IMessageRef[];
|
|
54
|
+
}
|
|
55
|
+
export type BundleStepKind = 'update_entity' | 'create_entity' | 'restore_field' | 'rename_field' | 'update_field' | 'add_field' | 'deprecate_field' | 'create_flow' | 'update_flow';
|
|
56
|
+
export interface IBundleStep {
|
|
57
|
+
kind: BundleStepKind;
|
|
58
|
+
entityCode?: string;
|
|
59
|
+
fieldCode?: string;
|
|
60
|
+
flowSlug?: string;
|
|
61
|
+
details: Record<string, unknown>;
|
|
62
|
+
preview: ISchemaChangePlan | null;
|
|
63
|
+
warnings: IMessageRef[];
|
|
64
|
+
blockers: IMessageRef[];
|
|
65
|
+
}
|
|
66
|
+
export interface IBundleExtra {
|
|
67
|
+
kind: 'entity' | 'field' | 'flow';
|
|
68
|
+
entityCode?: string;
|
|
69
|
+
fieldCode?: string;
|
|
70
|
+
flowSlug?: string;
|
|
71
|
+
}
|
|
72
|
+
export interface IBundleImportPlan {
|
|
73
|
+
checksum: string;
|
|
74
|
+
planChecksum: string;
|
|
75
|
+
steps: IBundleStep[];
|
|
76
|
+
unchanged: {
|
|
77
|
+
entities: number;
|
|
78
|
+
fields: number;
|
|
79
|
+
flows: number;
|
|
80
|
+
};
|
|
81
|
+
extras: IBundleExtra[];
|
|
82
|
+
blockers: IMessageRef[];
|
|
83
|
+
destructive: boolean;
|
|
84
|
+
mayLoseData: boolean;
|
|
85
|
+
}
|
|
86
|
+
export interface IBundleSettings {
|
|
87
|
+
readOnly: boolean;
|
|
88
|
+
variables: string[];
|
|
89
|
+
}
|
|
90
|
+
export interface IGeneratedApiKey {
|
|
91
|
+
flowSlug: string;
|
|
92
|
+
nodeId: string;
|
|
93
|
+
path: string | null;
|
|
94
|
+
key: string;
|
|
95
|
+
}
|
|
96
|
+
export interface IBundleStepResult {
|
|
97
|
+
kind: BundleStepKind;
|
|
98
|
+
entityCode?: string;
|
|
99
|
+
fieldCode?: string;
|
|
100
|
+
flowSlug?: string;
|
|
101
|
+
status: 'applied' | 'failed' | 'skipped';
|
|
102
|
+
error?: IMessageRef;
|
|
103
|
+
blockers?: IMessageRef[];
|
|
104
|
+
}
|
|
105
|
+
export interface IBundleImportResult {
|
|
106
|
+
checksum: string;
|
|
107
|
+
completed: boolean;
|
|
108
|
+
steps: IBundleStepResult[];
|
|
109
|
+
apiKeys: IGeneratedApiKey[];
|
|
110
|
+
warnings: IMessageRef[];
|
|
111
|
+
}
|
|
@@ -6,6 +6,12 @@ export interface IEntityBuilderConfig extends IDataSourceServiceOptions {
|
|
|
6
6
|
flows?: {
|
|
7
7
|
allowPrivateHttp?: boolean;
|
|
8
8
|
};
|
|
9
|
+
bundles?: {
|
|
10
|
+
variables?: Record<string, string>;
|
|
11
|
+
};
|
|
12
|
+
designer?: {
|
|
13
|
+
readOnly?: boolean;
|
|
14
|
+
};
|
|
9
15
|
}
|
|
10
16
|
export interface EntityBuilderModuleOptions extends IDynamicModuleConfig {
|
|
11
17
|
bootstrapAppConfig?: IBootstrapAppConfig;
|
|
@@ -1,20 +1,24 @@
|
|
|
1
1
|
import { type IIdentity } from '@flusys/nestjs-shared/interfaces';
|
|
2
|
-
import { type
|
|
2
|
+
import { type IFlowEdge, type IFlowNode } from '../flow-engine/flow.types.js';
|
|
3
3
|
export interface IFlowDefinition extends IIdentity {
|
|
4
4
|
name: string;
|
|
5
5
|
slug: string;
|
|
6
6
|
description: string | null;
|
|
7
7
|
isActive: boolean;
|
|
8
|
-
authMode: FlowAuthMode;
|
|
9
|
-
permissionCode: string | null;
|
|
10
|
-
runAs: FlowRunAs;
|
|
11
|
-
isTransactional: boolean;
|
|
12
|
-
timeoutMs: number;
|
|
13
|
-
rateLimitPerMinute: number;
|
|
14
8
|
retainExecutions: number;
|
|
15
|
-
bodyType: FlowBodyType;
|
|
16
|
-
inputSchema: IFlowInputField[];
|
|
17
9
|
nodes: IFlowNode[];
|
|
18
10
|
edges: IFlowEdge[];
|
|
19
11
|
version: number;
|
|
12
|
+
draft: IFlowSnapshot | null;
|
|
13
|
+
}
|
|
14
|
+
export declare const FLOW_VERSIONED_FIELDS: readonly ["name", "slug", "description", "isActive", "retainExecutions", "nodes", "edges"];
|
|
15
|
+
export type IFlowSnapshot = Pick<IFlowDefinition, (typeof FLOW_VERSIONED_FIELDS)[number]>;
|
|
16
|
+
export interface IFlowVersion {
|
|
17
|
+
id: string;
|
|
18
|
+
flowId: string;
|
|
19
|
+
version: number;
|
|
20
|
+
note: string | null;
|
|
21
|
+
publishedAt: Date;
|
|
22
|
+
publishedById: string | null;
|
|
23
|
+
definition?: IFlowSnapshot;
|
|
20
24
|
}
|
|
@@ -3,12 +3,22 @@ export interface IGenericRecord extends ObjectLiteral {
|
|
|
3
3
|
id: string;
|
|
4
4
|
[key: string]: unknown;
|
|
5
5
|
}
|
|
6
|
-
export declare const RECORD_FILTER_OPS: readonly ["eq", "ne", "gt", "gte", "lt", "lte", "in", "is_null", "not_null"];
|
|
6
|
+
export declare const RECORD_FILTER_OPS: readonly ["eq", "ne", "ieq", "gt", "gte", "lt", "lte", "between", "not_between", "in", "not_in", "contains", "not_contains", "starts_with", "ends_with", "has_any", "has_all", "has_none", "is_empty", "not_empty", "is_null", "not_null"];
|
|
7
7
|
export type RecordFilterOp = (typeof RECORD_FILTER_OPS)[number];
|
|
8
|
+
export type FilterValueKind = 'none' | 'single' | 'list' | 'range';
|
|
9
|
+
export declare const FILTER_OP_VALUE_KIND: Record<RecordFilterOp, FilterValueKind>;
|
|
10
|
+
export declare const TEXT_FILTER_OPS: readonly RecordFilterOp[];
|
|
11
|
+
export declare const LIST_FIELD_FILTER_OPS: readonly RecordFilterOp[];
|
|
12
|
+
export declare const EMPTY_FILTER_OPS: readonly RecordFilterOp[];
|
|
8
13
|
export interface IRecordFilterCondition {
|
|
9
14
|
op: RecordFilterOp;
|
|
10
15
|
value?: unknown;
|
|
11
16
|
}
|
|
17
|
+
export interface IFilterRange<T> {
|
|
18
|
+
from: T;
|
|
19
|
+
to: T;
|
|
20
|
+
}
|
|
21
|
+
export declare function isFilterRange(value: unknown): value is IFilterRange<unknown>;
|
|
12
22
|
export declare const RECORD_FILTER_LIMITS: {
|
|
13
23
|
readonly MAX_IN_VALUES: 100;
|
|
14
24
|
};
|
package/interfaces/index.d.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flusys/nestjs-entity-builder",
|
|
3
|
-
"version": "9.1.
|
|
3
|
+
"version": "9.1.2",
|
|
4
4
|
"description": "Dynamic entity builder module - runtime entity/field metadata, driven DDL, and generic CRUD",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./fesm/index.js",
|
|
@@ -75,19 +75,18 @@
|
|
|
75
75
|
"@nestjs/common": "^12.0.0",
|
|
76
76
|
"@nestjs/config": "^12.0.0",
|
|
77
77
|
"@nestjs/core": "^12.0.0",
|
|
78
|
-
"@nestjs/platform-express": "^12.
|
|
78
|
+
"@nestjs/platform-express": "^12.1.2",
|
|
79
79
|
"@nestjs/swagger": "^12.0.0",
|
|
80
80
|
"@nestjs/typeorm": "^12.0.0",
|
|
81
81
|
"class-transformer": "^0.5.1",
|
|
82
82
|
"class-validator": "^0.15.0",
|
|
83
|
-
"typeorm": "^0.3.
|
|
83
|
+
"typeorm": "^0.3.31",
|
|
84
84
|
"express": "^5.0.0",
|
|
85
85
|
"rxjs": "^7.8.0"
|
|
86
86
|
},
|
|
87
87
|
"dependencies": {
|
|
88
|
-
"@flusys/nestjs-core": "9.1.
|
|
89
|
-
"@flusys/nestjs-shared": "9.1.
|
|
90
|
-
"re2js": "^2.8.6",
|
|
88
|
+
"@flusys/nestjs-core": "9.1.2",
|
|
89
|
+
"@flusys/nestjs-shared": "9.1.2",
|
|
91
90
|
"quickjs-emscripten": "^0.32.0"
|
|
92
91
|
}
|
|
93
92
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type IPermissionResolver } from '@flusys/nestjs-shared/interfaces';
|
|
1
|
+
import { type IPermissionResolver, type IPermissionScope } from '@flusys/nestjs-shared/interfaces';
|
|
2
2
|
import { SharedPermissionCacheService } from '@flusys/nestjs-shared/modules';
|
|
3
3
|
import { type IRulePermissionResolver, type RuleEvaluationContext } from './rule-evaluation-context.interface.js';
|
|
4
4
|
import { type RuleCondition, type RuleExpression, type RuleGroup } from './rule.interface.js';
|
|
@@ -11,12 +11,14 @@ export declare class RuleEngineService {
|
|
|
11
11
|
private readonly permissionCache?;
|
|
12
12
|
constructor(permissionResolver?: IPermissionResolver | undefined, permissionCache?: SharedPermissionCacheService | undefined);
|
|
13
13
|
createPermissionResolver(user: RuleEvaluationContext['user']): IRulePermissionResolver;
|
|
14
|
+
permissionCodes(scope: IPermissionScope): Promise<string[]>;
|
|
14
15
|
evaluateGroup(group: RuleGroup, ctx: RuleEvaluationContext, depth?: number, budget?: IEvaluationBudget): Promise<boolean>;
|
|
15
16
|
private every;
|
|
16
17
|
evaluateCondition(condition: RuleCondition, ctx: RuleEvaluationContext, budget?: IEvaluationBudget): Promise<boolean>;
|
|
17
18
|
private resolveConditionLeft;
|
|
18
19
|
private resolveConditionValue;
|
|
19
20
|
resolveExpression(expression: RuleExpression, ctx: RuleEvaluationContext, budget?: IEvaluationBudget): Promise<unknown>;
|
|
21
|
+
resolveHtml(expression: RuleExpression, ctx: RuleEvaluationContext): Promise<unknown>;
|
|
20
22
|
private resolveLookup;
|
|
21
23
|
private resolveTemplate;
|
|
22
24
|
private resolveFieldReference;
|
|
@@ -1,10 +1,6 @@
|
|
|
1
|
-
import { type ILoggedUserInfo
|
|
2
|
-
import { type
|
|
1
|
+
import { type ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
|
|
2
|
+
import { type IPermissionSources } from '@flusys/nestjs-shared/utils';
|
|
3
3
|
import { type IRulePermissionResolver } from './rule-evaluation-context.interface.js';
|
|
4
|
-
export
|
|
5
|
-
resolver?: IPermissionResolver;
|
|
6
|
-
cache?: SharedPermissionCacheService;
|
|
7
|
-
}
|
|
8
|
-
export declare function createRulePermissionResolver(user: ILoggedUserInfo | null, sources: IRulePermissionSources): IRulePermissionResolver;
|
|
4
|
+
export declare function createRulePermissionResolver(user: ILoggedUserInfo | null, sources: IPermissionSources): IRulePermissionResolver;
|
|
9
5
|
export declare function parsePermissionCodes(value: unknown): string[];
|
|
10
6
|
export declare function toBranchArgument(args: unknown[], index: number): string | null | undefined;
|
|
@@ -1,4 +1,2 @@
|
|
|
1
|
-
export type RulePatternProblem = 'too_long' | 'invalid' | 'too_complex';
|
|
2
|
-
export declare function rulePatternProblem(pattern: string): RulePatternProblem | null;
|
|
3
1
|
export declare function matchesPattern(input: unknown, pattern: unknown): boolean;
|
|
4
2
|
export declare function extractPattern(input: unknown, pattern: unknown, group?: unknown): string | null;
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import { type IRecordFilterCondition } from '../interfaces/generic-record.interface.js';
|
|
2
|
+
import { type RuleExpression } from './rule.interface.js';
|
|
1
3
|
export declare const ISO_DATE_PREFIX: RegExp;
|
|
2
4
|
export declare function parseDateText(text: string): number;
|
|
3
5
|
export declare function valuesEqual(a: unknown, b: unknown): boolean;
|
|
4
6
|
export declare const includesValue: (list: readonly unknown[], value: unknown) => boolean;
|
|
5
|
-
export declare
|
|
7
|
+
export declare function resolveFilterEntry(item: unknown, resolve: (expression: RuleExpression) => Promise<unknown>): Promise<IRecordFilterCondition>;
|
|
8
|
+
export declare const isFilterValueMissing: (entry: IRecordFilterCondition) => boolean;
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type RecordFilterOp } from '../interfaces/generic-record.interface.js';
|
|
1
|
+
import { type IFilterRange, type RecordFilterOp } from '../interfaces/generic-record.interface.js';
|
|
2
2
|
export type RuleLogicOperator = 'AND' | 'OR' | 'NOT';
|
|
3
3
|
export declare const RULE_COMPARISON_OPERATORS: readonly ["equals", "not_equals", "greater_than", "less_than", "greater_or_equal", "less_or_equal", "contains", "not_contains", "starts_with", "ends_with", "is_empty", "is_not_empty", "in", "not_in", "is_any_of", "is_none_of", "is_true", "is_false", "matches", "not_matches"];
|
|
4
4
|
export type RuleComparisonOperator = (typeof RULE_COMPARISON_OPERATORS)[number];
|
|
@@ -30,7 +30,7 @@ export type RuleDurationUnit = (typeof RULE_DURATION_UNITS)[number];
|
|
|
30
30
|
export type RuleLookupMode = 'exists' | 'count' | 'first';
|
|
31
31
|
export interface RuleLookupFilterCondition {
|
|
32
32
|
op: RecordFilterOp;
|
|
33
|
-
value?: RuleExpression
|
|
33
|
+
value?: RuleExpression | IFilterRange<RuleExpression>;
|
|
34
34
|
}
|
|
35
35
|
export interface RuleLookupExpression {
|
|
36
36
|
type: 'lookup';
|
|
@@ -72,7 +72,6 @@ export declare const RULE_ENGINE_LIMITS: {
|
|
|
72
72
|
readonly MAX_REGEX_PATTERN_LENGTH: 500;
|
|
73
73
|
readonly MAX_REGEX_INPUT_LENGTH: 10000;
|
|
74
74
|
readonly MAX_REGEX_REPEAT: 100;
|
|
75
|
-
readonly MAX_REGEX_REPEAT_EXPANSION: 300;
|
|
76
75
|
readonly MAX_UTC_OFFSET_MINUTES: 840;
|
|
77
76
|
readonly MAX_PERMISSION_CODES: 50;
|
|
78
77
|
readonly MAX_IP_RANGES: 100;
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { type IMessageRef } from '@flusys/nestjs-shared/interfaces';
|
|
2
|
+
import { EntityStatus } from '../enums/entity-status.enum.js';
|
|
3
|
+
import { type IFlowNode } from '../flow-engine/flow.types.js';
|
|
4
|
+
import { type BundleStepKind, type IBundleEntity, type IBundleExtra, type IBundleField, type IBundleFlow, type IDefinitionBundle } from '../interfaces/definition-bundle.interface.js';
|
|
5
|
+
export declare function canonicalJson(value: unknown): string;
|
|
6
|
+
export declare const byCode: (a: string, b: string) => number;
|
|
7
|
+
export declare const bundleSubject: (item: {
|
|
8
|
+
entityCode?: string;
|
|
9
|
+
fieldCode?: string;
|
|
10
|
+
flowSlug?: string;
|
|
11
|
+
}) => string;
|
|
12
|
+
export declare const bundleChecksum: (bundle: IDefinitionBundle) => string;
|
|
13
|
+
export declare function stripApiKeys(nodes: IFlowNode[]): IFlowNode[];
|
|
14
|
+
export declare function extractVariables(nodes: IFlowNode[], variables: Record<string, string>): IFlowNode[];
|
|
15
|
+
export declare function applyVariables(nodes: IFlowNode[], variables: Record<string, string>): {
|
|
16
|
+
nodes: IFlowNode[];
|
|
17
|
+
missing: string[];
|
|
18
|
+
};
|
|
19
|
+
export declare function calledFlowSlugs(nodes: IFlowNode[]): string[];
|
|
20
|
+
export declare function orderFlows(flows: IBundleFlow[]): IBundleFlow[];
|
|
21
|
+
export interface ICurrentEntity {
|
|
22
|
+
id: string;
|
|
23
|
+
code: string;
|
|
24
|
+
label: string;
|
|
25
|
+
description: string | null;
|
|
26
|
+
status: EntityStatus;
|
|
27
|
+
isSoftDeleteEnabled: boolean;
|
|
28
|
+
isAuditEnabled: boolean;
|
|
29
|
+
uiConfig: Record<string, unknown> | null;
|
|
30
|
+
fields: IBundleField[];
|
|
31
|
+
}
|
|
32
|
+
export interface IPlannedOperation {
|
|
33
|
+
kind: BundleStepKind;
|
|
34
|
+
entityCode: string;
|
|
35
|
+
fieldCode?: string;
|
|
36
|
+
details: Record<string, unknown>;
|
|
37
|
+
dependsOnEarlierStep: boolean;
|
|
38
|
+
entity?: IBundleEntity;
|
|
39
|
+
field?: IBundleField;
|
|
40
|
+
targetFieldId?: string;
|
|
41
|
+
changes?: Record<string, unknown>;
|
|
42
|
+
warnings?: IMessageRef[];
|
|
43
|
+
}
|
|
44
|
+
export interface IEntityDiff {
|
|
45
|
+
operations: IPlannedOperation[];
|
|
46
|
+
unchangedEntities: number;
|
|
47
|
+
unchangedFields: number;
|
|
48
|
+
extras: IBundleExtra[];
|
|
49
|
+
blockers: IMessageRef[];
|
|
50
|
+
}
|
|
51
|
+
export declare const FIELD_COMPARED_KEYS: readonly ["label", "fieldType", "nullable", "unique", "isIndexed", "defaultValue", "validationRules", "selectOptions", "relationTarget", "order", "uiConfig", "isSearchable"];
|
|
52
|
+
export declare const ENTITY_COMPARED_KEYS: readonly ["label", "description", "uiConfig", "isSoftDeleteEnabled", "isAuditEnabled", "status"];
|
|
53
|
+
export declare function matchDefinitions<B extends {
|
|
54
|
+
id: string;
|
|
55
|
+
code: string;
|
|
56
|
+
}, C extends {
|
|
57
|
+
id: string;
|
|
58
|
+
code: string;
|
|
59
|
+
}>(items: B[], current: C[]): Map<B, C>;
|
|
60
|
+
export declare function diffEntities(entities: IBundleEntity[], current: ICurrentEntity[], options?: {
|
|
61
|
+
deprecateMissingFields?: boolean;
|
|
62
|
+
}): IEntityDiff;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { type IDefinitionBundle } from '../interfaces/definition-bundle.interface.js';
|
|
2
|
+
export interface IUploadedBundleFile {
|
|
3
|
+
buffer: Buffer;
|
|
4
|
+
size: number;
|
|
5
|
+
originalname?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function readBundleFile(file: IUploadedBundleFile | undefined): IDefinitionBundle;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { type ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
|
|
2
|
+
import { type ExportBundleDto } from '../dtos/definition-bundle.dto.js';
|
|
3
|
+
import { type IBundleExport, type IBundleImportPlan, type IBundleImportResult, type IImportBundleRequest } from '../interfaces/definition-bundle.interface.js';
|
|
4
|
+
import { EntityBuilderConfigService } from './entity-builder-config.service.js';
|
|
5
|
+
import { EntityBuilderDataSourceProvider } from './entity-builder-datasource.provider.js';
|
|
6
|
+
import { FlowDefinitionService } from './flow-definition.service.js';
|
|
7
|
+
import { SchemaEvolutionService } from './schema-evolution.service.js';
|
|
8
|
+
import { SchemaSyncService } from './schema-sync.service.js';
|
|
9
|
+
export declare class DefinitionBundleService {
|
|
10
|
+
private readonly provider;
|
|
11
|
+
private readonly config;
|
|
12
|
+
private readonly schemaSync;
|
|
13
|
+
private readonly evolution;
|
|
14
|
+
private readonly flows;
|
|
15
|
+
constructor(provider: EntityBuilderDataSourceProvider, config: EntityBuilderConfigService, schemaSync: SchemaSyncService, evolution: SchemaEvolutionService, flows: FlowDefinitionService);
|
|
16
|
+
private variables;
|
|
17
|
+
export(dto: ExportBundleDto): Promise<IBundleExport>;
|
|
18
|
+
private loadEntities;
|
|
19
|
+
planImport(dto: IImportBundleRequest, user: ILoggedUserInfo | null): Promise<IBundleImportPlan>;
|
|
20
|
+
private buildPlan;
|
|
21
|
+
private relationNotYetCreated;
|
|
22
|
+
private previewEntityStep;
|
|
23
|
+
private diffFlows;
|
|
24
|
+
private fieldSpec;
|
|
25
|
+
private createRequest;
|
|
26
|
+
private changeRequest;
|
|
27
|
+
applyImport(dto: IImportBundleRequest, user: ILoggedUserInfo | null): Promise<IBundleImportResult>;
|
|
28
|
+
private applyEntityStep;
|
|
29
|
+
private idIsFree;
|
|
30
|
+
private freeFieldIds;
|
|
31
|
+
private applyFlowStep;
|
|
32
|
+
}
|
|
@@ -9,4 +9,6 @@ export declare class EntityBuilderConfigService implements IModuleConfigService
|
|
|
9
9
|
isMultiTenant(): boolean;
|
|
10
10
|
getOptions(): EntityBuilderModuleOptions;
|
|
11
11
|
getConfig(): import("../index.js").IEntityBuilderConfig | undefined;
|
|
12
|
+
isDesignerReadOnly(): boolean;
|
|
13
|
+
getBundleVariables(): Record<string, string>;
|
|
12
14
|
}
|
|
@@ -8,6 +8,7 @@ export interface IEntityFlowField {
|
|
|
8
8
|
nullable?: boolean;
|
|
9
9
|
defaultValue?: unknown;
|
|
10
10
|
selectOptions?: unknown[] | null;
|
|
11
|
+
validationRules?: Record<string, unknown> | null;
|
|
11
12
|
}
|
|
12
13
|
export interface IEntityFlowSource {
|
|
13
14
|
code: string;
|
|
@@ -21,7 +22,6 @@ export interface IEntityFlowTexts {
|
|
|
21
22
|
noMatchMessage?: string;
|
|
22
23
|
}
|
|
23
24
|
export declare const ENTITY_FLOW_PATHS: Record<EntityFlowEndpoint, string>;
|
|
24
|
-
export declare const BULK_MAX_ITEMS = 200;
|
|
25
25
|
export declare const entityFlowSlug: (entityCode: string) => string;
|
|
26
26
|
export declare function buildEntityFlow(entity: IEntityFlowSource, endpoints: readonly EntityFlowEndpoint[], texts?: IEntityFlowTexts): CreateFlowDefinitionDto;
|
|
27
27
|
export {};
|
|
@@ -1,41 +1,47 @@
|
|
|
1
1
|
import { type IPermissionActionRegistry } from '@flusys/nestjs-shared';
|
|
2
2
|
import { ApiService, HybridCache } from '@flusys/nestjs-shared/classes';
|
|
3
3
|
import { type DeleteDto } from '@flusys/nestjs-shared/dtos';
|
|
4
|
-
import { type ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
|
|
4
|
+
import { type ICompanyAccessResolver, type IEmailAdapter, type ILogicNode, type ILoggedUserInfo, type INotificationAdapter } from '@flusys/nestjs-shared/interfaces';
|
|
5
5
|
import { SharedPermissionCacheService, UtilsService } from '@flusys/nestjs-shared/modules';
|
|
6
6
|
import { NotFoundException } from '@nestjs/common';
|
|
7
7
|
import { type QueryRunner } from 'typeorm';
|
|
8
8
|
import { type CreateFlowDefinitionDto, type UpdateFlowDefinitionDto } from '../dtos/flow.dto.js';
|
|
9
9
|
import { FlowDefinition } from '../entities/flow-definition.entity.js';
|
|
10
10
|
import { type IFlowValidationResult } from '../flow-engine/flow-graph.validator.js';
|
|
11
|
-
import { type IFlowSettings } from '../flow-engine/flow.types.js';
|
|
12
|
-
import { type IFlowDefinition } from '../interfaces/flow-definition.interface.js';
|
|
11
|
+
import { type IFlowEndpoint, type IFlowSettings } from '../flow-engine/flow.types.js';
|
|
12
|
+
import { type IFlowDefinition, type IFlowSnapshot, type IFlowVersion } from '../interfaces/flow-definition.interface.js';
|
|
13
13
|
import { EntityBuilderDataSourceProvider } from './entity-builder-datasource.provider.js';
|
|
14
14
|
export declare const defaultFlowPermissionCode: (slug: string) => string;
|
|
15
|
+
export declare const flowPermissions: (endpoint: Pick<IFlowEndpoint, "permissions">, slug: string) => ILogicNode;
|
|
15
16
|
export declare const flowNotFound: () => NotFoundException;
|
|
16
|
-
export declare
|
|
17
|
+
export declare const isPublished: (flow: Pick<FlowDefinition, "version">) => boolean;
|
|
18
|
+
export declare function snapshotOf(source: Partial<IFlowSnapshot>): IFlowSnapshot;
|
|
19
|
+
export declare const workingCopy: (flow: FlowDefinition) => IFlowSnapshot;
|
|
20
|
+
type FlowSettingsSource = Pick<Partial<CreateFlowDefinitionDto>, 'nodes' | 'edges'> & {
|
|
17
21
|
slug: string;
|
|
18
|
-
}): IFlowSettings & {
|
|
19
|
-
timeoutMs: number;
|
|
20
22
|
};
|
|
23
|
+
export declare function toFlowSettings(dto: FlowSettingsSource): IFlowSettings;
|
|
21
24
|
export declare class FlowDefinitionService extends ApiService<CreateFlowDefinitionDto, UpdateFlowDefinitionDto, IFlowDefinition, FlowDefinition> {
|
|
22
25
|
protected cacheManager: HybridCache;
|
|
23
26
|
protected utilsService: UtilsService;
|
|
24
27
|
private readonly provider;
|
|
25
28
|
private readonly permissionCache;
|
|
26
29
|
private readonly actionRegistry?;
|
|
27
|
-
|
|
30
|
+
private readonly notifications?;
|
|
31
|
+
private readonly email?;
|
|
32
|
+
private readonly companyAccess?;
|
|
33
|
+
constructor(cacheManager: HybridCache, utilsService: UtilsService, provider: EntityBuilderDataSourceProvider, permissionCache: SharedPermissionCacheService, actionRegistry?: IPermissionActionRegistry | undefined, notifications?: INotificationAdapter | undefined, email?: IEmailAdapter | undefined, companyAccess?: ICompanyAccessResolver | undefined);
|
|
28
34
|
findOrFail(id: string): Promise<FlowDefinition>;
|
|
29
35
|
validate(settings: IFlowSettings): Promise<IFlowValidationResult>;
|
|
30
36
|
private callersOf;
|
|
31
37
|
private assertNotCalled;
|
|
38
|
+
private assertCallersKept;
|
|
39
|
+
private assertCallsStillValid;
|
|
32
40
|
private assertEndpointsNotCalled;
|
|
33
41
|
private assertSaveable;
|
|
34
42
|
assertMayAuthor(settings: IFlowSettings, user: ILoggedUserInfo | null): Promise<void>;
|
|
35
43
|
assertMayCreate(user: ILoggedUserInfo | null): Promise<void>;
|
|
36
|
-
assertMayTest(settings: IFlowSettings
|
|
37
|
-
permissionCode?: string | null;
|
|
38
|
-
}, user: ILoggedUserInfo | null, run: {
|
|
44
|
+
assertMayTest(settings: IFlowSettings, endpoint: IFlowEndpoint | undefined, user: ILoggedUserInfo | null, run: {
|
|
39
45
|
mode: 'dry_run' | 'live';
|
|
40
46
|
draft: boolean;
|
|
41
47
|
saved: boolean;
|
|
@@ -43,8 +49,15 @@ export declare class FlowDefinitionService extends ApiService<CreateFlowDefiniti
|
|
|
43
49
|
private assertHasPermission;
|
|
44
50
|
protected beforeInsertOperation(dto: CreateFlowDefinitionDto | CreateFlowDefinitionDto[], user: ILoggedUserInfo | null, _qr: QueryRunner): Promise<void>;
|
|
45
51
|
protected beforeUpdateOperation(dto: UpdateFlowDefinitionDto | UpdateFlowDefinitionDto[], user: ILoggedUserInfo | null, _qr: QueryRunner): Promise<void>;
|
|
52
|
+
protected convertSingleDtoToEntity(dto: CreateFlowDefinitionDto | UpdateFlowDefinitionDto, user: ILoggedUserInfo | null): Promise<FlowDefinition>;
|
|
53
|
+
publish(id: string, note: string | undefined, user: ILoggedUserInfo | null): Promise<FlowDefinition>;
|
|
54
|
+
listVersions(flowId: string): Promise<IFlowVersion[]>;
|
|
55
|
+
getVersion(flowId: string, version: number): Promise<IFlowVersion>;
|
|
56
|
+
restoreVersion(flowId: string, version: number, user: ILoggedUserInfo | null): Promise<FlowDefinition>;
|
|
57
|
+
discardDraft(flowId: string, user: ILoggedUserInfo | null): Promise<FlowDefinition>;
|
|
58
|
+
private saveDraft;
|
|
59
|
+
private clearCaches;
|
|
46
60
|
protected beforeDeleteOperation(dto: DeleteDto, user: ILoggedUserInfo | null, _qr: QueryRunner): Promise<void>;
|
|
47
|
-
protected afterInsertOperation(entities: FlowDefinition[]): Promise<void>;
|
|
48
|
-
protected afterUpdateOperation(entities: FlowDefinition[]): Promise<void>;
|
|
49
61
|
private provisionPermissions;
|
|
50
62
|
}
|
|
63
|
+
export {};
|
|
@@ -4,7 +4,12 @@ import { EntityBuilderDataSourceProvider } from './entity-builder-datasource.pro
|
|
|
4
4
|
export interface IExecutionRecord {
|
|
5
5
|
flowId: string | null;
|
|
6
6
|
flowSlug: string;
|
|
7
|
+
flowVersion: number | null;
|
|
7
8
|
trigger: 'webhook' | 'test';
|
|
9
|
+
endpoint: {
|
|
10
|
+
nodeId: string;
|
|
11
|
+
path: string | null;
|
|
12
|
+
} | null;
|
|
8
13
|
mode: 'live' | 'dry_run';
|
|
9
14
|
input: unknown;
|
|
10
15
|
result: Pick<IFlowRunResult, 'status' | 'statusCode' | 'body' | 'error' | 'trace' | 'durationMs'>;
|
|
@@ -24,6 +29,8 @@ export declare class FlowExecutionService {
|
|
|
24
29
|
list(query: {
|
|
25
30
|
flowId?: string;
|
|
26
31
|
status?: string;
|
|
32
|
+
trigger?: string;
|
|
33
|
+
endpointNodeId?: string;
|
|
27
34
|
page: number;
|
|
28
35
|
pageSize: number;
|
|
29
36
|
}): Promise<{
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
|
|
1
|
+
import { type IBranchHierarchyResolver, type ICompanyAccessResolver, type IEmailAdapter, type ILoggedUserInfo, type INotificationAdapter } from '@flusys/nestjs-shared/interfaces';
|
|
2
2
|
import { SharedPermissionCacheService } from '@flusys/nestjs-shared/modules';
|
|
3
3
|
import { ModuleRef } from '@nestjs/core';
|
|
4
4
|
import { type IFlowRunResult } from '../flow-engine/flow-run.types.js';
|
|
@@ -12,22 +12,23 @@ export interface IFlowRunOptions {
|
|
|
12
12
|
input: FlowInput;
|
|
13
13
|
startAt?: string;
|
|
14
14
|
request: Record<string, unknown>;
|
|
15
|
+
authorization?: string;
|
|
15
16
|
exposeDetails: boolean;
|
|
16
|
-
systemAuthorized: boolean;
|
|
17
17
|
}
|
|
18
18
|
export declare const flowTimeout: (timeoutMs: unknown) => number;
|
|
19
|
-
type RunnableFlow = IFlowSettings & {
|
|
20
|
-
timeoutMs: number;
|
|
21
|
-
};
|
|
22
19
|
export declare class FlowExecutorService {
|
|
23
20
|
private readonly provider;
|
|
24
21
|
private readonly ruleEngine;
|
|
25
22
|
private readonly moduleRef;
|
|
26
23
|
private readonly permissionCache;
|
|
27
24
|
private readonly config;
|
|
25
|
+
private readonly companyAccess?;
|
|
26
|
+
private readonly notifications?;
|
|
27
|
+
private readonly email?;
|
|
28
|
+
private readonly branchHierarchy?;
|
|
28
29
|
private readonly logger;
|
|
29
|
-
constructor(provider: EntityBuilderDataSourceProvider, ruleEngine: RuleEngineService, moduleRef: ModuleRef, permissionCache: SharedPermissionCacheService, config: EntityBuilderConfigService);
|
|
30
|
-
run(
|
|
30
|
+
constructor(provider: EntityBuilderDataSourceProvider, ruleEngine: RuleEngineService, moduleRef: ModuleRef, permissionCache: SharedPermissionCacheService, config: EntityBuilderConfigService, companyAccess?: ICompanyAccessResolver | undefined, notifications?: INotificationAdapter | undefined, email?: IEmailAdapter | undefined, branchHierarchy?: IBranchHierarchyResolver | undefined);
|
|
31
|
+
run(flow: IFlowSettings, options: IFlowRunOptions): Promise<IFlowRunResult>;
|
|
31
32
|
private execute;
|
|
32
33
|
private limitStatementTime;
|
|
33
34
|
private commitProgress;
|
|
@@ -38,4 +39,3 @@ export declare class FlowExecutorService {
|
|
|
38
39
|
private createEnv;
|
|
39
40
|
private publishPendingEvents;
|
|
40
41
|
}
|
|
41
|
-
export {};
|
|
@@ -50,7 +50,7 @@ export declare class GenericEntityService {
|
|
|
50
50
|
private insertRow;
|
|
51
51
|
private updateRow;
|
|
52
52
|
private assertUpdatable;
|
|
53
|
-
delete(id: string, user: ILoggedUserInfo | null, options?: IGenericWriteOptions): Promise<
|
|
53
|
+
delete(id: string, user: ILoggedUserInfo | null, options?: IGenericWriteOptions): Promise<'deleted' | 'purged'>;
|
|
54
54
|
findById(id: string, options?: IGenericReadOptions): Promise<IGenericRecord>;
|
|
55
55
|
exists(id: string, options?: IGenericReadOptions): Promise<boolean>;
|
|
56
56
|
getAll(search: string | undefined, query: IGenericQuery, options?: IGenericReadOptions): Promise<{
|
|
@@ -58,6 +58,10 @@ export declare class GenericEntityService {
|
|
|
58
58
|
total: number;
|
|
59
59
|
}>;
|
|
60
60
|
private applyFilter;
|
|
61
|
+
private conditionSql;
|
|
62
|
+
private listOperand;
|
|
63
|
+
private fieldTypeOf;
|
|
64
|
+
private assertOperatorFits;
|
|
61
65
|
private unknownOperator;
|
|
62
66
|
private invalidFilterValue;
|
|
63
67
|
private applySort;
|
package/services/index.d.ts
CHANGED
|
@@ -19,9 +19,11 @@ export * from './reference-scanner.service.js';
|
|
|
19
19
|
export * from './field-value-validator.js';
|
|
20
20
|
export * from './database-error.mapper.js';
|
|
21
21
|
export * from './flow-definition.service.js';
|
|
22
|
-
export * from './flow-api-key.service.js';
|
|
23
22
|
export * from './flow-execution.service.js';
|
|
24
23
|
export * from './flow-executor.service.js';
|
|
25
24
|
export * from './flow-runtime.service.js';
|
|
26
25
|
export * from './flow-reference.provider.js';
|
|
27
26
|
export * from './entity-flow-scaffold.js';
|
|
27
|
+
export * from './definition-bundle.diff.js';
|
|
28
|
+
export * from './definition-bundle.file.js';
|
|
29
|
+
export * from './definition-bundle.service.js';
|
|
@@ -30,7 +30,9 @@ export declare class SchemaEvolutionService {
|
|
|
30
30
|
private readonly permissions;
|
|
31
31
|
constructor(dataSourceProvider: EntityBuilderDataSourceProvider, adapter: SchemaDialectAdapterService, executor: SchemaChangeExecutor, references: ReferenceScannerService, permissions: EntityPermissionService);
|
|
32
32
|
plan(request: SchemaChangeRequestDto, user: ILoggedUserInfo | null): Promise<ISchemaChangePlan>;
|
|
33
|
-
apply(request: SchemaChangeRequestDto, user: ILoggedUserInfo | null
|
|
33
|
+
apply(request: SchemaChangeRequestDto, user: ILoggedUserInfo | null, options?: {
|
|
34
|
+
fieldId?: string;
|
|
35
|
+
}): Promise<ISchemaChangeApplied>;
|
|
34
36
|
inspect(entityDefinitionId: string): Promise<ISchemaCheckResult>;
|
|
35
37
|
history(entityDefinitionId: string, limit?: number): Promise<SchemaChangeLog[]>;
|
|
36
38
|
private loadEntity;
|
|
@@ -11,6 +11,10 @@ export interface ICreatedEntity {
|
|
|
11
11
|
definition: EntityDefinition;
|
|
12
12
|
warnings: IMessageRef[];
|
|
13
13
|
}
|
|
14
|
+
export interface IPresetIds {
|
|
15
|
+
entityId?: string;
|
|
16
|
+
fieldIds?: Record<string, string>;
|
|
17
|
+
}
|
|
14
18
|
export declare class SchemaSyncService {
|
|
15
19
|
private readonly dataSourceProvider;
|
|
16
20
|
private readonly dialectAdapter;
|
|
@@ -24,5 +28,5 @@ export declare class SchemaSyncService {
|
|
|
24
28
|
private createRun;
|
|
25
29
|
private createEndpointFlow;
|
|
26
30
|
planCreateEntity(dto: CreateDynamicEntityDto, user: ILoggedUserInfo | null): Promise<ISchemaChangePlan>;
|
|
27
|
-
createEntity(dto: CreateDynamicEntityDto, user: ILoggedUserInfo | null): Promise<ICreatedEntity>;
|
|
31
|
+
createEntity(dto: CreateDynamicEntityDto, user: ILoggedUserInfo | null, ids?: IPresetIds): Promise<ICreatedEntity>;
|
|
28
32
|
}
|