request-scope-api 1.0.0

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 (75) hide show
  1. package/README.md +275 -0
  2. package/dist/cjs/adapters/adapter.interface.js +9 -0
  3. package/dist/cjs/adapters/adapter.interface.js.map +1 -0
  4. package/dist/cjs/adapters/mongo.adapter.js +188 -0
  5. package/dist/cjs/adapters/mongo.adapter.js.map +1 -0
  6. package/dist/cjs/adapters/mysql.adapter.js +243 -0
  7. package/dist/cjs/adapters/mysql.adapter.js.map +1 -0
  8. package/dist/cjs/adapters/pg.adapter.js +334 -0
  9. package/dist/cjs/adapters/pg.adapter.js.map +1 -0
  10. package/dist/cjs/capture.js +310 -0
  11. package/dist/cjs/capture.js.map +1 -0
  12. package/dist/cjs/config.js +122 -0
  13. package/dist/cjs/config.js.map +1 -0
  14. package/dist/cjs/dashboard/api.js +173 -0
  15. package/dist/cjs/dashboard/api.js.map +1 -0
  16. package/dist/cjs/dashboard/router.js +96 -0
  17. package/dist/cjs/dashboard/router.js.map +1 -0
  18. package/dist/cjs/index.js +49 -0
  19. package/dist/cjs/index.js.map +1 -0
  20. package/dist/cjs/masker.js +73 -0
  21. package/dist/cjs/masker.js.map +1 -0
  22. package/dist/cjs/middleware.js +198 -0
  23. package/dist/cjs/middleware.js.map +1 -0
  24. package/dist/cjs/queue.js +114 -0
  25. package/dist/cjs/queue.js.map +1 -0
  26. package/dist/cjs/retention.js +64 -0
  27. package/dist/cjs/retention.js.map +1 -0
  28. package/dist/cjs/types.js +9 -0
  29. package/dist/cjs/types.js.map +1 -0
  30. package/dist/dashboard/assets/index-C0TqFHk6.css +1 -0
  31. package/dist/dashboard/assets/index-MCuAZo4Q.js +67 -0
  32. package/dist/dashboard/index.html +13 -0
  33. package/dist/esm/adapters/adapter.interface.js +8 -0
  34. package/dist/esm/adapters/adapter.interface.js.map +1 -0
  35. package/dist/esm/adapters/mongo.adapter.js +184 -0
  36. package/dist/esm/adapters/mongo.adapter.js.map +1 -0
  37. package/dist/esm/adapters/mysql.adapter.js +236 -0
  38. package/dist/esm/adapters/mysql.adapter.js.map +1 -0
  39. package/dist/esm/adapters/pg.adapter.js +330 -0
  40. package/dist/esm/adapters/pg.adapter.js.map +1 -0
  41. package/dist/esm/capture.js +304 -0
  42. package/dist/esm/capture.js.map +1 -0
  43. package/dist/esm/config.js +117 -0
  44. package/dist/esm/config.js.map +1 -0
  45. package/dist/esm/dashboard/api.js +168 -0
  46. package/dist/esm/dashboard/api.js.map +1 -0
  47. package/dist/esm/dashboard/router.js +90 -0
  48. package/dist/esm/dashboard/router.js.map +1 -0
  49. package/dist/esm/index.js +50 -0
  50. package/dist/esm/index.js.map +1 -0
  51. package/dist/esm/masker.js +70 -0
  52. package/dist/esm/masker.js.map +1 -0
  53. package/dist/esm/middleware.js +193 -0
  54. package/dist/esm/middleware.js.map +1 -0
  55. package/dist/esm/queue.js +110 -0
  56. package/dist/esm/queue.js.map +1 -0
  57. package/dist/esm/retention.js +60 -0
  58. package/dist/esm/retention.js.map +1 -0
  59. package/dist/esm/types.js +8 -0
  60. package/dist/esm/types.js.map +1 -0
  61. package/dist/types/adapters/adapter.interface.d.ts +7 -0
  62. package/dist/types/adapters/mongo.adapter.d.ts +25 -0
  63. package/dist/types/adapters/mysql.adapter.d.ts +24 -0
  64. package/dist/types/adapters/pg.adapter.d.ts +29 -0
  65. package/dist/types/capture.d.ts +88 -0
  66. package/dist/types/config.d.ts +38 -0
  67. package/dist/types/dashboard/api.d.ts +49 -0
  68. package/dist/types/dashboard/router.d.ts +28 -0
  69. package/dist/types/index.d.ts +31 -0
  70. package/dist/types/masker.d.ts +15 -0
  71. package/dist/types/middleware.d.ts +67 -0
  72. package/dist/types/queue.d.ts +49 -0
  73. package/dist/types/retention.d.ts +30 -0
  74. package/dist/types/types.d.ts +101 -0
  75. package/package.json +48 -0
