emilsoftware-utilities 2.0.0-dev.35 → 2.0.0-dev.37

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.
Files changed (47) hide show
  1. package/dist/accessi-module/AccessiModule.d.ts +5 -0
  2. package/dist/accessi-module/AccessiModule.js +9 -4
  3. package/dist/accessi-module/AccessiModule.js.map +1 -1
  4. package/dist/accessi-module/Console/console.css +7 -0
  5. package/dist/accessi-module/Console/console.js +58 -4
  6. package/dist/accessi-module/Console/console.js.map +1 -1
  7. package/dist/accessi-module/Console/generated/accessiApi.d.ts +11 -1
  8. package/dist/accessi-module/Console/generated/accessiApi.js +9 -1
  9. package/dist/accessi-module/Console/generated/accessiApi.js.map +1 -1
  10. package/dist/accessi-module/Console/generated/model/getSchemaResponse.d.ts +14 -0
  11. package/dist/accessi-module/Console/generated/model/getSchemaResponse.js +3 -0
  12. package/dist/accessi-module/Console/generated/model/getSchemaResponse.js.map +1 -0
  13. package/dist/accessi-module/Console/generated/model/index.d.ts +3 -0
  14. package/dist/accessi-module/Console/generated/model/index.js +3 -0
  15. package/dist/accessi-module/Console/generated/model/index.js.map +1 -1
  16. package/dist/accessi-module/Console/generated/model/schemaDdlResult.d.ts +20 -0
  17. package/dist/accessi-module/Console/generated/model/schemaDdlResult.js +3 -0
  18. package/dist/accessi-module/Console/generated/model/schemaDdlResult.js.map +1 -0
  19. package/dist/accessi-module/Console/generated/model/schemaDdlSection.d.ts +12 -0
  20. package/dist/accessi-module/Console/generated/model/schemaDdlSection.js +9 -0
  21. package/dist/accessi-module/Console/generated/model/schemaDdlSection.js.map +1 -0
  22. package/dist/accessi-module/Console/index.html +6 -0
  23. package/dist/accessi-module/Console/wiki.js +6 -1
  24. package/dist/accessi-module/Console/wiki.js.map +1 -1
  25. package/dist/accessi-module/Controllers/SchemaController.d.ts +9 -0
  26. package/dist/accessi-module/Controllers/SchemaController.js +79 -0
  27. package/dist/accessi-module/Controllers/SchemaController.js.map +1 -0
  28. package/dist/accessi-module/Dtos/SchemaDtos.d.ts +19 -0
  29. package/dist/accessi-module/Dtos/SchemaDtos.js +84 -0
  30. package/dist/accessi-module/Dtos/SchemaDtos.js.map +1 -0
  31. package/dist/accessi-module/Dtos/index.d.ts +1 -0
  32. package/dist/accessi-module/Dtos/index.js +1 -0
  33. package/dist/accessi-module/Dtos/index.js.map +1 -1
  34. package/dist/accessi-module/Services/SchemaExportService/SchemaExportService.d.ts +36 -0
  35. package/dist/accessi-module/Services/SchemaExportService/SchemaExportService.js +125 -0
  36. package/dist/accessi-module/Services/SchemaExportService/SchemaExportService.js.map +1 -0
  37. package/dist/accessi-module/database-updates/AccessiCatalogMigrator.d.ts +19 -0
  38. package/dist/accessi-module/database-updates/AccessiCatalogMigrator.js +75 -3
  39. package/dist/accessi-module/database-updates/AccessiCatalogMigrator.js.map +1 -1
  40. package/dist/accessi-module/database-updates/runAccessiCatalogMigrations.js +14 -2
  41. package/dist/accessi-module/database-updates/runAccessiCatalogMigrations.js.map +1 -1
  42. package/dist/accessi-module/index.d.ts +3 -1
  43. package/dist/accessi-module/index.js +5 -1
  44. package/dist/accessi-module/index.js.map +1 -1
  45. package/dist/emilsoftware-utilities-2.0.0-dev.37.tgz +0 -0
  46. package/package.json +1 -1
  47. package/dist/emilsoftware-utilities-2.0.0-dev.35.tgz +0 -0
