@devopsplaybook.io/common-utils 1.1.0-beta.6.9ec503a → 1.2.0-beta.7.3382b46
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +11 -11
- package/dist/src/ConfigBase.d.ts +13 -0
- package/dist/src/ConfigBase.js +32 -11
- package/dist/src/PostgresDbUtils.d.ts +2 -1
- package/dist/src/PostgresDbUtils.js +7 -1
- package/package.json +1 -1
- package/src/ConfigBase.ts +51 -11
- package/src/PostgresDbUtils.ts +14 -19
package/README.md
CHANGED
|
@@ -206,17 +206,17 @@ await AuthDb.transaction(span, async (client) => {
|
|
|
206
206
|
await AuthDb.closeAll();
|
|
207
207
|
```
|
|
208
208
|
|
|
209
|
-
| Method
|
|
210
|
-
|
|
|
211
|
-
| `new PostgresSchemaDbUtils(schemaName)`
|
|
212
|
-
| `initOTel(tracer, logger)`
|
|
213
|
-
| `initSchema(context, config, sqlDir)`
|
|
214
|
-
| `initRuntimePool(config)`
|
|
215
|
-
| `execSQL(context, sql, params?, useSchemaPool?)`
|
|
216
|
-
| `execSQLFile(context, filename, useSchemaPool?)`
|
|
217
|
-
| `querySQL(context, sql, params?, useSchemaPool?)`
|
|
218
|
-
| `transaction(context, callback, useSchemaPool?)`
|
|
219
|
-
| `closeAll()`
|
|
209
|
+
| Method | Description |
|
|
210
|
+
| ------------------------------------------------- | --------------------------------------------------- |
|
|
211
|
+
| `new PostgresSchemaDbUtils(schemaName)` | Create instance for a specific schema |
|
|
212
|
+
| `initOTel(tracer, logger)` | Inject OTel instances (shared across all instances) |
|
|
213
|
+
| `initSchema(context, config, sqlDir)` | Create schema pool and run migrations |
|
|
214
|
+
| `initRuntimePool(config)` | Create shared runtime pool |
|
|
215
|
+
| `execSQL(context, sql, params?, useSchemaPool?)` | Execute write, returns `Promise<number>` |
|
|
216
|
+
| `execSQLFile(context, filename, useSchemaPool?)` | Execute an entire SQL file |
|
|
217
|
+
| `querySQL(context, sql, params?, useSchemaPool?)` | Execute read, returns `Promise<any[]>` |
|
|
218
|
+
| `transaction(context, callback, useSchemaPool?)` | Run callback inside a transaction |
|
|
219
|
+
| `closeAll()` | Close all pools managed by this instance |
|
|
220
220
|
|
|
221
221
|
`useSchemaPool` (default `true`) selects between the schema-specific pool (migrations) and the shared runtime pool (application queries).
|
|
222
222
|
|
package/dist/src/ConfigBase.d.ts
CHANGED
|
@@ -7,6 +7,19 @@ export interface ConfigFieldDef {
|
|
|
7
7
|
field: string;
|
|
8
8
|
/** When `true` the value is masked in log output. */
|
|
9
9
|
sensitive?: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* Alternative environment variable names to check when the primary field
|
|
12
|
+
* name is not found in `process.env`. Aliases are tried in order and the
|
|
13
|
+
* first match wins. Only checked in the environment layer, never in the
|
|
14
|
+
* config-file layer.
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* ```ts
|
|
18
|
+
* // Look for DATABASE_POSTGRES_HOST first, then fall back to POSTGRES_HOST
|
|
19
|
+
* { field: "DATABASE_POSTGRES_HOST", envAliases: ["POSTGRES_HOST"] }
|
|
20
|
+
* ```
|
|
21
|
+
*/
|
|
22
|
+
envAliases?: string[];
|
|
10
23
|
}
|
|
11
24
|
/**
|
|
12
25
|
* Database-specific configuration fields shared by every project that
|
package/dist/src/ConfigBase.js
CHANGED
|
@@ -117,11 +117,11 @@ class ConfigBase {
|
|
|
117
117
|
{ field: "JWT_KEY", sensitive: true },
|
|
118
118
|
{ field: "LOG_LEVEL" },
|
|
119
119
|
{ field: "DATABASE_TYPE" },
|
|
120
|
-
{ field: "DATABASE_POSTGRES_HOST" },
|
|
121
|
-
{ field: "DATABASE_POSTGRES_PORT" },
|
|
122
|
-
{ field: "DATABASE_POSTGRES_USER" },
|
|
123
|
-
{ field: "DATABASE_POSTGRES_PASSWORD", sensitive: true },
|
|
124
|
-
{ field: "DATABASE_POSTGRES_DATABASE" },
|
|
120
|
+
{ field: "DATABASE_POSTGRES_HOST", envAliases: ["POSTGRES_HOST"] },
|
|
121
|
+
{ field: "DATABASE_POSTGRES_PORT", envAliases: ["POSTGRES_PORT"] },
|
|
122
|
+
{ field: "DATABASE_POSTGRES_USER", envAliases: ["POSTGRES_USER"] },
|
|
123
|
+
{ field: "DATABASE_POSTGRES_PASSWORD", sensitive: true, envAliases: ["POSTGRES_PASSWORD"] },
|
|
124
|
+
{ field: "DATABASE_POSTGRES_DATABASE", envAliases: ["POSTGRES_DB"] },
|
|
125
125
|
{ field: "OPENTELEMETRY_COLLECTOR_HTTP_TRACES" },
|
|
126
126
|
{ field: "OPENTELEMETRY_COLLECTOR_HTTP_METRICS" },
|
|
127
127
|
{ field: "OPENTELEMETRY_COLLECTOR_HTTP_LOGS" },
|
|
@@ -146,10 +146,11 @@ class ConfigBase {
|
|
|
146
146
|
* Call this in your subclass constructor for every project-specific field.
|
|
147
147
|
*/
|
|
148
148
|
addConfigField(def) {
|
|
149
|
-
var _a;
|
|
149
|
+
var _a, _b;
|
|
150
150
|
this._fields.push({
|
|
151
151
|
field: def.field,
|
|
152
152
|
sensitive: (_a = def.sensitive) !== null && _a !== void 0 ? _a : false,
|
|
153
|
+
envAliases: (_b = def.envAliases) !== null && _b !== void 0 ? _b : [],
|
|
153
154
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
154
155
|
defaultValue: this[def.field],
|
|
155
156
|
});
|
|
@@ -175,14 +176,34 @@ class ConfigBase {
|
|
|
175
176
|
log(`Configuration Value: CONFIG_FILE: ${this.CONFIG_FILE}`);
|
|
176
177
|
log(`Configuration Value: SERVICE_ID: ${this.SERVICE_ID}`);
|
|
177
178
|
log(`Configuration Value: VERSION: ${this.VERSION}`);
|
|
178
|
-
for (const { field, sensitive } of this._fields) {
|
|
179
|
+
for (const { field, sensitive, envAliases } of this._fields) {
|
|
179
180
|
let from = "defaults";
|
|
181
|
+
let foundValue;
|
|
182
|
+
let usedAlias = false;
|
|
183
|
+
// 1. Primary environment variable name
|
|
180
184
|
if (process.env[field] !== undefined) {
|
|
181
|
-
|
|
182
|
-
this[field] = process.env[field];
|
|
185
|
+
foundValue = process.env[field];
|
|
183
186
|
from = "environment";
|
|
184
187
|
}
|
|
185
|
-
|
|
188
|
+
// 2. Check aliases if primary env var was not set
|
|
189
|
+
if (foundValue === undefined && envAliases.length > 0) {
|
|
190
|
+
for (const alias of envAliases) {
|
|
191
|
+
if (process.env[alias] !== undefined) {
|
|
192
|
+
foundValue = process.env[alias];
|
|
193
|
+
from = "environment";
|
|
194
|
+
usedAlias = true;
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// 3. Apply environment value (full name or alias) if found
|
|
200
|
+
if (foundValue !== undefined) {
|
|
201
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
202
|
+
this[field] = foundValue;
|
|
203
|
+
}
|
|
204
|
+
// 4. Config file override (environment always wins, but if neither
|
|
205
|
+
// environment nor alias matched, check config file)
|
|
206
|
+
if (foundValue === undefined && content[field] !== undefined) {
|
|
186
207
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
187
208
|
this[field] = content[field];
|
|
188
209
|
from = "config";
|
|
@@ -193,7 +214,7 @@ class ConfigBase {
|
|
|
193
214
|
else {
|
|
194
215
|
log(
|
|
195
216
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
196
|
-
`Configuration Value: ${field}: ${this[field]} (from ${from})`);
|
|
217
|
+
`Configuration Value: ${field}: ${this[field]} (from ${from}${usedAlias ? ` via alias` : ""})`);
|
|
197
218
|
}
|
|
198
219
|
}
|
|
199
220
|
}
|
|
@@ -24,8 +24,9 @@ export declare class PostgresSchemaDbUtils {
|
|
|
24
24
|
private schemaPool;
|
|
25
25
|
private runtimePool;
|
|
26
26
|
private readonly schemaName;
|
|
27
|
-
private
|
|
27
|
+
private _moduleLogger;
|
|
28
28
|
constructor(schemaName: string);
|
|
29
|
+
private get moduleLogger();
|
|
29
30
|
/**
|
|
30
31
|
* Create the schema-specific pool, ensure the schema exists, and apply
|
|
31
32
|
* any pending migration files from `sqlDir`.
|
|
@@ -68,8 +68,14 @@ class PostgresSchemaDbUtils {
|
|
|
68
68
|
constructor(schemaName) {
|
|
69
69
|
this.schemaPool = null;
|
|
70
70
|
this.runtimePool = null;
|
|
71
|
+
this._moduleLogger = null;
|
|
71
72
|
this.schemaName = schemaName;
|
|
72
|
-
|
|
73
|
+
}
|
|
74
|
+
get moduleLogger() {
|
|
75
|
+
if (!this._moduleLogger) {
|
|
76
|
+
this._moduleLogger = standardLogger.createModuleLogger(`PostgresSchemaDbUtils[${this.schemaName}]`);
|
|
77
|
+
}
|
|
78
|
+
return this._moduleLogger;
|
|
73
79
|
}
|
|
74
80
|
/**
|
|
75
81
|
* Create the schema-specific pool, ensure the schema exists, and apply
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@devopsplaybook.io/common-utils",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.2.0-beta.7.3382b46",
|
|
4
4
|
"description": "Shared utility modules for devopsplaybook.io projects (DB, Config, OTel context, system helpers)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"Open Telemetry",
|
package/src/ConfigBase.ts
CHANGED
|
@@ -11,6 +11,19 @@ export interface ConfigFieldDef {
|
|
|
11
11
|
field: string;
|
|
12
12
|
/** When `true` the value is masked in log output. */
|
|
13
13
|
sensitive?: boolean;
|
|
14
|
+
/**
|
|
15
|
+
* Alternative environment variable names to check when the primary field
|
|
16
|
+
* name is not found in `process.env`. Aliases are tried in order and the
|
|
17
|
+
* first match wins. Only checked in the environment layer, never in the
|
|
18
|
+
* config-file layer.
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* ```ts
|
|
22
|
+
* // Look for DATABASE_POSTGRES_HOST first, then fall back to POSTGRES_HOST
|
|
23
|
+
* { field: "DATABASE_POSTGRES_HOST", envAliases: ["POSTGRES_HOST"] }
|
|
24
|
+
* ```
|
|
25
|
+
*/
|
|
26
|
+
envAliases?: string[];
|
|
14
27
|
}
|
|
15
28
|
|
|
16
29
|
/**
|
|
@@ -97,7 +110,7 @@ export abstract class ConfigBase implements ConfigCommonInterface {
|
|
|
97
110
|
* should process. Common / DB / OTel fields are pre-registered.
|
|
98
111
|
*/
|
|
99
112
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
100
|
-
private _fields: { field: string; sensitive: boolean; defaultValue: any }[] =
|
|
113
|
+
private _fields: { field: string; sensitive: boolean; envAliases: string[]; defaultValue: any }[] =
|
|
101
114
|
[];
|
|
102
115
|
|
|
103
116
|
/**
|
|
@@ -127,11 +140,11 @@ export abstract class ConfigBase implements ConfigCommonInterface {
|
|
|
127
140
|
{ field: "JWT_KEY", sensitive: true },
|
|
128
141
|
{ field: "LOG_LEVEL" },
|
|
129
142
|
{ field: "DATABASE_TYPE" },
|
|
130
|
-
{ field: "DATABASE_POSTGRES_HOST" },
|
|
131
|
-
{ field: "DATABASE_POSTGRES_PORT" },
|
|
132
|
-
{ field: "DATABASE_POSTGRES_USER" },
|
|
133
|
-
{ field: "DATABASE_POSTGRES_PASSWORD", sensitive: true },
|
|
134
|
-
{ field: "DATABASE_POSTGRES_DATABASE" },
|
|
143
|
+
{ field: "DATABASE_POSTGRES_HOST", envAliases: ["POSTGRES_HOST"] },
|
|
144
|
+
{ field: "DATABASE_POSTGRES_PORT", envAliases: ["POSTGRES_PORT"] },
|
|
145
|
+
{ field: "DATABASE_POSTGRES_USER", envAliases: ["POSTGRES_USER"] },
|
|
146
|
+
{ field: "DATABASE_POSTGRES_PASSWORD", sensitive: true, envAliases: ["POSTGRES_PASSWORD"] },
|
|
147
|
+
{ field: "DATABASE_POSTGRES_DATABASE", envAliases: ["POSTGRES_DB"] },
|
|
135
148
|
{ field: "OPENTELEMETRY_COLLECTOR_HTTP_TRACES" },
|
|
136
149
|
{ field: "OPENTELEMETRY_COLLECTOR_HTTP_METRICS" },
|
|
137
150
|
{ field: "OPENTELEMETRY_COLLECTOR_HTTP_LOGS" },
|
|
@@ -160,6 +173,7 @@ export abstract class ConfigBase implements ConfigCommonInterface {
|
|
|
160
173
|
this._fields.push({
|
|
161
174
|
field: def.field,
|
|
162
175
|
sensitive: def.sensitive ?? false,
|
|
176
|
+
envAliases: def.envAliases ?? [],
|
|
163
177
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
164
178
|
defaultValue: (this as any)[def.field],
|
|
165
179
|
});
|
|
@@ -187,17 +201,43 @@ export abstract class ConfigBase implements ConfigCommonInterface {
|
|
|
187
201
|
log(`Configuration Value: SERVICE_ID: ${this.SERVICE_ID}`);
|
|
188
202
|
log(`Configuration Value: VERSION: ${this.VERSION}`);
|
|
189
203
|
|
|
190
|
-
for (const { field, sensitive } of this._fields) {
|
|
204
|
+
for (const { field, sensitive, envAliases } of this._fields) {
|
|
191
205
|
let from = "defaults";
|
|
206
|
+
let foundValue: string | undefined;
|
|
207
|
+
let usedAlias = false;
|
|
208
|
+
|
|
209
|
+
// 1. Primary environment variable name
|
|
192
210
|
if (process.env[field] !== undefined) {
|
|
193
|
-
|
|
194
|
-
(this as any)[field] = process.env[field];
|
|
211
|
+
foundValue = process.env[field];
|
|
195
212
|
from = "environment";
|
|
196
|
-
}
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// 2. Check aliases if primary env var was not set
|
|
216
|
+
if (foundValue === undefined && envAliases.length > 0) {
|
|
217
|
+
for (const alias of envAliases) {
|
|
218
|
+
if (process.env[alias] !== undefined) {
|
|
219
|
+
foundValue = process.env[alias];
|
|
220
|
+
from = "environment";
|
|
221
|
+
usedAlias = true;
|
|
222
|
+
break;
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// 3. Apply environment value (full name or alias) if found
|
|
228
|
+
if (foundValue !== undefined) {
|
|
229
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
230
|
+
(this as any)[field] = foundValue;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// 4. Config file override (environment always wins, but if neither
|
|
234
|
+
// environment nor alias matched, check config file)
|
|
235
|
+
if (foundValue === undefined && content[field] !== undefined) {
|
|
197
236
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
198
237
|
(this as any)[field] = content[field];
|
|
199
238
|
from = "config";
|
|
200
239
|
}
|
|
240
|
+
|
|
201
241
|
if (sensitive) {
|
|
202
242
|
log(
|
|
203
243
|
`Configuration Value: ${field}: ******************** (from ${from})`,
|
|
@@ -205,7 +245,7 @@ export abstract class ConfigBase implements ConfigCommonInterface {
|
|
|
205
245
|
} else {
|
|
206
246
|
log(
|
|
207
247
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
208
|
-
`Configuration Value: ${field}: ${(this as any)[field]} (from ${from})`,
|
|
248
|
+
`Configuration Value: ${field}: ${(this as any)[field]} (from ${from}${usedAlias ? ` via alias` : ""})`,
|
|
209
249
|
);
|
|
210
250
|
}
|
|
211
251
|
}
|
package/src/PostgresDbUtils.ts
CHANGED
|
@@ -45,13 +45,19 @@ export class PostgresSchemaDbUtils {
|
|
|
45
45
|
private schemaPool: Pool | null = null;
|
|
46
46
|
private runtimePool: Pool | null = null;
|
|
47
47
|
private readonly schemaName: string;
|
|
48
|
-
private
|
|
48
|
+
private _moduleLogger: ModuleLogger | null = null;
|
|
49
49
|
|
|
50
50
|
constructor(schemaName: string) {
|
|
51
51
|
this.schemaName = schemaName;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
private get moduleLogger(): ModuleLogger {
|
|
55
|
+
if (!this._moduleLogger) {
|
|
56
|
+
this._moduleLogger = standardLogger.createModuleLogger(
|
|
57
|
+
`PostgresSchemaDbUtils[${this.schemaName}]`,
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
return this._moduleLogger;
|
|
55
61
|
}
|
|
56
62
|
|
|
57
63
|
/**
|
|
@@ -93,10 +99,7 @@ export class PostgresSchemaDbUtils {
|
|
|
93
99
|
span,
|
|
94
100
|
`CREATE SCHEMA IF NOT EXISTS ${this.schemaName};`,
|
|
95
101
|
);
|
|
96
|
-
await this.execSQLForSchema(
|
|
97
|
-
span,
|
|
98
|
-
`SET search_path TO ${this.schemaName};`,
|
|
99
|
-
);
|
|
102
|
+
await this.execSQLForSchema(span, `SET search_path TO ${this.schemaName};`);
|
|
100
103
|
|
|
101
104
|
// Run init SQL files
|
|
102
105
|
await this.execSQLFileForSchema(span, `${sqlDir}/init-0000.sql`);
|
|
@@ -108,9 +111,7 @@ export class PostgresSchemaDbUtils {
|
|
|
108
111
|
span,
|
|
109
112
|
"SELECT MAX(value) as version FROM metadata WHERE type='db_version'",
|
|
110
113
|
);
|
|
111
|
-
if (
|
|
112
|
-
(dbVersionQuery[0] as Record<string, unknown>).version
|
|
113
|
-
) {
|
|
114
|
+
if ((dbVersionQuery[0] as Record<string, unknown>).version) {
|
|
114
115
|
dbVersionApplied = Number(
|
|
115
116
|
(dbVersionQuery[0] as Record<string, unknown>).version,
|
|
116
117
|
);
|
|
@@ -223,10 +224,7 @@ export class PostgresSchemaDbUtils {
|
|
|
223
224
|
filename: string,
|
|
224
225
|
useSchemaPool = false,
|
|
225
226
|
): Promise<void> {
|
|
226
|
-
const span = tracer.startSpan(
|
|
227
|
-
"PostgresSchemaDbUtilsExecSQLFile",
|
|
228
|
-
context,
|
|
229
|
-
);
|
|
227
|
+
const span = tracer.startSpan("PostgresSchemaDbUtilsExecSQLFile", context);
|
|
230
228
|
const sql = (await fs.readFile(filename)).toString();
|
|
231
229
|
const pool = useSchemaPool ? this.schemaPool : this.runtimePool;
|
|
232
230
|
|
|
@@ -306,10 +304,7 @@ export class PostgresSchemaDbUtils {
|
|
|
306
304
|
callback: (client: any) => Promise<void>,
|
|
307
305
|
useSchemaPool = false,
|
|
308
306
|
): Promise<void> {
|
|
309
|
-
const span = tracer.startSpan(
|
|
310
|
-
"PostgresSchemaDbUtilsTransaction",
|
|
311
|
-
context,
|
|
312
|
-
);
|
|
307
|
+
const span = tracer.startSpan("PostgresSchemaDbUtilsTransaction", context);
|
|
313
308
|
const pool = useSchemaPool ? this.schemaPool : this.runtimePool;
|
|
314
309
|
|
|
315
310
|
if (!pool) {
|