emilsoftware-utilities 2.0.0-dev.36 → 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 (41) hide show
  1. package/dist/accessi-module/AccessiModule.js +9 -4
  2. package/dist/accessi-module/AccessiModule.js.map +1 -1
  3. package/dist/accessi-module/Console/console.css +7 -0
  4. package/dist/accessi-module/Console/console.js +54 -3
  5. package/dist/accessi-module/Console/console.js.map +1 -1
  6. package/dist/accessi-module/Console/generated/accessiApi.d.ts +11 -1
  7. package/dist/accessi-module/Console/generated/accessiApi.js +9 -1
  8. package/dist/accessi-module/Console/generated/accessiApi.js.map +1 -1
  9. package/dist/accessi-module/Console/generated/model/getSchemaResponse.d.ts +14 -0
  10. package/dist/accessi-module/Console/generated/model/getSchemaResponse.js +3 -0
  11. package/dist/accessi-module/Console/generated/model/getSchemaResponse.js.map +1 -0
  12. package/dist/accessi-module/Console/generated/model/index.d.ts +3 -0
  13. package/dist/accessi-module/Console/generated/model/index.js +3 -0
  14. package/dist/accessi-module/Console/generated/model/index.js.map +1 -1
  15. package/dist/accessi-module/Console/generated/model/schemaDdlResult.d.ts +20 -0
  16. package/dist/accessi-module/Console/generated/model/schemaDdlResult.js +3 -0
  17. package/dist/accessi-module/Console/generated/model/schemaDdlResult.js.map +1 -0
  18. package/dist/accessi-module/Console/generated/model/schemaDdlSection.d.ts +12 -0
  19. package/dist/accessi-module/Console/generated/model/schemaDdlSection.js +9 -0
  20. package/dist/accessi-module/Console/generated/model/schemaDdlSection.js.map +1 -0
  21. package/dist/accessi-module/Console/index.html +6 -0
  22. package/dist/accessi-module/Console/wiki.js +2 -0
  23. package/dist/accessi-module/Console/wiki.js.map +1 -1
  24. package/dist/accessi-module/Controllers/SchemaController.d.ts +9 -0
  25. package/dist/accessi-module/Controllers/SchemaController.js +79 -0
  26. package/dist/accessi-module/Controllers/SchemaController.js.map +1 -0
  27. package/dist/accessi-module/Dtos/SchemaDtos.d.ts +19 -0
  28. package/dist/accessi-module/Dtos/SchemaDtos.js +84 -0
  29. package/dist/accessi-module/Dtos/SchemaDtos.js.map +1 -0
  30. package/dist/accessi-module/Dtos/index.d.ts +1 -0
  31. package/dist/accessi-module/Dtos/index.js +1 -0
  32. package/dist/accessi-module/Dtos/index.js.map +1 -1
  33. package/dist/accessi-module/Services/SchemaExportService/SchemaExportService.d.ts +36 -0
  34. package/dist/accessi-module/Services/SchemaExportService/SchemaExportService.js +125 -0
  35. package/dist/accessi-module/Services/SchemaExportService/SchemaExportService.js.map +1 -0
  36. package/dist/accessi-module/index.d.ts +2 -0
  37. package/dist/accessi-module/index.js +3 -1
  38. package/dist/accessi-module/index.js.map +1 -1
  39. package/dist/emilsoftware-utilities-2.0.0-dev.37.tgz +0 -0
  40. package/package.json +1 -1
  41. package/dist/emilsoftware-utilities-2.0.0-dev.36.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":"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","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"]}
@@ -21,6 +21,8 @@ export { AccessiCatalogMigrator, applyCatalogScripts, listPendingCatalogScripts,
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.leadingStatementKeyword = exports.analyzeCatalogScript = 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");
@@ -136,6 +136,8 @@ Object.defineProperty(exports, "computeCatalogScriptChecksum", { enumerable: tru
136
136
  Object.defineProperty(exports, "discoverCatalogScripts", { enumerable: true, get: function () { return AccessiCatalogMigrator_1.discoverCatalogScripts; } });
137
137
  var ServiceTokenService_1 = require("./Services/ServiceTokenService/ServiceTokenService");
138
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; } });
139
141
  var serviceTokenGuard_1 = require("./security/serviceTokenGuard");
