@devopsplaybook.io/common-utils 1.0.0-beta.5.18ca754

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 (51) hide show
  1. package/.github/workflows/main-build.yml +17 -0
  2. package/.github/workflows/npm-upgrade.yml +16 -0
  3. package/.github/workflows/pr-check.yml +26 -0
  4. package/.github/workflows/reusable-merge-build.yml +141 -0
  5. package/.github/workflows/reusable-npm-merge.yml +135 -0
  6. package/.github/workflows/reusable-npm-pr.yml +153 -0
  7. package/.github/workflows/reusable-npm-upgrade.yml +92 -0
  8. package/.github/workflows/reusable-pr-verify.yml +135 -0
  9. package/AGENTS.md +84 -0
  10. package/README.md +413 -0
  11. package/dist/index.d.ts +8 -0
  12. package/dist/index.js +24 -0
  13. package/dist/src/ConfigBase.d.ts +104 -0
  14. package/dist/src/ConfigBase.js +201 -0
  15. package/dist/src/DbUtils.d.ts +50 -0
  16. package/dist/src/DbUtils.js +117 -0
  17. package/dist/src/DbUtilsNoTelemetry.d.ts +27 -0
  18. package/dist/src/DbUtilsNoTelemetry.js +89 -0
  19. package/dist/src/OTelContext.d.ts +35 -0
  20. package/dist/src/OTelContext.js +42 -0
  21. package/dist/src/PostgresDbUtils.d.ts +52 -0
  22. package/dist/src/PostgresDbUtils.js +217 -0
  23. package/dist/src/SqlDbUtils.d.ts +40 -0
  24. package/dist/src/SqlDbUtils.js +156 -0
  25. package/dist/src/SystemCommand.d.ts +9 -0
  26. package/dist/src/SystemCommand.js +56 -0
  27. package/dist/src/Timeout.d.ts +6 -0
  28. package/dist/src/Timeout.js +15 -0
  29. package/eslint.config.mjs +10 -0
  30. package/index.ts +8 -0
  31. package/jest.config.js +13 -0
  32. package/package.json +50 -0
  33. package/prettierrc.json +5 -0
  34. package/src/ConfigBase.spec.ts +108 -0
  35. package/src/ConfigBase.ts +213 -0
  36. package/src/DbUtils.spec.ts +23 -0
  37. package/src/DbUtils.ts +118 -0
  38. package/src/DbUtilsNoTelemetry.spec.ts +174 -0
  39. package/src/DbUtilsNoTelemetry.ts +121 -0
  40. package/src/OTelContext.spec.ts +58 -0
  41. package/src/OTelContext.ts +65 -0
  42. package/src/PostgresDbUtils.spec.ts +155 -0
  43. package/src/PostgresDbUtils.ts +233 -0
  44. package/src/SqlDbUtils.spec.ts +111 -0
  45. package/src/SqlDbUtils.ts +153 -0
  46. package/src/SystemCommand.spec.ts +18 -0
  47. package/src/SystemCommand.ts +23 -0
  48. package/src/Timeout.spec.ts +18 -0
  49. package/src/Timeout.ts +12 -0
  50. package/tsconfig.json +14 -0
  51. package/tsconfig.spec.json +7 -0
