@restura/core 1.0.19 → 1.1.1
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/dist/index.d.ts +28 -5
- package/dist/index.js +139 -42
- package/dist/index.js.map +1 -1
- package/package.json +4 -3
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import
|
|
1
|
+
import { SerializerFn } from 'pino';
|
|
2
2
|
import { z } from 'zod';
|
|
3
3
|
import { UUID } from 'crypto';
|
|
4
4
|
import * as express from 'express';
|
|
@@ -6,16 +6,40 @@ import { IncomingHttpHeaders } from 'http2';
|
|
|
6
6
|
import { QueryResultRow, QueryConfigValues, QueryResult, PoolConfig, Pool, ClientConfig, Client } from 'pg';
|
|
7
7
|
import peg from 'pegjs';
|
|
8
8
|
|
|
9
|
-
|
|
9
|
+
type LogFunction = {
|
|
10
|
+
(msg: string, ...args: unknown[]): void;
|
|
11
|
+
(msg: unknown): void;
|
|
12
|
+
};
|
|
13
|
+
declare const logger: {
|
|
14
|
+
level: "fatal" | "error" | "warn" | "info" | "debug" | "silly" | "trace";
|
|
15
|
+
fatal: LogFunction;
|
|
16
|
+
error: LogFunction;
|
|
17
|
+
warn: LogFunction;
|
|
18
|
+
info: LogFunction;
|
|
19
|
+
debug: LogFunction;
|
|
20
|
+
silly: LogFunction;
|
|
21
|
+
trace: LogFunction;
|
|
22
|
+
};
|
|
10
23
|
|
|
24
|
+
type ErrorSerializerFactory = (baseSerializer: SerializerFn) => SerializerFn;
|
|
11
25
|
declare const loggerConfigSchema: z.ZodObject<{
|
|
12
26
|
level: z.ZodDefault<z.ZodEnum<{
|
|
13
|
-
|
|
14
|
-
warn: "warn";
|
|
27
|
+
fatal: "fatal";
|
|
15
28
|
error: "error";
|
|
29
|
+
warn: "warn";
|
|
30
|
+
info: "info";
|
|
16
31
|
debug: "debug";
|
|
17
32
|
silly: "silly";
|
|
33
|
+
trace: "trace";
|
|
18
34
|
}>>;
|
|
35
|
+
transports: z.ZodOptional<z.ZodArray<z.ZodObject<{
|
|
36
|
+
target: z.ZodString;
|
|
37
|
+
level: z.ZodOptional<z.ZodString>;
|
|
38
|
+
options: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodUnknown>>;
|
|
39
|
+
}, z.core.$strip>>>;
|
|
40
|
+
serializers: z.ZodOptional<z.ZodObject<{
|
|
41
|
+
err: z.ZodOptional<z.ZodCustom<ErrorSerializerFactory, ErrorSerializerFactory>>;
|
|
42
|
+
}, z.core.$strip>>;
|
|
19
43
|
}, z.core.$strip>;
|
|
20
44
|
type LoggerConfigSchema = z.infer<typeof loggerConfigSchema>;
|
|
21
45
|
|
|
@@ -943,7 +967,6 @@ declare abstract class PsqlConnection {
|
|
|
943
967
|
queryOneSchema<T>(query: string, params: unknown[], requesterDetails: RequesterDetails, zodSchema: z.ZodSchema<T>): Promise<T>;
|
|
944
968
|
runQuery<T>(query: string, options: unknown[], requesterDetails: RequesterDetails): Promise<T[]>;
|
|
945
969
|
runQuerySchema<T>(query: string, params: unknown[], requesterDetails: RequesterDetails, zodSchema: z.ZodSchema<T>): Promise<T[]>;
|
|
946
|
-
private logQueryDuration;
|
|
947
970
|
private logSqlStatement;
|
|
948
971
|
}
|
|
949
972
|
|
package/dist/index.js
CHANGED
|
@@ -11,39 +11,138 @@ var __decorateClass = (decorators, target, key, kind) => {
|
|
|
11
11
|
|
|
12
12
|
// src/logger/logger.ts
|
|
13
13
|
import { config } from "@restura/internal";
|
|
14
|
-
import
|
|
15
|
-
import { format } from "logform";
|
|
14
|
+
import pino from "pino";
|
|
16
15
|
|
|
17
16
|
// src/logger/loggerConfigSchema.ts
|
|
18
17
|
import { z } from "zod";
|
|
19
18
|
var loggerConfigSchema = z.object({
|
|
20
|
-
level: z.enum(["
|
|
19
|
+
level: z.enum(["fatal", "error", "warn", "info", "debug", "silly", "trace"]).default("info"),
|
|
20
|
+
transports: z.array(
|
|
21
|
+
z.object({
|
|
22
|
+
target: z.string(),
|
|
23
|
+
level: z.string().optional(),
|
|
24
|
+
options: z.record(z.string(), z.unknown()).optional()
|
|
25
|
+
})
|
|
26
|
+
).optional(),
|
|
27
|
+
serializers: z.object({
|
|
28
|
+
err: z.custom().optional()
|
|
29
|
+
}).optional()
|
|
21
30
|
});
|
|
22
31
|
|
|
23
32
|
// src/logger/logger.ts
|
|
24
33
|
var loggerConfig = await config.validate("logger", loggerConfigSchema);
|
|
25
|
-
var
|
|
26
|
-
|
|
27
|
-
|
|
34
|
+
var logLevelMap = {
|
|
35
|
+
fatal: "fatal",
|
|
36
|
+
error: "error",
|
|
37
|
+
warn: "warn",
|
|
38
|
+
info: "info",
|
|
39
|
+
debug: "debug",
|
|
40
|
+
silly: "trace",
|
|
41
|
+
trace: "trace"
|
|
42
|
+
};
|
|
43
|
+
var currentLogLevel = logLevelMap[loggerConfig.level];
|
|
44
|
+
var defaultTransports = [
|
|
45
|
+
{
|
|
46
|
+
target: "pino-pretty",
|
|
47
|
+
options: {
|
|
48
|
+
colorize: true,
|
|
49
|
+
translateTime: "yyyy-mm-dd HH:MM:ss.l",
|
|
50
|
+
ignore: "pid,hostname,_meta",
|
|
51
|
+
// _meta allows a user to pass in metadata for JSON but not print it to the console
|
|
52
|
+
messageFormat: "{msg}",
|
|
53
|
+
levelFirst: true,
|
|
54
|
+
customColors: "error:red,warn:yellow,info:green,debug:blue,trace:magenta"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
];
|
|
58
|
+
var baseErrSerializer = pino.stdSerializers.err;
|
|
59
|
+
var errorSerializer = (() => {
|
|
60
|
+
try {
|
|
61
|
+
return loggerConfig.serializers?.err ? loggerConfig.serializers.err(baseErrSerializer) : baseErrSerializer;
|
|
62
|
+
} catch (error) {
|
|
63
|
+
console.error("Failed to initialize custom error serializer, falling back to default", error);
|
|
64
|
+
return baseErrSerializer;
|
|
65
|
+
}
|
|
66
|
+
})();
|
|
67
|
+
var pinoLogger = pino({
|
|
68
|
+
level: currentLogLevel,
|
|
69
|
+
transport: {
|
|
70
|
+
targets: loggerConfig.transports ?? defaultTransports
|
|
71
|
+
},
|
|
72
|
+
serializers: {
|
|
73
|
+
err: errorSerializer
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
function buildContext(args) {
|
|
77
|
+
const ctx = {};
|
|
78
|
+
const prims = [];
|
|
79
|
+
for (const arg of args) {
|
|
80
|
+
if (arg instanceof Error && !ctx.err) {
|
|
81
|
+
ctx.err = arg;
|
|
82
|
+
} else if (arg && typeof arg === "object" && !Array.isArray(arg)) {
|
|
83
|
+
Object.assign(ctx, arg);
|
|
84
|
+
} else {
|
|
85
|
+
prims.push(arg);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (prims.length) ctx.args = prims;
|
|
89
|
+
return ctx;
|
|
90
|
+
}
|
|
91
|
+
function log(level, message, ...args) {
|
|
92
|
+
pinoLogger[level](buildContext(args), message);
|
|
93
|
+
}
|
|
94
|
+
var logger = {
|
|
95
|
+
level: loggerConfig.level,
|
|
96
|
+
fatal: ((msg, ...args) => {
|
|
97
|
+
if (typeof msg === "string") {
|
|
98
|
+
log("fatal", msg, ...args);
|
|
99
|
+
} else {
|
|
100
|
+
pinoLogger.fatal(msg);
|
|
101
|
+
}
|
|
102
|
+
}),
|
|
103
|
+
error: ((msg, ...args) => {
|
|
104
|
+
if (typeof msg === "string") {
|
|
105
|
+
log("error", msg, ...args);
|
|
106
|
+
} else {
|
|
107
|
+
pinoLogger.error(msg);
|
|
108
|
+
}
|
|
109
|
+
}),
|
|
110
|
+
warn: ((msg, ...args) => {
|
|
111
|
+
if (typeof msg === "string") {
|
|
112
|
+
log("warn", msg, ...args);
|
|
113
|
+
} else {
|
|
114
|
+
pinoLogger.warn(msg);
|
|
115
|
+
}
|
|
28
116
|
}),
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
117
|
+
info: ((msg, ...args) => {
|
|
118
|
+
if (typeof msg === "string") {
|
|
119
|
+
log("info", msg, ...args);
|
|
120
|
+
} else {
|
|
121
|
+
pinoLogger.info(msg);
|
|
122
|
+
}
|
|
123
|
+
}),
|
|
124
|
+
debug: ((msg, ...args) => {
|
|
125
|
+
if (typeof msg === "string") {
|
|
126
|
+
log("debug", msg, ...args);
|
|
127
|
+
} else {
|
|
128
|
+
pinoLogger.debug(msg);
|
|
129
|
+
}
|
|
130
|
+
}),
|
|
131
|
+
silly: ((msg, ...args) => {
|
|
132
|
+
if (typeof msg === "string") {
|
|
133
|
+
log("trace", msg, ...args);
|
|
134
|
+
} else {
|
|
135
|
+
pinoLogger.trace(msg);
|
|
136
|
+
}
|
|
137
|
+
}),
|
|
138
|
+
trace: ((msg, ...args) => {
|
|
139
|
+
if (typeof msg === "string") {
|
|
140
|
+
log("trace", msg, ...args);
|
|
141
|
+
} else {
|
|
142
|
+
pinoLogger.trace(msg);
|
|
143
|
+
}
|
|
34
144
|
})
|
|
35
|
-
|
|
36
|
-
var logger = winston.createLogger({
|
|
37
|
-
level: loggerConfig.level,
|
|
38
|
-
format: format.combine(
|
|
39
|
-
format.timestamp({
|
|
40
|
-
format: "YYYY-MM-DD HH:mm:ss.sss"
|
|
41
|
-
}),
|
|
42
|
-
format.errors({ stack: true }),
|
|
43
|
-
format.json()
|
|
44
|
-
),
|
|
45
|
-
transports: [new winston.transports.Console({ format: consoleFormat })]
|
|
46
|
-
});
|
|
145
|
+
};
|
|
47
146
|
|
|
48
147
|
// src/restura/eventManager.ts
|
|
49
148
|
import Bluebird from "bluebird";
|
|
@@ -1636,12 +1735,12 @@ import pg from "pg";
|
|
|
1636
1735
|
|
|
1637
1736
|
// src/restura/sql/PsqlConnection.ts
|
|
1638
1737
|
import crypto from "crypto";
|
|
1639
|
-
import
|
|
1738
|
+
import format2 from "pg-format";
|
|
1640
1739
|
import { format as sqlFormat } from "sql-formatter";
|
|
1641
1740
|
import { z as z6 } from "zod";
|
|
1642
1741
|
|
|
1643
1742
|
// src/restura/sql/PsqlUtils.ts
|
|
1644
|
-
import
|
|
1743
|
+
import format from "pg-format";
|
|
1645
1744
|
function escapeColumnName(columnName) {
|
|
1646
1745
|
if (columnName === void 0) return "";
|
|
1647
1746
|
return `"${columnName.replace(/"/g, "")}"`.replace(".", '"."');
|
|
@@ -1698,9 +1797,9 @@ function SQL(strings, ...values) {
|
|
|
1698
1797
|
} else if (typeof value === "number") {
|
|
1699
1798
|
query += value;
|
|
1700
1799
|
} else if (Array.isArray(value)) {
|
|
1701
|
-
query +=
|
|
1800
|
+
query += format.literal(JSON.stringify(value)) + "::jsonb";
|
|
1702
1801
|
} else {
|
|
1703
|
-
query +=
|
|
1802
|
+
query += format.literal(value);
|
|
1704
1803
|
}
|
|
1705
1804
|
query += strings[index + 1];
|
|
1706
1805
|
});
|
|
@@ -1716,17 +1815,17 @@ var PsqlConnection = class {
|
|
|
1716
1815
|
async queryOne(query, options, requesterDetails) {
|
|
1717
1816
|
const formattedQuery = questionMarksToOrderedParams(query);
|
|
1718
1817
|
const meta = { connectionInstanceId: this.instanceId, ...requesterDetails };
|
|
1719
|
-
this.logSqlStatement(formattedQuery, options, meta);
|
|
1720
1818
|
const queryMetadata = `--QUERY_METADATA(${JSON.stringify(meta)})
|
|
1721
1819
|
`;
|
|
1722
1820
|
const startTime = process.hrtime();
|
|
1723
1821
|
try {
|
|
1724
1822
|
const response = await this.query(queryMetadata + formattedQuery, options);
|
|
1725
|
-
this.
|
|
1823
|
+
this.logSqlStatement(formattedQuery, options, meta, startTime);
|
|
1726
1824
|
if (response.rows.length === 0) throw new RsError("NOT_FOUND", "No results found");
|
|
1727
1825
|
else if (response.rows.length > 1) throw new RsError("DUPLICATE", "More than one result found");
|
|
1728
1826
|
return response.rows[0];
|
|
1729
1827
|
} catch (error) {
|
|
1828
|
+
this.logSqlStatement(formattedQuery, options, meta, startTime);
|
|
1730
1829
|
if (RsError.isRsError(error)) throw error;
|
|
1731
1830
|
if (error?.routine === "_bt_check_unique") {
|
|
1732
1831
|
throw new RsError("DUPLICATE", error.message);
|
|
@@ -1752,15 +1851,15 @@ var PsqlConnection = class {
|
|
|
1752
1851
|
async runQuery(query, options, requesterDetails) {
|
|
1753
1852
|
const formattedQuery = questionMarksToOrderedParams(query);
|
|
1754
1853
|
const meta = { connectionInstanceId: this.instanceId, ...requesterDetails };
|
|
1755
|
-
this.logSqlStatement(formattedQuery, options, meta);
|
|
1756
1854
|
const queryMetadata = `--QUERY_METADATA(${JSON.stringify(meta)})
|
|
1757
1855
|
`;
|
|
1758
1856
|
const startTime = process.hrtime();
|
|
1759
1857
|
try {
|
|
1760
1858
|
const response = await this.query(queryMetadata + formattedQuery, options);
|
|
1761
|
-
this.
|
|
1859
|
+
this.logSqlStatement(formattedQuery, options, meta, startTime);
|
|
1762
1860
|
return response.rows;
|
|
1763
1861
|
} catch (error) {
|
|
1862
|
+
this.logSqlStatement(formattedQuery, options, meta, startTime);
|
|
1764
1863
|
if (error?.routine === "_bt_check_unique") {
|
|
1765
1864
|
throw new RsError("DUPLICATE", error.message);
|
|
1766
1865
|
}
|
|
@@ -1782,15 +1881,8 @@ var PsqlConnection = class {
|
|
|
1782
1881
|
throw new RsError("DATABASE_ERROR", `Invalid data returned from database`);
|
|
1783
1882
|
}
|
|
1784
1883
|
}
|
|
1785
|
-
|
|
1786
|
-
if (logger.level
|
|
1787
|
-
const [seconds, nanoseconds] = process.hrtime(startTime);
|
|
1788
|
-
const duration = seconds * 1e3 + nanoseconds / 1e6;
|
|
1789
|
-
logger.silly(`Query duration: ${duration.toFixed(2)}ms`);
|
|
1790
|
-
}
|
|
1791
|
-
}
|
|
1792
|
-
logSqlStatement(query, options, queryMetadata, prefix = "") {
|
|
1793
|
-
if (logger.level !== "silly") return;
|
|
1884
|
+
logSqlStatement(query, options, queryMetadata, startTime, prefix = "") {
|
|
1885
|
+
if (logger.level !== "trace" && logger.level !== "silly") return;
|
|
1794
1886
|
let sqlStatement = "";
|
|
1795
1887
|
if (options.length === 0) {
|
|
1796
1888
|
sqlStatement = query;
|
|
@@ -1803,7 +1895,7 @@ var PsqlConnection = class {
|
|
|
1803
1895
|
const value = options[paramIndex];
|
|
1804
1896
|
if (typeof value === "number") return value.toString();
|
|
1805
1897
|
if (typeof value === "boolean") return value.toString();
|
|
1806
|
-
return
|
|
1898
|
+
return format2.literal(value);
|
|
1807
1899
|
});
|
|
1808
1900
|
}
|
|
1809
1901
|
const formattedSql = sqlFormat(sqlStatement, {
|
|
@@ -1814,12 +1906,17 @@ var PsqlConnection = class {
|
|
|
1814
1906
|
useTabs: true,
|
|
1815
1907
|
tabWidth: 4
|
|
1816
1908
|
});
|
|
1909
|
+
const [seconds, nanoseconds] = process.hrtime(startTime);
|
|
1910
|
+
const durationMs = seconds * 1e3 + nanoseconds / 1e6;
|
|
1817
1911
|
let initiator = "Anonymous";
|
|
1818
1912
|
if ("userId" in queryMetadata && queryMetadata.userId)
|
|
1819
1913
|
initiator = `User Id (${queryMetadata.userId.toString()})`;
|
|
1820
1914
|
if ("isSystemUser" in queryMetadata && queryMetadata.isSystemUser) initiator = "SYSTEM";
|
|
1821
1915
|
logger.silly(`${prefix}query by ${initiator}, Query ->
|
|
1822
|
-
${formattedSql}
|
|
1916
|
+
${formattedSql}`, {
|
|
1917
|
+
duration: `${durationMs.toFixed(2)}ms`,
|
|
1918
|
+
_meta: { durationNs: nanoseconds }
|
|
1919
|
+
});
|
|
1823
1920
|
}
|
|
1824
1921
|
};
|
|
1825
1922
|
|