@@ -0,0 +1,36 @@
1
+ import type { AccessiOptions } from '../../AccessiModule';
2
+ export interface SchemaDdlSection {
3
+ id: string;
4
+ title: string;
5
+ sql: string;
6
+ }
7
+ export interface SchemaDdlResult {
8
+ version: string;
9
+ sections: SchemaDdlSection[];
10
+ script: string;
11
+ }
12
+ export interface SchemaEntitiesResult {
13
+ presentTables: string[];
14
+ extraTables: string[];
15
+ canonicalTables: string[];
16
+ presentGenerators: string[];
17
+ }
18
+ /**
19
+ * Genera il DDL delle entita Accessi a partire dallo schema canonico (stessa fonte della
20
+ * riconciliazione) e rileva le entita effettivamente presenti nel database. Serve a
21
+ * esportare lo schema per replicarlo su altre installazioni.
22
+ */
23
+ export declare class SchemaExportService {
24
+ private readonly options;
25
+ constructor(options: AccessiOptions);
26
+ /** DDL completo e deterministico dello schema Accessi. */
27
+ buildDdl(): SchemaDdlResult;
28
+ /** Elenca le tabelle/generatori presenti nel database e segnala quelli fuori schema canonical. */
29
+ presentEntities(): Promise<SchemaEntitiesResult>;
30
+ private buildTablesSection;
31
+ private buildGeneratorsSection;
32
+ private buildForeignKeysSection;
33
+ private buildIndexesSection;
34
+ private buildChecksSection;
35
+ private buildTriggersSection;
36
+ }
@@ -0,0 +1,125 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
15
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
16
+ return new (P || (P = Promise))(function (resolve, reject) {
17
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
18
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
19
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
20
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
21
+ });
22
+ };
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.SchemaExportService = void 0;
25
+ const common_1 = require("@nestjs/common");
26
+ const Orm_1 = require("../../../Orm");
27
+ const Utilities_1 = require("../../../Utilities");
28
+ const accessiSchema_1 = require("../../database-updates/accessiSchema");
29
+ /**
30
+ * Genera il DDL delle entita Accessi a partire dallo schema canonico (stessa fonte della
31
+ * riconciliazione) e rileva le entita effettivamente presenti nel database. Serve a
32
+ * esportare lo schema per replicarlo su altre installazioni.
33
+ */
34
+ let SchemaExportService = class SchemaExportService {
35
+ constructor(options) {
36
+ this.options = options;
37
+ }
38
+ /** DDL completo e deterministico dello schema Accessi. */
39
+ buildDdl() {
40
+ const sections = [
41
+ this.buildTablesSection(),
42
+ this.buildGeneratorsSection(),
43
+ this.buildForeignKeysSection(),
44
+ this.buildIndexesSection(),
45
+ this.buildChecksSection(),
46
+ this.buildTriggersSection(),
47
+ ];
48
+ const script = sections
49
+ .map((section) => `-- ============================================================\n-- ${section.title}\n-- ============================================================\n${section.sql}`)
50
+ .join('\n\n');
51
+ return { version: accessiSchema_1.ACCESSI_SCHEMA_VERSION, sections, script };
52
+ }
53
+ /** Elenca le tabelle/generatori presenti nel database e segnala quelli fuori schema canonical. */
54
+ presentEntities() {
55
+ return __awaiter(this, void 0, void 0, function* () {
56
+ const canonicalTables = Object.keys(accessiSchema_1.accessiTables).sort();
57
+ const canonicalSet = new Set(canonicalTables);
58
+ const tableRows = (yield Orm_1.Orm.query(this.options.databaseOptions, `SELECT TRIM(RDB$RELATION_NAME) AS NAME
59
+ FROM RDB$RELATIONS
60
+ WHERE COALESCE(RDB$SYSTEM_FLAG, 0) = 0 AND RDB$VIEW_BLR IS NULL
61
+ ORDER BY RDB$RELATION_NAME`, [], false));
62
+ const presentTables = tableRows
63
+ .map((row) => { var _a; return String((_a = Utilities_1.RestUtilities.convertKeysToCamelCase(row).name) !== null && _a !== void 0 ? _a : '').trim(); })
64
+ .filter(Boolean);
65
+ const generatorRows = (yield Orm_1.Orm.query(this.options.databaseOptions, `SELECT TRIM(RDB$GENERATOR_NAME) AS NAME
66
+ FROM RDB$GENERATORS
67
+ WHERE COALESCE(RDB$SYSTEM_FLAG, 0) = 0
68
+ ORDER BY RDB$GENERATOR_NAME`, [], false));
69
+ const presentGenerators = generatorRows
70
+ .map((row) => { var _a; return String((_a = Utilities_1.RestUtilities.convertKeysToCamelCase(row).name) !== null && _a !== void 0 ? _a : '').trim(); })
71
+ .filter(Boolean);
72
+ return {
73
+ presentTables,
74
+ extraTables: presentTables.filter((name) => !canonicalSet.has(name)),
75
+ canonicalTables,
76
+ presentGenerators,
77
+ };
78
+ });
79
+ }
80
+ buildTablesSection() {
81
+ const statements = [];
82
+ for (const [table, schema] of Object.entries(accessiSchema_1.accessiTables)) {
83
+ const columns = Object.entries(schema.columns)
84
+ .map(([name, definition]) => ` ${name} ${definition}`)
85
+ .join(',\n');
86
+ statements.push(`CREATE TABLE ${table} (\n${columns}\n);`);
87
+ statements.push(`ALTER TABLE ${table} ADD CONSTRAINT PK_${table} PRIMARY KEY (${schema.primaryKey.join(', ')});`);
88
+ }
89
+ return { id: 'tables', title: `Tabelle (${Object.keys(accessiSchema_1.accessiTables).length})`, sql: statements.join('\n\n') };
90
+ }
91
+ buildGeneratorsSection() {
92
+ const statements = accessiSchema_1.accessiGenerators.map((generator) => `-- Firebird 2.5: CREATE GENERATOR ${generator.name}\nCREATE SEQUENCE ${generator.name};`);
93
+ return { id: 'generators', title: `Generatori/Sequenze (${accessiSchema_1.accessiGenerators.length})`, sql: statements.join('\n\n') };
94
+ }
95
+ buildForeignKeysSection() {
96
+ const statements = accessiSchema_1.accessiForeignKeys.map((fk) => `ALTER TABLE ${fk.table} ADD CONSTRAINT ${fk.name} FOREIGN KEY (${fk.column}) REFERENCES ${fk.target} (${fk.targetColumn})${fk.cascade ? ' ON DELETE CASCADE' : ''};`);
97
+ return { id: 'foreignKeys', title: `Chiavi esterne (${accessiSchema_1.accessiForeignKeys.length})`, sql: statements.join('\n\n') };
98
+ }
99
+ buildIndexesSection() {
100
+ const statements = accessiSchema_1.accessiIndexes.map((index) => `CREATE INDEX ${index.name} ON ${index.table} (${index.columns.join(', ')});`);
101
+ return { id: 'indexes', title: `Indici (${accessiSchema_1.accessiIndexes.length})`, sql: statements.join('\n\n') };
102
+ }
103
+ buildChecksSection() {
104
+ const statements = accessiSchema_1.accessiChecks.map((check) => `ALTER TABLE ${check.table} ADD CONSTRAINT ${check.name} CHECK (${check.expression});`);
105
+ return { id: 'checks', title: `Vincoli CHECK (${accessiSchema_1.accessiChecks.length})`, sql: statements.join('\n\n') };
106
+ }
107
+ buildTriggersSection() {
108
+ if (accessiSchema_1.accessiTriggers.length === 0) {
109
+ return { id: 'triggers', title: 'Trigger (0)', sql: '-- Nessun trigger di dominio.' };
110
+ }
111
+ const statements = accessiSchema_1.accessiTriggers.map((trigger) => `CREATE TRIGGER ${trigger.name} FOR ${trigger.table} ACTIVE ${trigger.event} ${trigger.body}`);
112
+ return {
113
+ id: 'triggers',
114
+ title: `Trigger (${accessiSchema_1.accessiTriggers.length})`,
115
+ sql: `SET TERM ^ ;\n\n${statements.join('^\n\n')}^\n\nSET TERM ; ^`,
116
+ };
117
+ }
118
+ };
119
+ exports.SchemaExportService = SchemaExportService;
120
+ exports.SchemaExportService = SchemaExportService = __decorate([
121
+ (0, common_1.Injectable)(),
122
+ __param(0, (0, common_1.Inject)('ACCESSI_OPTIONS')),
123
+ __metadata("design:paramtypes", [Object])
124
+ ], SchemaExportService);
125
+ //# sourceMappingURL=SchemaExportService.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SchemaExportService.js","sourceRoot":"","sources":["../../../../src/accessi-module/Services/SchemaExportService/SchemaExportService.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;AAAA,2CAAoD;AACpD,sCAAmC;AACnC,kDAAmD;AAEnD,wEAQ8C;AAqB9C;;;;GAIG;AAEI,IAAM,mBAAmB,GAAzB,MAAM,mBAAmB;IAC9B,YAAwD,OAAuB;QAAvB,YAAO,GAAP,OAAO,CAAgB;IAAG,CAAC;IAEnF,0DAA0D;IAC1D,QAAQ;QACN,MAAM,QAAQ,GAAuB;YACnC,IAAI,CAAC,kBAAkB,EAAE;YACzB,IAAI,CAAC,sBAAsB,EAAE;YAC7B,IAAI,CAAC,uBAAuB,EAAE;YAC9B,IAAI,CAAC,mBAAmB,EAAE;YAC1B,IAAI,CAAC,kBAAkB,EAAE;YACzB,IAAI,CAAC,oBAAoB,EAAE;SAC5B,CAAC;QAEF,MAAM,MAAM,GAAG,QAAQ;aACpB,GAAG,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,uEAAuE,OAAO,CAAC,KAAK,sEAAsE,OAAO,CAAC,GAAG,EAAE,CAAC;aACzL,IAAI,CAAC,MAAM,CAAC,CAAC;QAEhB,OAAO,EAAE,OAAO,EAAE,sCAAsB,EAAE,QAAQ,EAAE,MAAM,EAAE,CAAC;IAC/D,CAAC;IAED,kGAAkG;IAC5F,eAAe;;YACnB,MAAM,eAAe,GAAG,MAAM,CAAC,IAAI,CAAC,6BAAa,CAAC,CAAC,IAAI,EAAE,CAAC;YAC1D,MAAM,YAAY,GAAG,IAAI,GAAG,CAAC,eAAe,CAAC,CAAC;YAE9C,MAAM,SAAS,GAAG,CAAC,MAAM,SAAG,CAAC,KAAK,CAChC,IAAI,CAAC,OAAO,CAAC,eAAe,EAC5B;;;kCAG4B,EAC5B,EAAE,EACF,KAAK,CACN,CAAmC,CAAC;YACrC,MAAM,aAAa,GAAG,SAAS;iBAC5B,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,WAAC,OAAA,MAAM,CAAC,MAAA,yBAAa,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC,IAAI,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA,EAAA,CAAC;iBACjF,MAAM,CAAC,OAAO,CAAC,CAAC;YAEnB,MAAM,aAAa,GAAG,CAAC,MAAM,SAAG,CAAC,KAAK,CACpC,IAAI,CAAC,OAAO,CAAC,eAAe,EAC5B;;;mCAG6B,EAC7B,EAAE,EACF,KAAK,CACN,CAAmC,CAAC;YACrC,MAAM,iBAAiB,GAAG,aAAa;iBACpC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,WAAC,OAAA,MAAM,CAAC,MAAA,yBAAa,CAAC,sBAAsB,CAAC,GAAG,CAAC,CAAC,IAAI,mCAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAA,EAAA,CAAC;iBACjF,MAAM,CAAC,OAAO,CAAC,CAAC;YAEnB,OAAO;gBACL,aAAa;gBACb,WAAW,EAAE,aAAa,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,YAAY,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;gBACpE,eAAe;gBACf,iBAAiB;aAClB,CAAC;QACJ,CAAC;KAAA;IAEO,kBAAkB;QACxB,MAAM,UAAU,GAAa,EAAE,CAAC;QAChC,KAAK,MAAM,CAAC,KAAK,EAAE,MAAM,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,6BAAa,CAAC,EAAE,CAAC;YAC5D,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC;iBAC3C,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,UAAU,CAAC,EAAE,EAAE,CAAC,OAAO,IAAI,IAAI,UAAU,EAAE,CAAC;iBACxD,IAAI,CAAC,KAAK,CAAC,CAAC;YACf,UAAU,CAAC,IAAI,CAAC,gBAAgB,KAAK,OAAO,OAAO,MAAM,CAAC,CAAC;YAC3D,UAAU,CAAC,IAAI,CAAC,eAAe,KAAK,sBAAsB,KAAK,iBAAiB,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACpH,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,YAAY,MAAM,CAAC,IAAI,CAAC,6BAAa,CAAC,CAAC,MAAM,GAAG,EAAE,GAAG,EAAE,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;IACjH,CAAC;IAEO,sBAAsB;QAC5B,MAAM,UAAU,GAAG,iCAAiB,CAAC,GAAG,CACtC,CAAC,SAAS,EAAE,EAAE,CACZ,qCAAqC,SAAS,CAAC,IAAI,qBAAqB,SAAS,CAAC,IAAI,GAAG,CAC5F,CAAC;QACF,OAAO,EAAE,EAAE,EAAE,YAAY,EAAE,KAAK,EAAE,wBAAwB,iCAAiB,CAAC,MAAM,GAAG,EAAE,GAAG,EAAE,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;IACxH,CAAC;IAEO,uBAAuB;QAC7B,MAAM,UAAU,GAAG,kCAAkB,CAAC,GAAG,CACvC,CAAC,EAAE,EAAE,EAAE,CACL,eAAe,EAAE,CAAC,KAAK,mBAAmB,EAAE,CAAC,IAAI,iBAAiB,EAAE,CAAC,MAAM,gBAAgB,EAAE,CAAC,MAAM,KAAK,EAAE,CAAC,YAAY,IAAI,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,oBAAoB,CAAC,CAAC,CAAC,EAAE,GAAG,CACxK,CAAC;QACF,OAAO,EAAE,EAAE,EAAE,aAAa,EAAE,KAAK,EAAE,mBAAmB,kCAAkB,CAAC,MAAM,GAAG,EAAE,GAAG,EAAE,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;IACrH,CAAC;IAEO,mBAAmB;QACzB,MAAM,UAAU,GAAG,8BAAc,CAAC,GAAG,CACnC,CAAC,KAAK,EAAE,EAAE,CAAC,gBAAgB,KAAK,CAAC,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,CACzF,CAAC;QACF,OAAO,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,WAAW,8BAAc,CAAC,MAAM,GAAG,EAAE,GAAG,EAAE,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;IACrG,CAAC;IAEO,kBAAkB;QACxB,MAAM,UAAU,GAAG,6BAAa,CAAC,GAAG,CAClC,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,KAAK,CAAC,KAAK,mBAAmB,KAAK,CAAC,IAAI,WAAW,KAAK,CAAC,UAAU,IAAI,CAClG,CAAC;QACF,OAAO,EAAE,EAAE,EAAE,QAAQ,EAAE,KAAK,EAAE,kBAAkB,6BAAa,CAAC,MAAM,GAAG,EAAE,GAAG,EAAE,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;IAC1G,CAAC;IAEO,oBAAoB;QAC1B,IAAI,+BAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,OAAO,EAAE,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,aAAa,EAAE,GAAG,EAAE,+BAA+B,EAAE,CAAC;QACxF,CAAC;QACD,MAAM,UAAU,GAAG,+BAAe,CAAC,GAAG,CACpC,CAAC,OAAO,EAAE,EAAE,CAAC,kBAAkB,OAAO,CAAC,IAAI,QAAQ,OAAO,CAAC,KAAK,WAAW,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,IAAI,EAAE,CAC3G,CAAC;QACF,OAAO;YACL,EAAE,EAAE,UAAU;YACd,KAAK,EAAE,YAAY,+BAAe,CAAC,MAAM,GAAG;YAC5C,GAAG,EAAE,mBAAmB,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,mBAAmB;SACpE,CAAC;IACJ,CAAC;CACF,CAAA;AAnHY,kDAAmB;8BAAnB,mBAAmB;IAD/B,IAAA,mBAAU,GAAE;IAEE,WAAA,IAAA,eAAM,EAAC,iBAAiB,CAAC,CAAA;;GAD3B,mBAAmB,CAmH/B","sourcesContent":["import { Inject, Injectable } from '@nestjs/common';\nimport { Orm } from '../../../Orm';\nimport { RestUtilities } from '../../../Utilities';\nimport type { AccessiOptions } from '../../AccessiModule';\nimport {\n ACCESSI_SCHEMA_VERSION,\n accessiTables,\n accessiForeignKeys,\n accessiIndexes,\n accessiChecks,\n accessiTriggers,\n accessiGenerators,\n} from '../../database-updates/accessiSchema';\n\nexport interface SchemaDdlSection {\n id: string;\n title: string;\n sql: string;\n}\n\nexport interface SchemaDdlResult {\n version: string;\n sections: SchemaDdlSection[];\n script: string;\n}\n\nexport interface SchemaEntitiesResult {\n presentTables: string[];\n extraTables: string[];\n canonicalTables: string[];\n presentGenerators: string[];\n}\n\n/**\n * Genera il DDL delle entita Accessi a partire dallo schema canonico (stessa fonte della\n * riconciliazione) e rileva le entita effettivamente presenti nel database. Serve a\n * esportare lo schema per replicarlo su altre installazioni.\n */\n@Injectable()\nexport class SchemaExportService {\n constructor(@Inject('ACCESSI_OPTIONS') private readonly options: AccessiOptions) {}\n\n /** DDL completo e deterministico dello schema Accessi. */\n buildDdl(): SchemaDdlResult {\n const sections: SchemaDdlSection[] = [\n this.buildTablesSection(),\n this.buildGeneratorsSection(),\n this.buildForeignKeysSection(),\n this.buildIndexesSection(),\n this.buildChecksSection(),\n this.buildTriggersSection(),\n ];\n\n const script = sections\n .map((section) => `-- ============================================================\\n-- ${section.title}\\n-- ============================================================\\n${section.sql}`)\n .join('\\n\\n');\n\n return { version: ACCESSI_SCHEMA_VERSION, sections, script };\n }\n\n /** Elenca le tabelle/generatori presenti nel database e segnala quelli fuori schema canonical. */\n async presentEntities(): Promise<SchemaEntitiesResult> {\n const canonicalTables = Object.keys(accessiTables).sort();\n const canonicalSet = new Set(canonicalTables);\n\n const tableRows = (await Orm.query(\n this.options.databaseOptions,\n `SELECT TRIM(RDB$RELATION_NAME) AS NAME\n FROM RDB$RELATIONS\n WHERE COALESCE(RDB$SYSTEM_FLAG, 0) = 0 AND RDB$VIEW_BLR IS NULL\n ORDER BY RDB$RELATION_NAME`,\n [],\n false,\n )) as Array<Record<string, unknown>>;\n const presentTables = tableRows\n .map((row) => String(RestUtilities.convertKeysToCamelCase(row).name ?? '').trim())\n .filter(Boolean);\n\n const generatorRows = (await Orm.query(\n this.options.databaseOptions,\n `SELECT TRIM(RDB$GENERATOR_NAME) AS NAME\n FROM RDB$GENERATORS\n WHERE COALESCE(RDB$SYSTEM_FLAG, 0) = 0\n ORDER BY RDB$GENERATOR_NAME`,\n [],\n false,\n )) as Array<Record<string, unknown>>;\n const presentGenerators = generatorRows\n .map((row) => String(RestUtilities.convertKeysToCamelCase(row).name ?? '').trim())\n .filter(Boolean);\n\n return {\n presentTables,\n extraTables: presentTables.filter((name) => !canonicalSet.has(name)),\n canonicalTables,\n presentGenerators,\n };\n }\n\n private buildTablesSection(): SchemaDdlSection {\n const statements: string[] = [];\n for (const [table, schema] of Object.entries(accessiTables)) {\n const columns = Object.entries(schema.columns)\n .map(([name, definition]) => ` ${name} ${definition}`)\n .join(',\\n');\n statements.push(`CREATE TABLE ${table} (\\n${columns}\\n);`);\n statements.push(`ALTER TABLE ${table} ADD CONSTRAINT PK_${table} PRIMARY KEY (${schema.primaryKey.join(', ')});`);\n }\n return { id: 'tables', title: `Tabelle (${Object.keys(accessiTables).length})`, sql: statements.join('\\n\\n') };\n }\n\n private buildGeneratorsSection(): SchemaDdlSection {\n const statements = accessiGenerators.map(\n (generator) =>\n `-- Firebird 2.5: CREATE GENERATOR ${generator.name}\\nCREATE SEQUENCE ${generator.name};`,\n );\n return { id: 'generators', title: `Generatori/Sequenze (${accessiGenerators.length})`, sql: statements.join('\\n\\n') };\n }\n\n private buildForeignKeysSection(): SchemaDdlSection {\n const statements = accessiForeignKeys.map(\n (fk) =>\n `ALTER TABLE ${fk.table} ADD CONSTRAINT ${fk.name} FOREIGN KEY (${fk.column}) REFERENCES ${fk.target} (${fk.targetColumn})${fk.cascade ? ' ON DELETE CASCADE' : ''};`,\n );\n return { id: 'foreignKeys', title: `Chiavi esterne (${accessiForeignKeys.length})`, sql: statements.join('\\n\\n') };\n }\n\n private buildIndexesSection(): SchemaDdlSection {\n const statements = accessiIndexes.map(\n (index) => `CREATE INDEX ${index.name} ON ${index.table} (${index.columns.join(', ')});`,\n );\n return { id: 'indexes', title: `Indici (${accessiIndexes.length})`, sql: statements.join('\\n\\n') };\n }\n\n private buildChecksSection(): SchemaDdlSection {\n const statements = accessiChecks.map(\n (check) => `ALTER TABLE ${check.table} ADD CONSTRAINT ${check.name} CHECK (${check.expression});`,\n );\n return { id: 'checks', title: `Vincoli CHECK (${accessiChecks.length})`, sql: statements.join('\\n\\n') };\n }\n\n private buildTriggersSection(): SchemaDdlSection {\n if (accessiTriggers.length === 0) {\n return { id: 'triggers', title: 'Trigger (0)', sql: '-- Nessun trigger di dominio.' };\n }\n const statements = accessiTriggers.map(\n (trigger) => `CREATE TRIGGER ${trigger.name} FOR ${trigger.table} ACTIVE ${trigger.event} ${trigger.body}`,\n );\n return {\n id: 'triggers',\n title: `Trigger (${accessiTriggers.length})`,\n sql: `SET TERM ^ ;\\n\\n${statements.join('^\\n\\n')}^\\n\\nSET TERM ; ^`,\n };\n }\n}\n"]}
@@ -11,11 +11,22 @@ export interface CatalogMigrationReport {
11
11
  discovered: number;
12
12
  applied: string[];
13
13
  skipped: string[];
14
+ invalid: {
15
+ script: string;
16
+ violations: string[];
17
+ }[];
14
18
  failed: {
15
19
  script: string;
16
20
  error: string;
17
21
  }[];
18
22
  }