@@ -0,0 +1,243 @@
1
+ "use strict";
2
+ /**
3
+ * MySQLAdapter — StorageAdapter implementation for MySQL using mysql2/promise.
4
+ *
5
+ * Compiles under `strict: true` with zero errors.
6
+ * Requirements: 1.6, 1.7, 6.1, 6.3, 6.5, 7.4
7
+ */
8
+ var __importDefault = (this && this.__importDefault) || function (mod) {
9
+ return (mod && mod.__esModule) ? mod : { "default": mod };
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.MySQLAdapter = void 0;
13
+ const promise_1 = __importDefault(require("mysql2/promise"));
14
+ // ---------------------------------------------------------------------------
15
+ // Column name mapping: JS camelCase → SQL snake_case
16
+ // ---------------------------------------------------------------------------
17
+ const SORT_COLUMN_MAP = {
18
+ timestamp: 'timestamp',
19
+ responseTime: 'response_time',
20
+ statusCode: 'status_code',
21
+ };
22
+ // ---------------------------------------------------------------------------
23
+ // DDL
24
+ // ---------------------------------------------------------------------------
25
+ const DDL = `
26
+ CREATE TABLE IF NOT EXISTS requestscope_records (
27
+ id VARCHAR(36) NOT NULL PRIMARY KEY,
28
+ method VARCHAR(10) NOT NULL,
29
+ url TEXT NOT NULL,
30
+ route VARCHAR(500) NULL,
31
+ query_params JSON NOT NULL,
32
+ path_params JSON NOT NULL,
33
+ request_headers JSON NOT NULL,
34
+ request_body MEDIUMTEXT NOT NULL,
35
+ request_body_size INT UNSIGNED NOT NULL,
36
+ client_ip VARCHAR(45) NOT NULL,
37
+ user_agent TEXT NOT NULL,
38
+ status_code SMALLINT NOT NULL,
39
+ response_headers JSON NOT NULL,
40
+ response_body MEDIUMTEXT NOT NULL,
41
+ response_body_size INT UNSIGNED NOT NULL,
42
+ response_time FLOAT NOT NULL,
43
+ error_message TEXT NULL,
44
+ error_stack TEXT NULL,
45
+ error_status_code SMALLINT NULL,
46
+ timestamp VARCHAR(30) NOT NULL,
47
+ INDEX idx_timestamp (timestamp),
48
+ INDEX idx_status_code (status_code),
49
+ INDEX idx_method (method)
50
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
51
+ `.trim();
52
+ // ---------------------------------------------------------------------------
53
+ // Helpers
54
+ // ---------------------------------------------------------------------------
55
+ /**
56
+ * Parse a JSON column value. MySQL drivers may return it as a string or
57
+ * as an already-parsed object depending on the version/config.
58
+ */
59
+ function parseJson(value) {
60
+ if (value === null || value === undefined)
61
+ return {};
62
+ if (typeof value === 'object')
63
+ return value;
64
+ if (typeof value === 'string') {
65
+ try {
66
+ return JSON.parse(value);
67
+ }
68
+ catch {
69
+ return {};
70
+ }
71
+ }
72
+ return {};
73
+ }
74
+ /** Map a database row back to a `RequestRecord`. */
75
+ function rowToRecord(row) {
76
+ return {
77
+ id: row.id,
78
+ method: row.method,
79
+ url: row.url,
80
+ route: row.route,
81
+ queryParams: parseJson(row.query_params),
82
+ pathParams: parseJson(row.path_params),
83
+ requestHeaders: parseJson(row.request_headers),
84
+ requestBody: row.request_body,
85
+ requestBodySize: row.request_body_size,
86
+ clientIp: row.client_ip,
87
+ userAgent: row.user_agent,
88
+ statusCode: row.status_code,
89
+ responseHeaders: parseJson(row.response_headers),
90
+ responseBody: row.response_body,
91
+ responseBodySize: row.response_body_size,
92
+ responseTime: row.response_time,
93
+ errorMessage: row.error_message,
94
+ errorStack: row.error_stack,
95
+ errorStatusCode: row.error_status_code,
96
+ timestamp: row.timestamp,
97
+ };
98
+ }
99
+ /** Resolve the `statusCodeGroup` filter to a `[min, max)` pair. */
100
+ function statusGroupRange(group) {
101
+ const base = parseInt(group[0], 10) * 100;
102
+ return [base, base + 100];
103
+ }
104
+ // ---------------------------------------------------------------------------
105
+ // MySQLAdapter
106
+ // ---------------------------------------------------------------------------
107
+ class MySQLAdapter {
108
+ constructor(config) {
109
+ this.pool = null;
110
+ this.config = config;
111
+ }
112
+ // -------------------------------------------------------------------------
113
+ // initialize
114
+ // -------------------------------------------------------------------------
115
+ async initialize() {
116
+ const options = {
117
+ host: this.config.host ?? 'localhost',
118
+ port: this.config.port ?? 3306,
119
+ database: this.config.database,
120
+ user: this.config.username,
121
+ password: this.config.password,
122
+ connectionLimit: this.config.poolSize ?? 5,
123
+ ssl: this.config.ssl ? { rejectUnauthorized: true } : undefined,
124
+ // Return JSON columns as strings so we control the parsing
125
+ typeCast: false,
126
+ };
127
+ this.pool = promise_1.default.createPool(options);
128
+ await this.pool.execute(DDL);
129
+ }
130
+ // -------------------------------------------------------------------------
131
+ // insert
132
+ // -------------------------------------------------------------------------
133
+ async insert(records) {
134
+ if (records.length === 0)
135
+ return;
136
+ const pool = this.getPool();
137
+ // Build: INSERT INTO ... VALUES (?, ...), (?, ...), ...
138
+ const columnList = [
139
+ 'id', 'method', 'url', 'route',
140
+ 'query_params', 'path_params', 'request_headers',
141
+ 'request_body', 'request_body_size',
142
+ 'client_ip', 'user_agent',
143
+ 'status_code', 'response_headers',
144
+ 'response_body', 'response_body_size',
145
+ 'response_time',
146
+ 'error_message', 'error_stack', 'error_status_code',
147
+ 'timestamp',
148
+ ];
149
+ const placeholderRow = `(${columnList.map(() => '?').join(', ')})`;
150
+ const placeholders = records.map(() => placeholderRow).join(', ');
151
+ const sql = `INSERT INTO requestscope_records (${columnList.join(', ')}) VALUES ${placeholders}`;
152
+ const values = [];
153
+ for (const r of records) {
154
+ values.push(r.id, r.method, r.url, r.route, JSON.stringify(r.queryParams), JSON.stringify(r.pathParams), JSON.stringify(r.requestHeaders), r.requestBody, r.requestBodySize, r.clientIp, r.userAgent, r.statusCode, JSON.stringify(r.responseHeaders), r.responseBody, r.responseBodySize, r.responseTime, r.errorMessage, r.errorStack, r.errorStatusCode, r.timestamp);
155
+ }
156
+ await pool.execute(sql, values);
157
+ }
158
+ // -------------------------------------------------------------------------
159
+ // query
160
+ // -------------------------------------------------------------------------
161
+ async query(filters, pagination) {
162
+ const pool = this.getPool();
163
+ const conditions = [];
164
+ const params = [];
165
+ // id — exact match
166
+ if (filters.id !== undefined) {
167
+ conditions.push('id = ?');
168
+ params.push(filters.id);
169
+ }
170
+ // search — url LIKE ?
171
+ if (filters.search !== undefined) {
172
+ conditions.push('url LIKE ?');
173
+ params.push(`%${filters.search}%`);
174
+ }
175
+ // startDate — timestamp >= ?
176
+ if (filters.startDate !== undefined) {
177
+ conditions.push('timestamp >= ?');
178
+ params.push(filters.startDate);
179
+ }
180
+ // endDate — timestamp <= ?
181
+ if (filters.endDate !== undefined) {
182
+ conditions.push('timestamp <= ?');
183
+ params.push(filters.endDate);
184
+ }
185
+ // statusCode (exact, takes precedence over group)
186
+ if (filters.statusCode !== undefined) {
187
+ conditions.push('status_code = ?');
188
+ params.push(filters.statusCode);
189
+ }
190
+ else if (filters.statusCodeGroup !== undefined) {
191
+ const [min, max] = statusGroupRange(filters.statusCodeGroup);
192
+ conditions.push('status_code >= ? AND status_code < ?');
193
+ params.push(min, max);
194
+ }
195
+ // method — case-insensitive
196
+ if (filters.method !== undefined) {
197
+ conditions.push('LOWER(method) = LOWER(?)');
198
+ params.push(filters.method);
199
+ }
200
+ const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
201
+ // Sort
202
+ const sortColRaw = filters.sortBy ?? 'timestamp';
203
+ const sortCol = SORT_COLUMN_MAP[sortColRaw] ?? 'timestamp';
204
+ const sortDir = (filters.sortOrder ?? 'desc').toUpperCase() === 'ASC' ? 'ASC' : 'DESC';
205
+ const orderClause = `ORDER BY ${sortCol} ${sortDir}`;
206
+ // COUNT query (reuses same params)
207
+ const countSql = `SELECT COUNT(*) AS total FROM requestscope_records ${whereClause}`;
208
+ const [countRows] = await pool.execute(countSql, params);
209
+ const total = Number(countRows[0]?.total ?? 0);
210
+ // Page slice
211
+ const { page, pageSize } = pagination;
212
+ const offset = (Math.max(1, page) - 1) * pageSize;
213
+ const dataSql = `
214
+ SELECT * FROM requestscope_records
215
+ ${whereClause}
216
+ ${orderClause}
217
+ LIMIT ? OFFSET ?
218
+ `.trim();
219
+ const [rows] = await pool.execute(dataSql, [...params, pageSize, offset]);
220
+ const records = rows.map(rowToRecord);
221
+ return { records, total };
222
+ }
223
+ // -------------------------------------------------------------------------
224
+ // deleteOlderThan
225
+ // -------------------------------------------------------------------------
226
+ async deleteOlderThan(date) {
227
+ const pool = this.getPool();
228
+ const iso = date.toISOString();
229
+ const [result] = await pool.execute('DELETE FROM requestscope_records WHERE timestamp < ?', [iso]);
230
+ return result.affectedRows;
231
+ }
232
+ // -------------------------------------------------------------------------
233
+ // Private helpers
234
+ // -------------------------------------------------------------------------
235
+ getPool() {
236
+ if (this.pool === null) {
237
+ throw new Error('MySQLAdapter: call initialize() before using the adapter');
238
+ }
239
+ return this.pool;
240
+ }
241
+ }
242
+ exports.MySQLAdapter = MySQLAdapter;
243
+ //# sourceMappingURL=mysql.adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mysql.adapter.js","sourceRoot":"","sources":["../../../src/adapters/mysql.adapter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,334 @@
1
+ "use strict";
2
+ /**
3
+ * PgAdapter — StorageAdapter implementation for PostgreSQL using pg.
4
+ *
5
+ * Compiles under `strict: true` with zero errors.
6
+ * Requirements: 1.6, 1.7, 6.1, 6.4, 6.5, 7.4
7
+ */
8
+ Object.defineProperty(exports, "__esModule", { value: true });
9
+ exports.PgAdapter = void 0;
10
+ const pg_1 = require("pg");
11
+ // ---------------------------------------------------------------------------
12
+ // Column name mapping: JS camelCase → SQL snake_case
13
+ // ---------------------------------------------------------------------------
14
+ const SORT_COLUMN_MAP = {
15
+ timestamp: 'timestamp',
16
+ responseTime: 'response_time',
17
+ statusCode: 'status_code',
18
+ };
19
+ // ---------------------------------------------------------------------------
20
+ // DDL
21
+ // ---------------------------------------------------------------------------
22
+ const DDL_TABLE = `
23
+ CREATE TABLE IF NOT EXISTS requestscope_records (
24
+ id VARCHAR(36) NOT NULL PRIMARY KEY,
25
+ method VARCHAR(10) NOT NULL,
26
+ url TEXT NOT NULL,
27
+ route TEXT,
28
+ query_params JSONB NOT NULL,
29
+ path_params JSONB NOT NULL,
30
+ request_headers JSONB NOT NULL,
31
+ request_body TEXT NOT NULL,
32
+ request_body_size INTEGER NOT NULL,
33
+ client_ip VARCHAR(45) NOT NULL,
34
+ user_agent TEXT NOT NULL,
35
+ status_code SMALLINT NOT NULL,
36
+ response_headers JSONB NOT NULL,
37
+ response_body TEXT NOT NULL,
38
+ response_body_size INTEGER NOT NULL,
39
+ response_time REAL NOT NULL,
40
+ error_message TEXT,
41
+ error_stack TEXT,
42
+ error_status_code SMALLINT,
43
+ timestamp VARCHAR(30) NOT NULL
44
+ )
45
+ `.trim();
46
+ const DDL_IDX_TIMESTAMP = `CREATE INDEX IF NOT EXISTS idx_rs_timestamp ON requestscope_records (timestamp DESC)`;
47
+ const DDL_IDX_STATUS = `CREATE INDEX IF NOT EXISTS idx_rs_status ON requestscope_records (status_code)`;
48
+ const DDL_IDX_METHOD = `CREATE INDEX IF NOT EXISTS idx_rs_method ON requestscope_records (method)`;
49
+ // ---------------------------------------------------------------------------
50
+ // Helpers
51
+ // ---------------------------------------------------------------------------
52
+ /**
53
+ * Ensure a JSONB column value (which pg already parses to an object) is
54
+ * returned as `Record<string, string>`. Falls back to `{}` on any error.
55
+ */
56
+ function parseJsonb(value) {
57
+ if (value === null || value === undefined)
58
+ return {};
59
+ if (typeof value === 'object')
60
+ return value;
61
+ if (typeof value === 'string') {
62
+ try {
63
+ return JSON.parse(value);
64
+ }
65
+ catch {
66
+ return {};
67
+ }
68
+ }
69
+ return {};
70
+ }
71
+ /** Map a database row back to a `RequestRecord`. */
72
+ function rowToRecord(row) {
73
+ return {
74
+ id: row.id,
75
+ method: row.method,
76
+ url: row.url,
77
+ route: row.route,
78
+ queryParams: parseJsonb(row.query_params),
79
+ pathParams: parseJsonb(row.path_params),
80
+ requestHeaders: parseJsonb(row.request_headers),
81
+ requestBody: row.request_body,
82
+ requestBodySize: Number(row.request_body_size),
83
+ clientIp: row.client_ip,
84
+ userAgent: row.user_agent,
85
+ statusCode: Number(row.status_code),
86
+ responseHeaders: parseJsonb(row.response_headers),
87
+ responseBody: row.response_body,
88
+ responseBodySize: Number(row.response_body_size),
89
+ responseTime: Number(row.response_time),
90
+ errorMessage: row.error_message,
91
+ errorStack: row.error_stack,
92
+ errorStatusCode: row.error_status_code !== null ? Number(row.error_status_code) : null,
93
+ timestamp: row.timestamp,
94
+ };
95
+ }
96
+ /** Resolve the `statusCodeGroup` filter to a `[min, max)` pair. */
97
+ function statusGroupRange(group) {
98
+ const base = parseInt(group[0], 10) * 100;
99
+ return [base, base + 100];
100
+ }
101
+ // ---------------------------------------------------------------------------
102
+ // PgAdapter
103
+ // ---------------------------------------------------------------------------
104
+ class PgAdapter {
105
+ constructor(config) {
106
+ this.pool = null;
107
+ this.config = config;
108
+ }
109
+ // -------------------------------------------------------------------------
110
+ // initialize
111
+ // -------------------------------------------------------------------------
112
+ async initialize() {
113
+ const poolConfig = {
114
+ host: this.config.host ?? 'localhost',
115
+ port: this.config.port ?? 5432,
116
+ database: this.config.database,
117
+ user: this.config.username,
118
+ password: this.config.password,
119
+ max: this.config.poolSize ?? 5,
120
+ ssl: this.config.ssl ? { rejectUnauthorized: true } : undefined,
121
+ };
122
+ this.pool = new pg_1.Pool(poolConfig);
123
+ const client = await this.pool.connect();
124
+ try {
125
+ await client.query(DDL_TABLE);
126
+ await client.query(DDL_IDX_TIMESTAMP);
127
+ await client.query(DDL_IDX_STATUS);
128
+ await client.query(DDL_IDX_METHOD);
129
+ }
130
+ finally {
131
+ client.release();
132
+ }
133
+ }
134
+ // -------------------------------------------------------------------------
135
+ // insert
136
+ // -------------------------------------------------------------------------
137
+ /**
138
+ * Batch-inserts records using unnest arrays for efficient multi-row inserts.
139
+ *
140
+ * INSERT INTO requestscope_records (col1, col2, ...)
141
+ * SELECT * FROM unnest($1::varchar[], $2::text[], ...)
142
+ */
143
+ async insert(records) {
144
+ if (records.length === 0)
145
+ return;
146
+ const pool = this.getPool();
147
+ // Collect per-column arrays
148
+ const ids = [];
149
+ const methods = [];
150
+ const urls = [];
151
+ const routes = [];
152
+ const queryParams = [];
153
+ const pathParams = [];
154
+ const requestHeaders = [];
155
+ const requestBodies = [];
156
+ const requestBodySizes = [];
157
+ const clientIps = [];
158
+ const userAgents = [];
159
+ const statusCodes = [];
160
+ const responseHeaders = [];
161
+ const responseBodies = [];
162
+ const responseBodySizes = [];
163
+ const responseTimes = [];
164
+ const errorMessages = [];
165
+ const errorStacks = [];
166
+ const errorStatusCodes = [];
167
+ const timestamps = [];
168
+ for (const r of records) {
169
+ ids.push(r.id);
170
+ methods.push(r.method);
171
+ urls.push(r.url);
172
+ routes.push(r.route);
173
+ queryParams.push(JSON.stringify(r.queryParams));
174
+ pathParams.push(JSON.stringify(r.pathParams));
175
+ requestHeaders.push(JSON.stringify(r.requestHeaders));
176
+ requestBodies.push(r.requestBody);
177
+ requestBodySizes.push(r.requestBodySize);
178
+ clientIps.push(r.clientIp);
179
+ userAgents.push(r.userAgent);
180
+ statusCodes.push(r.statusCode);
181
+ responseHeaders.push(JSON.stringify(r.responseHeaders));
182
+ responseBodies.push(r.responseBody);
183
+ responseBodySizes.push(r.responseBodySize);
184
+ responseTimes.push(r.responseTime);
185
+ errorMessages.push(r.errorMessage);
186
+ errorStacks.push(r.errorStack);
187
+ errorStatusCodes.push(r.errorStatusCode);
188
+ timestamps.push(r.timestamp);
189
+ }
190
+ const sql = `
191
+ INSERT INTO requestscope_records (
192
+ id, method, url, route,
193
+ query_params, path_params, request_headers,
194
+ request_body, request_body_size,
195
+ client_ip, user_agent,
196
+ status_code, response_headers,
197
+ response_body, response_body_size,
198
+ response_time,
199
+ error_message, error_stack, error_status_code,
200
+ timestamp
201
+ )
202
+ SELECT * FROM unnest(
203
+ $1::varchar[],
204
+ $2::varchar[],
205
+ $3::text[],
206
+ $4::text[],
207
+ $5::jsonb[],
208
+ $6::jsonb[],
209
+ $7::jsonb[],
210
+ $8::text[],
211
+ $9::integer[],
212
+ $10::varchar[],
213
+ $11::text[],
214
+ $12::smallint[],
215
+ $13::jsonb[],
216
+ $14::text[],
217
+ $15::integer[],
218
+ $16::real[],
219
+ $17::text[],
220
+ $18::text[],
221
+ $19::smallint[],
222
+ $20::varchar[]
223
+ )
224
+ `.trim();
225
+ await pool.query(sql, [
226
+ ids,
227
+ methods,
228
+ urls,
229
+ routes,
230
+ queryParams,
231
+ pathParams,
232
+ requestHeaders,
233
+ requestBodies,
234
+ requestBodySizes,
235
+ clientIps,
236
+ userAgents,
237
+ statusCodes,
238
+ responseHeaders,
239
+ responseBodies,
240
+ responseBodySizes,
241
+ responseTimes,
242
+ errorMessages,
243
+ errorStacks,
244
+ errorStatusCodes,
245
+ timestamps,
246
+ ]);
247
+ }
248
+ // -------------------------------------------------------------------------
249
+ // query
250
+ // -------------------------------------------------------------------------
251
+ async query(filters, pagination) {
252
+ const pool = this.getPool();
253
+ const conditions = [];
254
+ const params = [];
255
+ let paramIdx = 1;
256
+ // Helper to add a parameter and return its $N placeholder
257
+ const addParam = (value) => {
258
+ params.push(value);
259
+ return `$${paramIdx++}`;
260
+ };
261
+ // id — exact match
262
+ if (filters.id !== undefined) {
263
+ conditions.push(`id = ${addParam(filters.id)}`);
264
+ }
265
+ // search — url ILIKE $N
266
+ if (filters.search !== undefined) {
267
+ conditions.push(`url ILIKE ${addParam(`%${filters.search}%`)}`);
268
+ }
269
+ // startDate — timestamp >= $N
270
+ if (filters.startDate !== undefined) {
271
+ conditions.push(`timestamp >= ${addParam(filters.startDate)}`);
272
+ }
273
+ // endDate — timestamp <= $N
274
+ if (filters.endDate !== undefined) {
275
+ conditions.push(`timestamp <= ${addParam(filters.endDate)}`);
276
+ }
277
+ // statusCode (exact, takes precedence over group)
278
+ if (filters.statusCode !== undefined) {
279
+ conditions.push(`status_code = ${addParam(filters.statusCode)}`);
280
+ }
281
+ else if (filters.statusCodeGroup !== undefined) {
282
+ const [min, max] = statusGroupRange(filters.statusCodeGroup);
283
+ conditions.push(`status_code >= ${addParam(min)} AND status_code < ${addParam(max)}`);
284
+ }
285
+ // method — case-insensitive
286
+ if (filters.method !== undefined) {
287
+ conditions.push(`LOWER(method) = LOWER(${addParam(filters.method)})`);
288
+ }
289
+ const whereClause = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';
290
+ // Sort
291
+ const sortColRaw = filters.sortBy ?? 'timestamp';
292
+ const sortCol = SORT_COLUMN_MAP[sortColRaw] ?? 'timestamp';
293
+ const sortDir = (filters.sortOrder ?? 'desc').toUpperCase() === 'ASC' ? 'ASC' : 'DESC';
294
+ const orderClause = `ORDER BY ${sortCol} ${sortDir}`;
295
+ // COUNT query (reuses same params)
296
+ const countSql = `SELECT COUNT(*) AS total FROM requestscope_records ${whereClause}`;
297
+ const countResult = await pool.query(countSql, params);
298
+ const total = Number(countResult.rows[0]?.total ?? 0);
299
+ // Page slice — add LIMIT and OFFSET as the next params
300
+ const { page, pageSize } = pagination;
301
+ const offset = (Math.max(1, page) - 1) * pageSize;
302
+ const limitPlaceholder = addParam(pageSize);
303
+ const offsetPlaceholder = addParam(offset);
304
+ const dataSql = `
305
+ SELECT * FROM requestscope_records
306
+ ${whereClause}
307
+ ${orderClause}
308
+ LIMIT ${limitPlaceholder} OFFSET ${offsetPlaceholder}
309
+ `.trim();
310
+ const dataResult = await pool.query(dataSql, params);
311
+ const records = dataResult.rows.map(rowToRecord);
312
+ return { records, total };
313
+ }
314
+ // -------------------------------------------------------------------------
315
+ // deleteOlderThan
316
+ // -------------------------------------------------------------------------
317
+ async deleteOlderThan(date) {
318
+ const pool = this.getPool();
319
+ const iso = date.toISOString();
320
+ const result = await pool.query('DELETE FROM requestscope_records WHERE timestamp < $1', [iso]);
321
+ return result.rowCount ?? 0;
322
+ }
323
+ // -------------------------------------------------------------------------
324
+ // Private helpers
325
+ // -------------------------------------------------------------------------
326
+ getPool() {
327
+ if (this.pool === null) {
328
+ throw new Error('PgAdapter: call initialize() before using the adapter');
329
+ }
330
+ return this.pool;
331
+ }
332
+ }
333
+ exports.PgAdapter = PgAdapter;
334
+ //# sourceMappingURL=pg.adapter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pg.adapter.js","sourceRoot":"","sources":["../../../src/adapters/pg.adapter.ts"],"names":[],"mappings":";AAAA;;;;;GAKG;;;AAEH,2BAAmD;AAGnD,8EAA8E;AAC9E,qDAAqD;AACrD,8EAA8E;AAE9E,MAAM,eAAe,GAA2B;IAC9C,SAAS,EAAE,WAAW;IACtB,YAAY,EAAE,eAAe;IAC7B,UAAU,EAAE,aAAa;CAC1B,CAAC;AAEF,8EAA8E;AAC9E,MAAM;AACN,8EAA8E;AAE9E,MAAM,SAAS,GAAG;;;;;;;;;;;;;;;;;;;;;;;CAuBjB,CAAC,IAAI,EAAE,CAAC;AAET,MAAM,iBAAiB,GAAG,sFAAsF,CAAC;AACjH,MAAM,cAAc,GAAM,gFAAgF,CAAC;AAC3G,MAAM,cAAc,GAAM,2EAA2E,CAAC;AAiCtG,8EAA8E;AAC9E,UAAU;AACV,8EAA8E;AAE9E;;;GAGG;AACH,SAAS,UAAU,CAAC,KAAc;IAChC,IAAI,KAAK,KAAK,IAAI,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IACrD,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,KAA+B,CAAC;IACtE,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,CAAC;YACH,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAA2B,CAAC;QACrD,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;IACH,CAAC;IACD,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,oDAAoD;AACpD,SAAS,WAAW,CAAC,GAAc;IACjC,OAAO;QACL,EAAE,EAAE,GAAG,CAAC,EAAE;QACV,MAAM,EAAE,GAAG,CAAC,MAAM;QAClB,GAAG,EAAE,GAAG,CAAC,GAAG;QACZ,KAAK,EAAE,GAAG,CAAC,KAAK;QAChB,WAAW,EAAE,UAAU,CAAC,GAAG,CAAC,YAAY,CAAC;QACzC,UAAU,EAAE,UAAU,CAAC,GAAG,CAAC,WAAW,CAAC;QACvC,cAAc,EAAE,UAAU,CAAC,GAAG,CAAC,eAAe,CAAC;QAC/C,WAAW,EAAE,GAAG,CAAC,YAAY;QAC7B,eAAe,EAAE,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC;QAC9C,QAAQ,EAAE,GAAG,CAAC,SAAS;QACvB,SAAS,EAAE,GAAG,CAAC,UAAU;QACzB,UAAU,EAAE,MAAM,CAAC,GAAG,CAAC,WAAW,CAAC;QACnC,eAAe,EAAE,UAAU,CAAC,GAAG,CAAC,gBAAgB,CAAC;QACjD,YAAY,EAAE,GAAG,CAAC,aAAa;QAC/B,gBAAgB,EAAE,MAAM,CAAC,GAAG,CAAC,kBAAkB,CAAC;QAChD,YAAY,EAAE,MAAM,CAAC,GAAG,CAAC,aAAa,CAAC;QACvC,YAAY,EAAE,GAAG,CAAC,aAAa;QAC/B,UAAU,EAAE,GAAG,CAAC,WAAW;QAC3B,eAAe,EAAE,GAAG,CAAC,iBAAiB,KAAK,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,CAAC,CAAC,IAAI;QACtF,SAAS,EAAE,GAAG,CAAC,SAAS;KACzB,CAAC;AACJ,CAAC;AAED,mEAAmE;AACnE,SAAS,gBAAgB,CAAC,KAAoC;IAC5D,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC;IAC1C,OAAO,CAAC,IAAI,EAAE,IAAI,GAAG,GAAG,CAAC,CAAC;AAC5B,CAAC;AAED,8EAA8E;AAC9E,YAAY;AACZ,8EAA8E;AAE9E,MAAa,SAAS;IAIpB,YAAY,MAAqB;QAHzB,SAAI,GAAgB,IAAI,CAAC;QAI/B,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,4EAA4E;IAC5E,aAAa;IACb,4EAA4E;IAE5E,KAAK,CAAC,UAAU;QACd,MAAM,UAAU,GAAe;YAC7B,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,WAAW;YACrC,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,IAAI,IAAI;YAC9B,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;YAC9B,IAAI,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;YAC1B,QAAQ,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ;YAC9B,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,QAAQ,IAAI,CAAC;YAC9B,GAAG,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,kBAAkB,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,SAAS;SAChE,CAAC;QAEF,IAAI,CAAC,IAAI,GAAG,IAAI,SAAI,CAAC,UAAU,CAAC,CAAC;QAEjC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;QACzC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;YAC9B,MAAM,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,CAAC;YACtC,MAAM,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;YACnC,MAAM,MAAM,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC;QACrC,CAAC;gBAAS,CAAC;YACT,MAAM,CAAC,OAAO,EAAE,CAAC;QACnB,CAAC;IACH,CAAC;IAED,4EAA4E;IAC5E,SAAS;IACT,4EAA4E;IAE5E;;;;;OAKG;IACH,KAAK,CAAC,MAAM,CAAC,OAAwB;QACnC,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QAEjC,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAE5B,4BAA4B;QAC5B,MAAM,GAAG,GAAuB,EAAE,CAAC;QACnC,MAAM,OAAO,GAAoB,EAAE,CAAC;QACpC,MAAM,IAAI,GAAuB,EAAE,CAAC;QACpC,MAAM,MAAM,GAAqB,EAAE,CAAC;QACpC,MAAM,WAAW,GAAgB,EAAE,CAAC;QACpC,MAAM,UAAU,GAAiB,EAAE,CAAC;QACpC,MAAM,cAAc,GAAa,EAAE,CAAC;QACpC,MAAM,aAAa,GAAc,EAAE,CAAC;QACpC,MAAM,gBAAgB,GAAY,EAAE,CAAC;QACrC,MAAM,SAAS,GAAkB,EAAE,CAAC;QACpC,MAAM,UAAU,GAAiB,EAAE,CAAC;QACpC,MAAM,WAAW,GAAgB,EAAE,CAAC;QACpC,MAAM,eAAe,GAAY,EAAE,CAAC;QACpC,MAAM,cAAc,GAAa,EAAE,CAAC;QACpC,MAAM,iBAAiB,GAAY,EAAE,CAAC;QACtC,MAAM,aAAa,GAAc,EAAE,CAAC;QACpC,MAAM,aAAa,GAAuB,EAAE,CAAC;QAC7C,MAAM,WAAW,GAAyB,EAAE,CAAC;QAC7C,MAAM,gBAAgB,GAAqB,EAAE,CAAC;QAC9C,MAAM,UAAU,GAAiB,EAAE,CAAC;QAEpC,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;YACxB,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;YACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YACvB,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;YACjB,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;YACrB,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC;YAChD,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;YAC9C,cAAc,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC;YACtD,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC;YAClC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;YACzC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC;YAC3B,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;YAC7B,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;YAC/B,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC;YACxD,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;YACpC,iBAAiB,CAAC,IAAI,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC;YAC3C,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;YACnC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;YACnC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;YAC/B,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;YACzC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;QAC/B,CAAC;QAED,MAAM,GAAG,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KAkCX,CAAC,IAAI,EAAE,CAAC;QAET,MAAM,IAAI,CAAC,KAAK,CAAC,GAAG,EAAE;YACpB,GAAG;YACH,OAAO;YACP,IAAI;YACJ,MAAM;YACN,WAAW;YACX,UAAU;YACV,cAAc;YACd,aAAa;YACb,gBAAgB;YAChB,SAAS;YACT,UAAU;YACV,WAAW;YACX,eAAe;YACf,cAAc;YACd,iBAAiB;YACjB,aAAa;YACb,aAAa;YACb,WAAW;YACX,gBAAgB;YAChB,UAAU;SACX,CAAC,CAAC;IACL,CAAC;IAED,4EAA4E;IAC5E,QAAQ;IACR,4EAA4E;IAE5E,KAAK,CAAC,KAAK,CACT,OAAqB,EACrB,UAA8C;QAE9C,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAE5B,MAAM,UAAU,GAAa,EAAE,CAAC;QAChC,MAAM,MAAM,GAAc,EAAE,CAAC;QAE7B,IAAI,QAAQ,GAAG,CAAC,CAAC;QAEjB,0DAA0D;QAC1D,MAAM,QAAQ,GAAG,CAAC,KAAc,EAAU,EAAE;YAC1C,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YACnB,OAAO,IAAI,QAAQ,EAAE,EAAE,CAAC;QAC1B,CAAC,CAAC;QAEF,mBAAmB;QACnB,IAAI,OAAO,CAAC,EAAE,KAAK,SAAS,EAAE,CAAC;YAC7B,UAAU,CAAC,IAAI,CAAC,QAAQ,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAClD,CAAC;QAED,wBAAwB;QACxB,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACjC,UAAU,CAAC,IAAI,CAAC,aAAa,QAAQ,CAAC,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,CAAC;QAClE,CAAC;QAED,8BAA8B;QAC9B,IAAI,OAAO,CAAC,SAAS,KAAK,SAAS,EAAE,CAAC;YACpC,UAAU,CAAC,IAAI,CAAC,gBAAgB,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACjE,CAAC;QAED,4BAA4B;QAC5B,IAAI,OAAO,CAAC,OAAO,KAAK,SAAS,EAAE,CAAC;YAClC,UAAU,CAAC,IAAI,CAAC,gBAAgB,QAAQ,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;QAC/D,CAAC;QAED,kDAAkD;QAClD,IAAI,OAAO,CAAC,UAAU,KAAK,SAAS,EAAE,CAAC;YACrC,UAAU,CAAC,IAAI,CAAC,iBAAiB,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;QACnE,CAAC;aAAM,IAAI,OAAO,CAAC,eAAe,KAAK,SAAS,EAAE,CAAC;YACjD,MAAM,CAAC,GAAG,EAAE,GAAG,CAAC,GAAG,gBAAgB,CAAC,OAAO,CAAC,eAAe,CAAC,CAAC;YAC7D,UAAU,CAAC,IAAI,CAAC,kBAAkB,QAAQ,CAAC,GAAG,CAAC,sBAAsB,QAAQ,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACxF,CAAC;QAED,4BAA4B;QAC5B,IAAI,OAAO,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;YACjC,UAAU,CAAC,IAAI,CAAC,yBAAyB,QAAQ,CAAC,OAAO,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACxE,CAAC;QAED,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,UAAU,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QAErF,OAAO;QACP,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,IAAI,WAAW,CAAC;QACjD,MAAM,OAAO,GAAG,eAAe,CAAC,UAAU,CAAC,IAAI,WAAW,CAAC;QAC3D,MAAM,OAAO,GAAG,CAAC,OAAO,CAAC,SAAS,IAAI,MAAM,CAAC,CAAC,WAAW,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;QACvF,MAAM,WAAW,GAAG,YAAY,OAAO,IAAI,OAAO,EAAE,CAAC;QAErD,mCAAmC;QACnC,MAAM,QAAQ,GAAG,sDAAsD,WAAW,EAAE,CAAC;QACrF,MAAM,WAAW,GAA0B,MAAM,IAAI,CAAC,KAAK,CAAW,QAAQ,EAAE,MAAM,CAAC,CAAC;QACxF,MAAM,KAAK,GAAG,MAAM,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC;QAEtD,uDAAuD;QACvD,MAAM,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,UAAU,CAAC;QACtC,MAAM,MAAM,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,CAAC,GAAG,QAAQ,CAAC;QAClD,MAAM,gBAAgB,GAAI,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC7C,MAAM,iBAAiB,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC;QAE3C,MAAM,OAAO,GAAG;;QAEZ,WAAW;QACX,WAAW;cACL,gBAAgB,WAAW,iBAAiB;KACrD,CAAC,IAAI,EAAE,CAAC;QAET,MAAM,UAAU,GAA2B,MAAM,IAAI,CAAC,KAAK,CAAY,OAAO,EAAE,MAAM,CAAC,CAAC;QACxF,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC;QAEjD,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;IAC5B,CAAC;IAED,4EAA4E;IAC5E,kBAAkB;IAClB,4EAA4E;IAE5E,KAAK,CAAC,eAAe,CAAC,IAAU;QAC9B,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;QAC5B,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,KAAK,CAC7B,uDAAuD,EACvD,CAAC,GAAG,CAAC,CACN,CAAC;QACF,OAAO,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC;IAC9B,CAAC;IAED,4EAA4E;IAC5E,kBAAkB;IAClB,4EAA4E;IAEpE,OAAO;QACb,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE,CAAC;YACvB,MAAM,IAAI,KAAK,CAAC,uDAAuD,CAAC,CAAC;QAC3E,CAAC;QACD,OAAO,IAAI,CAAC,IAAI,CAAC;IACnB,CAAC;CACF;AA1QD,8BA0QC"}