@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 CHANGED
@@ -1,4 +1,4 @@
1
- import winston from 'winston';
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
- declare const logger: winston.Logger;
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
- info: "info";
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 winston from "winston";
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(["info", "warn", "error", "debug", "silly"]).default("info")
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 consoleFormat = format.combine(
26
- format.timestamp({
27
- format: "YYYY-MM-DD HH:mm:ss.sss"
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
- format.errors({ stack: true }),
30
- format.padLevels(),
31
- format.colorize({ all: true }),
32
- format.printf((info) => {
33
- return `[${info.timestamp}] ${info.level} ${info.message}`;
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 format3 from "pg-format";
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 format2 from "pg-format";
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 += format2.literal(JSON.stringify(value)) + "::jsonb";
1800
+ query += format.literal(JSON.stringify(value)) + "::jsonb";
1702
1801
  } else {
1703
- query += format2.literal(value);
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.logQueryDuration(startTime);
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.logQueryDuration(startTime);
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
- logQueryDuration(startTime) {
1786
- if (logger.level === "silly") {
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 format3.literal(value);
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