@@ -0,0 +1,52 @@
1
+ import { Pool } from "pg";
2
+ import { Span } from "@opentelemetry/sdk-trace-base";
3
+ import { StandardTracer, StandardLogger } from "@devopsplaybook.io/otel-utils";
4
+ /**
5
+ * Configuration subset required by the Postgres module.
6
+ */
7
+ export interface PostgresDbConfig {
8
+ DATABASE_POSTGRES_HOST: string;
9
+ DATABASE_POSTGRES_PORT: number;
10
+ DATABASE_POSTGRES_USER: string;
11
+ DATABASE_POSTGRES_PASSWORD: string;
12
+ DATABASE_POSTGRES_DATABASE: string;
13
+ }
14
+ /**
15
+ * Injects the OTel tracer and logger instances used by all Postgres operations.
16
+ * Must be called once at startup, before {@link PostgresDbUtilsInit}.
17
+ */
18
+ export declare function PostgresDbUtilsSetOTel(tracerIn: StandardTracer, loggerIn: StandardLogger): void;
19
+ /**
20
+ * Creates the Postgres connection pool and applies pending migration files
21
+ * from `sqlDir`.
22
+ *
23
+ * Migration files must follow the naming convention `init-NNNN.sql` and are
24
+ * applied in lexicographic order. A `metadata` table tracks which migrations
25
+ * have already been applied so they are idempotent.
26
+ *
27
+ * @param context Parent OTel span.
28
+ * @param config Configuration with Postgres connection fields.
29
+ * @param sqlDir Absolute path to the directory containing SQL migration files
30
+ * written for Postgres (with `$1,$2...` placeholders).
31
+ * If migrations are SQLite-first, use `convertToPostgresPlaceholders`
32
+ * before passing them.
33
+ */
34
+ export declare function PostgresDbUtilsInit(context: Span, config: PostgresDbConfig, sqlDir: string): Promise<void>;
35
+ /** Returns the underlying `pg.Pool` instance. */
36
+ export declare function PostgresDbUtilsGetPool(): Pool;
37
+ /**
38
+ * Execute a write SQL statement with OTel tracing.
39
+ * @returns Number of rows changed.
40
+ */
41
+ export declare function PostgresDbUtilsExecSQL(context: Span, sql: string, params?: unknown[]): Promise<number>;
42
+ /** Execute an entire SQL file (used for migrations). */
43
+ export declare function PostgresDbUtilsExecSQLFile(context: Span, filename: string): Promise<void>;
44
+ /**
45
+ * Execute a read SQL query with OTel tracing.
46
+ * @returns Array of row objects.
47
+ */
48
+ export declare function PostgresDbUtilsQuerySQL(context: Span, sql: string, params?: unknown[], debug?: boolean): Promise<any[]>;
49
+ /** Start a transaction. */
50
+ export declare function PostgresDbUtilsTransactionStart(context: Span): Promise<void>;
51
+ /** Commit a transaction. */
52
+ export declare function PostgresDbUtilsTransactionCommit(context: Span): Promise<void>;
@@ -0,0 +1,217 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.PostgresDbUtilsSetOTel = PostgresDbUtilsSetOTel;
37
+ exports.PostgresDbUtilsInit = PostgresDbUtilsInit;
38
+ exports.PostgresDbUtilsGetPool = PostgresDbUtilsGetPool;
39
+ exports.PostgresDbUtilsExecSQL = PostgresDbUtilsExecSQL;
40
+ exports.PostgresDbUtilsExecSQLFile = PostgresDbUtilsExecSQLFile;
41
+ exports.PostgresDbUtilsQuerySQL = PostgresDbUtilsQuerySQL;
42
+ exports.PostgresDbUtilsTransactionStart = PostgresDbUtilsTransactionStart;
43
+ exports.PostgresDbUtilsTransactionCommit = PostgresDbUtilsTransactionCommit;
44
+ const pg_1 = require("pg");
45
+ const fs = __importStar(require("fs-extra"));
46
+ const api_1 = require("@opentelemetry/api");
47
+ let pool;
48
+ let tracer;
49
+ let logger;
50
+ /**
51
+ * Injects the OTel tracer and logger instances used by all Postgres operations.
52
+ * Must be called once at startup, before {@link PostgresDbUtilsInit}.
53
+ */
54
+ function PostgresDbUtilsSetOTel(tracerIn, loggerIn) {
55
+ tracer = tracerIn;
56
+ logger = loggerIn.createModuleLogger("PostgresDbUtils");
57
+ }
58
+ /**
59
+ * Creates the Postgres connection pool and applies pending migration files
60
+ * from `sqlDir`.
61
+ *
62
+ * Migration files must follow the naming convention `init-NNNN.sql` and are
63
+ * applied in lexicographic order. A `metadata` table tracks which migrations
64
+ * have already been applied so they are idempotent.
65
+ *
66
+ * @param context Parent OTel span.
67
+ * @param config Configuration with Postgres connection fields.
68
+ * @param sqlDir Absolute path to the directory containing SQL migration files
69
+ * written for Postgres (with `$1,$2...` placeholders).
70
+ * If migrations are SQLite-first, use `convertToPostgresPlaceholders`
71
+ * before passing them.
72
+ */
73
+ async function PostgresDbUtilsInit(context, config, sqlDir) {
74
+ const span = tracer.startSpan("PostgresDbUtilsInit", context);
75
+ pool = new pg_1.Pool({
76
+ host: config.DATABASE_POSTGRES_HOST,
77
+ port: config.DATABASE_POSTGRES_PORT || 5432,
78
+ user: config.DATABASE_POSTGRES_USER,
79
+ password: config.DATABASE_POSTGRES_PASSWORD,
80
+ database: config.DATABASE_POSTGRES_DATABASE,
81
+ max: 20,
82
+ idleTimeoutMillis: 30000,
83
+ connectionTimeoutMillis: 10000,
84
+ keepAlive: true,
85
+ });
86
+ pool.on("error", (err) => {
87
+ logger.error("PostgreSQL pool connection error", err);
88
+ });
89
+ await PostgresDbUtilsExecSQLFile(span, `${sqlDir}/init-0000.sql`);
90
+ const initFiles = (await fs.readdir(sqlDir)).sort();
91
+ let dbVersionApplied = 0;
92
+ const dbVersionQuery = await PostgresDbUtilsQuerySQL(span, "SELECT MAX(value) as version FROM metadata WHERE \"type\" = 'db_version'");
93
+ if (dbVersionQuery.length > 0 && dbVersionQuery[0].version) {
94
+ dbVersionApplied = Number(dbVersionQuery[0].version);
95
+ }
96
+ logger.info(`Current DB Version: ${dbVersionApplied}`, span);
97
+ for (const initFile of initFiles) {
98
+ const regex = /init-(\d+).sql/g;
99
+ const match = regex.exec(initFile);
100
+ if (match) {
101
+ const dbVersionInitFile = Number(match[1]);
102
+ if (dbVersionInitFile > dbVersionApplied) {
103
+ logger.info(`Loading init file: ${initFile}`, span);
104
+ await PostgresDbUtilsExecSQLFile(span, `${sqlDir}/${initFile}`);
105
+ await PostgresDbUtilsQuerySQL(span, 'INSERT INTO metadata ("type", "value", "dateCreated") VALUES ($1, $2, $3)', ["db_version", dbVersionInitFile, new Date().toISOString()]);
106
+ }
107
+ }
108
+ }
109
+ span.end();
110
+ }
111
+ /** Returns the underlying `pg.Pool` instance. */
112
+ function PostgresDbUtilsGetPool() {
113
+ return pool;
114
+ }
115
+ /**
116
+ * Execute a write SQL statement with OTel tracing.
117
+ * @returns Number of rows changed.
118
+ */
119
+ function PostgresDbUtilsExecSQL(context, sql, params = []) {
120
+ const span = tracer.startSpan("PostgresDbUtilsExecSQL", context);
121
+ return new Promise((resolve, reject) => {
122
+ pool.query(sql, params, (error, result) => {
123
+ if (error) {
124
+ span.setStatus({
125
+ code: api_1.SpanStatusCode.ERROR,
126
+ message: error.message,
127
+ });
128
+ span.end();
129
+ reject(error);
130
+ }
131
+ else {
132
+ span.addEvent(`Impacted Rows: ${result.rowCount || 0}`);
133
+ span.end();
134
+ resolve(result.rowCount || 0);
135
+ }
136
+ });
137
+ });
138
+ }
139
+ /** Execute an entire SQL file (used for migrations). */
140
+ async function PostgresDbUtilsExecSQLFile(context, filename) {
141
+ const span = tracer.startSpan("PostgresDbUtilsExecSQLFile", context);
142
+ const sql = (await fs.readFile(filename)).toString();
143
+ return new Promise((resolve, reject) => {
144
+ pool.query(sql, (error) => {
145
+ if (error) {
146
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
147
+ span.end();
148
+ reject(error);
149
+ }
150
+ else {
151
+ span.end();
152
+ resolve();
153
+ }
154
+ });
155
+ });
156
+ }
157
+ /**
158
+ * Execute a read SQL query with OTel tracing.
159
+ * @returns Array of row objects.
160
+ */
161
+ function PostgresDbUtilsQuerySQL(context, sql, params = [], debug = false) {
162
+ const span = tracer.startSpan("PostgresDbUtilsQuerySQL", context);
163
+ if (debug) {
164
+ console.log(sql);
165
+ }
166
+ return new Promise((resolve, reject) => {
167
+ pool.query(sql, params, (error, result) => {
168
+ if (error) {
169
+ span.setStatus({
170
+ code: api_1.SpanStatusCode.ERROR,
171
+ message: error.message,
172
+ });
173
+ logger.error(`SQL ERROR: ${sql}`, error, span);
174
+ span.end();
175
+ reject(error);
176
+ }
177
+ else {
178
+ span.end();
179
+ resolve(result.rows);
180
+ }
181
+ });
182
+ });
183
+ }
184
+ /** Start a transaction. */
185
+ function PostgresDbUtilsTransactionStart(context) {
186
+ const span = tracer.startSpan("PostgresDbUtilsTransactionStart", context);
187
+ return new Promise((resolve, reject) => {
188
+ pool.query("BEGIN", (error) => {
189
+ if (error) {
190
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
191
+ span.end();
192
+ reject(error);
193
+ }
194
+ else {
195
+ span.end();
196
+ resolve();
197
+ }
198
+ });
199
+ });
200
+ }
201
+ /** Commit a transaction. */
202
+ function PostgresDbUtilsTransactionCommit(context) {
203
+ const span = tracer.startSpan("PostgresDbUtilsTransactionCommit", context);
204
+ return new Promise((resolve, reject) => {
205
+ pool.query("COMMIT", (error) => {
206
+ if (error) {
207
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: error.message });
208
+ span.end();
209
+ reject(error);
210
+ }
211
+ else {
212
+ span.end();
213
+ resolve();
214
+ }
215
+ });
216
+ });
217
+ }
@@ -0,0 +1,40 @@
1
+ import Database from "better-sqlite3";
2
+ import { Span } from "@opentelemetry/sdk-trace-base";
3
+ import { StandardTracer, StandardLogger } from "@devopsplaybook.io/otel-utils";
4
+ /**
5
+ * Configuration subset required by the SQLite module.
6
+ */
7
+ export interface SqlDbConfig {
8
+ DATA_DIR: string;
9
+ }
10
+ /**
11
+ * Injects the OTel tracer and logger instances used by all SQL operations.
12
+ * Must be called once at startup, before {@link SqlDbUtilsInit}.
13
+ */
14
+ export declare function SqlDbUtilsSetOTel(tracerIn: StandardTracer, loggerIn: StandardLogger): void;
15
+ /**
16
+ * Opens the SQLite database and applies pending migration files from `sqlDir`.
17
+ *
18
+ * Migration files must follow the naming convention `init-NNNN.sql` and are
19
+ * applied in lexicographic order. A `metadata` table tracks which migrations
20
+ * have already been applied so they are idempotent.
21
+ *
22
+ * @param context Parent OTel span.
23
+ * @param config Configuration with `DATA_DIR`.
24
+ * @param sqlDir Absolute path to the directory containing SQL migration files.
25
+ */
26
+ export declare function SqlDbUtilsInit(context: Span, config: SqlDbConfig, sqlDir: string): Promise<void>;
27
+ /** Returns the underlying `better-sqlite3` Database instance. */
28
+ export declare function SqlDbUtilsGetDatabase(): Database.Database;
29
+ /**
30
+ * Execute a write SQL statement with OTel tracing.
31
+ * @returns Number of rows changed.
32
+ */
33
+ export declare function SqlDbUtilsExecSQL(context: Span, sql: string, params?: unknown[]): number;
34
+ /** Execute an entire SQL file (used for migrations). */
35
+ export declare function SqlDbUtilsExecSQLFile(context: Span, filename: string): void;
36
+ /**
37
+ * Execute a read SQL query with OTel tracing.
38
+ * @returns Array of row objects.
39
+ */
40
+ export declare function SqlDbUtilsQuerySQL(context: Span, sql: string, params?: unknown[], debug?: boolean): any[];
@@ -0,0 +1,156 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.SqlDbUtilsSetOTel = SqlDbUtilsSetOTel;
40
+ exports.SqlDbUtilsInit = SqlDbUtilsInit;
41
+ exports.SqlDbUtilsGetDatabase = SqlDbUtilsGetDatabase;
42
+ exports.SqlDbUtilsExecSQL = SqlDbUtilsExecSQL;
43
+ exports.SqlDbUtilsExecSQLFile = SqlDbUtilsExecSQLFile;
44
+ exports.SqlDbUtilsQuerySQL = SqlDbUtilsQuerySQL;
45
+ const better_sqlite3_1 = __importDefault(require("better-sqlite3"));
46
+ const fs = __importStar(require("fs-extra"));
47
+ const api_1 = require("@opentelemetry/api");
48
+ let database;
49
+ let tracer;
50
+ let logger;
51
+ /**
52
+ * Injects the OTel tracer and logger instances used by all SQL operations.
53
+ * Must be called once at startup, before {@link SqlDbUtilsInit}.
54
+ */
55
+ function SqlDbUtilsSetOTel(tracerIn, loggerIn) {
56
+ tracer = tracerIn;
57
+ logger = loggerIn.createModuleLogger("SqlDbUtils");
58
+ }
59
+ /**
60
+ * Opens the SQLite database and applies pending migration files from `sqlDir`.
61
+ *
62
+ * Migration files must follow the naming convention `init-NNNN.sql` and are
63
+ * applied in lexicographic order. A `metadata` table tracks which migrations
64
+ * have already been applied so they are idempotent.
65
+ *
66
+ * @param context Parent OTel span.
67
+ * @param config Configuration with `DATA_DIR`.
68
+ * @param sqlDir Absolute path to the directory containing SQL migration files.
69
+ */
70
+ async function SqlDbUtilsInit(context, config, sqlDir) {
71
+ const span = tracer.startSpan("SqlDbUtilsInit", context);
72
+ await fs.ensureDir(config.DATA_DIR);
73
+ database = new better_sqlite3_1.default(`${config.DATA_DIR}/database.db`);
74
+ SqlDbUtilsExecSQLFile(span, `${sqlDir}/init-0000.sql`);
75
+ const initFiles = (await fs.readdir(sqlDir)).sort();
76
+ let dbVersionApplied = 0;
77
+ const rows = SqlDbUtilsQuerySQL(span, "SELECT MAX(value) as maxVersion FROM metadata WHERE type='db_version'");
78
+ if (rows.length > 0 && rows[0].maxVersion) {
79
+ dbVersionApplied = Number(rows[0].maxVersion);
80
+ }
81
+ logger.info(`Current DB Version: ${dbVersionApplied}`, span);
82
+ for (const initFile of initFiles) {
83
+ const regex = /init-(\d+).sql/g;
84
+ const match = regex.exec(initFile);
85
+ if (match) {
86
+ const dbVersionInitFile = Number(match[1]);
87
+ if (dbVersionInitFile > dbVersionApplied) {
88
+ logger.info(`Loading init file: ${initFile}`, span);
89
+ SqlDbUtilsExecSQLFile(span, `${sqlDir}/${initFile}`);
90
+ SqlDbUtilsExecSQL(span, "INSERT INTO metadata (type, value, dateCreated) VALUES ('db_version',?,?)", [dbVersionInitFile, new Date().toISOString()]);
91
+ }
92
+ }
93
+ }
94
+ span.end();
95
+ }
96
+ /** Returns the underlying `better-sqlite3` Database instance. */
97
+ function SqlDbUtilsGetDatabase() {
98
+ return database;
99
+ }
100
+ /**
101
+ * Execute a write SQL statement with OTel tracing.
102
+ * @returns Number of rows changed.
103
+ */
104
+ function SqlDbUtilsExecSQL(context, sql, params = []) {
105
+ const span = tracer.startSpan("SqlDbUtilsExecSQL", context);
106
+ try {
107
+ const stmt = database.prepare(sql);
108
+ const result = stmt.run(params);
109
+ span.addEvent(`Impacted Rows: ${result.changes}`);
110
+ span.end();
111
+ return result.changes;
112
+ }
113
+ catch (error) {
114
+ const err = error;
115
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: err.message });
116
+ span.end();
117
+ throw error;
118
+ }
119
+ }
120
+ /** Execute an entire SQL file (used for migrations). */
121
+ function SqlDbUtilsExecSQLFile(context, filename) {
122
+ const span = tracer.startSpan("SqlDbUtilsExecSQLFile", context);
123
+ try {
124
+ const sql = fs.readFileSync(filename).toString();
125
+ database.exec(sql);
126
+ span.end();
127
+ }
128
+ catch (error) {
129
+ const err = error;
130
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: err.message });
131
+ span.end();
132
+ throw error;
133
+ }
134
+ }
135
+ /**
136
+ * Execute a read SQL query with OTel tracing.
137
+ * @returns Array of row objects.
138
+ */
139
+ function SqlDbUtilsQuerySQL(context, sql, params = [], debug = false) {
140
+ const span = tracer.startSpan("SqlDbUtilsQuerySQL", context);
141
+ if (debug) {
142
+ console.log(sql);
143
+ }
144
+ try {
145
+ const stmt = database.prepare(sql);
146
+ const rows = stmt.all(params);
147
+ span.end();
148
+ return rows;
149
+ }
150
+ catch (error) {
151
+ const err = error;
152
+ span.setStatus({ code: api_1.SpanStatusCode.ERROR, message: err.message });
153
+ span.end();
154
+ throw error;
155
+ }
156
+ }
@@ -0,0 +1,9 @@
1
+ import * as childProcess from "child_process";
2
+ /**
3
+ * Execute a shell command and return its stdout.
4
+ *
5
+ * @param command The command string to execute.
6
+ * @param options Optional `child_process.exec` options.
7
+ * @returns Resolves with stdout on success, rejects on error.
8
+ */
9
+ export declare function SystemCommandExecute(command: string, options?: childProcess.ExecOptions): Promise<string>;
@@ -0,0 +1,56 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.SystemCommandExecute = SystemCommandExecute;
37
+ const childProcess = __importStar(require("child_process"));
38
+ /**
39
+ * Execute a shell command and return its stdout.
40
+ *
41
+ * @param command The command string to execute.
42
+ * @param options Optional `child_process.exec` options.
43
+ * @returns Resolves with stdout on success, rejects on error.
44
+ */
45
+ function SystemCommandExecute(command, options) {
46
+ return new Promise((resolve, reject) => {
47
+ childProcess.exec(command, options || {}, (error, stdout) => {
48
+ if (error) {
49
+ reject(error);
50
+ }
51
+ else {
52
+ resolve(String(stdout));
53
+ }
54
+ });
55
+ });
56
+ }
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Promise-based wrapper around `setTimeout`.
3
+ *
4
+ * @param duration Delay in milliseconds.
5
+ */
6
+ export declare function TimeoutWait(duration: number): Promise<void>;
@@ -0,0 +1,15 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.TimeoutWait = TimeoutWait;
4
+ /**
5
+ * Promise-based wrapper around `setTimeout`.
6
+ *
7
+ * @param duration Delay in milliseconds.
8
+ */
9
+ function TimeoutWait(duration) {
10
+ return new Promise((resolve) => {
11
+ setTimeout(() => {
12
+ resolve();
13
+ }, duration);
14
+ });
15
+ }
@@ -0,0 +1,10 @@
1
+ // @ts-check
2
+
3
+ import eslint from "@eslint/js";
4
+ import tseslint from "typescript-eslint";
5
+
6
+ export default tseslint.config(
7
+ eslint.configs.recommended,
8
+ ...tseslint.configs.strict,
9
+ ...tseslint.configs.stylistic,
10
+ );
package/index.ts ADDED
@@ -0,0 +1,8 @@
1
+ export * from "./src/OTelContext";
2
+ export * from "./src/ConfigBase";
3
+ export * from "./src/DbUtils";
4
+ export * from "./src/DbUtilsNoTelemetry";
5
+ export * from "./src/SqlDbUtils";
6
+ export * from "./src/PostgresDbUtils";
7
+ export * from "./src/SystemCommand";
8
+ export * from "./src/Timeout";
package/jest.config.js ADDED
@@ -0,0 +1,13 @@
1
+ module.exports = {
2
+ moduleFileExtensions: ["ts", "js"],
3
+ transform: {
4
+ "^.+\\.(ts|tsx)$": [
5
+ "ts-jest",
6
+ {
7
+ tsconfig: "tsconfig.spec.json",
8
+ },
9
+ ],
10
+ },
11
+ testMatch: ["/**/src/**/*.spec.(ts|js)"],
12
+ testEnvironment: "node",
13
+ };
package/package.json ADDED
@@ -0,0 +1,50 @@
1
+ {
2
+ "name": "@devopsplaybook.io/common-utils",
3
+ "version": "1.0.0-beta.5.18ca754",
4
+ "description": "Shared utility modules for devopsplaybook.io projects (DB, Config, OTel context, system helpers)",
5
+ "keywords": [
6
+ "Open Telemetry",
7
+ "OTel",
8
+ "SQLite",
9
+ "Postgres",
10
+ "Config",
11
+ "Utilities"
12
+ ],
13
+ "license": "ISC",
14
+ "author": "",
15
+ "type": "commonjs",
16
+ "main": "dist/index.js",
17
+ "types": "dist/index.d.ts",
18
+ "scripts": {
19
+ "build": "tsc",
20
+ "lint": "eslint src",
21
+ "test": "jest --coverage"
22
+ },
23
+ "dependencies": {
24
+ "@devopsplaybook.io/otel-utils": "^1.1.0",
25
+ "@opentelemetry/api": "^1.9.1",
26
+ "@opentelemetry/sdk-trace-base": "^2.7.1",
27
+ "better-sqlite3": "^12.9.0",
28
+ "fs-extra": "^11.3.5",
29
+ "pg": "^8.21.0",
30
+ "uuid": "^14.0.0"
31
+ },
32
+ "devDependencies": {
33
+ "@eslint/js": "^10.0.1",
34
+ "@types/better-sqlite3": "^7.6.13",
35
+ "@types/fs-extra": "^11.0.4",
36
+ "@types/jest": "^30.0.0",
37
+ "@types/node": "^25.9.1",
38
+ "@types/pg": "^8.20.0",
39
+ "@types/uuid": "^10.0.0",
40
+ "eslint": "^10.4.0",
41
+ "jest": "^30.4.2",
42
+ "ts-jest": "^29.4.11",
43
+ "ts-node": "^10.9.2",
44
+ "typescript": "^6.0.3",
45
+ "typescript-eslint": "^8.59.4"
46
+ },
47
+ "publishConfig": {
48
+ "access": "public"
49
+ }
50
+ }
@@ -0,0 +1,5 @@
1
+ {
2
+ "tabWidth": 2,
3
+ "semi": true,
4
+ "singleQuote": false
5
+ }