23
+ /** Estrae la prima parola chiave di uno statement, saltando spazi e commenti iniziali. */
24
+ export declare function leadingStatementKeyword(statement: string): string;
25
+ /**
26
+ * Valida gli statement di una catalog migration: ritorna la lista delle violazioni (vuota se conforme).
27
+ * Regola tassativa: solo DML. Nessuna modifica a colonne/schema/trigger/permessi.
28
+ */
29
+ export declare function analyzeCatalogScript(statements: string[]): string[];
19
30
  /** Hash SHA-256 del contenuto dello script, usato per rilevare modifiche non versionate. */
20
31
  export declare function computeCatalogScriptChecksum(content: string): string;
21
32
  /**
@@ -40,6 +51,10 @@ export declare function listPendingCatalogScripts(options: AccessiOptions): Prom
40
51
  applied: string[];
41
52
  pending: string[];
42
53
  changed: string[];
54
+ invalid: {
55
+ script: string;
56
+ violations: string[];
57
+ }[];
43
58
  }>;
44
59
  /**
45
60
  * Applica le catalog migrations presenti nella cartella configurata.
@@ -60,5 +75,9 @@ export declare class AccessiCatalogMigrator {
60
75
  applied: string[];
61
76
  pending: string[];
62
77
  changed: string[];
78
+ invalid: {
79
+ script: string;
80
+ violations: string[];
81
+ }[];
63
82
  }>;
64
83
  }
@@ -10,6 +10,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.AccessiCatalogMigrator = void 0;
13
+ exports.leadingStatementKeyword = leadingStatementKeyword;
14
+ exports.analyzeCatalogScript = analyzeCatalogScript;
13
15
  exports.computeCatalogScriptChecksum = computeCatalogScriptChecksum;
14
16
  exports.splitSqlStatements = splitSqlStatements;
15
17
  exports.discoverCatalogScripts = discoverCatalogScripts;
@@ -20,6 +22,58 @@ const fs_1 = require("fs");
20
22
  const path_1 = require("path");
21
23
  const Orm_1 = require("../../Orm");
22
24
  const Logger_1 = require("../../Logger");
25
+ /**
26
+ * Le catalog migrations possono modificare SOLO righe (DML). Questa whitelist rende tassativo il
27
+ * vincolo: qualunque altro statement (DDL, trigger, transazioni, GRANT, ...) viene rifiutato.
28
+ */
29
+ const ALLOWED_STATEMENT_KEYWORDS = new Set([
30
+ 'INSERT', 'UPDATE', 'DELETE', 'MERGE', 'SELECT', 'EXECUTE',
31
+ ]);
32
+ /** Estrae la prima parola chiave di uno statement, saltando spazi e commenti iniziali. */
33
+ function leadingStatementKeyword(statement) {
34
+ let index = 0;
35
+ while (index < statement.length) {
36
+ const char = statement[index];
37
+ if (/\s/.test(char)) {
38
+ index += 1;
39
+ continue;
40
+ }
41
+ if (char === '-' && statement[index + 1] === '-') {
42
+ const newline = statement.indexOf('\n', index);
43
+ if (newline === -1)
44
+ return '';
45
+ index = newline + 1;
46
+ continue;
47
+ }
48
+ if (char === '/' && statement[index + 1] === '*') {
49
+ const end = statement.indexOf('*/', index + 2);
50
+ if (end === -1)
51
+ return '';
52
+ index = end + 2;
53
+ continue;
54
+ }
55
+ break;
56
+ }
57
+ const match = /^([A-Za-z]+)/.exec(statement.slice(index));
58
+ return match ? match[1].toUpperCase() : '';
59
+ }
60
+ /**
61
+ * Valida gli statement di una catalog migration: ritorna la lista delle violazioni (vuota se conforme).
62
+ * Regola tassativa: solo DML. Nessuna modifica a colonne/schema/trigger/permessi.
63
+ */
64
+ function analyzeCatalogScript(statements) {
65
+ const violations = [];
66
+ for (const statement of statements) {
67
+ const keyword = leadingStatementKeyword(statement);
68
+ if (!keyword)
69
+ continue;
70
+ if (!ALLOWED_STATEMENT_KEYWORDS.has(keyword)) {
71
+ const preview = statement.replace(/\s+/g, ' ').trim().slice(0, 120);
72
+ violations.push(`Statement non consentito (${keyword}): le catalog migrations possono modificare solo righe (INSERT/UPDATE/DELETE/MERGE). Estratto: "${preview}"`);
73
+ }
74
+ }
75
+ return violations;
76
+ }
23
77
  /** Ritorna la policy di checksum effettiva (default `error`). */
