@resolveio/server-lib 22.2.5 → 22.2.8

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.
@@ -0,0 +1,468 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
14
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
15
+ return new (P || (P = Promise))(function (resolve, reject) {
16
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
17
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
18
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
19
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
20
+ });
21
+ };
22
+ var __generator = (this && this.__generator) || function (thisArg, body) {
23
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype);
24
+ return g.next = verb(0), g["throw"] = verb(1), g["return"] = verb(2), typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
25
+ function verb(n) { return function (v) { return step([n, v]); }; }
26
+ function step(op) {
27
+ if (f) throw new TypeError("Generator is already executing.");
28
+ while (g && (g = 0, op[0] && (_ = 0)), _) try {
29
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
30
+ if (y = 0, t) op = [op[0] & 2, t.value];
31
+ switch (op[0]) {
32
+ case 0: case 1: t = op; break;
33
+ case 4: _.label++; return { value: op[1], done: false };
34
+ case 5: _.label++; y = op[1]; op = [0]; continue;
35
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
36
+ default:
37
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
38
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
39
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
40
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
41
+ if (t[2]) _.ops.pop();
42
+ _.trys.pop(); continue;
43
+ }
44
+ op = body.call(thisArg, _);
45
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
46
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
47
+ }
48
+ };
49
+ Object.defineProperty(exports, "__esModule", { value: true });
50
+ exports.SlowQueryManager = void 0;
51
+ exports.registerSlowQueryManagerDependencies = registerSlowQueryManagerDependencies;
52
+ exports.ensureSlowQueryManager = ensureSlowQueryManager;
53
+ var resolveio_server_app_1 = require("../resolveio-server-app");
54
+ var common_1 = require("../util/common");
55
+ var crypto_1 = require("crypto");
56
+ var slow_query_report_1 = require("../types/slow-query-report");
57
+ var SlowQueryLogs = null;
58
+ var configuredSlowQueryManagerDependencies = null;
59
+ function resolveSlowQueryManagerDependencies(overrides) {
60
+ var resolved = __assign(__assign({}, (configuredSlowQueryManagerDependencies || {})), (overrides || {}));
61
+ if (!resolved.SlowQueryLogs) {
62
+ throw new Error('SlowQueryManager dependencies are not configured.');
63
+ }
64
+ return resolved;
65
+ }
66
+ function applySlowQueryManagerDependencies(dependencies) {
67
+ configuredSlowQueryManagerDependencies = dependencies;
68
+ SlowQueryLogs = dependencies.SlowQueryLogs;
69
+ }
70
+ function registerSlowQueryManagerDependencies(dependencies) {
71
+ applySlowQueryManagerDependencies(dependencies);
72
+ ensureSlowQueryManager();
73
+ }
74
+ var OBJECT_ID_PATTERN = /^[a-f0-9]{24}$/i;
75
+ var UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
76
+ var ISO_DATE_PATTERN = /^\d{4}-\d{2}-\d{2}(?:[tT ][\d:.+-]+)?(?:[zZ]|[+-]\d{2}:?\d{2})?$/;
77
+ var NUMERIC_STRING_PATTERN = /^[-+]?\d+(?:\.\d+)?$/;
78
+ var TOKEN_LIKE_PATTERN = /^[A-Za-z0-9._-]{16,}$/;
79
+ var DATE_HINT_KEY_PATTERN = /(date|time|timestamp|created|updated|expires|expiry|start|end|at)$/i;
80
+ var ID_HINT_KEY_PATTERN = /(^|_)(id|uuid|guid|token|hash|key)$/i;
81
+ var SlowQueryManager = /** @class */ (function () {
82
+ function SlowQueryManager(serverConfig, dependencies) {
83
+ var resolvedDependencies = resolveSlowQueryManagerDependencies(dependencies);
84
+ applySlowQueryManagerDependencies(resolvedDependencies);
85
+ this.serverConfig = serverConfig || {};
86
+ this.config = this.resolveConfig();
87
+ }
88
+ SlowQueryManager.prototype.isReady = function () {
89
+ return !!this.config.enabled;
90
+ };
91
+ SlowQueryManager.prototype.validateIngestKey = function (candidate) {
92
+ var keys = Array.isArray(this.config.ingestKeys) ? this.config.ingestKeys.filter(Boolean) : [];
93
+ if (!keys.length) {
94
+ return true;
95
+ }
96
+ if (!candidate) {
97
+ return false;
98
+ }
99
+ return keys.includes(candidate.trim());
100
+ };
101
+ SlowQueryManager.prototype.ingestSlowQuery = function (payload) {
102
+ return __awaiter(this, void 0, void 0, function () {
103
+ var now, rawFilterValue, rawPipelineValue, rawOptionsValue, provisionalFingerprint, provisionalScopeKey, existing, existingOccurrences, occurrences, existingAvg, totalDuration, avgDuration, previousMax, maxBase, maxDuration, resolvedStatus, resolvedIgnored, filterValue, pipelineValue, optionsValue, explainPlanValue, explainStatsValue, explainGeneratedAtValue, fingerprintScopeKey, canonicalFingerprint, setFields, cleaned, doc;
104
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s, _t, _u;
105
+ return __generator(this, function (_v) {
106
+ switch (_v.label) {
107
+ case 0:
108
+ if (!this.isReady()) {
109
+ throw new Error('SlowQueryManager is not enabled.');
110
+ }
111
+ if (!payload || !payload.queryHash || !payload.collection || typeof payload.durationMs !== 'number' || Number.isNaN(payload.durationMs)) {
112
+ throw new Error('Invalid slow query payload.');
113
+ }
114
+ now = new Date();
115
+ rawFilterValue = (_a = payload.filter) !== null && _a !== void 0 ? _a : {};
116
+ rawPipelineValue = Array.isArray(payload.pipeline) ? payload.pipeline : undefined;
117
+ rawOptionsValue = payload.options;
118
+ provisionalFingerprint = this.buildCanonicalFingerprint(payload.collection, rawFilterValue, rawPipelineValue, rawOptionsValue);
119
+ provisionalScopeKey = this.buildFingerprintScopeKey({
120
+ clientSlug: payload.clientSlug,
121
+ clientName: payload.clientName,
122
+ sourceApp: payload.sourceApp,
123
+ environment: payload.environment,
124
+ publication: payload.publication,
125
+ serverUrl: payload.server_url
126
+ });
127
+ return [4 /*yield*/, SlowQueryLogs.findOne({
128
+ collection: payload.collection,
129
+ canonical_fingerprint_hash: provisionalFingerprint.hash,
130
+ fingerprint_scope_key: provisionalScopeKey
131
+ })];
132
+ case 1:
133
+ existing = _v.sent();
134
+ if (!!existing) return [3 /*break*/, 3];
135
+ return [4 /*yield*/, SlowQueryLogs.findOne(this.buildLegacyDedupeQuery(payload))];
136
+ case 2:
137
+ existing = _v.sent();
138
+ _v.label = 3;
139
+ case 3:
140
+ existingOccurrences = typeof (existing === null || existing === void 0 ? void 0 : existing.occurrences) === 'number' ? existing.occurrences : 0;
141
+ occurrences = existingOccurrences + 1;
142
+ existingAvg = typeof (existing === null || existing === void 0 ? void 0 : existing.avg_duration_ms) === 'number' ? existing.avg_duration_ms : 0;
143
+ totalDuration = existingAvg * existingOccurrences;
144
+ avgDuration = (totalDuration + payload.durationMs) / occurrences;
145
+ previousMax = typeof (existing === null || existing === void 0 ? void 0 : existing.max_duration_ms) === 'number' ? existing.max_duration_ms : payload.durationMs;
146
+ maxBase = Math.max(payload.durationMs, previousMax);
147
+ maxDuration = typeof payload.maxDurationMs === 'number'
148
+ ? Math.max(maxBase, payload.maxDurationMs)
149
+ : maxBase;
150
+ resolvedStatus = payload.status && slow_query_report_1.slowQueryLogStatuses.includes(payload.status)
151
+ ? payload.status
152
+ : ((existing === null || existing === void 0 ? void 0 : existing.status) || 'new');
153
+ resolvedIgnored = typeof payload.ignored === 'boolean'
154
+ ? payload.ignored
155
+ : (typeof (existing === null || existing === void 0 ? void 0 : existing.ignored) === 'boolean' ? existing.ignored : false);
156
+ filterValue = (_c = (_b = payload.filter) !== null && _b !== void 0 ? _b : existing === null || existing === void 0 ? void 0 : existing.filter) !== null && _c !== void 0 ? _c : {};
157
+ pipelineValue = Array.isArray(payload.pipeline)
158
+ ? payload.pipeline
159
+ : existing === null || existing === void 0 ? void 0 : existing.pipeline;
160
+ if (this.config.debugLogging) {
161
+ this.logPipelineDebug(payload, pipelineValue, Array.isArray(existing === null || existing === void 0 ? void 0 : existing.pipeline) ? existing.pipeline : undefined);
162
+ }
163
+ optionsValue = (_d = payload.options) !== null && _d !== void 0 ? _d : existing === null || existing === void 0 ? void 0 : existing.options;
164
+ explainPlanValue = typeof payload.explainPlan !== 'undefined' ? payload.explainPlan : existing === null || existing === void 0 ? void 0 : existing.explain_plan;
165
+ explainStatsValue = typeof payload.explainExecutionStats !== 'undefined' ? payload.explainExecutionStats : existing === null || existing === void 0 ? void 0 : existing.explain_execution_stats;
166
+ explainGeneratedAtValue = typeof payload.explainGeneratedAt !== 'undefined'
167
+ ? this.coerceDate(payload.explainGeneratedAt)
168
+ : existing === null || existing === void 0 ? void 0 : existing.explain_generated_at;
169
+ fingerprintScopeKey = this.buildFingerprintScopeKey({
170
+ clientSlug: (_e = payload.clientSlug) !== null && _e !== void 0 ? _e : existing === null || existing === void 0 ? void 0 : existing.client_slug,
171
+ clientName: (_f = payload.clientName) !== null && _f !== void 0 ? _f : existing === null || existing === void 0 ? void 0 : existing.client_name,
172
+ sourceApp: (_g = payload.sourceApp) !== null && _g !== void 0 ? _g : existing === null || existing === void 0 ? void 0 : existing.source_app,
173
+ environment: (_h = payload.environment) !== null && _h !== void 0 ? _h : existing === null || existing === void 0 ? void 0 : existing.environment,
174
+ publication: (_j = payload.publication) !== null && _j !== void 0 ? _j : existing === null || existing === void 0 ? void 0 : existing.publication,
175
+ serverUrl: (_k = payload.server_url) !== null && _k !== void 0 ? _k : existing === null || existing === void 0 ? void 0 : existing.server_url
176
+ });
177
+ canonicalFingerprint = this.buildCanonicalFingerprint(payload.collection, filterValue, pipelineValue, optionsValue);
178
+ setFields = {
179
+ query_hash: payload.queryHash,
180
+ collection: payload.collection,
181
+ canonical_fingerprint: canonicalFingerprint.serialized,
182
+ canonical_fingerprint_hash: canonicalFingerprint.hash,
183
+ fingerprint_scope_key: fingerprintScopeKey,
184
+ filter: filterValue,
185
+ pipeline: pipelineValue,
186
+ options: optionsValue,
187
+ duration_ms: payload.durationMs,
188
+ max_duration_ms: maxDuration,
189
+ avg_duration_ms: avgDuration,
190
+ threshold_ms: typeof payload.thresholdMs === 'number' ? payload.thresholdMs : existing === null || existing === void 0 ? void 0 : existing.threshold_ms,
191
+ explain_plan: explainPlanValue,
192
+ explain_execution_stats: explainStatsValue,
193
+ explain_generated_at: explainGeneratedAtValue,
194
+ client_slug: (_l = payload.clientSlug) !== null && _l !== void 0 ? _l : existing === null || existing === void 0 ? void 0 : existing.client_slug,
195
+ client_name: (_m = payload.clientName) !== null && _m !== void 0 ? _m : existing === null || existing === void 0 ? void 0 : existing.client_name,
196
+ environment: (_o = payload.environment) !== null && _o !== void 0 ? _o : existing === null || existing === void 0 ? void 0 : existing.environment,
197
+ source_app: (_p = payload.sourceApp) !== null && _p !== void 0 ? _p : existing === null || existing === void 0 ? void 0 : existing.source_app,
198
+ node_hostname: (_q = payload.nodeHostname) !== null && _q !== void 0 ? _q : existing === null || existing === void 0 ? void 0 : existing.node_hostname,
199
+ server_url: (_r = payload.server_url) !== null && _r !== void 0 ? _r : existing === null || existing === void 0 ? void 0 : existing.server_url,
200
+ occurrences: occurrences,
201
+ last_seen_at: now,
202
+ status: resolvedStatus,
203
+ ignored: resolvedIgnored,
204
+ notes: typeof payload.notes === 'string' ? payload.notes : existing === null || existing === void 0 ? void 0 : existing.notes,
205
+ publication: (_s = payload.publication) !== null && _s !== void 0 ? _s : existing === null || existing === void 0 ? void 0 : existing.publication,
206
+ subscription_data: (_t = payload.subscription_data) !== null && _t !== void 0 ? _t : existing === null || existing === void 0 ? void 0 : existing.subscription_data,
207
+ user_id: (_u = payload.userId) !== null && _u !== void 0 ? _u : existing === null || existing === void 0 ? void 0 : existing.user_id
208
+ };
209
+ cleaned = this.cleanSet(setFields);
210
+ if (!existing) return [3 /*break*/, 6];
211
+ cleaned.updatedAt = now;
212
+ return [4 /*yield*/, SlowQueryLogs.updateOne({ _id: existing._id }, { $set: cleaned })];
213
+ case 4:
214
+ _v.sent();
215
+ return [4 /*yield*/, SlowQueryLogs.findOne({ _id: existing._id })];
216
+ case 5: return [2 /*return*/, _v.sent()];
217
+ case 6:
218
+ doc = __assign(__assign({ _id: (0, common_1.objectIdHexString)() }, cleaned), { slow_query_count: 0, slow_query_count_string: 'Pending', auto_fix_attempt_count: 0, first_seen_at: now, createdAt: now, updatedAt: now, verification_status: 'pending', verification_runs: [], verification_next_run_at: now });
219
+ return [4 /*yield*/, SlowQueryLogs.insertOne(doc)];
220
+ case 7:
221
+ _v.sent();
222
+ return [4 /*yield*/, SlowQueryLogs.findOne({ _id: doc._id })];
223
+ case 8: return [2 /*return*/, _v.sent()];
224
+ }
225
+ });
226
+ });
227
+ };
228
+ SlowQueryManager.prototype.buildLegacyDedupeQuery = function (payload) {
229
+ var dedupeQuery = {
230
+ query_hash: payload.queryHash,
231
+ collection: payload.collection
232
+ };
233
+ if (payload.clientSlug) {
234
+ dedupeQuery.client_slug = payload.clientSlug;
235
+ }
236
+ if (payload.environment) {
237
+ dedupeQuery.environment = payload.environment;
238
+ }
239
+ if (payload.sourceApp) {
240
+ dedupeQuery.source_app = payload.sourceApp;
241
+ }
242
+ if (payload.publication) {
243
+ dedupeQuery.publication = payload.publication;
244
+ }
245
+ if (payload.server_url) {
246
+ dedupeQuery.server_url = payload.server_url;
247
+ }
248
+ return dedupeQuery;
249
+ };
250
+ SlowQueryManager.prototype.buildFingerprintScopeKey = function (scope) {
251
+ var clientKey = this.normalizeScopeSegment(scope.clientSlug || scope.clientName || '');
252
+ var sourceApp = this.normalizeScopeSegment(scope.sourceApp || '');
253
+ var environment = this.normalizeScopeSegment(scope.environment || '');
254
+ var publication = this.normalizeScopeSegment(scope.publication || '');
255
+ var serverUrl = this.normalizeScopeSegment(scope.serverUrl || '');
256
+ return [clientKey, sourceApp, environment, publication, serverUrl].join('|');
257
+ };
258
+ SlowQueryManager.prototype.normalizeScopeSegment = function (value) {
259
+ var normalized = String(value || '')
260
+ .trim()
261
+ .toLowerCase()
262
+ .replace(/\s+/g, ' ');
263
+ return normalized || '_';
264
+ };
265
+ SlowQueryManager.prototype.buildCanonicalFingerprint = function (collection, filterValue, pipelineValue, optionsValue) {
266
+ var canonicalPayload = {
267
+ collection: this.normalizeScopeSegment(collection),
268
+ filter: this.normalizeCanonicalValue(filterValue, 'filter'),
269
+ pipeline: this.normalizeCanonicalValue(Array.isArray(pipelineValue) ? pipelineValue : [], 'pipeline'),
270
+ options: this.normalizeCanonicalValue(optionsValue !== null && optionsValue !== void 0 ? optionsValue : {}, 'options')
271
+ };
272
+ var serialized = JSON.stringify(canonicalPayload);
273
+ var hash = (0, crypto_1.createHash)('sha256').update(serialized, 'utf8').digest('hex');
274
+ return { serialized: serialized, hash: hash };
275
+ };
276
+ SlowQueryManager.prototype.normalizeCanonicalValue = function (value, parentKey) {
277
+ var _this = this;
278
+ if (parentKey === void 0) { parentKey = ''; }
279
+ if (value === null || typeof value === 'undefined') {
280
+ return null;
281
+ }
282
+ if (value instanceof Date) {
283
+ return '__date__';
284
+ }
285
+ if (value instanceof RegExp) {
286
+ return '__regex__';
287
+ }
288
+ if (Buffer.isBuffer(value)) {
289
+ return '__binary__';
290
+ }
291
+ var valueType = typeof value;
292
+ if (valueType === 'string') {
293
+ return this.normalizeCanonicalString(value, parentKey);
294
+ }
295
+ if (valueType === 'number') {
296
+ return '__num__';
297
+ }
298
+ if (valueType === 'boolean') {
299
+ return value;
300
+ }
301
+ if (valueType === 'bigint') {
302
+ return '__num__';
303
+ }
304
+ if (valueType === 'function') {
305
+ return '__fn__';
306
+ }
307
+ if (Array.isArray(value)) {
308
+ var normalizedItems = value.map(function (entry) { return _this.normalizeCanonicalValue(entry, parentKey); });
309
+ if (['$and', '$or', '$in', '$nin', '$all'].includes(parentKey)) {
310
+ var sortable = normalizedItems.map(function (item) { return ({
311
+ item: item,
312
+ serialized: JSON.stringify(item)
313
+ }); });
314
+ sortable.sort(function (left, right) { return left.serialized.localeCompare(right.serialized); });
315
+ return sortable.map(function (entry) { return entry.item; });
316
+ }
317
+ return normalizedItems;
318
+ }
319
+ if (valueType === 'object') {
320
+ if (this.isObjectIdLikeValue(value)) {
321
+ return '__objectid__';
322
+ }
323
+ var normalizedObj_1 = {};
324
+ Object.keys(value).sort().forEach(function (key) {
325
+ normalizedObj_1[key] = _this.normalizeCanonicalValue(value[key], key);
326
+ });
327
+ return normalizedObj_1;
328
+ }
329
+ return '__literal__';
330
+ };
331
+ SlowQueryManager.prototype.normalizeCanonicalString = function (value, parentKey) {
332
+ if (parentKey === void 0) { parentKey = ''; }
333
+ var trimmed = String(value || '').trim();
334
+ if (!trimmed) {
335
+ return '__empty__';
336
+ }
337
+ if (parentKey === '$regex') {
338
+ return '__regex__';
339
+ }
340
+ if (DATE_HINT_KEY_PATTERN.test(parentKey) || ISO_DATE_PATTERN.test(trimmed)) {
341
+ return '__date__';
342
+ }
343
+ if (OBJECT_ID_PATTERN.test(trimmed)) {
344
+ return '__objectid__';
345
+ }
346
+ if (UUID_PATTERN.test(trimmed)) {
347
+ return '__uuid__';
348
+ }
349
+ if (NUMERIC_STRING_PATTERN.test(trimmed)) {
350
+ return trimmed.length >= 10 ? '__numstr_large__' : '__numstr__';
351
+ }
352
+ if (ID_HINT_KEY_PATTERN.test(parentKey) || TOKEN_LIKE_PATTERN.test(trimmed)) {
353
+ return '__token__';
354
+ }
355
+ return '__str__';
356
+ };
357
+ SlowQueryManager.prototype.isObjectIdLikeValue = function (value) {
358
+ if (!value || typeof value !== 'object') {
359
+ return false;
360
+ }
361
+ var bsonType = String(value._bsontype || '').trim().toLowerCase();
362
+ if (bsonType === 'objectid') {
363
+ return true;
364
+ }
365
+ if (typeof value.toHexString === 'function') {
366
+ var hexValue = String(value.toHexString() || '').trim();
367
+ return OBJECT_ID_PATTERN.test(hexValue);
368
+ }
369
+ return false;
370
+ };
371
+ SlowQueryManager.prototype.resolveConfig = function () {
372
+ var slowQueryConfig = (this.serverConfig && (this.serverConfig.slowQuery || this.serverConfig.SLOW_QUERY)) || {};
373
+ var getBoolean = function (envKey, configKey, fallback) {
374
+ if (fallback === void 0) { fallback = true; }
375
+ if (typeof process.env[envKey] !== 'undefined') {
376
+ return process.env[envKey] === 'true';
377
+ }
378
+ if (typeof slowQueryConfig[configKey] !== 'undefined') {
379
+ return !!slowQueryConfig[configKey];
380
+ }
381
+ return fallback;
382
+ };
383
+ var parseKeyList = function (value) {
384
+ if (Array.isArray(value)) {
385
+ return value.map(function (item) { return "".concat(item || '').trim(); }).filter(Boolean);
386
+ }
387
+ if (typeof value === 'string') {
388
+ return value.split(',').map(function (item) { return item.trim(); }).filter(Boolean);
389
+ }
390
+ return [];
391
+ };
392
+ var ingestSource = typeof process.env.SLOW_QUERY_INGEST_KEYS !== 'undefined'
393
+ ? process.env.SLOW_QUERY_INGEST_KEYS
394
+ : slowQueryConfig.ingestKeys;
395
+ return {
396
+ enabled: getBoolean('SLOW_QUERY_ENABLED', 'enabled', true),
397
+ ingestKeys: parseKeyList(ingestSource),
398
+ debugLogging: getBoolean('SLOW_QUERY_DEBUG_LOGS', 'debugLogging', false),
399
+ configSource: process.env.SLOW_QUERY_ENABLED ? 'environment' : (Object.keys(slowQueryConfig).length ? 'serverConfig' : 'defaults')
400
+ };
401
+ };
402
+ SlowQueryManager.prototype.cleanSet = function (input) {
403
+ var output = {};
404
+ Object.keys(input).forEach(function (key) {
405
+ if (typeof input[key] !== 'undefined') {
406
+ output[key] = input[key];
407
+ }
408
+ });
409
+ return output;
410
+ };
411
+ SlowQueryManager.prototype.coerceDate = function (value) {
412
+ if (!value) {
413
+ return undefined;
414
+ }
415
+ if (value instanceof Date && !Number.isNaN(value.getTime())) {
416
+ return value;
417
+ }
418
+ var parsed = new Date(value);
419
+ return Number.isNaN(parsed.getTime()) ? undefined : parsed;
420
+ };
421
+ SlowQueryManager.prototype.logPipelineDebug = function (payload, pipelineValue, existingPipeline) {
422
+ if (!this.config.debugLogging) {
423
+ return;
424
+ }
425
+ var source = Array.isArray(payload.pipeline)
426
+ ? 'payload'
427
+ : (Array.isArray(existingPipeline) ? 'existing' : 'none');
428
+ var length = Array.isArray(pipelineValue) ? pipelineValue.length : 0;
429
+ var stages = this.describePipelineStages(pipelineValue);
430
+ console.info("[SlowQueryManager][pipeline] collection=".concat(payload.collection, " queryHash=").concat(payload.queryHash, " source=").concat(source, " len=").concat(length, " stages=").concat(stages));
431
+ };
432
+ SlowQueryManager.prototype.describePipelineStages = function (pipeline) {
433
+ if (!Array.isArray(pipeline) || pipeline.length === 0) {
434
+ return 'empty';
435
+ }
436
+ var snippet = pipeline.slice(0, 3).map(function (stage) {
437
+ if (!stage || typeof stage !== 'object') {
438
+ return 'unknown';
439
+ }
440
+ var key = Object.keys(stage)[0];
441
+ return key ? key : 'stage';
442
+ });
443
+ var additional = pipeline.length > snippet.length
444
+ ? " (+".concat(pipeline.length - snippet.length, " more)")
445
+ : '';
446
+ return "".concat(snippet.join(', ')).concat(additional);
447
+ };
448
+ return SlowQueryManager;
449
+ }());
450
+ exports.SlowQueryManager = SlowQueryManager;
451
+ function ensureSlowQueryManager(serverConfig) {
452
+ var existing = resolveio_server_app_1.ResolveIOServer['SlowQueryManager'];
453
+ if (existing) {
454
+ return existing;
455
+ }
456
+ if (!configuredSlowQueryManagerDependencies) {
457
+ return null;
458
+ }
459
+ var resolvedServerConfig = serverConfig || resolveio_server_app_1.ResolveIOServer.getServerConfig();
460
+ if (!resolvedServerConfig) {
461
+ return null;
462
+ }
463
+ var manager = new SlowQueryManager(resolvedServerConfig);
464
+ resolveio_server_app_1.ResolveIOServer['SlowQueryManager'] = manager;
465
+ return manager;
466
+ }
467
+
468
+ //# sourceMappingURL=slow-query.manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/managers/slow-query.manager.ts"],"names":[],"mappings":"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","file":"slow-query.manager.js","sourcesContent":["import { ResolveIOServer } from '../resolveio-server-app';\nimport { objectIdHexString } from '../util/common';\nimport { createHash } from 'crypto';\nimport { SlowQueryReportPayload, slowQueryLogStatuses } from '../types/slow-query-report';\n\ntype SlowQueryLogModel = Record<string, any>;\n\nexport interface SlowQueryManagerDependencies {\n\tSlowQueryLogs: any;\n}\n\nlet SlowQueryLogs: any = null;\nlet configuredSlowQueryManagerDependencies: SlowQueryManagerDependencies | null = null;\n\nfunction resolveSlowQueryManagerDependencies(\n\toverrides?: Partial<SlowQueryManagerDependencies>\n): SlowQueryManagerDependencies {\n\tconst resolved: SlowQueryManagerDependencies = {\n\t\t...(configuredSlowQueryManagerDependencies || {} as SlowQueryManagerDependencies),\n\t\t...(overrides || {})\n\t};\n\n\tif (!resolved.SlowQueryLogs) {\n\t\tthrow new Error('SlowQueryManager dependencies are not configured.');\n\t}\n\n\treturn resolved;\n}\n\nfunction applySlowQueryManagerDependencies(dependencies: SlowQueryManagerDependencies): void {\n\tconfiguredSlowQueryManagerDependencies = dependencies;\n\tSlowQueryLogs = dependencies.SlowQueryLogs;\n}\n\nexport function registerSlowQueryManagerDependencies(dependencies: SlowQueryManagerDependencies): void {\n\tapplySlowQueryManagerDependencies(dependencies);\n\tensureSlowQueryManager();\n}\n\ninterface SlowQueryConfig {\n\tenabled: boolean;\n\tingestKeys: string[];\n\tdebugLogging: boolean;\n\tconfigSource: string;\n}\n\nconst OBJECT_ID_PATTERN = /^[a-f0-9]{24}$/i;\nconst UUID_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\nconst ISO_DATE_PATTERN = /^\\d{4}-\\d{2}-\\d{2}(?:[tT ][\\d:.+-]+)?(?:[zZ]|[+-]\\d{2}:?\\d{2})?$/;\nconst NUMERIC_STRING_PATTERN = /^[-+]?\\d+(?:\\.\\d+)?$/;\nconst TOKEN_LIKE_PATTERN = /^[A-Za-z0-9._-]{16,}$/;\nconst DATE_HINT_KEY_PATTERN = /(date|time|timestamp|created|updated|expires|expiry|start|end|at)$/i;\nconst ID_HINT_KEY_PATTERN = /(^|_)(id|uuid|guid|token|hash|key)$/i;\n\nexport class SlowQueryManager {\n\tprivate config: SlowQueryConfig;\n\tprivate serverConfig: Record<string, any> | null;\n\n\tconstructor(serverConfig, dependencies?: Partial<SlowQueryManagerDependencies>) {\n\t\tconst resolvedDependencies = resolveSlowQueryManagerDependencies(dependencies);\n\t\tapplySlowQueryManagerDependencies(resolvedDependencies);\n\n\t\tthis.serverConfig = serverConfig || {};\n\t\tthis.config = this.resolveConfig();\n\t}\n\n\tpublic isReady(): boolean {\n\t\treturn !!this.config.enabled;\n\t}\n\n\tpublic validateIngestKey(candidate?: string): boolean {\n\t\tconst keys = Array.isArray(this.config.ingestKeys) ? this.config.ingestKeys.filter(Boolean) : [];\n\n\t\tif (!keys.length) {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (!candidate) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn keys.includes(candidate.trim());\n\t}\n\n\tpublic async ingestSlowQuery(payload: SlowQueryReportPayload): Promise<SlowQueryLogModel> {\n\t\tif (!this.isReady()) {\n\t\t\tthrow new Error('SlowQueryManager is not enabled.');\n\t\t}\n\n\t\tif (!payload || !payload.queryHash || !payload.collection || typeof payload.durationMs !== 'number' || Number.isNaN(payload.durationMs)) {\n\t\t\tthrow new Error('Invalid slow query payload.');\n\t\t}\n\n\t\tconst now = new Date();\n\t\tconst rawFilterValue = payload.filter ?? {};\n\t\tconst rawPipelineValue = Array.isArray(payload.pipeline) ? payload.pipeline : undefined;\n\t\tconst rawOptionsValue = payload.options;\n\t\tconst provisionalFingerprint = this.buildCanonicalFingerprint(payload.collection, rawFilterValue, rawPipelineValue, rawOptionsValue);\n\t\tconst provisionalScopeKey = this.buildFingerprintScopeKey({\n\t\t\tclientSlug: payload.clientSlug,\n\t\t\tclientName: payload.clientName,\n\t\t\tsourceApp: payload.sourceApp,\n\t\t\tenvironment: payload.environment,\n\t\t\tpublication: payload.publication,\n\t\t\tserverUrl: payload.server_url\n\t\t});\n\n\t\tlet existing = await SlowQueryLogs.findOne({\n\t\t\tcollection: payload.collection,\n\t\t\tcanonical_fingerprint_hash: provisionalFingerprint.hash,\n\t\t\tfingerprint_scope_key: provisionalScopeKey\n\t\t});\n\n\t\tif (!existing) {\n\t\t\texisting = await SlowQueryLogs.findOne(this.buildLegacyDedupeQuery(payload));\n\t\t}\n\t\tconst existingOccurrences = typeof existing?.occurrences === 'number' ? existing.occurrences : 0;\n\t\tconst occurrences = existingOccurrences + 1;\n\t\tconst existingAvg = typeof existing?.avg_duration_ms === 'number' ? existing.avg_duration_ms : 0;\n\t\tconst totalDuration = existingAvg * existingOccurrences;\n\t\tconst avgDuration = (totalDuration + payload.durationMs) / occurrences;\n\n\t\tconst previousMax = typeof existing?.max_duration_ms === 'number' ? existing.max_duration_ms : payload.durationMs;\n\t\tconst maxBase = Math.max(payload.durationMs, previousMax);\n\t\tconst maxDuration = typeof payload.maxDurationMs === 'number'\n\t\t\t? Math.max(maxBase, payload.maxDurationMs)\n\t\t\t: maxBase;\n\n\t\tconst resolvedStatus = payload.status && slowQueryLogStatuses.includes(payload.status)\n\t\t\t? payload.status\n\t\t\t: (existing?.status || 'new');\n\t\tconst resolvedIgnored = typeof payload.ignored === 'boolean'\n\t\t\t? payload.ignored\n\t\t\t: (typeof existing?.ignored === 'boolean' ? existing.ignored : false);\n\n\t\tconst filterValue = payload.filter ?? existing?.filter ?? {};\n\t\tconst pipelineValue = Array.isArray(payload.pipeline)\n\t\t\t? payload.pipeline\n\t\t\t: existing?.pipeline;\n\t\tif (this.config.debugLogging) {\n\t\t\tthis.logPipelineDebug(payload, pipelineValue, Array.isArray(existing?.pipeline) ? existing.pipeline : undefined);\n\t\t}\n\t\tconst optionsValue = payload.options ?? existing?.options;\n\t\tconst explainPlanValue = typeof payload.explainPlan !== 'undefined' ? payload.explainPlan : existing?.explain_plan;\n\t\tconst explainStatsValue = typeof payload.explainExecutionStats !== 'undefined' ? payload.explainExecutionStats : existing?.explain_execution_stats;\n\t\tconst explainGeneratedAtValue = typeof payload.explainGeneratedAt !== 'undefined'\n\t\t\t? this.coerceDate(payload.explainGeneratedAt)\n\t\t\t: existing?.explain_generated_at;\n\t\tconst fingerprintScopeKey = this.buildFingerprintScopeKey({\n\t\t\tclientSlug: payload.clientSlug ?? existing?.client_slug,\n\t\t\tclientName: payload.clientName ?? existing?.client_name,\n\t\t\tsourceApp: payload.sourceApp ?? existing?.source_app,\n\t\t\tenvironment: payload.environment ?? existing?.environment,\n\t\t\tpublication: payload.publication ?? existing?.publication,\n\t\t\tserverUrl: payload.server_url ?? existing?.server_url\n\t\t});\n\t\tconst canonicalFingerprint = this.buildCanonicalFingerprint(\n\t\t\tpayload.collection,\n\t\t\tfilterValue,\n\t\t\tpipelineValue,\n\t\t\toptionsValue\n\t\t);\n\n\t\tconst setFields: Partial<SlowQueryLogModel> = {\n\t\t\tquery_hash: payload.queryHash,\n\t\t\tcollection: payload.collection,\n\t\t\tcanonical_fingerprint: canonicalFingerprint.serialized,\n\t\t\tcanonical_fingerprint_hash: canonicalFingerprint.hash,\n\t\t\tfingerprint_scope_key: fingerprintScopeKey,\n\t\t\tfilter: filterValue,\n\t\t\tpipeline: pipelineValue,\n\t\t\toptions: optionsValue,\n\t\t\tduration_ms: payload.durationMs,\n\t\t\tmax_duration_ms: maxDuration,\n\t\t\tavg_duration_ms: avgDuration,\n\t\t\tthreshold_ms: typeof payload.thresholdMs === 'number' ? payload.thresholdMs : existing?.threshold_ms,\n\t\t\texplain_plan: explainPlanValue,\n\t\t\texplain_execution_stats: explainStatsValue,\n\t\t\texplain_generated_at: explainGeneratedAtValue,\n\t\t\tclient_slug: payload.clientSlug ?? existing?.client_slug,\n\t\t\tclient_name: payload.clientName ?? existing?.client_name,\n\t\t\tenvironment: payload.environment ?? existing?.environment,\n\t\t\tsource_app: payload.sourceApp ?? existing?.source_app,\n\t\t\tnode_hostname: payload.nodeHostname ?? existing?.node_hostname,\n\t\t\tserver_url: payload.server_url ?? existing?.server_url,\n\t\t\toccurrences,\n\t\t\tlast_seen_at: now,\n\t\t\tstatus: resolvedStatus,\n\t\t\tignored: resolvedIgnored,\n\t\t\tnotes: typeof payload.notes === 'string' ? payload.notes : existing?.notes,\n\t\t\tpublication: payload.publication ?? existing?.publication,\n\t\t\tsubscription_data: payload.subscription_data ?? existing?.subscription_data,\n\t\t\tuser_id: payload.userId ?? existing?.user_id\n\t\t};\n\n\t\tconst cleaned = this.cleanSet(setFields);\n\t\tif (existing) {\n\t\t\tcleaned.updatedAt = now;\n\t\t\tawait SlowQueryLogs.updateOne({_id: existing._id}, {$set: cleaned});\n\t\t\treturn await SlowQueryLogs.findOne({_id: existing._id});\n\t\t}\n\n\t\tconst doc: SlowQueryLogModel = {\n\t\t\t_id: objectIdHexString(),\n\t\t\t...cleaned,\n\t\t\tslow_query_count: 0,\n\t\t\tslow_query_count_string: 'Pending',\n\t\t\tauto_fix_attempt_count: 0,\n\t\t\tfirst_seen_at: now,\n\t\t\tcreatedAt: now,\n\t\t\tupdatedAt: now,\n\t\t\tverification_status: 'pending',\n\t\t\tverification_runs: [],\n\t\t\tverification_next_run_at: now\n\t\t} as SlowQueryLogModel;\n\n\t\tawait SlowQueryLogs.insertOne(doc as any);\n\t\treturn await SlowQueryLogs.findOne({_id: doc._id});\n\t}\n\n\tprivate buildLegacyDedupeQuery(payload: SlowQueryReportPayload): {[key: string]: any} {\n\t\tconst dedupeQuery: {[key: string]: any} = {\n\t\t\tquery_hash: payload.queryHash,\n\t\t\tcollection: payload.collection\n\t\t};\n\n\t\tif (payload.clientSlug) {\n\t\t\tdedupeQuery.client_slug = payload.clientSlug;\n\t\t}\n\n\t\tif (payload.environment) {\n\t\t\tdedupeQuery.environment = payload.environment;\n\t\t}\n\n\t\tif (payload.sourceApp) {\n\t\t\tdedupeQuery.source_app = payload.sourceApp;\n\t\t}\n\n\t\tif (payload.publication) {\n\t\t\tdedupeQuery.publication = payload.publication;\n\t\t}\n\n\t\tif (payload.server_url) {\n\t\t\tdedupeQuery.server_url = payload.server_url;\n\t\t}\n\n\t\treturn dedupeQuery;\n\t}\n\n\tprivate buildFingerprintScopeKey(scope: {\n\t\tclientSlug?: string;\n\t\tclientName?: string;\n\t\tsourceApp?: string;\n\t\tenvironment?: string;\n\t\tpublication?: string;\n\t\tserverUrl?: string;\n\t}): string {\n\t\tconst clientKey = this.normalizeScopeSegment(scope.clientSlug || scope.clientName || '');\n\t\tconst sourceApp = this.normalizeScopeSegment(scope.sourceApp || '');\n\t\tconst environment = this.normalizeScopeSegment(scope.environment || '');\n\t\tconst publication = this.normalizeScopeSegment(scope.publication || '');\n\t\tconst serverUrl = this.normalizeScopeSegment(scope.serverUrl || '');\n\t\treturn [clientKey, sourceApp, environment, publication, serverUrl].join('|');\n\t}\n\n\tprivate normalizeScopeSegment(value: any): string {\n\t\tconst normalized = String(value || '')\n\t\t\t.trim()\n\t\t\t.toLowerCase()\n\t\t\t.replace(/\\s+/g, ' ');\n\t\treturn normalized || '_';\n\t}\n\n\tprivate buildCanonicalFingerprint(\n\t\tcollection: string,\n\t\tfilterValue: any,\n\t\tpipelineValue?: any[],\n\t\toptionsValue?: Record<string, any>\n\t): {serialized: string; hash: string} {\n\t\tconst canonicalPayload = {\n\t\t\tcollection: this.normalizeScopeSegment(collection),\n\t\t\tfilter: this.normalizeCanonicalValue(filterValue, 'filter'),\n\t\t\tpipeline: this.normalizeCanonicalValue(Array.isArray(pipelineValue) ? pipelineValue : [], 'pipeline'),\n\t\t\toptions: this.normalizeCanonicalValue(optionsValue ?? {}, 'options')\n\t\t};\n\t\tconst serialized = JSON.stringify(canonicalPayload);\n\t\tconst hash = createHash('sha256').update(serialized, 'utf8').digest('hex');\n\t\treturn {serialized, hash};\n\t}\n\n\tprivate normalizeCanonicalValue(value: any, parentKey = ''): any {\n\t\tif (value === null || typeof value === 'undefined') {\n\t\t\treturn null;\n\t\t}\n\n\t\tif (value instanceof Date) {\n\t\t\treturn '__date__';\n\t\t}\n\n\t\tif (value instanceof RegExp) {\n\t\t\treturn '__regex__';\n\t\t}\n\n\t\tif (Buffer.isBuffer(value)) {\n\t\t\treturn '__binary__';\n\t\t}\n\n\t\tconst valueType = typeof value;\n\t\tif (valueType === 'string') {\n\t\t\treturn this.normalizeCanonicalString(value, parentKey);\n\t\t}\n\t\tif (valueType === 'number') {\n\t\t\treturn '__num__';\n\t\t}\n\t\tif (valueType === 'boolean') {\n\t\t\treturn value;\n\t\t}\n\t\tif (valueType === 'bigint') {\n\t\t\treturn '__num__';\n\t\t}\n\t\tif (valueType === 'function') {\n\t\t\treturn '__fn__';\n\t\t}\n\n\t\tif (Array.isArray(value)) {\n\t\t\tconst normalizedItems = value.map(entry => this.normalizeCanonicalValue(entry, parentKey));\n\t\t\tif (['$and', '$or', '$in', '$nin', '$all'].includes(parentKey)) {\n\t\t\t\tconst sortable = normalizedItems.map(item => ({\n\t\t\t\t\titem,\n\t\t\t\t\tserialized: JSON.stringify(item)\n\t\t\t\t}));\n\t\t\t\tsortable.sort((left, right) => left.serialized.localeCompare(right.serialized));\n\t\t\t\treturn sortable.map(entry => entry.item);\n\t\t\t}\n\t\t\treturn normalizedItems;\n\t\t}\n\n\t\tif (valueType === 'object') {\n\t\t\tif (this.isObjectIdLikeValue(value)) {\n\t\t\t\treturn '__objectid__';\n\t\t\t}\n\t\t\tconst normalizedObj: Record<string, any> = {};\n\t\t\tObject.keys(value).sort().forEach((key) => {\n\t\t\t\tnormalizedObj[key] = this.normalizeCanonicalValue(value[key], key);\n\t\t\t});\n\t\t\treturn normalizedObj;\n\t\t}\n\n\t\treturn '__literal__';\n\t}\n\n\tprivate normalizeCanonicalString(value: string, parentKey = ''): string {\n\t\tconst trimmed = String(value || '').trim();\n\t\tif (!trimmed) {\n\t\t\treturn '__empty__';\n\t\t}\n\n\t\tif (parentKey === '$regex') {\n\t\t\treturn '__regex__';\n\t\t}\n\n\t\tif (DATE_HINT_KEY_PATTERN.test(parentKey) || ISO_DATE_PATTERN.test(trimmed)) {\n\t\t\treturn '__date__';\n\t\t}\n\n\t\tif (OBJECT_ID_PATTERN.test(trimmed)) {\n\t\t\treturn '__objectid__';\n\t\t}\n\n\t\tif (UUID_PATTERN.test(trimmed)) {\n\t\t\treturn '__uuid__';\n\t\t}\n\n\t\tif (NUMERIC_STRING_PATTERN.test(trimmed)) {\n\t\t\treturn trimmed.length >= 10 ? '__numstr_large__' : '__numstr__';\n\t\t}\n\n\t\tif (ID_HINT_KEY_PATTERN.test(parentKey) || TOKEN_LIKE_PATTERN.test(trimmed)) {\n\t\t\treturn '__token__';\n\t\t}\n\n\t\treturn '__str__';\n\t}\n\n\tprivate isObjectIdLikeValue(value: any): boolean {\n\t\tif (!value || typeof value !== 'object') {\n\t\t\treturn false;\n\t\t}\n\n\t\tconst bsonType = String((value as any)._bsontype || '').trim().toLowerCase();\n\t\tif (bsonType === 'objectid') {\n\t\t\treturn true;\n\t\t}\n\n\t\tif (typeof (value as any).toHexString === 'function') {\n\t\t\tconst hexValue = String((value as any).toHexString() || '').trim();\n\t\t\treturn OBJECT_ID_PATTERN.test(hexValue);\n\t\t}\n\n\t\treturn false;\n\t}\n\n\tprivate resolveConfig(): SlowQueryConfig {\n\t\tconst slowQueryConfig = (this.serverConfig && (this.serverConfig.slowQuery || this.serverConfig.SLOW_QUERY)) || {};\n\n\t\tconst getBoolean = (envKey: string, configKey: string, fallback = true) => {\n\t\t\tif (typeof process.env[envKey] !== 'undefined') {\n\t\t\t\treturn process.env[envKey] === 'true';\n\t\t\t}\n\t\t\tif (typeof slowQueryConfig[configKey] !== 'undefined') {\n\t\t\t\treturn !!slowQueryConfig[configKey];\n\t\t\t}\n\t\t\treturn fallback;\n\t\t};\n\n\t\tconst parseKeyList = (value: any): string[] => {\n\t\t\tif (Array.isArray(value)) {\n\t\t\t\treturn value.map(item => `${item || ''}`.trim()).filter(Boolean);\n\t\t\t}\n\n\t\t\tif (typeof value === 'string') {\n\t\t\t\treturn value.split(',').map(item => item.trim()).filter(Boolean);\n\t\t\t}\n\n\t\t\treturn [];\n\t\t};\n\n\t\tconst ingestSource = typeof process.env.SLOW_QUERY_INGEST_KEYS !== 'undefined'\n\t\t\t? process.env.SLOW_QUERY_INGEST_KEYS\n\t\t\t: slowQueryConfig.ingestKeys;\n\n\t\treturn {\n\t\t\tenabled: getBoolean('SLOW_QUERY_ENABLED', 'enabled', true),\n\t\t\tingestKeys: parseKeyList(ingestSource),\n\t\t\tdebugLogging: getBoolean('SLOW_QUERY_DEBUG_LOGS', 'debugLogging', false),\n\t\t\tconfigSource: process.env.SLOW_QUERY_ENABLED ? 'environment' : (Object.keys(slowQueryConfig).length ? 'serverConfig' : 'defaults')\n\t\t};\n\t}\n\n\tprivate cleanSet<T extends Record<string, any>>(input: T): T {\n\t\tconst output: Record<string, any> = {};\n\n\t\tObject.keys(input).forEach(key => {\n\t\t\tif (typeof input[key] !== 'undefined') {\n\t\t\t\toutput[key] = input[key];\n\t\t\t}\n\t\t});\n\n\t\treturn output as T;\n\t}\n\n\tprivate coerceDate(value: any): Date | undefined {\n\t\tif (!value) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tif (value instanceof Date && !Number.isNaN(value.getTime())) {\n\t\t\treturn value;\n\t\t}\n\n\t\tconst parsed = new Date(value);\n\t\treturn Number.isNaN(parsed.getTime()) ? undefined : parsed;\n\t}\n\n\tprivate logPipelineDebug(payload: SlowQueryReportPayload, pipelineValue: any, existingPipeline?: any[]): void {\n\t\tif (!this.config.debugLogging) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst source = Array.isArray(payload.pipeline)\n\t\t\t? 'payload'\n\t\t\t: (Array.isArray(existingPipeline) ? 'existing' : 'none');\n\t\tconst length = Array.isArray(pipelineValue) ? pipelineValue.length : 0;\n\t\tconst stages = this.describePipelineStages(pipelineValue);\n\n\t\tconsole.info(`[SlowQueryManager][pipeline] collection=${payload.collection} queryHash=${payload.queryHash} source=${source} len=${length} stages=${stages}`);\n\t}\n\n\tprivate describePipelineStages(pipeline?: any[]): string {\n\t\tif (!Array.isArray(pipeline) || pipeline.length === 0) {\n\t\t\treturn 'empty';\n\t\t}\n\n\t\tconst snippet = pipeline.slice(0, 3).map(stage => {\n\t\t\tif (!stage || typeof stage !== 'object') {\n\t\t\t\treturn 'unknown';\n\t\t\t}\n\n\t\t\tconst key = Object.keys(stage)[0];\n\t\t\treturn key ? key : 'stage';\n\t\t});\n\n\t\tconst additional = pipeline.length > snippet.length\n\t\t\t? ` (+${pipeline.length - snippet.length} more)`\n\t\t\t: '';\n\n\t\treturn `${snippet.join(', ')}${additional}`;\n\t}\n}\n\nexport function ensureSlowQueryManager(serverConfig?: any): SlowQueryManager | null {\n\tconst existing = ResolveIOServer['SlowQueryManager'] as SlowQueryManager | null;\n\tif (existing) {\n\t\treturn existing;\n\t}\n\n\tif (!configuredSlowQueryManagerDependencies) {\n\t\treturn null;\n\t}\n\n\tconst resolvedServerConfig = serverConfig || ResolveIOServer.getServerConfig();\n\tif (!resolvedServerConfig) {\n\t\treturn null;\n\t}\n\n\tconst manager = new SlowQueryManager(resolvedServerConfig);\n\tResolveIOServer['SlowQueryManager'] = manager;\n\treturn manager;\n}\n"]}
@@ -153,9 +153,68 @@ function uniqueUserIds(input) {
153
153
  }
