@flusys/nestjs-entity-builder 9.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 +111 -0
- package/config/entity-builder.constants.d.ts +6 -0
- package/config/event-actions.d.ts +8 -0
- package/config/index.d.ts +3 -0
- package/config/message-keys.d.ts +542 -0
- package/controllers/entity-definition.controller.d.ts +40 -0
- package/controllers/field-definition.controller.d.ts +22 -0
- package/controllers/flow-definition.controller.d.ts +51 -0
- package/controllers/flow-execution.controller.d.ts +21 -0
- package/controllers/flow-runtime.controller.d.ts +24 -0
- package/controllers/index.d.ts +5 -0
- package/docs/entity-builder-swagger.config.d.ts +3 -0
- package/docs/index.d.ts +1 -0
- package/dtos/entity-definition.dto.d.ts +58 -0
- package/dtos/field-definition.dto.d.ts +42 -0
- package/dtos/flow.dto.d.ts +76 -0
- package/dtos/index.d.ts +3 -0
- package/dtos/schema-change.dto.d.ts +53 -0
- package/entities/entity-definition.entity.d.ts +15 -0
- package/entities/field-definition.entity.d.ts +23 -0
- package/entities/flow-definition.entity.d.ts +14 -0
- package/entities/flow-execution.entity.d.ts +19 -0
- package/entities/flow-version.entity.d.ts +10 -0
- package/entities/index.d.ts +14 -0
- package/entities/schema-change-log.entity.d.ts +15 -0
- package/enums/ddl-operation.enum.d.ts +13 -0
- package/enums/entity-status.enum.d.ts +5 -0
- package/enums/field-type.enum.d.ts +15 -0
- package/enums/index.d.ts +3 -0
- package/fesm/21.js +576 -0
- package/fesm/362.js +1074 -0
- package/fesm/458.js +649 -0
- package/fesm/582.js +1247 -0
- package/fesm/677.js +7534 -0
- package/fesm/719.js +3597 -0
- package/fesm/794.js +979 -0
- package/fesm/913.js +1620 -0
- package/fesm/config/index.js +126 -0
- package/fesm/controllers/index.js +27 -0
- package/fesm/docs/index.js +82 -0
- package/fesm/dtos/index.js +327 -0
- package/fesm/entities/index.js +18 -0
- package/fesm/enums/index.js +97 -0
- package/fesm/guards/index.js +226 -0
- package/fesm/index.js +548 -0
- package/fesm/interfaces/index.js +80 -0
- package/fesm/modules/index.js +25 -0
- package/fesm/rule-engine/index.js +21 -0
- package/fesm/runtime.js +85 -0
- package/fesm/services/index.js +526 -0
- package/flow-engine/flow-api-key.d.ts +6 -0
- package/flow-engine/flow-code-sandbox.d.ts +5 -0
- package/flow-engine/flow-engine.d.ts +22 -0
- package/flow-engine/flow-graph.validator.d.ts +20 -0
- package/flow-engine/flow-http.client.d.ts +15 -0
- package/flow-engine/flow-input.validator.d.ts +7 -0
- package/flow-engine/flow-node-handlers.d.ts +5 -0
- package/flow-engine/flow-rate-limiter.d.ts +8 -0
- package/flow-engine/flow-reference.d.ts +7 -0
- package/flow-engine/flow-run.types.d.ts +131 -0
- package/flow-engine/flow.errors.d.ts +27 -0
- package/flow-engine/flow.types.d.ts +315 -0
- package/flow-engine/index.d.ts +4 -0
- package/flow-engine/redact.d.ts +3 -0
- package/flow-engine/ssrf-guard.d.ts +6 -0
- package/guards/flow-access.guard.d.ts +11 -0
- package/guards/index.d.ts +1 -0
- package/index.d.ts +11 -0
- package/interfaces/entity-builder-module.interface.d.ts +28 -0
- package/interfaces/field-definition.interface.d.ts +33 -0
- package/interfaces/flow-definition.interface.d.ts +24 -0
- package/interfaces/generic-record.interface.d.ts +15 -0
- package/interfaces/index.d.ts +5 -0
- package/interfaces/reference-provider.interface.d.ts +8 -0
- package/interfaces/schema-dialect-adapter.interface.d.ts +15 -0
- package/modules/entity-builder.module.d.ts +10 -0
- package/modules/index.d.ts +1 -0
- package/package.json +93 -0
- package/rule-engine/index.d.ts +3 -0
- package/rule-engine/rule-engine.service.d.ts +40 -0
- package/rule-engine/rule-evaluation-context.interface.d.ts +28 -0
- package/rule-engine/rule-ip.d.ts +3 -0
- package/rule-engine/rule-permission.d.ts +10 -0
- package/rule-engine/rule-regex.d.ts +4 -0
- package/rule-engine/rule-values.d.ts +5 -0
- package/rule-engine/rule.interface.d.ts +79 -0
- package/services/database-error.mapper.d.ts +2 -0
- package/services/definition-cache.service.d.ts +8 -0
- package/services/entity-builder-config.service.d.ts +12 -0
- package/services/entity-builder-datasource.provider.d.ts +24 -0
- package/services/entity-definition.service.d.ts +17 -0
- package/services/entity-flow-scaffold.d.ts +27 -0
- package/services/entity-permission.service.d.ts +8 -0
- package/services/field-definition.service.d.ts +17 -0
- package/services/field-type-conversion.d.ts +15 -0
- package/services/field-value-validator.d.ts +17 -0
- package/services/flow-definition.service.d.ts +62 -0
- package/services/flow-execution.service.d.ts +38 -0
- package/services/flow-executor.service.d.ts +41 -0
- package/services/flow-reference.provider.d.ts +13 -0
- package/services/flow-runtime.service.d.ts +30 -0
- package/services/generic-entity-service.factory.d.ts +12 -0
- package/services/generic-entity.service.d.ts +67 -0
- package/services/identifier-rules.d.ts +9 -0
- package/services/index.d.ts +26 -0
- package/services/reference-rewrite.d.ts +7 -0
- package/services/reference-scanner.service.d.ts +10 -0
- package/services/schema-change-executor.service.d.ts +39 -0
- package/services/schema-change.types.d.ts +59 -0
- package/services/schema-columns.d.ts +26 -0
- package/services/schema-dialect-adapter.service.d.ts +13 -0
- package/services/schema-evolution.service.d.ts +67 -0
- package/services/schema-registry.service.d.ts +13 -0
- package/services/schema-sync.service.d.ts +28 -0
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { FlowExecution } from '../entities/flow-execution.entity.js';
|
|
2
|
+
import { type IFlowRunResult, type IFlowSavePoint } from '../flow-engine/flow-run.types.js';
|
|
3
|
+
import { EntityBuilderDataSourceProvider } from './entity-builder-datasource.provider.js';
|
|
4
|
+
export interface IExecutionRecord {
|
|
5
|
+
flowId: string | null;
|
|
6
|
+
flowSlug: string;
|
|
7
|
+
flowVersion: number | null;
|
|
8
|
+
trigger: 'webhook' | 'test';
|
|
9
|
+
mode: 'live' | 'dry_run';
|
|
10
|
+
input: unknown;
|
|
11
|
+
result: Pick<IFlowRunResult, 'status' | 'statusCode' | 'body' | 'error' | 'trace' | 'durationMs'>;
|
|
12
|
+
startedAt: Date;
|
|
13
|
+
actorId: string | null;
|
|
14
|
+
callerIp: string | null;
|
|
15
|
+
retain: number;
|
|
16
|
+
}
|
|
17
|
+
export declare const DRAFT_TEST_RETAIN = 200;
|
|
18
|
+
export declare class FlowExecutionService {
|
|
19
|
+
private readonly provider;
|
|
20
|
+
private readonly logger;
|
|
21
|
+
private static writes;
|
|
22
|
+
constructor(provider: EntityBuilderDataSourceProvider);
|
|
23
|
+
record(entry: IExecutionRecord): Promise<void>;
|
|
24
|
+
prune(flowId: string | null, retain: number): Promise<void>;
|
|
25
|
+
list(query: {
|
|
26
|
+
flowId?: string;
|
|
27
|
+
status?: string;
|
|
28
|
+
page: number;
|
|
29
|
+
pageSize: number;
|
|
30
|
+
}): Promise<{
|
|
31
|
+
rows: FlowExecution[];
|
|
32
|
+
total: number;
|
|
33
|
+
}>;
|
|
34
|
+
get(id: string): Promise<(FlowExecution & {
|
|
35
|
+
savedUpTo: IFlowSavePoint | null;
|
|
36
|
+
}) | null>;
|
|
37
|
+
private repo;
|
|
38
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type ICompanyAccessResolver, type IEmailAdapter, type ILoggedUserInfo, type INotificationAdapter } from '@flusys/nestjs-shared/interfaces';
|
|
2
|
+
import { SharedPermissionCacheService } from '@flusys/nestjs-shared/modules';
|
|
3
|
+
import { ModuleRef } from '@nestjs/core';
|
|
4
|
+
import { type IFlowRunResult } from '../flow-engine/flow-run.types.js';
|
|
5
|
+
import { type FlowInput, type FlowRunMode, type IFlowSettings } from '../flow-engine/flow.types.js';
|
|
6
|
+
import { RuleEngineService } from '../rule-engine/index.js';
|
|
7
|
+
import { EntityBuilderConfigService } from './entity-builder-config.service.js';
|
|
8
|
+
import { EntityBuilderDataSourceProvider } from './entity-builder-datasource.provider.js';
|
|
9
|
+
export interface IFlowRunOptions {
|
|
10
|
+
mode: FlowRunMode;
|
|
11
|
+
user: ILoggedUserInfo | null;
|
|
12
|
+
input: FlowInput;
|
|
13
|
+
startAt?: string;
|
|
14
|
+
request: Record<string, unknown>;
|
|
15
|
+
authorization?: string;
|
|
16
|
+
exposeDetails: boolean;
|
|
17
|
+
systemAuthorized: boolean;
|
|
18
|
+
}
|
|
19
|
+
export declare const flowTimeout: (timeoutMs: unknown) => number;
|
|
20
|
+
export declare class FlowExecutorService {
|
|
21
|
+
private readonly provider;
|
|
22
|
+
private readonly ruleEngine;
|
|
23
|
+
private readonly moduleRef;
|
|
24
|
+
private readonly permissionCache;
|
|
25
|
+
private readonly config;
|
|
26
|
+
private readonly companyAccess?;
|
|
27
|
+
private readonly notifications?;
|
|
28
|
+
private readonly email?;
|
|
29
|
+
private readonly logger;
|
|
30
|
+
constructor(provider: EntityBuilderDataSourceProvider, ruleEngine: RuleEngineService, moduleRef: ModuleRef, permissionCache: SharedPermissionCacheService, config: EntityBuilderConfigService, companyAccess?: ICompanyAccessResolver | undefined, notifications?: INotificationAdapter | undefined, email?: IEmailAdapter | undefined);
|
|
31
|
+
run(flow: IFlowSettings, options: IFlowRunOptions): Promise<IFlowRunResult>;
|
|
32
|
+
private execute;
|
|
33
|
+
private limitStatementTime;
|
|
34
|
+
private commitProgress;
|
|
35
|
+
private atomic;
|
|
36
|
+
private callFlow;
|
|
37
|
+
private findCallable;
|
|
38
|
+
private assertMayCall;
|
|
39
|
+
private createEnv;
|
|
40
|
+
private publishPendingEvents;
|
|
41
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type EntityManager } from 'typeorm';
|
|
2
|
+
import { type IEntityReferenceProvider } from '../interfaces/reference-provider.interface.js';
|
|
3
|
+
import { EntityBuilderDataSourceProvider } from './entity-builder-datasource.provider.js';
|
|
4
|
+
import { type ISchemaImpact } from './schema-change.types.js';
|
|
5
|
+
export declare class FlowReferenceProvider implements IEntityReferenceProvider {
|
|
6
|
+
private readonly provider;
|
|
7
|
+
constructor(provider: EntityBuilderDataSourceProvider);
|
|
8
|
+
private flows;
|
|
9
|
+
private repo;
|
|
10
|
+
findEntityReferences(entityCode: string): Promise<ISchemaImpact[]>;
|
|
11
|
+
findFieldReferences(entityCode: string, fieldCode: string): Promise<ISchemaImpact[]>;
|
|
12
|
+
rewriteFieldReferences(entityCode: string, from: string, to: string, manager?: EntityManager): Promise<number>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { type ILoggedUserInfo, type IMessageRef } from '@flusys/nestjs-shared/interfaces';
|
|
2
|
+
import { type TestFlowDto } from '../dtos/flow.dto.js';
|
|
3
|
+
import { FlowDefinition } from '../entities/flow-definition.entity.js';
|
|
4
|
+
import { type IFlowRunResult } from '../flow-engine/flow-run.types.js';
|
|
5
|
+
import { type IFlowEndpoint } from '../flow-engine/flow.types.js';
|
|
6
|
+
import { EntityBuilderDataSourceProvider } from './entity-builder-datasource.provider.js';
|
|
7
|
+
import { FlowDefinitionService } from './flow-definition.service.js';
|
|
8
|
+
import { FlowExecutionService } from './flow-execution.service.js';
|
|
9
|
+
import { FlowExecutorService } from './flow-executor.service.js';
|
|
10
|
+
export interface IFlowCaller {
|
|
11
|
+
ip: string | null;
|
|
12
|
+
headers: Record<string, unknown>;
|
|
13
|
+
query?: Record<string, unknown>;
|
|
14
|
+
path?: string | null;
|
|
15
|
+
}
|
|
16
|
+
export declare function requestInfo(caller: IFlowCaller): Record<string, unknown>;
|
|
17
|
+
export declare class FlowRuntimeService {
|
|
18
|
+
private readonly provider;
|
|
19
|
+
private readonly executor;
|
|
20
|
+
private readonly executions;
|
|
21
|
+
private readonly definitions;
|
|
22
|
+
constructor(provider: EntityBuilderDataSourceProvider, executor: FlowExecutorService, executions: FlowExecutionService, definitions: FlowDefinitionService);
|
|
23
|
+
findActive(slug: string): Promise<FlowDefinition | null>;
|
|
24
|
+
handle(flow: FlowDefinition, endpoint: IFlowEndpoint, body: unknown, caller: IFlowCaller, user: ILoggedUserInfo | null): Promise<IFlowRunResult>;
|
|
25
|
+
testRun(dto: TestFlowDto, user: ILoggedUserInfo | null, caller: IFlowCaller): Promise<{
|
|
26
|
+
result: IFlowRunResult;
|
|
27
|
+
warnings: IMessageRef[];
|
|
28
|
+
}>;
|
|
29
|
+
private logWebhook;
|
|
30
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { type QueryRunner } from 'typeorm';
|
|
2
|
+
import { EntityBuilderDataSourceProvider } from './entity-builder-datasource.provider.js';
|
|
3
|
+
import { GenericEntityService } from './generic-entity.service.js';
|
|
4
|
+
import { SchemaRegistryService } from './schema-registry.service.js';
|
|
5
|
+
export declare class GenericEntityServiceFactory {
|
|
6
|
+
private readonly schemaRegistry;
|
|
7
|
+
private readonly dataSourceProvider;
|
|
8
|
+
constructor(schemaRegistry: SchemaRegistryService, dataSourceProvider: EntityBuilderDataSourceProvider);
|
|
9
|
+
forEntityCode(entityCode: string, queryRunner?: QueryRunner): Promise<GenericEntityService>;
|
|
10
|
+
forEntityDefinitionId(entityDefinitionId: string, queryRunner?: QueryRunner): Promise<GenericEntityService>;
|
|
11
|
+
private build;
|
|
12
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { type ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
|
|
2
|
+
import { type EntitySchema, type QueryRunner } from 'typeorm';
|
|
3
|
+
import { EntityDefinition } from '../entities/entity-definition.entity.js';
|
|
4
|
+
import { FieldDefinition } from '../entities/field-definition.entity.js';
|
|
5
|
+
import { type IGenericRecord } from '../interfaces/generic-record.interface.js';
|
|
6
|
+
import { EntityBuilderDataSourceProvider } from './entity-builder-datasource.provider.js';
|
|
7
|
+
export interface IGenericReadOptions {
|
|
8
|
+
queryRunner?: QueryRunner;
|
|
9
|
+
}
|
|
10
|
+
export interface IGenericQuery {
|
|
11
|
+
filter?: Record<string, unknown>;
|
|
12
|
+
sort?: Record<string, 'ASC' | 'DESC'>;
|
|
13
|
+
pagination?: {
|
|
14
|
+
currentPage: number;
|
|
15
|
+
pageSize: number;
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
export interface IGenericWriteOptions {
|
|
19
|
+
queryRunner?: QueryRunner;
|
|
20
|
+
publishEvents?: boolean;
|
|
21
|
+
}
|
|
22
|
+
export declare const ACTOR_BRANCH_METADATA_KEY = "_actorBranchId";
|
|
23
|
+
export declare function actorMetadata(user: ILoggedUserInfo | null): Record<string, unknown>;
|
|
24
|
+
export type RelatedServiceResolver = (entityDefinitionId: string, queryRunner?: QueryRunner) => Promise<GenericEntityService>;
|
|
25
|
+
export declare class GenericEntityService {
|
|
26
|
+
private readonly definition;
|
|
27
|
+
private readonly schema;
|
|
28
|
+
private readonly fields;
|
|
29
|
+
private readonly dataSourceProvider;
|
|
30
|
+
private readonly resolveRelated?;
|
|
31
|
+
private repository?;
|
|
32
|
+
private readonly activeFieldCodes;
|
|
33
|
+
private readonly presentSystemColumns;
|
|
34
|
+
constructor(definition: EntityDefinition, schema: EntitySchema, fields: FieldDefinition[], dataSourceProvider: EntityBuilderDataSourceProvider, resolveRelated?: RelatedServiceResolver | undefined);
|
|
35
|
+
get entityCode(): string;
|
|
36
|
+
private validateValues;
|
|
37
|
+
private throwIfInvalid;
|
|
38
|
+
private assertRelationsExist;
|
|
39
|
+
private notFound;
|
|
40
|
+
private auditFields;
|
|
41
|
+
private stampDeletedBy;
|
|
42
|
+
private ensureActive;
|
|
43
|
+
private repositoryFor;
|
|
44
|
+
private ensureRepository;
|
|
45
|
+
private validateKeys;
|
|
46
|
+
insert(dto: Record<string, unknown>, user: ILoggedUserInfo | null, options?: IGenericWriteOptions): Promise<IGenericRecord>;
|
|
47
|
+
update(dto: Record<string, unknown> & {
|
|
48
|
+
id: string;
|
|
49
|
+
}, user: ILoggedUserInfo | null, options?: IGenericWriteOptions): Promise<IGenericRecord>;
|
|
50
|
+
private insertRow;
|
|
51
|
+
private updateRow;
|
|
52
|
+
private assertUpdatable;
|
|
53
|
+
delete(id: string, user: ILoggedUserInfo | null, options?: IGenericWriteOptions): Promise<'deleted' | 'purged'>;
|
|
54
|
+
findById(id: string, options?: IGenericReadOptions): Promise<IGenericRecord>;
|
|
55
|
+
exists(id: string, options?: IGenericReadOptions): Promise<boolean>;
|
|
56
|
+
getAll(search: string | undefined, query: IGenericQuery, options?: IGenericReadOptions): Promise<{
|
|
57
|
+
data: IGenericRecord[];
|
|
58
|
+
total: number;
|
|
59
|
+
}>;
|
|
60
|
+
private applyFilter;
|
|
61
|
+
private unknownOperator;
|
|
62
|
+
private invalidFilterValue;
|
|
63
|
+
private applySort;
|
|
64
|
+
private applySearch;
|
|
65
|
+
private assertKnownColumn;
|
|
66
|
+
private withTransaction;
|
|
67
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { type FieldType } from '../enums/field-type.enum.js';
|
|
2
|
+
export declare const RESERVED_WORDS: Set<string>;
|
|
3
|
+
export declare function assertValidIdentifier(code: string, kind: 'entity' | 'field'): void;
|
|
4
|
+
export declare function assertIndexableField(field: {
|
|
5
|
+
code: string;
|
|
6
|
+
fieldType: FieldType;
|
|
7
|
+
unique?: boolean | null;
|
|
8
|
+
isIndexed?: boolean | null;
|
|
9
|
+
}): void;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export * from './entity-builder-config.service.js';
|
|
2
|
+
export * from './entity-builder-datasource.provider.js';
|
|
3
|
+
export * from './schema-dialect-adapter.service.js';
|
|
4
|
+
export * from './schema-registry.service.js';
|
|
5
|
+
export * from './schema-sync.service.js';
|
|
6
|
+
export * from './entity-definition.service.js';
|
|
7
|
+
export * from './field-definition.service.js';
|
|
8
|
+
export * from './generic-entity.service.js';
|
|
9
|
+
export * from './generic-entity-service.factory.js';
|
|
10
|
+
export * from './entity-permission.service.js';
|
|
11
|
+
export * from './definition-cache.service.js';
|
|
12
|
+
export * from './schema-change-executor.service.js';
|
|
13
|
+
export * from './schema-change.types.js';
|
|
14
|
+
export * from './schema-columns.js';
|
|
15
|
+
export * from './field-type-conversion.js';
|
|
16
|
+
export * from './identifier-rules.js';
|
|
17
|
+
export * from './schema-evolution.service.js';
|
|
18
|
+
export * from './reference-scanner.service.js';
|
|
19
|
+
export * from './field-value-validator.js';
|
|
20
|
+
export * from './database-error.mapper.js';
|
|
21
|
+
export * from './flow-definition.service.js';
|
|
22
|
+
export * from './flow-execution.service.js';
|
|
23
|
+
export * from './flow-executor.service.js';
|
|
24
|
+
export * from './flow-runtime.service.js';
|
|
25
|
+
export * from './flow-reference.provider.js';
|
|
26
|
+
export * from './entity-flow-scaffold.js';
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
type Json = unknown;
|
|
2
|
+
export declare function mapStrings(value: Json, fn: (s: string) => string): Json;
|
|
3
|
+
export declare function anyString(value: Json, test: (s: string) => boolean): boolean;
|
|
4
|
+
export declare const escapeRe: (s: string) => string;
|
|
5
|
+
export declare const referencePatternSource: (prefixSource: string, field: string, flags?: string) => RegExp;
|
|
6
|
+
export declare const replaceReferenceSource: (s: string, prefixSource: string, from: string, to: string) => string;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { type EntityManager } from 'typeorm';
|
|
2
|
+
import { type IEntityReferenceProvider } from '../interfaces/reference-provider.interface.js';
|
|
3
|
+
import { type ISchemaImpact } from './schema-change.types.js';
|
|
4
|
+
export declare class ReferenceScannerService {
|
|
5
|
+
private readonly flowReferences?;
|
|
6
|
+
constructor(flowReferences?: IEntityReferenceProvider | undefined);
|
|
7
|
+
forEntity(entityCode: string): Promise<ISchemaImpact[]>;
|
|
8
|
+
forField(entityCode: string, fieldCode: string): Promise<ISchemaImpact[]>;
|
|
9
|
+
rewriteFieldCode(entityCode: string, from: string, to: string, manager?: EntityManager): Promise<number>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { type ILoggedUserInfo } from '@flusys/nestjs-shared/interfaces';
|
|
2
|
+
import { DefinitionCacheService } from './definition-cache.service.js';
|
|
3
|
+
import { EntityBuilderDataSourceProvider } from './entity-builder-datasource.provider.js';
|
|
4
|
+
import { SchemaDialectAdapterService } from './schema-dialect-adapter.service.js';
|
|
5
|
+
import { SchemaRegistryService } from './schema-registry.service.js';
|
|
6
|
+
import { type ISchemaChangeOutcome, type ISchemaChangePlan, type ISchemaImpact, type SchemaChangeRun } from './schema-change.types.js';
|
|
7
|
+
export interface ISchemaChangeTarget {
|
|
8
|
+
action: string;
|
|
9
|
+
entityDefinitionId: string | null;
|
|
10
|
+
entityCode: string;
|
|
11
|
+
tableName: string;
|
|
12
|
+
user: ILoggedUserInfo | null;
|
|
13
|
+
lockCodes?: string[];
|
|
14
|
+
}
|
|
15
|
+
export interface IApplyOptions {
|
|
16
|
+
confirm?: boolean;
|
|
17
|
+
impact?: ISchemaImpact[];
|
|
18
|
+
}
|
|
19
|
+
export declare function relationTargetCodes(provider: EntityBuilderDataSourceProvider, ids: Array<string | null | undefined>): Promise<string[]>;
|
|
20
|
+
export declare class SchemaChangeExecutor {
|
|
21
|
+
private readonly dataSourceProvider;
|
|
22
|
+
private readonly dialectAdapter;
|
|
23
|
+
private readonly schemaRegistry;
|
|
24
|
+
private readonly definitionCache;
|
|
25
|
+
private readonly logger;
|
|
26
|
+
constructor(dataSourceProvider: EntityBuilderDataSourceProvider, dialectAdapter: SchemaDialectAdapterService, schemaRegistry: SchemaRegistryService, definitionCache: DefinitionCacheService);
|
|
27
|
+
simulate(target: ISchemaChangeTarget, run: SchemaChangeRun, impact?: ISchemaImpact[]): Promise<ISchemaChangePlan>;
|
|
28
|
+
apply(target: ISchemaChangeTarget, run: SchemaChangeRun, options?: IApplyOptions): Promise<{
|
|
29
|
+
plan: ISchemaChangePlan;
|
|
30
|
+
outcome: ISchemaChangeOutcome;
|
|
31
|
+
}>;
|
|
32
|
+
private compensate;
|
|
33
|
+
private withUndo;
|
|
34
|
+
private logFailure;
|
|
35
|
+
private operationFor;
|
|
36
|
+
private newState;
|
|
37
|
+
private toPlan;
|
|
38
|
+
private buildContext;
|
|
39
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { type IMessageRef } from '@flusys/nestjs-shared/interfaces';
|
|
2
|
+
import { type QueryRunner } from 'typeorm';
|
|
3
|
+
import { type DdlOperation } from '../enums/ddl-operation.enum.js';
|
|
4
|
+
import { type SupportedDbDriver } from '../interfaces/schema-dialect-adapter.interface.js';
|
|
5
|
+
export interface IPlanStep {
|
|
6
|
+
description: IMessageRef;
|
|
7
|
+
sql: string[];
|
|
8
|
+
}
|
|
9
|
+
export declare const describeImpact: (impact: ISchemaImpact[]) => string;
|
|
10
|
+
export interface ISchemaImpact {
|
|
11
|
+
kind: 'flow';
|
|
12
|
+
id: string;
|
|
13
|
+
name: string;
|
|
14
|
+
detail: IMessageRef;
|
|
15
|
+
}
|
|
16
|
+
export interface ISchemaChangePlan {
|
|
17
|
+
action: string;
|
|
18
|
+
entityCode: string;
|
|
19
|
+
tableName: string;
|
|
20
|
+
steps: IPlanStep[];
|
|
21
|
+
downSql: string[];
|
|
22
|
+
warnings: IMessageRef[];
|
|
23
|
+
blockers: IMessageRef[];
|
|
24
|
+
impact: ISchemaImpact[];
|
|
25
|
+
affectedRows: number | null;
|
|
26
|
+
destructive: boolean;
|
|
27
|
+
metadataOnly: boolean;
|
|
28
|
+
}
|
|
29
|
+
export interface ISchemaChangeApplied extends ISchemaChangePlan {
|
|
30
|
+
result: Record<string, unknown>;
|
|
31
|
+
}
|
|
32
|
+
export interface ISchemaUndoReport {
|
|
33
|
+
reverted: boolean;
|
|
34
|
+
pendingSql: string[];
|
|
35
|
+
dataNotReverted: boolean;
|
|
36
|
+
}
|
|
37
|
+
export interface ISchemaChangeContext {
|
|
38
|
+
readonly qr: QueryRunner;
|
|
39
|
+
readonly driver: SupportedDbDriver;
|
|
40
|
+
readonly blocked: boolean;
|
|
41
|
+
q(identifier: string): string;
|
|
42
|
+
ddl(description: IMessageRef, fn: () => Promise<void>): Promise<void>;
|
|
43
|
+
rawDdl(description: IMessageRef, sql: string[], downSql?: string[]): Promise<void>;
|
|
44
|
+
data(description: IMessageRef, sqlPreview: string, fn: () => Promise<void>): Promise<void>;
|
|
45
|
+
metadata(fn: () => Promise<void>): Promise<void>;
|
|
46
|
+
warn(message: IMessageRef): void;
|
|
47
|
+
block(message: IMessageRef): void;
|
|
48
|
+
setAffectedRows(count: number): void;
|
|
49
|
+
markDestructive(): void;
|
|
50
|
+
}
|
|
51
|
+
export interface ISchemaChangeOutcome {
|
|
52
|
+
operation: DdlOperation;
|
|
53
|
+
entityDefinitionId?: string | null;
|
|
54
|
+
fieldDefinitionId?: string | null;
|
|
55
|
+
diff: Record<string, unknown>;
|
|
56
|
+
bumpVersion?: boolean;
|
|
57
|
+
afterCommit?: () => Promise<void>;
|
|
58
|
+
}
|
|
59
|
+
export type SchemaChangeRun = (ctx: ISchemaChangeContext) => Promise<ISchemaChangeOutcome>;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { type QueryRunner, type Table, TableColumn, TableIndex, TableUnique } from 'typeorm';
|
|
2
|
+
import { type FieldDefinition } from '../entities/field-definition.entity.js';
|
|
3
|
+
import { FieldType } from '../enums/field-type.enum.js';
|
|
4
|
+
import { type SupportedDbDriver } from '../interfaces/schema-dialect-adapter.interface.js';
|
|
5
|
+
import { type SchemaDialectAdapterService } from './schema-dialect-adapter.service.js';
|
|
6
|
+
export declare const SYSTEM_COLUMN_NAMES: readonly ["id", "created_at", "updated_at", "deleted_at", "created_by_id", "updated_by_id", "deleted_by_id"];
|
|
7
|
+
export declare const NON_INDEXABLE_FIELD_TYPES: readonly FieldType[];
|
|
8
|
+
export declare const isIndexableFieldType: (fieldType: FieldType) => boolean;
|
|
9
|
+
export interface ISystemColumnFlags {
|
|
10
|
+
isSoftDeleteEnabled: boolean;
|
|
11
|
+
isAuditEnabled: boolean;
|
|
12
|
+
}
|
|
13
|
+
export declare function buildSystemColumns(flags: ISystemColumnFlags, driver: SupportedDbDriver): TableColumn[];
|
|
14
|
+
export declare const softDeleteColumn: () => TableColumn;
|
|
15
|
+
export declare const auditColumns: (driver: SupportedDbDriver) => TableColumn[];
|
|
16
|
+
export declare const sameColumns: (columnNames: string[], expected: string[]) => boolean;
|
|
17
|
+
export declare function indexName(prefix: 'idx' | 'uq', table: string, column: string, maxLength: number): string;
|
|
18
|
+
export declare const plainIndex: (table: string, column: string, driver: SupportedDbDriver, adapter: SchemaDialectAdapterService) => TableIndex;
|
|
19
|
+
export declare const tableUnique: (table: string, column: string, driver: SupportedDbDriver, adapter: SchemaDialectAdapterService) => TableUnique;
|
|
20
|
+
export declare function addUnique(qr: QueryRunner, table: Table, column: string, driver: SupportedDbDriver, adapter: SchemaDialectAdapterService): Promise<void>;
|
|
21
|
+
export declare function buildFieldColumn(field: Pick<FieldDefinition, 'code' | 'fieldType' | 'dbType' | 'nullable' | 'unique'>, driver: SupportedDbDriver, adapter: SchemaDialectAdapterService, options: {
|
|
22
|
+
enforceNotNull: boolean;
|
|
23
|
+
withUnique: boolean;
|
|
24
|
+
}): TableColumn;
|
|
25
|
+
export declare function sqlTypeFor(fieldType: FieldType, driver: SupportedDbDriver, adapter: SchemaDialectAdapterService): string;
|
|
26
|
+
export declare function typeFamily(type: string): string;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { type ColumnType, type QueryRunner } from 'typeorm';
|
|
2
|
+
import { FieldType } from '../enums/field-type.enum.js';
|
|
3
|
+
import { type IColumnSizing, type ISchemaDialectAdapter, type SupportedDbDriver } from '../interfaces/schema-dialect-adapter.interface.js';
|
|
4
|
+
export declare function fitIdentifier(text: string, max: number): string;
|
|
5
|
+
export declare class SchemaDialectAdapterService implements ISchemaDialectAdapter {
|
|
6
|
+
mapFieldType(fieldType: FieldType, driver: SupportedDbDriver): ColumnType;
|
|
7
|
+
getColumnSizing(fieldType: FieldType, driver?: SupportedDbDriver): IColumnSizing;
|
|
8
|
+
maxIdentifierLength(driver: SupportedDbDriver): number;
|
|
9
|
+
sqlLiteral(value: unknown, driver: SupportedDbDriver): string;
|
|
10
|
+
lockName(lockKey: string): string;
|
|
11
|
+
acquireEntityLock(queryRunner: QueryRunner, lockKey: string, driver: SupportedDbDriver): Promise<void>;
|
|
12
|
+
releaseEntityLock(queryRunner: QueryRunner, lockKey: string, driver: SupportedDbDriver): Promise<void>;
|
|
13
|
+
}
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { type ILoggedUserInfo, type IMessageRef } from '@flusys/nestjs-shared/interfaces';
|
|
2
|
+
import { SchemaChangeAction, type SchemaChangeRequestDto } from '../dtos/schema-change.dto.js';
|
|
3
|
+
import { SchemaChangeLog } from '../entities/schema-change-log.entity.js';
|
|
4
|
+
import { EntityBuilderDataSourceProvider } from './entity-builder-datasource.provider.js';
|
|
5
|
+
import { EntityPermissionService } from './entity-permission.service.js';
|
|
6
|
+
import { ReferenceScannerService } from './reference-scanner.service.js';
|
|
7
|
+
import { SchemaChangeExecutor } from './schema-change-executor.service.js';
|
|
8
|
+
import { type ISchemaChangeApplied, type ISchemaChangePlan } from './schema-change.types.js';
|
|
9
|
+
import { SchemaDialectAdapterService } from './schema-dialect-adapter.service.js';
|
|
10
|
+
export type SchemaFindingKind = 'missing_table' | 'missing_column' | 'extra_column' | 'type_mismatch' | 'nullability_mismatch' | 'missing_index' | 'missing_unique' | 'stale_metadata';
|
|
11
|
+
export interface ISchemaFinding extends IMessageRef {
|
|
12
|
+
kind: SchemaFindingKind;
|
|
13
|
+
severity: 'error' | 'warning';
|
|
14
|
+
field?: string;
|
|
15
|
+
repairable: boolean;
|
|
16
|
+
}
|
|
17
|
+
export interface ISchemaCheckResult {
|
|
18
|
+
entityCode: string;
|
|
19
|
+
tableName: string;
|
|
20
|
+
healthy: boolean;
|
|
21
|
+
rowCount: number | null;
|
|
22
|
+
findings: ISchemaFinding[];
|
|
23
|
+
}
|
|
24
|
+
export declare const isDestructiveSchemaAction: (action: SchemaChangeAction) => boolean;
|
|
25
|
+
export declare class SchemaEvolutionService {
|
|
26
|
+
private readonly dataSourceProvider;
|
|
27
|
+
private readonly adapter;
|
|
28
|
+
private readonly executor;
|
|
29
|
+
private readonly references;
|
|
30
|
+
private readonly permissions;
|
|
31
|
+
constructor(dataSourceProvider: EntityBuilderDataSourceProvider, adapter: SchemaDialectAdapterService, executor: SchemaChangeExecutor, references: ReferenceScannerService, permissions: EntityPermissionService);
|
|
32
|
+
plan(request: SchemaChangeRequestDto, user: ILoggedUserInfo | null): Promise<ISchemaChangePlan>;
|
|
33
|
+
apply(request: SchemaChangeRequestDto, user: ILoggedUserInfo | null): Promise<ISchemaChangeApplied>;
|
|
34
|
+
inspect(entityDefinitionId: string): Promise<ISchemaCheckResult>;
|
|
35
|
+
history(entityDefinitionId: string, limit?: number): Promise<SchemaChangeLog[]>;
|
|
36
|
+
private loadEntity;
|
|
37
|
+
private loadField;
|
|
38
|
+
private definitions;
|
|
39
|
+
private rejectUnknownKeys;
|
|
40
|
+
private validateChanges;
|
|
41
|
+
private current;
|
|
42
|
+
private assertNotStale;
|
|
43
|
+
private changedUnderneath;
|
|
44
|
+
private prepare;
|
|
45
|
+
private target;
|
|
46
|
+
private scalar;
|
|
47
|
+
private advisoryScalar;
|
|
48
|
+
private paramValue;
|
|
49
|
+
private notNullSql;
|
|
50
|
+
private setRequired;
|
|
51
|
+
private checkValue;
|
|
52
|
+
private requireTable;
|
|
53
|
+
private countDuplicates;
|
|
54
|
+
private dropUniques;
|
|
55
|
+
private hasUnique;
|
|
56
|
+
private indexOn;
|
|
57
|
+
private prepareAddField;
|
|
58
|
+
private prepareUpdateField;
|
|
59
|
+
private prepareDeprecateField;
|
|
60
|
+
private prepareRestoreField;
|
|
61
|
+
private preparePurgeField;
|
|
62
|
+
private prepareUpdateEntity;
|
|
63
|
+
private relationsInto;
|
|
64
|
+
private prepareDropEntity;
|
|
65
|
+
private diff;
|
|
66
|
+
private prepareRepair;
|
|
67
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { EntitySchema, type QueryRunner } from 'typeorm';
|
|
2
|
+
import { EntityBuilderDataSourceProvider } from './entity-builder-datasource.provider.js';
|
|
3
|
+
import { SchemaDialectAdapterService } from './schema-dialect-adapter.service.js';
|
|
4
|
+
export declare class SchemaRegistryService {
|
|
5
|
+
private readonly dataSourceProvider;
|
|
6
|
+
private readonly dialectAdapter;
|
|
7
|
+
private static readonly cache;
|
|
8
|
+
constructor(dataSourceProvider: EntityBuilderDataSourceProvider, dialectAdapter: SchemaDialectAdapterService);
|
|
9
|
+
getSchema(entityDefinitionId: string, queryRunner?: QueryRunner): Promise<EntitySchema>;
|
|
10
|
+
invalidate(entityDefinitionId: string): void;
|
|
11
|
+
private cacheKey;
|
|
12
|
+
private buildEntitySchema;
|
|
13
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type ILoggedUserInfo, type IMessageRef } from '@flusys/nestjs-shared/interfaces';
|
|
2
|
+
import { CreateDynamicEntityDto } from '../dtos/index.js';
|
|
3
|
+
import { EntityDefinition } from '../entities/entity-definition.entity.js';
|
|
4
|
+
import { EntityBuilderDataSourceProvider } from './entity-builder-datasource.provider.js';
|
|
5
|
+
import { EntityPermissionService } from './entity-permission.service.js';
|
|
6
|
+
import { FlowDefinitionService } from './flow-definition.service.js';
|
|
7
|
+
import { SchemaChangeExecutor } from './schema-change-executor.service.js';
|
|
8
|
+
import { type ISchemaChangePlan } from './schema-change.types.js';
|
|
9
|
+
import { SchemaDialectAdapterService } from './schema-dialect-adapter.service.js';
|
|
10
|
+
export interface ICreatedEntity {
|
|
11
|
+
definition: EntityDefinition;
|
|
12
|
+
warnings: IMessageRef[];
|
|
13
|
+
}
|
|
14
|
+
export declare class SchemaSyncService {
|
|
15
|
+
private readonly dataSourceProvider;
|
|
16
|
+
private readonly dialectAdapter;
|
|
17
|
+
private readonly executor;
|
|
18
|
+
private readonly entityPermissionService;
|
|
19
|
+
private readonly flowDefinitionService;
|
|
20
|
+
private readonly logger;
|
|
21
|
+
constructor(dataSourceProvider: EntityBuilderDataSourceProvider, dialectAdapter: SchemaDialectAdapterService, executor: SchemaChangeExecutor, entityPermissionService: EntityPermissionService, flowDefinitionService: FlowDefinitionService);
|
|
22
|
+
private validateCreateRequest;
|
|
23
|
+
private createTarget;
|
|
24
|
+
private createRun;
|
|
25
|
+
private createEndpointFlow;
|
|
26
|
+
planCreateEntity(dto: CreateDynamicEntityDto, user: ILoggedUserInfo | null): Promise<ISchemaChangePlan>;
|
|
27
|
+
createEntity(dto: CreateDynamicEntityDto, user: ILoggedUserInfo | null): Promise<ICreatedEntity>;
|
|
28
|
+
}
|