24
78
  function checksumPolicy(options) {
25
79
  var _a;
@@ -183,19 +237,27 @@ function listPendingCatalogScripts(options) {
183
237
  if (!(yield isLedgerPresent(options))) {
184
238
  throw new Error('AccessiCatalogMigrator: tabella ACCESSI_CATALOG_SCRIPT assente. Eseguire prima AccessiDatabaseUpdater.run (db:update:accessi).');
185
239
  }
240
+ const allowDdl = config.allowDdl === true;
186
241
  const ledger = yield readLedger(options);
187
242
  const discovered = discoverCatalogScripts(config);
188
243
  const pending = [];
189
244
  const changed = [];
245
+ const invalid = [];
190
246
  for (const script of discovered) {
191
- const checksum = computeCatalogScriptChecksum((0, fs_1.readFileSync)(script.path, 'utf8'));
247
+ const content = (0, fs_1.readFileSync)(script.path, 'utf8');
248
+ const checksum = computeCatalogScriptChecksum(content);
249
+ const violations = allowDdl ? [] : analyzeCatalogScript(splitSqlStatements(content));
250
+ if (violations.length > 0) {
251
+ invalid.push({ script: script.name, violations });
252
+ continue;
253
+ }
192
254
  const appliedChecksum = ledger.get(script.name);
193
255
  if (appliedChecksum === undefined)
194
256
  pending.push(script.name);
195
257
  else if (appliedChecksum !== checksum)
196
258
  changed.push(script.name);
197
259
  }
198
- return { applied: [...ledger.keys()].sort(), pending, changed };
260
+ return { applied: [...ledger.keys()].sort(), pending, changed, invalid };
199
261
  });
200
262
  }