154
154
  return Array.from(unique);
155
155
  }
156
+ function buildClientMembershipCriteria(idClient) {
157
+ return {
158
+ $or: [
159
+ { 'other.id_client': idClient },
160
+ { 'other.idClient': idClient },
161
+ { id_client: idClient }
162
+ ]
163
+ };
164
+ }
165
+ function buildInternalUserCriteria() {
166
+ return {
167
+ $and: [
168
+ {
169
+ is_customer: {
170
+ $ne: true
171
+ }
172
+ },
173
+ {
174
+ $nor: [
175
+ {
176
+ 'other.id_customer': {
177
+ $exists: true,
178
+ $nin: ['', null]
179
+ }
180
+ },
181
+ {
182
+ id_customer: {
183
+ $exists: true,
184
+ $nin: ['', null]
185
+ }
186
+ }
187
+ ]
188
+ }
189
+ ]
190
+ };
191
+ }
192
+ function buildAdminUserCriteria() {
193
+ return {
194
+ $or: [
195
+ {
196
+ 'roles.super_admin': true
197
+ },
198
+ {
199
+ 'roles.groups.name': {
200
+ $regex: 'admin',
201
+ $options: 'i'
202
+ }
203
+ },
204
+ {
205
+ 'roles.groups.views': {
206
+ $regex: '^/manage'
207
+ }
208
+ },
209
+ {
210
+ 'roles.groups.views': '/manage'
211
+ }
212
+ ]
213
+ };
214
+ }
156
215
  function resolveTargetUsers(payload) {
157
216
  return __awaiter(this, void 0, void 0, function () {
158
- var targetType, users_1, idClient, users;
217
+ var targetType, users_1, idClient, andClauses, users;
159
218
  return __generator(this, function (_a) {
160
219
  switch (_a.label) {
161
220
  case 0:
@@ -183,16 +242,25 @@ function resolveTargetUsers(payload) {
183
242
  if (!idClient) {
184
243
  return [2 /*return*/, []];
185
244
  }
186
- return [4 /*yield*/, user_collection_1.Users.find({
187
- active: true,
245
+ andClauses = [
246
+ {
247
+ active: true
248
+ },
249
+ {
188
250
  username: {
189
251
  $exists: true
190
- },
191
- $or: [
192
- { 'other.id_client': idClient },
193
- { 'other.idClient': idClient },
194
- { id_client: idClient }
195
- ]
252
+ }
253
+ },
254
+ buildClientMembershipCriteria(idClient)
255
+ ];
256
+ if (targetType === 'client_internal' || targetType === 'client_admins') {
257
+ andClauses.push(buildInternalUserCriteria());
258
+ }
259
+ if (targetType === 'client_admins') {
260
+ andClauses.push(buildAdminUserCriteria());
261
+ }
262
+ return [4 /*yield*/, user_collection_1.Users.find({
263
+ $and: andClauses
196
264
  }, {
197
265
  projection: {
198
266
  _id: 1