140
142
  Object.defineProperty(exports, "ServiceTokenGuard", { enumerable: true, get: function () { return serviceTokenGuard_1.ServiceTokenGuard; } });
141
143
  Object.defineProperty(exports, "RequireServiceTokenScopes", { enumerable: true, get: function () { return serviceTokenGuard_1.RequireServiceTokenScopes; } });
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/accessi-module/index.ts"],"names":[],"mappings":"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","sourcesContent":["import express, { Application, Request } from \"express\";\nimport { NestFactory } from \"@nestjs/core\";\nimport { ExpressAdapter } from \"@nestjs/platform-express\";\nimport { AccessiModule, AccessiOptions } from \"./AccessiModule\";\nimport { Logger } from \"../Logger\";\nimport { AuthService } from \"./Services/AuthService/AuthService\";\nimport { setupSwagger } from \"../swagger/SwaggerConfig\";\nimport {\n beginAccessiAuthInitialization,\n failAccessiAuthInitialization,\n setAccessiAuthService\n} from \"./middleware/authenticateGen\";\nimport { registerAccessiModuleServices } from \"./accessiRuntime\";\nimport { createAccessiValidationPipe } from './security/accessiValidation';\nimport { AccessiHttpExceptionFilter } from './security/AccessiHttpExceptionFilter';\nimport { assertEmailConfigured } from './security/emailConfiguration';\n\nfunction describeDatabaseTarget(options: AccessiOptions): string {\n const dbOptions = options.databaseOptions as {\n host?: string;\n port?: number;\n database?: string;\n user?: string;\n };\n\n return `${dbOptions.host ?? \"?\"}:${dbOptions.port ?? \"?\"} -> ${dbOptions.database ?? \"?\"} as ${dbOptions.user ?? \"?\"}`;\n}\n\n/**\n * Monta il modulo Accessi in un'applicazione Express gia esistente.\n *\n * Il bootstrap crea un host Nest isolato per le rotte `/api/accessi`, inizializza Swagger,\n * validazione ed error handler, quindi rende disponibile `authorizeAccessi` al resto dell'app.\n * Attendere questa Promise prima di aprire la porta HTTP: durante il bootstrap il middleware\n * restituisce `ACCESSI_AUTH_INITIALIZING` invece di autorizzare richieste parzialmente inizializzate.\n *\n * @param app Applicazione Express ospitante. Non viene sostituita ne vengono intercettate rotte estranee ad Accessi.\n * @param options Configurazione riservata del modulo; proviene normalmente da variabili d'ambiente o secret manager.\n */\nexport async function initializeAccessiModule(app: Application, options: AccessiOptions): Promise<void> {\n // Il servizio email e obbligatorio: reset password, 2FA e creazione utente ne dipendono.\n assertEmailConfigured(options);\n const logger: Logger = new Logger(\"initializeAccessiModule\");\n beginAccessiAuthInitialization();\n const startedAt = performance.now();\n\n try {\n logger.info(\"Inizializzazione modulo accessi avviata.\");\n logger.info(`Target database accessi: ${describeDatabaseTarget(options)}`);\n logger.info(\n `Configurazione accessi: autoUpdateDatabase=${options.autoUpdateDatabase !== false}, legacyPasswordMigrationOnStartup=${options.legacyPasswordMigrationOnStartup !== false}`\n );\n const nestHostApp = express();\n const isNestRoute = (path: string) =>\n path === \"/api/accessi\" ||\n path.startsWith(\"/api/accessi/\") ||\n path === \"/accessi/swagger\" ||\n path.startsWith(\"/accessi/swagger/\") ||\n path === \"/accessi/swagger.json\" ||\n path === \"/accessi/swagger-json\";\n\n app.use((req: Request, res, next) => {\n if (!isNestRoute(req.path)) {\n return next();\n }\n\n return nestHostApp(req, res, next);\n });\n\n const nestExpressInstance = new ExpressAdapter(nestHostApp);\n\n const nestApp = await NestFactory.create(AccessiModule.forRoot(options), nestExpressInstance, {\n bufferLogs: true\n });\n logger.info(\"Applicazione Nest accessi creata.\");\n\n nestApp.enableCors({ exposedHeaders: ['X-Total-Count'] });\n nestApp.useGlobalPipes(createAccessiValidationPipe());\n nestApp.useGlobalFilters(new AccessiHttpExceptionFilter());\n\n nestApp.setGlobalPrefix('api', {\n exclude: ['/swagger', '/swagger/(.*)']\n });\n\n setupSwagger(nestApp, {\n swaggerPath: \"accessi/swagger\",\n swaggerJsonPath: \"accessi/swagger.json\",\n title: \"Accessi API Documentation\",\n description: \"API del modulo accessi\",\n });\n logger.info(\"Avvio init del modulo accessi.\");\n await nestApp.init();\n logger.info(\"Init del modulo accessi completata.\");\n if (options.legacyPasswordMigrationOnStartup !== false) {\n logger.info(\"Avvio migrazione password legacy accessi.\");\n const passwordMigrationService = nestApp.get(AuthService);\n await passwordMigrationService.migrateLegacyEncryptedPasswords();\n logger.info(\"Migrazione password legacy accessi completata.\");\n }\n\n const accessiServices = registerAccessiModuleServices(app, nestApp);\n app.locals.accessiAuthService = accessiServices.authenticateGenService;\n setAccessiAuthService(accessiServices.authenticateGenService);\n const elapsedMs = performance.now() - startedAt;\n logger.info(`Accessi initialized. Tempo totale bootstrap: ${elapsedMs.toFixed(2)} ms`);\n\n } catch (error) {\n failAccessiAuthInitialization(error);\n logger.error(\n \"Errore in initialize AccessiModule:\",\n error instanceof Error\n ? { name: error.name, message: error.message, stack: error.stack }\n : { error: String(error) }\n );\n throw error;\n }\n}\n\nexport { AccessiModule } from \"./AccessiModule\";\nexport { AccessiDatabaseUpdater } from \"./database-updates/AccessiDatabaseUpdater\";\nexport type { AccessiOptions, EmailOptions, JwtOptions, ExtensionFieldsOptions, PublicAuthRateLimitOptions, PublicAuthRateLimitRuleOptions } from \"./AccessiModule\";\nexport type { PublicRegistrationOptions, FederatedAuthenticationOptions, ServiceTokenOptions } from \"./AccessiModule\";\nexport type { CatalogScriptsOptions, CatalogScriptChecksumPolicy } from \"./AccessiModule\";\nexport {\n AccessiCatalogMigrator,\n applyCatalogScripts,\n listPendingCatalogScripts,\n splitSqlStatements,\n analyzeCatalogScript,\n leadingStatementKeyword,\n computeCatalogScriptChecksum,\n discoverCatalogScripts\n} from \"./database-updates/AccessiCatalogMigrator\";\nexport type { CatalogMigrationReport, CatalogScriptMigration } from \"./database-updates/AccessiCatalogMigrator\";\nexport { ServiceTokenService } from './Services/ServiceTokenService/ServiceTokenService';\nexport type {\n ServiceTokenMetadata,\n IssuedServiceToken,\n VerifiedServiceToken,\n IssueServiceTokenInput\n} from './Services/ServiceTokenService/ServiceTokenService';\nexport { ServiceTokenGuard, RequireServiceTokenScopes, getAccessiServiceToken } from './security/serviceTokenGuard';\nexport { assertEmailConfigured, isEmailConfigured, AccessiEmailNotConfiguredError, ACCESSI_EMAIL_NOT_CONFIGURED } from './security/emailConfiguration';\nexport { FederatedAuthService } from './federated-auth/FederatedAuthService';\nexport type { FederatedAuthenticationResult, FederatedIdentity, FederatedProvider, VerifiedFederatedIdentity } from './federated-auth/FederatedAuthTypes';\nexport * from \"./Dtos\";\nexport {\n authorizeAccessi,\n authenticateGen\n} from \"./middleware/authenticateGen\";\nexport { accessiRequirement } from \"./middleware/accessiRequirements\";\nexport {\n registerAccessiModuleServices,\n getAccessiModuleServices,\n ACCESSI_MODULE_SERVICES_LOCALS_KEY\n} from \"./accessiRuntime\";\nexport type { AccessiModuleServices } from \"./accessiRuntime\";\nexport type {\n AccessiAuthorizationOptions,\n AccessiRequirementNode,\n AccessiCustomRequirementContext,\n AccessiCustomRequirementHandler\n} from \"./middleware/accessiRequirements\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/accessi-module/index.ts"],"names":[],"mappings":"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","sourcesContent":["import express, { Application, Request } from \"express\";\nimport { NestFactory } from \"@nestjs/core\";\nimport { ExpressAdapter } from \"@nestjs/platform-express\";\nimport { AccessiModule, AccessiOptions } from \"./AccessiModule\";\nimport { Logger } from \"../Logger\";\nimport { AuthService } from \"./Services/AuthService/AuthService\";\nimport { setupSwagger } from \"../swagger/SwaggerConfig\";\nimport {\n beginAccessiAuthInitialization,\n failAccessiAuthInitialization,\n setAccessiAuthService\n} from \"./middleware/authenticateGen\";\nimport { registerAccessiModuleServices } from \"./accessiRuntime\";\nimport { createAccessiValidationPipe } from './security/accessiValidation';\nimport { AccessiHttpExceptionFilter } from './security/AccessiHttpExceptionFilter';\nimport { assertEmailConfigured } from './security/emailConfiguration';\n\nfunction describeDatabaseTarget(options: AccessiOptions): string {\n const dbOptions = options.databaseOptions as {\n host?: string;\n port?: number;\n database?: string;\n user?: string;\n };\n\n return `${dbOptions.host ?? \"?\"}:${dbOptions.port ?? \"?\"} -> ${dbOptions.database ?? \"?\"} as ${dbOptions.user ?? \"?\"}`;\n}\n\n/**\n * Monta il modulo Accessi in un'applicazione Express gia esistente.\n *\n * Il bootstrap crea un host Nest isolato per le rotte `/api/accessi`, inizializza Swagger,\n * validazione ed error handler, quindi rende disponibile `authorizeAccessi` al resto dell'app.\n * Attendere questa Promise prima di aprire la porta HTTP: durante il bootstrap il middleware\n * restituisce `ACCESSI_AUTH_INITIALIZING` invece di autorizzare richieste parzialmente inizializzate.\n *\n * @param app Applicazione Express ospitante. Non viene sostituita ne vengono intercettate rotte estranee ad Accessi.\n * @param options Configurazione riservata del modulo; proviene normalmente da variabili d'ambiente o secret manager.\n */\nexport async function initializeAccessiModule(app: Application, options: AccessiOptions): Promise<void> {\n // Il servizio email e obbligatorio: reset password, 2FA e creazione utente ne dipendono.\n assertEmailConfigured(options);\n const logger: Logger = new Logger(\"initializeAccessiModule\");\n beginAccessiAuthInitialization();\n const startedAt = performance.now();\n\n try {\n logger.info(\"Inizializzazione modulo accessi avviata.\");\n logger.info(`Target database accessi: ${describeDatabaseTarget(options)}`);\n logger.info(\n `Configurazione accessi: autoUpdateDatabase=${options.autoUpdateDatabase !== false}, legacyPasswordMigrationOnStartup=${options.legacyPasswordMigrationOnStartup !== false}`\n );\n const nestHostApp = express();\n const isNestRoute = (path: string) =>\n path === \"/api/accessi\" ||\n path.startsWith(\"/api/accessi/\") ||\n path === \"/accessi/swagger\" ||\n path.startsWith(\"/accessi/swagger/\") ||\n path === \"/accessi/swagger.json\" ||\n path === \"/accessi/swagger-json\";\n\n app.use((req: Request, res, next) => {\n if (!isNestRoute(req.path)) {\n return next();\n }\n\n return nestHostApp(req, res, next);\n });\n\n const nestExpressInstance = new ExpressAdapter(nestHostApp);\n\n const nestApp = await NestFactory.create(AccessiModule.forRoot(options), nestExpressInstance, {\n bufferLogs: true\n });\n logger.info(\"Applicazione Nest accessi creata.\");\n\n nestApp.enableCors({ exposedHeaders: ['X-Total-Count'] });\n nestApp.useGlobalPipes(createAccessiValidationPipe());\n nestApp.useGlobalFilters(new AccessiHttpExceptionFilter());\n\n nestApp.setGlobalPrefix('api', {\n exclude: ['/swagger', '/swagger/(.*)']\n });\n\n setupSwagger(nestApp, {\n swaggerPath: \"accessi/swagger\",\n swaggerJsonPath: \"accessi/swagger.json\",\n title: \"Accessi API Documentation\",\n description: \"API del modulo accessi\",\n });\n logger.info(\"Avvio init del modulo accessi.\");\n await nestApp.init();\n logger.info(\"Init del modulo accessi completata.\");\n if (options.legacyPasswordMigrationOnStartup !== false) {\n logger.info(\"Avvio migrazione password legacy accessi.\");\n const passwordMigrationService = nestApp.get(AuthService);\n await passwordMigrationService.migrateLegacyEncryptedPasswords();\n logger.info(\"Migrazione password legacy accessi completata.\");\n }\n\n const accessiServices = registerAccessiModuleServices(app, nestApp);\n app.locals.accessiAuthService = accessiServices.authenticateGenService;\n setAccessiAuthService(accessiServices.authenticateGenService);\n const elapsedMs = performance.now() - startedAt;\n logger.info(`Accessi initialized. Tempo totale bootstrap: ${elapsedMs.toFixed(2)} ms`);\n\n } catch (error) {\n failAccessiAuthInitialization(error);\n logger.error(\n \"Errore in initialize AccessiModule:\",\n error instanceof Error\n ? { name: error.name, message: error.message, stack: error.stack }\n : { error: String(error) }\n );\n throw error;\n }\n}\n\nexport { AccessiModule } from \"./AccessiModule\";\nexport { AccessiDatabaseUpdater } from \"./database-updates/AccessiDatabaseUpdater\";\nexport type { AccessiOptions, EmailOptions, JwtOptions, ExtensionFieldsOptions, PublicAuthRateLimitOptions, PublicAuthRateLimitRuleOptions } from \"./AccessiModule\";\nexport type { PublicRegistrationOptions, FederatedAuthenticationOptions, ServiceTokenOptions } from \"./AccessiModule\";\nexport type { CatalogScriptsOptions, CatalogScriptChecksumPolicy } from \"./AccessiModule\";\nexport {\n AccessiCatalogMigrator,\n applyCatalogScripts,\n listPendingCatalogScripts,\n splitSqlStatements,\n analyzeCatalogScript,\n leadingStatementKeyword,\n computeCatalogScriptChecksum,\n discoverCatalogScripts\n} from \"./database-updates/AccessiCatalogMigrator\";\nexport type { CatalogMigrationReport, CatalogScriptMigration } from \"./database-updates/AccessiCatalogMigrator\";\nexport { ServiceTokenService } from './Services/ServiceTokenService/ServiceTokenService';\nexport type {\n ServiceTokenMetadata,\n IssuedServiceToken,\n VerifiedServiceToken,\n IssueServiceTokenInput\n} from './Services/ServiceTokenService/ServiceTokenService';\nexport { SchemaExportService } from './Services/SchemaExportService/SchemaExportService';\nexport type { SchemaDdlResult, SchemaDdlSection, SchemaEntitiesResult } from './Services/SchemaExportService/SchemaExportService';\nexport { ServiceTokenGuard, RequireServiceTokenScopes, getAccessiServiceToken } from './security/serviceTokenGuard';\nexport { assertEmailConfigured, isEmailConfigured, AccessiEmailNotConfiguredError, ACCESSI_EMAIL_NOT_CONFIGURED } from './security/emailConfiguration';\nexport { FederatedAuthService } from './federated-auth/FederatedAuthService';\nexport type { FederatedAuthenticationResult, FederatedIdentity, FederatedProvider, VerifiedFederatedIdentity } from './federated-auth/FederatedAuthTypes';\nexport * from \"./Dtos\";\nexport {\n authorizeAccessi,\n authenticateGen\n} from \"./middleware/authenticateGen\";\nexport { accessiRequirement } from \"./middleware/accessiRequirements\";\nexport {\n registerAccessiModuleServices,\n getAccessiModuleServices,\n ACCESSI_MODULE_SERVICES_LOCALS_KEY\n} from \"./accessiRuntime\";\nexport type { AccessiModuleServices } from \"./accessiRuntime\";\nexport type {\n AccessiAuthorizationOptions,\n AccessiRequirementNode,\n AccessiCustomRequirementContext,\n AccessiCustomRequirementHandler\n} from \"./middleware/accessiRequirements\";\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "emilsoftware-utilities",
3
- "version": "2.0.0-dev.36",
3
+ "version": "2.0.0-dev.37",
4
4
  "description": "Utilities for EmilSoftware",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.js",