201
263
  /**
@@ -223,8 +285,9 @@ function applyCatalogScripts(options) {
223
285
  const discovered = discoverCatalogScripts(config);
224
286
  const ledger = yield readLedger(options);
225
287
  const stopOnError = config.stopOnError !== false;
288
+ const allowDdl = config.allowDdl === true;
226
289
  const maxScripts = Number.isInteger(config.maxScriptsPerRun) && ((_a = config.maxScriptsPerRun) !== null && _a !== void 0 ? _a : 0) > 0 ? config.maxScriptsPerRun : undefined;
227
- const report = { folder, discovered: discovered.length, applied: [], skipped: [], failed: [] };
290
+ const report = { folder, discovered: discovered.length, applied: [], skipped: [], invalid: [], failed: [] };
228
291
  logger.info(`Catalog migrations: ${discovered.length} script trovati in ${folder}.`);
229
292
  for (const script of discovered) {
230
293
  if (maxScripts !== undefined && report.applied.length >= maxScripts) {
@@ -255,6 +318,15 @@ function applyCatalogScripts(options) {
255
318
  }
256
319
  try {
257
320
  const statements = splitSqlStatements(content);
321
+ const violations = allowDdl ? [] : analyzeCatalogScript(statements);
322
+ if (violations.length > 0) {
323
+ report.invalid.push({ script: script.name, violations });
324
+ for (const violation of violations) {
325
+ logger.error(`Catalog migration non conforme: ${script.name}. ${violation}`);
326
+ }
327
+ // Il file non viene applicato ne registrato nel ledger; il run prosegue con gli altri.
328
+ continue;
329
+ }
258
330
  for (const statement of statements) {
259
331
  yield Orm_1.Orm.execute(options.databaseOptions, statement, [], false);
260
332
  }
@@ -1 +1 @@
1
- {"version":3,"file":"AccessiCatalogMigrator.js","sourceRoot":"","sources":["../../../src/accessi-module/database-updates/AccessiCatalogMigrator.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from 'crypto';\nimport { existsSync, readFileSync, readdirSync } from 'fs';\nimport { extname, join, relative, resolve, sep } from 'path';\nimport { Orm } from '../../Orm';\nimport { Logger } from '../../Logger';\nimport type { AccessiOptions, CatalogScriptChecksumPolicy, CatalogScriptsOptions } from '../AccessiModule';\n\nexport interface CatalogScriptMigration {\n name: string;\n applied: boolean;\n skipped: boolean;\n reapplied: boolean;\n error?: string;\n}\n\nexport interface CatalogMigrationReport {\n folder: string;\n discovered: number;\n applied: string[];\n skipped: string[];\n failed: { script: string; error: string }[];\n}\n\n/** Ritorna la policy di checksum effettiva (default `error`). */\nfunction checksumPolicy(options: CatalogScriptsOptions): CatalogScriptChecksumPolicy {\n return options.onChecksumMismatch ?? 'error';\n}\n\n/** Hash SHA-256 del contenuto dello script, usato per rilevare modifiche non versionate. */\nexport function computeCatalogScriptChecksum(content: string): string {\n return createHash('sha256').update(content, 'utf8').digest('hex');\n}\n\n/**\n * Divide un file SQL in statement eseguibili separatamente.\n *\n * Supporta:\n * - terminator personalizzati con `SET TERM <char>` / `SET TERM <char> ;`\n * - stringhe `'...'` con escape `''`\n * - commenti di riga `--` e di blocco `/* ... * /`\n *\n * Non interpreta la semantica SQL: e volutamente un tokenizer prudente che non spezza\n * mai all'interno di stringhe o commenti.\n */\nexport function splitSqlStatements(sql: string, defaultTerminator = ';'): string[] {\n const statements: string[] = [];\n const lines = sql.replace(/\\r\\n?/g, '\\n').split('\\n');\n let buffer = '';\n let terminator = defaultTerminator;\n let inString = false;\n let inLineComment = false;\n let inBlockComment = false;\n\n for (const line of lines) {\n const setTerm = /^\\s*SET\\s+TERM\\s+(\\S+)/i.exec(line);\n if (setTerm && !inString && !inLineComment && !inBlockComment) {\n const raw = setTerm[1] ?? '';\n terminator = raw.length > 1 && raw.endsWith(';') ? raw.slice(0, -1) : raw || defaultTerminator;\n continue;\n }\n\n buffer += `${line}\\n`;\n\n let start = 0;\n let index = 0;\n while (index < buffer.length) {\n const char = buffer[index] as string;\n const next = buffer[index + 1];\n\n if (inLineComment) {\n if (char === '\\n') inLineComment = false;\n index += 1;\n continue;\n }\n if (inBlockComment) {\n if (char === '*' && next === '/') {\n inBlockComment = false;\n index += 2;\n continue;\n }\n index += 1;\n continue;\n }\n if (inString) {\n if (char === \"'\") {\n if (next === \"'\") {\n index += 2;\n continue;\n }\n inString = false;\n }\n index += 1;\n continue;\n }\n\n if (char === \"'\") {\n inString = true;\n index += 1;\n continue;\n }\n if (char === '-' && next === '-') {\n inLineComment = true;\n index += 2;\n continue;\n }\n if (char === '/' && next === '*') {\n inBlockComment = true;\n index += 2;\n continue;\n }\n if (buffer.startsWith(terminator, index)) {\n const statement = buffer.slice(start, index).trim();\n if (statement) statements.push(statement);\n index += terminator.length;\n start = index;\n continue;\n }\n index += 1;\n }\n\n buffer = buffer.slice(start);\n }\n\n const trailing = buffer.trim();\n if (trailing) statements.push(trailing);\n return statements;\n}\n\n/** Elenca gli script `.sql` della cartella, ordinati per percorso (prefissi numerici consigliati). */\nexport function discoverCatalogScripts(options: CatalogScriptsOptions): { name: string; path: string }[] {\n const folder = resolve(options.folder);\n if (!existsSync(folder)) {\n throw new Error(`AccessiCatalogMigrator: cartella non trovata: ${folder}`);\n }\n\n const include = options.include && options.include.length > 0 ? options.include : ['.sql'];\n const found: { name: string; path: string }[] = [];\n\n const walk = (directory: string): void => {\n for (const entry of readdirSync(directory, { withFileTypes: true })) {\n const absolute = join(directory, entry.name);\n if (entry.isDirectory()) {\n walk(absolute);\n continue;\n }\n if (!entry.isFile()) continue;\n const matches = include.some((pattern) =>\n pattern.startsWith('.') ? extname(entry.name).toLowerCase() === pattern.toLowerCase() : entry.name.includes(pattern),\n );\n if (!matches) continue;\n const name = relative(folder, absolute).split(sep).join('/');\n found.push({ name, path: absolute });\n }\n };\n\n walk(folder);\n return found.sort((a, b) => a.name.localeCompare(b.name));\n}\n\nfunction isLedgerPresent(options: AccessiOptions): Promise<boolean> {\n return Orm.query(\n options.databaseOptions,\n \"SELECT 1 FROM RDB$RELATIONS WHERE TRIM(RDB$RELATION_NAME) = 'ACCESSI_CATALOG_SCRIPT'\",\n [],\n false,\n ).then((rows) => rows.length > 0);\n}\n\n/** Legge il ledger come mappa `script -> checksum`. */\nasync function readLedger(options: AccessiOptions): Promise<Map<string, string>> {\n const rows = (await Orm.query(\n options.databaseOptions,\n 'SELECT SCRIPT_NAME AS NAME, CHECKSUM FROM ACCESSI_CATALOG_SCRIPT',\n [],\n false,\n )) as Array<Record<string, unknown>>;\n const ledger = new Map<string, string>();\n for (const row of rows) {\n const name = String(row.NAME ?? row.name ?? '').trim();\n const checksum = String(row.CHECKSUM ?? row.checksum ?? '').trim();\n if (name) ledger.set(name, checksum);\n }\n return ledger;\n}\n\nasync function upsertLedger(options: AccessiOptions, name: string, checksum: string, reapplied: boolean): Promise<void> {\n if (reapplied) {\n await Orm.execute(\n options.databaseOptions,\n 'UPDATE ACCESSI_CATALOG_SCRIPT SET CHECKSUM = ?, APPLIED_AT = CURRENT_TIMESTAMP, APPLIED_COUNT = APPLIED_COUNT + 1 WHERE SCRIPT_NAME = ?',\n [checksum, name],\n false,\n );\n return;\n }\n await Orm.execute(\n options.databaseOptions,\n 'UPDATE OR INSERT INTO ACCESSI_CATALOG_SCRIPT (SCRIPT_NAME, CHECKSUM, APPLIED_AT, APPLIED_COUNT) VALUES (?, ?, CURRENT_TIMESTAMP, 1) MATCHING (SCRIPT_NAME)',\n [name, checksum],\n false,\n );\n}\n\n/** Elenca gli script non ancora applicati (o con checksum diverso) senza eseguirli. */\nexport async function listPendingCatalogScripts(options: AccessiOptions): Promise<{ applied: string[]; pending: string[]; changed: string[] }> {\n const config = options.catalogScripts;\n if (!config?.folder) throw new Error('AccessiCatalogMigrator: catalogScripts.folder non configurato.');\n if (!(await isLedgerPresent(options))) {\n throw new Error('AccessiCatalogMigrator: tabella ACCESSI_CATALOG_SCRIPT assente. Eseguire prima AccessiDatabaseUpdater.run (db:update:accessi).');\n }\n\n const ledger = await readLedger(options);\n const discovered = discoverCatalogScripts(config);\n const pending: string[] = [];\n const changed: string[] = [];\n\n for (const script of discovered) {\n const checksum = computeCatalogScriptChecksum(readFileSync(script.path, 'utf8'));\n const appliedChecksum = ledger.get(script.name);\n if (appliedChecksum === undefined) pending.push(script.name);\n else if (appliedChecksum !== checksum) changed.push(script.name);\n }\n\n return { applied: [...ledger.keys()].sort(), pending, changed };\n}\n\n/**\n * Applica le catalog migrations presenti nella cartella configurata.\n *\n * Idempotenza:\n * - uno script gia presente nel ledger con lo stesso checksum viene saltato;\n * - uno script gia applicato ma modificato segue `onChecksumMismatch` (`error` default, `warn`, `reapply`);\n * - un errore interrompe il run (default) senza avanzare, lasciando il ledger all'ultimo script completato.\n *\n * Il chiamante deve avere gia riconciliato lo schema (`AccessiDatabaseUpdater.run`): la tabella\n * ledger `ACCESSI_CATALOG_SCRIPT` e creata dall'updater.\n */\nexport async function applyCatalogScripts(options: AccessiOptions): Promise<CatalogMigrationReport> {\n const logger = new Logger(AccessiCatalogMigrator.name);\n const config = options.catalogScripts;\n if (!config?.folder) throw new Error('AccessiCatalogMigrator: catalogScripts.folder non configurato.');\n if (!(await isLedgerPresent(options))) {\n throw new Error('AccessiCatalogMigrator: tabella ACCESSI_CATALOG_SCRIPT assente. Eseguire prima AccessiDatabaseUpdater.run (db:update:accessi).');\n }\n\n const folder = resolve(config.folder);\n const discovered = discoverCatalogScripts(config);\n const ledger = await readLedger(options);\n const stopOnError = config.stopOnError !== false;\n const maxScripts = Number.isInteger(config.maxScriptsPerRun) && (config.maxScriptsPerRun ?? 0) > 0 ? config.maxScriptsPerRun : undefined;\n const report: CatalogMigrationReport = { folder, discovered: discovered.length, applied: [], skipped: [], failed: [] };\n\n logger.info(`Catalog migrations: ${discovered.length} script trovati in ${folder}.`);\n\n for (const script of discovered) {\n if (maxScripts !== undefined && report.applied.length >= maxScripts) {\n logger.warning(`Catalog migrations: limite maxScriptsPerRun=${maxScripts} raggiunto, resto rimandato.`);\n break;\n }\n\n const content = readFileSync(script.path, 'utf8');\n const checksum = computeCatalogScriptChecksum(content);\n const appliedChecksum = ledger.get(script.name);\n\n if (appliedChecksum === checksum) {\n report.skipped.push(script.name);\n continue;\n }\n\n let reapplied = false;\n if (appliedChecksum !== undefined && appliedChecksum !== checksum) {\n const policy = checksumPolicy(config);\n if (policy === 'error') {\n throw new Error(\n `AccessiCatalogMigrator: lo script \"${script.name}\" e gia applicato con un checksum diverso (migrazioni immutabili). ` +\n `Ripristina il file o configura onChecksumMismatch='reapply'/'warn' consapevolmente.`,\n );\n }\n if (policy === 'warn') {\n logger.warning(`Catalog migrations: \"${script.name}\" applicato con checksum diverso, ignorato (policy warn).`);\n report.skipped.push(script.name);\n continue;\n }\n reapplied = true;\n logger.warning(`Catalog migrations: \"${script.name}\" riapplicato (policy reapply).`);\n }\n\n try {\n const statements = splitSqlStatements(content);\n for (const statement of statements) {\n await Orm.execute(options.databaseOptions, statement, [], false);\n }\n await upsertLedger(options, script.name, checksum, reapplied);\n ledger.set(script.name, checksum);\n report.applied.push(script.name);\n logger.info(`Catalog migration applicata: ${script.name} (${statements.length} statement).`);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n report.failed.push({ script: script.name, error: message });\n logger.error(`Catalog migration fallita: ${script.name}. ${message}`);\n if (stopOnError) {\n throw new Error(`AccessiCatalogMigrator: script \"${script.name}\" fallito. ${message}`);\n }\n }\n }\n\n return report;\n}\n\n/** Esegue la riconciliazione dello schema non e responsabilita di questa classe: usare l'updater prima. */\nexport class AccessiCatalogMigrator {\n static apply(options: AccessiOptions): Promise<CatalogMigrationReport> {\n return applyCatalogScripts(options);\n }\n\n static listPending(options: AccessiOptions): Promise<{ applied: string[]; pending: string[]; changed: string[] }> {\n return listPendingCatalogScripts(options);\n }\n}\n"]}
1
+ {"version":3,"file":"AccessiCatalogMigrator.js","sourceRoot":"","sources":["../../../src/accessi-module/database-updates/AccessiCatalogMigrator.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHash } from 'crypto';\nimport { existsSync, readFileSync, readdirSync } from 'fs';\nimport { extname, join, relative, resolve, sep } from 'path';\nimport { Orm } from '../../Orm';\nimport { Logger } from '../../Logger';\nimport type { AccessiOptions, CatalogScriptChecksumPolicy, CatalogScriptsOptions } from '../AccessiModule';\n\nexport interface CatalogScriptMigration {\n name: string;\n applied: boolean;\n skipped: boolean;\n reapplied: boolean;\n error?: string;\n}\n\nexport interface CatalogMigrationReport {\n folder: string;\n discovered: number;\n applied: string[];\n skipped: string[];\n invalid: { script: string; violations: string[] }[];\n failed: { script: string; error: string }[];\n}\n\n/**\n * Le catalog migrations possono modificare SOLO righe (DML). Questa whitelist rende tassativo il\n * vincolo: qualunque altro statement (DDL, trigger, transazioni, GRANT, ...) viene rifiutato.\n */\nconst ALLOWED_STATEMENT_KEYWORDS: ReadonlySet<string> = new Set([\n 'INSERT', 'UPDATE', 'DELETE', 'MERGE', 'SELECT', 'EXECUTE',\n]);\n\n/** Estrae la prima parola chiave di uno statement, saltando spazi e commenti iniziali. */\nexport function leadingStatementKeyword(statement: string): string {\n let index = 0;\n while (index < statement.length) {\n const char = statement[index] as string;\n if (/\\s/.test(char)) { index += 1; continue; }\n if (char === '-' && statement[index + 1] === '-') {\n const newline = statement.indexOf('\\n', index);\n if (newline === -1) return '';\n index = newline + 1;\n continue;\n }\n if (char === '/' && statement[index + 1] === '*') {\n const end = statement.indexOf('*/', index + 2);\n if (end === -1) return '';\n index = end + 2;\n continue;\n }\n break;\n }\n const match = /^([A-Za-z]+)/.exec(statement.slice(index));\n return match ? (match[1] as string).toUpperCase() : '';\n}\n\n/**\n * Valida gli statement di una catalog migration: ritorna la lista delle violazioni (vuota se conforme).\n * Regola tassativa: solo DML. Nessuna modifica a colonne/schema/trigger/permessi.\n */\nexport function analyzeCatalogScript(statements: string[]): string[] {\n const violations: string[] = [];\n for (const statement of statements) {\n const keyword = leadingStatementKeyword(statement);\n if (!keyword) continue;\n if (!ALLOWED_STATEMENT_KEYWORDS.has(keyword)) {\n const preview = statement.replace(/\\s+/g, ' ').trim().slice(0, 120);\n violations.push(\n `Statement non consentito (${keyword}): le catalog migrations possono modificare solo righe (INSERT/UPDATE/DELETE/MERGE). Estratto: \"${preview}\"`,\n );\n }\n }\n return violations;\n}\n\n/** Ritorna la policy di checksum effettiva (default `error`). */\nfunction checksumPolicy(options: CatalogScriptsOptions): CatalogScriptChecksumPolicy {\n return options.onChecksumMismatch ?? 'error';\n}\n\n/** Hash SHA-256 del contenuto dello script, usato per rilevare modifiche non versionate. */\nexport function computeCatalogScriptChecksum(content: string): string {\n return createHash('sha256').update(content, 'utf8').digest('hex');\n}\n\n/**\n * Divide un file SQL in statement eseguibili separatamente.\n *\n * Supporta:\n * - terminator personalizzati con `SET TERM <char>` / `SET TERM <char> ;`\n * - stringhe `'...'` con escape `''`\n * - commenti di riga `--` e di blocco `/* ... * /`\n *\n * Non interpreta la semantica SQL: e volutamente un tokenizer prudente che non spezza\n * mai all'interno di stringhe o commenti.\n */\nexport function splitSqlStatements(sql: string, defaultTerminator = ';'): string[] {\n const statements: string[] = [];\n const lines = sql.replace(/\\r\\n?/g, '\\n').split('\\n');\n let buffer = '';\n let terminator = defaultTerminator;\n let inString = false;\n let inLineComment = false;\n let inBlockComment = false;\n\n for (const line of lines) {\n const setTerm = /^\\s*SET\\s+TERM\\s+(\\S+)/i.exec(line);\n if (setTerm && !inString && !inLineComment && !inBlockComment) {\n const raw = setTerm[1] ?? '';\n terminator = raw.length > 1 && raw.endsWith(';') ? raw.slice(0, -1) : raw || defaultTerminator;\n continue;\n }\n\n buffer += `${line}\\n`;\n\n let start = 0;\n let index = 0;\n while (index < buffer.length) {\n const char = buffer[index] as string;\n const next = buffer[index + 1];\n\n if (inLineComment) {\n if (char === '\\n') inLineComment = false;\n index += 1;\n continue;\n }\n if (inBlockComment) {\n if (char === '*' && next === '/') {\n inBlockComment = false;\n index += 2;\n continue;\n }\n index += 1;\n continue;\n }\n if (inString) {\n if (char === \"'\") {\n if (next === \"'\") {\n index += 2;\n continue;\n }\n inString = false;\n }\n index += 1;\n continue;\n }\n\n if (char === \"'\") {\n inString = true;\n index += 1;\n continue;\n }\n if (char === '-' && next === '-') {\n inLineComment = true;\n index += 2;\n continue;\n }\n if (char === '/' && next === '*') {\n inBlockComment = true;\n index += 2;\n continue;\n }\n if (buffer.startsWith(terminator, index)) {\n const statement = buffer.slice(start, index).trim();\n if (statement) statements.push(statement);\n index += terminator.length;\n start = index;\n continue;\n }\n index += 1;\n }\n\n buffer = buffer.slice(start);\n }\n\n const trailing = buffer.trim();\n if (trailing) statements.push(trailing);\n return statements;\n}\n\n/** Elenca gli script `.sql` della cartella, ordinati per percorso (prefissi numerici consigliati). */\nexport function discoverCatalogScripts(options: CatalogScriptsOptions): { name: string; path: string }[] {\n const folder = resolve(options.folder);\n if (!existsSync(folder)) {\n throw new Error(`AccessiCatalogMigrator: cartella non trovata: ${folder}`);\n }\n\n const include = options.include && options.include.length > 0 ? options.include : ['.sql'];\n const found: { name: string; path: string }[] = [];\n\n const walk = (directory: string): void => {\n for (const entry of readdirSync(directory, { withFileTypes: true })) {\n const absolute = join(directory, entry.name);\n if (entry.isDirectory()) {\n walk(absolute);\n continue;\n }\n if (!entry.isFile()) continue;\n const matches = include.some((pattern) =>\n pattern.startsWith('.') ? extname(entry.name).toLowerCase() === pattern.toLowerCase() : entry.name.includes(pattern),\n );\n if (!matches) continue;\n const name = relative(folder, absolute).split(sep).join('/');\n found.push({ name, path: absolute });\n }\n };\n\n walk(folder);\n return found.sort((a, b) => a.name.localeCompare(b.name));\n}\n\nfunction isLedgerPresent(options: AccessiOptions): Promise<boolean> {\n return Orm.query(\n options.databaseOptions,\n \"SELECT 1 FROM RDB$RELATIONS WHERE TRIM(RDB$RELATION_NAME) = 'ACCESSI_CATALOG_SCRIPT'\",\n [],\n false,\n ).then((rows) => rows.length > 0);\n}\n\n/** Legge il ledger come mappa `script -> checksum`. */\nasync function readLedger(options: AccessiOptions): Promise<Map<string, string>> {\n const rows = (await Orm.query(\n options.databaseOptions,\n 'SELECT SCRIPT_NAME AS NAME, CHECKSUM FROM ACCESSI_CATALOG_SCRIPT',\n [],\n false,\n )) as Array<Record<string, unknown>>;\n const ledger = new Map<string, string>();\n for (const row of rows) {\n const name = String(row.NAME ?? row.name ?? '').trim();\n const checksum = String(row.CHECKSUM ?? row.checksum ?? '').trim();\n if (name) ledger.set(name, checksum);\n }\n return ledger;\n}\n\nasync function upsertLedger(options: AccessiOptions, name: string, checksum: string, reapplied: boolean): Promise<void> {\n if (reapplied) {\n await Orm.execute(\n options.databaseOptions,\n 'UPDATE ACCESSI_CATALOG_SCRIPT SET CHECKSUM = ?, APPLIED_AT = CURRENT_TIMESTAMP, APPLIED_COUNT = APPLIED_COUNT + 1 WHERE SCRIPT_NAME = ?',\n [checksum, name],\n false,\n );\n return;\n }\n await Orm.execute(\n options.databaseOptions,\n 'UPDATE OR INSERT INTO ACCESSI_CATALOG_SCRIPT (SCRIPT_NAME, CHECKSUM, APPLIED_AT, APPLIED_COUNT) VALUES (?, ?, CURRENT_TIMESTAMP, 1) MATCHING (SCRIPT_NAME)',\n [name, checksum],\n false,\n );\n}\n\n/** Elenca gli script non ancora applicati (o con checksum diverso) senza eseguirli. */\nexport async function listPendingCatalogScripts(options: AccessiOptions): Promise<{ applied: string[]; pending: string[]; changed: string[]; invalid: { script: string; violations: string[] }[] }> {\n const config = options.catalogScripts;\n if (!config?.folder) throw new Error('AccessiCatalogMigrator: catalogScripts.folder non configurato.');\n if (!(await isLedgerPresent(options))) {\n throw new Error('AccessiCatalogMigrator: tabella ACCESSI_CATALOG_SCRIPT assente. Eseguire prima AccessiDatabaseUpdater.run (db:update:accessi).');\n }\n\n const allowDdl = config.allowDdl === true;\n const ledger = await readLedger(options);\n const discovered = discoverCatalogScripts(config);\n const pending: string[] = [];\n const changed: string[] = [];\n const invalid: { script: string; violations: string[] }[] = [];\n\n for (const script of discovered) {\n const content = readFileSync(script.path, 'utf8');\n const checksum = computeCatalogScriptChecksum(content);\n const violations = allowDdl ? [] : analyzeCatalogScript(splitSqlStatements(content));\n if (violations.length > 0) {\n invalid.push({ script: script.name, violations });\n continue;\n }\n const appliedChecksum = ledger.get(script.name);\n if (appliedChecksum === undefined) pending.push(script.name);\n else if (appliedChecksum !== checksum) changed.push(script.name);\n }\n\n return { applied: [...ledger.keys()].sort(), pending, changed, invalid };\n}\n\n/**\n * Applica le catalog migrations presenti nella cartella configurata.\n *\n * Idempotenza:\n * - uno script gia presente nel ledger con lo stesso checksum viene saltato;\n * - uno script gia applicato ma modificato segue `onChecksumMismatch` (`error` default, `warn`, `reapply`);\n * - un errore interrompe il run (default) senza avanzare, lasciando il ledger all'ultimo script completato.\n *\n * Il chiamante deve avere gia riconciliato lo schema (`AccessiDatabaseUpdater.run`): la tabella\n * ledger `ACCESSI_CATALOG_SCRIPT` e creata dall'updater.\n */\nexport async function applyCatalogScripts(options: AccessiOptions): Promise<CatalogMigrationReport> {\n const logger = new Logger(AccessiCatalogMigrator.name);\n const config = options.catalogScripts;\n if (!config?.folder) throw new Error('AccessiCatalogMigrator: catalogScripts.folder non configurato.');\n if (!(await isLedgerPresent(options))) {\n throw new Error('AccessiCatalogMigrator: tabella ACCESSI_CATALOG_SCRIPT assente. Eseguire prima AccessiDatabaseUpdater.run (db:update:accessi).');\n }\n\n const folder = resolve(config.folder);\n const discovered = discoverCatalogScripts(config);\n const ledger = await readLedger(options);\n const stopOnError = config.stopOnError !== false;\n const allowDdl = config.allowDdl === true;\n const maxScripts = Number.isInteger(config.maxScriptsPerRun) && (config.maxScriptsPerRun ?? 0) > 0 ? config.maxScriptsPerRun : undefined;\n const report: CatalogMigrationReport = { folder, discovered: discovered.length, applied: [], skipped: [], invalid: [], failed: [] };\n\n logger.info(`Catalog migrations: ${discovered.length} script trovati in ${folder}.`);\n\n for (const script of discovered) {\n if (maxScripts !== undefined && report.applied.length >= maxScripts) {\n logger.warning(`Catalog migrations: limite maxScriptsPerRun=${maxScripts} raggiunto, resto rimandato.`);\n break;\n }\n\n const content = readFileSync(script.path, 'utf8');\n const checksum = computeCatalogScriptChecksum(content);\n const appliedChecksum = ledger.get(script.name);\n\n if (appliedChecksum === checksum) {\n report.skipped.push(script.name);\n continue;\n }\n\n let reapplied = false;\n if (appliedChecksum !== undefined && appliedChecksum !== checksum) {\n const policy = checksumPolicy(config);\n if (policy === 'error') {\n throw new Error(\n `AccessiCatalogMigrator: lo script \"${script.name}\" e gia applicato con un checksum diverso (migrazioni immutabili). ` +\n `Ripristina il file o configura onChecksumMismatch='reapply'/'warn' consapevolmente.`,\n );\n }\n if (policy === 'warn') {\n logger.warning(`Catalog migrations: \"${script.name}\" applicato con checksum diverso, ignorato (policy warn).`);\n report.skipped.push(script.name);\n continue;\n }\n reapplied = true;\n logger.warning(`Catalog migrations: \"${script.name}\" riapplicato (policy reapply).`);\n }\n\n try {\n const statements = splitSqlStatements(content);\n const violations = allowDdl ? [] : analyzeCatalogScript(statements);\n if (violations.length > 0) {\n report.invalid.push({ script: script.name, violations });\n for (const violation of violations) {\n logger.error(`Catalog migration non conforme: ${script.name}. ${violation}`);\n }\n // Il file non viene applicato ne registrato nel ledger; il run prosegue con gli altri.\n continue;\n }\n for (const statement of statements) {\n await Orm.execute(options.databaseOptions, statement, [], false);\n }\n await upsertLedger(options, script.name, checksum, reapplied);\n ledger.set(script.name, checksum);\n report.applied.push(script.name);\n logger.info(`Catalog migration applicata: ${script.name} (${statements.length} statement).`);\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n report.failed.push({ script: script.name, error: message });\n logger.error(`Catalog migration fallita: ${script.name}. ${message}`);\n if (stopOnError) {\n throw new Error(`AccessiCatalogMigrator: script \"${script.name}\" fallito. ${message}`);\n }\n }\n }\n\n return report;\n}\n\n/** Esegue la riconciliazione dello schema non e responsabilita di questa classe: usare l'updater prima. */\nexport class AccessiCatalogMigrator {\n static apply(options: AccessiOptions): Promise<CatalogMigrationReport> {\n return applyCatalogScripts(options);\n }\n\n static listPending(options: AccessiOptions): Promise<{ applied: string[]; pending: string[]; changed: string[]; invalid: { script: string; violations: string[] }[] }> {\n return listPendingCatalogScripts(options);\n }\n}\n"]}
@@ -33,17 +33,29 @@ function main() {
33
33
  console.log(`[Accessi Catalog] Gia applicati: ${pending.applied.length}`);
34
34
  console.log(`[Accessi Catalog] Da applicare: ${pending.pending.length}${pending.pending.length ? ` -> ${pending.pending.join(', ')}` : ''}`);
35
35
  console.log(`[Accessi Catalog] Modificati (checksum diverso): ${pending.changed.length}${pending.changed.length ? ` -> ${pending.changed.join(', ')}` : ''}`);
36
+ console.log(`[Accessi Catalog] Non conformi (solo DML): ${pending.invalid.length}`);
37
+ for (const entry of pending.invalid) {
38
+ for (const violation of entry.violations)
39
+ console.error(`[Accessi Catalog] Non conforme: ${entry.script} -> ${violation}`);
40
+ }
41
+ if (pending.invalid.length)
42
+ process.exitCode = 1;
36
43
  return;
37
44
  }
38
45
  const report = yield (0, AccessiCatalogMigrator_1.applyCatalogScripts)(options);
39
- console.log(`[Accessi Catalog] Scoperti: ${report.discovered} | Applicati: ${report.applied.length} | Saltati: ${report.skipped.length} | Falliti: ${report.failed.length}`);
46
+ console.log(`[Accessi Catalog] Scoperti: ${report.discovered} | Applicati: ${report.applied.length} | Saltati: ${report.skipped.length} | Non conformi: ${report.invalid.length} | Falliti: ${report.failed.length}`);
40
47
  if (report.applied.length)
41
48
  console.log(`[Accessi Catalog] Applicati: ${report.applied.join(', ')}`);
49
+ for (const entry of report.invalid) {
50
+ for (const violation of entry.violations)
51
+ console.error(`[Accessi Catalog] Non conforme: ${entry.script} -> ${violation}`);
52
+ }
42
53
  if (report.failed.length) {
43
54
  for (const failure of report.failed)
44
55
  console.error(`[Accessi Catalog] Fallito: ${failure.script} -> ${failure.error}`);
45
- process.exitCode = 1;
46
56
  }
57
+ if (report.failed.length || report.invalid.length)
58
+ process.exitCode = 1;
47
59
  });
48
60
  }
49
61
  main()
@@ -1 +1 @@
1
- {"version":3,"file":"runAccessiCatalogMigrations.js","sourceRoot":"","sources":["../../../src/accessi-module/database-updates/runAccessiCatalogMigrations.ts"],"names":[],"mappings":"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","sourcesContent":["import { AccessiDatabaseUpdater } from \"./AccessiDatabaseUpdater\";\nimport { applyCatalogScripts, listPendingCatalogScripts } from \"./AccessiCatalogMigrator\";\nimport { createAccessiOptionsFromEnv } from \"./accessiOptionsFromEnv\";\nimport { Orm } from \"../../Orm\";\n\nasync function main(): Promise<void> {\n const options = createAccessiOptionsFromEnv();\n if (!options.catalogScripts?.folder) {\n throw new Error(\"Variabile ambiente mancante: ACCESSI_CATALOG_FOLDER (cartella delle catalog migrations).\");\n }\n\n const checkOnly = process.argv.includes('--check');\n console.log(`[Accessi Catalog] Target: ${options.databaseOptions.host}:${options.databaseOptions.port} -> ${options.databaseOptions.database}`);\n console.log(`[Accessi Catalog] Cartella: ${options.catalogScripts.folder}`);\n\n // Prima lo schema si adegua, poi si eseguono gli script di catalogo.\n if (!checkOnly) {\n console.log('[Accessi Catalog] Riconciliazione schema...');\n await AccessiDatabaseUpdater.run(options);\n }\n\n if (checkOnly) {\n const pending = await listPendingCatalogScripts(options);\n console.log(`[Accessi Catalog] Gia applicati: ${pending.applied.length}`);\n console.log(`[Accessi Catalog] Da applicare: ${pending.pending.length}${pending.pending.length ? ` -> ${pending.pending.join(', ')}` : ''}`);\n console.log(`[Accessi Catalog] Modificati (checksum diverso): ${pending.changed.length}${pending.changed.length ? ` -> ${pending.changed.join(', ')}` : ''}`);\n return;\n }\n\n const report = await applyCatalogScripts(options);\n console.log(`[Accessi Catalog] Scoperti: ${report.discovered} | Applicati: ${report.applied.length} | Saltati: ${report.skipped.length} | Falliti: ${report.failed.length}`);\n if (report.applied.length) console.log(`[Accessi Catalog] Applicati: ${report.applied.join(', ')}`);\n if (report.failed.length) {\n for (const failure of report.failed) console.error(`[Accessi Catalog] Fallito: ${failure.script} -> ${failure.error}`);\n process.exitCode = 1;\n }\n}\n\nmain()\n .then(() => Orm.closePools())\n .then(() => process.exit(process.exitCode ?? 0))\n .catch(async (error) => {\n console.error(\"[Accessi Catalog] Errore durante l'esecuzione:\", error);\n await Orm.closePools().catch(() => undefined);\n process.exit(1);\n });\n"]}
1
+ {"version":3,"file":"runAccessiCatalogMigrations.js","sourceRoot":"","sources":["../../../src/accessi-module/database-updates/runAccessiCatalogMigrations.ts"],"names":[],"mappings":"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","sourcesContent":["import { AccessiDatabaseUpdater } from \"./AccessiDatabaseUpdater\";\nimport { applyCatalogScripts, listPendingCatalogScripts } from \"./AccessiCatalogMigrator\";\nimport { createAccessiOptionsFromEnv } from \"./accessiOptionsFromEnv\";\nimport { Orm } from \"../../Orm\";\n\nasync function main(): Promise<void> {\n const options = createAccessiOptionsFromEnv();\n if (!options.catalogScripts?.folder) {\n throw new Error(\"Variabile ambiente mancante: ACCESSI_CATALOG_FOLDER (cartella delle catalog migrations).\");\n }\n\n const checkOnly = process.argv.includes('--check');\n console.log(`[Accessi Catalog] Target: ${options.databaseOptions.host}:${options.databaseOptions.port} -> ${options.databaseOptions.database}`);\n console.log(`[Accessi Catalog] Cartella: ${options.catalogScripts.folder}`);\n\n // Prima lo schema si adegua, poi si eseguono gli script di catalogo.\n if (!checkOnly) {\n console.log('[Accessi Catalog] Riconciliazione schema...');\n await AccessiDatabaseUpdater.run(options);\n }\n\n if (checkOnly) {\n const pending = await listPendingCatalogScripts(options);\n console.log(`[Accessi Catalog] Gia applicati: ${pending.applied.length}`);\n console.log(`[Accessi Catalog] Da applicare: ${pending.pending.length}${pending.pending.length ? ` -> ${pending.pending.join(', ')}` : ''}`);\n console.log(`[Accessi Catalog] Modificati (checksum diverso): ${pending.changed.length}${pending.changed.length ? ` -> ${pending.changed.join(', ')}` : ''}`);\n console.log(`[Accessi Catalog] Non conformi (solo DML): ${pending.invalid.length}`);\n for (const entry of pending.invalid) {\n for (const violation of entry.violations) console.error(`[Accessi Catalog] Non conforme: ${entry.script} -> ${violation}`);\n }\n if (pending.invalid.length) process.exitCode = 1;\n return;\n }\n\n const report = await applyCatalogScripts(options);\n console.log(`[Accessi Catalog] Scoperti: ${report.discovered} | Applicati: ${report.applied.length} | Saltati: ${report.skipped.length} | Non conformi: ${report.invalid.length} | Falliti: ${report.failed.length}`);\n if (report.applied.length) console.log(`[Accessi Catalog] Applicati: ${report.applied.join(', ')}`);\n for (const entry of report.invalid) {\n for (const violation of entry.violations) console.error(`[Accessi Catalog] Non conforme: ${entry.script} -> ${violation}`);\n }\n if (report.failed.length) {\n for (const failure of report.failed) console.error(`[Accessi Catalog] Fallito: ${failure.script} -> ${failure.error}`);\n }\n if (report.failed.length || report.invalid.length) process.exitCode = 1;\n}\n\nmain()\n .then(() => Orm.closePools())\n .then(() => process.exit(process.exitCode ?? 0))\n .catch(async (error) => {\n console.error(\"[Accessi Catalog] Errore durante l'esecuzione:\", error);\n await Orm.closePools().catch(() => undefined);\n process.exit(1);\n });\n"]}
@@ -17,10 +17,12 @@ export { AccessiDatabaseUpdater } from "./database-updates/AccessiDatabaseUpdate
17
17
  export type { AccessiOptions, EmailOptions, JwtOptions, ExtensionFieldsOptions, PublicAuthRateLimitOptions, PublicAuthRateLimitRuleOptions } from "./AccessiModule";
18
18
  export type { PublicRegistrationOptions, FederatedAuthenticationOptions, ServiceTokenOptions } from "./AccessiModule";
19
19
  export type { CatalogScriptsOptions, CatalogScriptChecksumPolicy } from "./AccessiModule";
20
- export { AccessiCatalogMigrator, applyCatalogScripts, listPendingCatalogScripts, splitSqlStatements, computeCatalogScriptChecksum, discoverCatalogScripts } from "./database-updates/AccessiCatalogMigrator";
20
+ export { AccessiCatalogMigrator, applyCatalogScripts, listPendingCatalogScripts, splitSqlStatements, analyzeCatalogScript, leadingStatementKeyword, computeCatalogScriptChecksum, discoverCatalogScripts } from "./database-updates/AccessiCatalogMigrator";
21
21
  export type { CatalogMigrationReport, CatalogScriptMigration } from "./database-updates/AccessiCatalogMigrator";
22
22
  export { ServiceTokenService } from './Services/ServiceTokenService/ServiceTokenService';
23
23
  export type { ServiceTokenMetadata, IssuedServiceToken, VerifiedServiceToken, IssueServiceTokenInput } from './Services/ServiceTokenService/ServiceTokenService';
24
+ export { SchemaExportService } from './Services/SchemaExportService/SchemaExportService';
25
+ export type { SchemaDdlResult, SchemaDdlSection, SchemaEntitiesResult } from './Services/SchemaExportService/SchemaExportService';
24
26
  export { ServiceTokenGuard, RequireServiceTokenScopes, getAccessiServiceToken } from './security/serviceTokenGuard';
25
27
  export { assertEmailConfigured, isEmailConfigured, AccessiEmailNotConfiguredError, ACCESSI_EMAIL_NOT_CONFIGURED } from './security/emailConfiguration';
26
28
  export { FederatedAuthService } from './federated-auth/FederatedAuthService';
@@ -26,7 +26,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
26
26
  return (mod && mod.__esModule) ? mod : { "default": mod };
27
27
  };
28
28
  Object.defineProperty(exports, "__esModule", { value: true });
29
- exports.ACCESSI_MODULE_SERVICES_LOCALS_KEY = exports.getAccessiModuleServices = exports.registerAccessiModuleServices = exports.accessiRequirement = exports.authenticateGen = exports.authorizeAccessi = exports.FederatedAuthService = exports.ACCESSI_EMAIL_NOT_CONFIGURED = exports.AccessiEmailNotConfiguredError = exports.isEmailConfigured = exports.assertEmailConfigured = exports.getAccessiServiceToken = exports.RequireServiceTokenScopes = exports.ServiceTokenGuard = exports.ServiceTokenService = exports.discoverCatalogScripts = exports.computeCatalogScriptChecksum = exports.splitSqlStatements = exports.listPendingCatalogScripts = exports.applyCatalogScripts = exports.AccessiCatalogMigrator = exports.AccessiDatabaseUpdater = exports.AccessiModule = void 0;
29
+ exports.ACCESSI_MODULE_SERVICES_LOCALS_KEY = exports.getAccessiModuleServices = exports.registerAccessiModuleServices = exports.accessiRequirement = exports.authenticateGen = exports.authorizeAccessi = exports.FederatedAuthService = exports.ACCESSI_EMAIL_NOT_CONFIGURED = exports.AccessiEmailNotConfiguredError = exports.isEmailConfigured = exports.assertEmailConfigured = exports.getAccessiServiceToken = exports.RequireServiceTokenScopes = exports.ServiceTokenGuard = exports.SchemaExportService = exports.ServiceTokenService = exports.discoverCatalogScripts = exports.computeCatalogScriptChecksum = exports.leadingStatementKeyword = exports.analyzeCatalogScript = exports.splitSqlStatements = exports.listPendingCatalogScripts = exports.applyCatalogScripts = exports.AccessiCatalogMigrator = exports.AccessiDatabaseUpdater = exports.AccessiModule = void 0;
30
30
  exports.initializeAccessiModule = initializeAccessiModule;
31
31
  const express_1 = __importDefault(require("express"));
32
32
  const core_1 = require("@nestjs/core");
@@ -130,10 +130,14 @@ Object.defineProperty(exports, "AccessiCatalogMigrator", { enumerable: true, get
130
130
  Object.defineProperty(exports, "applyCatalogScripts", { enumerable: true, get: function () { return AccessiCatalogMigrator_1.applyCatalogScripts; } });
131
131
  Object.defineProperty(exports, "listPendingCatalogScripts", { enumerable: true, get: function () { return AccessiCatalogMigrator_1.listPendingCatalogScripts; } });
132
132
  Object.defineProperty(exports, "splitSqlStatements", { enumerable: true, get: function () { return AccessiCatalogMigrator_1.splitSqlStatements; } });
133
+ Object.defineProperty(exports, "analyzeCatalogScript", { enumerable: true, get: function () { return AccessiCatalogMigrator_1.analyzeCatalogScript; } });
134
+ Object.defineProperty(exports, "leadingStatementKeyword", { enumerable: true, get: function () { return AccessiCatalogMigrator_1.leadingStatementKeyword; } });
133
135
  Object.defineProperty(exports, "computeCatalogScriptChecksum", { enumerable: true, get: function () { return AccessiCatalogMigrator_1.computeCatalogScriptChecksum; } });
134
136
  Object.defineProperty(exports, "discoverCatalogScripts", { enumerable: true, get: function () { return AccessiCatalogMigrator_1.discoverCatalogScripts; } });
135
137
  var ServiceTokenService_1 = require("./Services/ServiceTokenService/ServiceTokenService");
136
138
  Object.defineProperty(exports, "ServiceTokenService", { enumerable: true, get: function () { return ServiceTokenService_1.ServiceTokenService; } });
139
+ var SchemaExportService_1 = require("./Services/SchemaExportService/SchemaExportService");
140
+ Object.defineProperty(exports, "SchemaExportService", { enumerable: true, get: function () { return SchemaExportService_1.SchemaExportService; } });
137
141
  var serviceTokenGuard_1 = require("./security/serviceTokenGuard");
138
142
  Object.defineProperty(exports, "ServiceTokenGuard", { enumerable: true, get: function () { return serviceTokenGuard_1.ServiceTokenGuard; } });
139
143
  Object.defineProperty(exports, "RequireServiceTokenScopes", { enumerable: true, get: function () { return serviceTokenGuard_1.RequireServiceTokenScopes; } });