@reprova/sdk 0.4.0 → 0.6.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.
- package/README.md +170 -8
- package/dist/cjs/context.js +28 -0
- package/dist/cjs/distributionBaselinePoller.js +87 -0
- package/dist/cjs/distributionDrift.js +170 -0
- package/dist/cjs/drizzle.js +204 -0
- package/dist/cjs/frameworkAdapter.js +2 -0
- package/dist/cjs/httpFetch.js +59 -0
- package/dist/cjs/idempotency.js +132 -0
- package/dist/cjs/idempotencySettingsPoller.js +71 -0
- package/dist/cjs/index.js +96 -0
- package/dist/cjs/invariantInference.js +90 -0
- package/dist/cjs/invariantRules.js +142 -0
- package/dist/cjs/knex.js +86 -0
- package/dist/cjs/kysely.js +175 -0
- package/dist/cjs/legacyPrisma.js +130 -0
- package/dist/cjs/mikroorm.js +74 -0
- package/dist/cjs/mongoSchemaReporter.js +85 -0
- package/dist/cjs/mongoose.js +335 -0
- package/dist/cjs/nPlusOne.js +0 -0
- package/dist/cjs/nest.js +136 -0
- package/dist/cjs/nextjs.js +180 -0
- package/dist/cjs/package.json +1 -0
- package/dist/cjs/prisma.js +363 -0
- package/dist/cjs/proto.gen.js +4 -0
- package/dist/cjs/registry.js +100 -0
- package/dist/cjs/retryStorm.js +70 -0
- package/dist/cjs/rulesPoller.js +77 -0
- package/dist/cjs/sdk.js +1231 -0
- package/dist/cjs/sequelize.js +108 -0
- package/dist/cjs/shape.js +45 -0
- package/dist/cjs/stack.js +51 -0
- package/dist/cjs/transport.js +71 -0
- package/dist/cjs/typeorm.js +200 -0
- package/dist/context.d.ts +32 -0
- package/dist/context.d.ts.map +1 -1
- package/dist/context.js +18 -0
- package/dist/context.js.map +1 -1
- package/dist/distributionBaselinePoller.d.ts +36 -0
- package/dist/distributionBaselinePoller.d.ts.map +1 -0
- package/dist/distributionBaselinePoller.js +84 -0
- package/dist/distributionBaselinePoller.js.map +1 -0
- package/dist/distributionDrift.d.ts +41 -0
- package/dist/distributionDrift.d.ts.map +1 -0
- package/dist/distributionDrift.js +161 -0
- package/dist/distributionDrift.js.map +1 -0
- package/dist/drizzle.d.ts +22 -0
- package/dist/drizzle.d.ts.map +1 -1
- package/dist/drizzle.js +129 -1
- package/dist/drizzle.js.map +1 -1
- package/dist/frameworkAdapter.d.ts +5 -0
- package/dist/frameworkAdapter.d.ts.map +1 -0
- package/dist/frameworkAdapter.js +2 -0
- package/dist/frameworkAdapter.js.map +1 -0
- package/dist/httpFetch.d.ts +13 -0
- package/dist/httpFetch.d.ts.map +1 -0
- package/dist/httpFetch.js +54 -0
- package/dist/httpFetch.js.map +1 -0
- package/dist/idempotency.d.ts +26 -0
- package/dist/idempotency.d.ts.map +1 -0
- package/dist/idempotency.js +124 -0
- package/dist/idempotency.js.map +1 -0
- package/dist/idempotencySettingsPoller.d.ts +23 -0
- package/dist/idempotencySettingsPoller.d.ts.map +1 -0
- package/dist/idempotencySettingsPoller.js +68 -0
- package/dist/idempotencySettingsPoller.js.map +1 -0
- package/dist/index.d.ts +33 -6
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +19 -4
- package/dist/index.js.map +1 -1
- package/dist/invariantInference.d.ts +28 -0
- package/dist/invariantInference.d.ts.map +1 -0
- package/dist/invariantInference.js +87 -0
- package/dist/invariantInference.js.map +1 -0
- package/dist/invariantRules.d.ts +16 -0
- package/dist/invariantRules.d.ts.map +1 -0
- package/dist/invariantRules.js +104 -0
- package/dist/invariantRules.js.map +1 -0
- package/dist/knex.d.ts.map +1 -1
- package/dist/knex.js +1 -0
- package/dist/knex.js.map +1 -1
- package/dist/kysely.d.ts.map +1 -1
- package/dist/kysely.js +2 -1
- package/dist/kysely.js.map +1 -1
- package/dist/legacyPrisma.d.ts +6 -0
- package/dist/legacyPrisma.d.ts.map +1 -0
- package/dist/legacyPrisma.js +128 -0
- package/dist/legacyPrisma.js.map +1 -0
- package/dist/mikroorm.d.ts +2 -0
- package/dist/mikroorm.d.ts.map +1 -0
- package/dist/mikroorm.js +72 -0
- package/dist/mikroorm.js.map +1 -0
- package/dist/mongoSchemaReporter.d.ts +23 -0
- package/dist/mongoSchemaReporter.d.ts.map +1 -0
- package/dist/mongoSchemaReporter.js +82 -0
- package/dist/mongoSchemaReporter.js.map +1 -0
- package/dist/mongoose.d.ts +48 -0
- package/dist/mongoose.d.ts.map +1 -0
- package/dist/mongoose.js +331 -0
- package/dist/mongoose.js.map +1 -0
- package/dist/nPlusOne.d.ts +52 -0
- package/dist/nPlusOne.d.ts.map +1 -0
- package/dist/nPlusOne.js +0 -0
- package/dist/nPlusOne.js.map +1 -0
- package/dist/nest.d.ts +31 -0
- package/dist/nest.d.ts.map +1 -0
- package/dist/nest.js +133 -0
- package/dist/nest.js.map +1 -0
- package/dist/nextjs.d.ts +27 -0
- package/dist/nextjs.d.ts.map +1 -0
- package/dist/nextjs.js +178 -0
- package/dist/nextjs.js.map +1 -0
- package/dist/prisma.d.ts +21 -5
- package/dist/prisma.d.ts.map +1 -1
- package/dist/prisma.js +247 -22
- package/dist/prisma.js.map +1 -1
- package/dist/proto.gen.d.ts +19 -1
- package/dist/proto.gen.d.ts.map +1 -1
- package/dist/registry.d.ts +1 -0
- package/dist/registry.d.ts.map +1 -1
- package/dist/registry.js +24 -0
- package/dist/registry.js.map +1 -1
- package/dist/retryStorm.d.ts +42 -0
- package/dist/retryStorm.d.ts.map +1 -0
- package/dist/retryStorm.js +65 -0
- package/dist/retryStorm.js.map +1 -0
- package/dist/rulesPoller.d.ts +26 -0
- package/dist/rulesPoller.d.ts.map +1 -0
- package/dist/rulesPoller.js +74 -0
- package/dist/rulesPoller.js.map +1 -0
- package/dist/sdk.d.ts +53 -6
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +663 -34
- package/dist/sdk.js.map +1 -1
- package/dist/sequelize.d.ts.map +1 -1
- package/dist/sequelize.js +4 -3
- package/dist/sequelize.js.map +1 -1
- package/dist/stack.d.ts.map +1 -1
- package/dist/stack.js +6 -3
- package/dist/stack.js.map +1 -1
- package/dist/transport.d.ts.map +1 -1
- package/dist/transport.js +2 -1
- package/dist/transport.js.map +1 -1
- package/dist/typeorm.d.ts +1 -0
- package/dist/typeorm.d.ts.map +1 -1
- package/dist/typeorm.js +133 -1
- package/dist/typeorm.js.map +1 -1
- package/package.json +20 -5
package/dist/mongoose.js
ADDED
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
import { contextStorage } from './context.js';
|
|
2
|
+
import { shapeArgs } from './shape.js';
|
|
3
|
+
const SELECT_QUERY_OPS = ['find', 'findOne', 'count', 'countDocuments', 'distinct', 'estimatedDocumentCount'];
|
|
4
|
+
const UPDATE_QUERY_OPS = ['updateOne', 'updateMany', 'findOneAndUpdate', 'findOneAndReplace'];
|
|
5
|
+
const DELETE_QUERY_OPS = ['deleteOne', 'deleteMany', 'findOneAndDelete', 'findOneAndRemove', 'remove'];
|
|
6
|
+
// _id(s) from a query/document result, whatever shape it happens to be
|
|
7
|
+
// (array of docs, single doc, null, or a driver-level count/ack object with
|
|
8
|
+
// no docs at all — idsOf simply yields nothing for the last case).
|
|
9
|
+
function idsOf(value) {
|
|
10
|
+
if (!value)
|
|
11
|
+
return [];
|
|
12
|
+
const docs = Array.isArray(value) ? value : [value];
|
|
13
|
+
const ids = [];
|
|
14
|
+
for (const d of docs) {
|
|
15
|
+
const id = d?._id;
|
|
16
|
+
if (id !== undefined && id !== null)
|
|
17
|
+
ids.push(String(id));
|
|
18
|
+
}
|
|
19
|
+
return ids;
|
|
20
|
+
}
|
|
21
|
+
// updateMany/deleteMany/findOneAndUpdate-family results carry no document
|
|
22
|
+
// ids at all (just {acknowledged, modifiedCount|deletedCount|matchedCount}
|
|
23
|
+
// or a plain number for count()) — this is the bulk-op analog of
|
|
24
|
+
// FootprintQuery.where_shape existing for "no concrete rows, but here's how
|
|
25
|
+
// many and what shape of filter."
|
|
26
|
+
function affectedCountOf(result) {
|
|
27
|
+
if (typeof result === 'number')
|
|
28
|
+
return result;
|
|
29
|
+
const r = result;
|
|
30
|
+
return r?.modifiedCount ?? r?.deletedCount ?? r?.matchedCount ?? 0;
|
|
31
|
+
}
|
|
32
|
+
// The MongoDB driver connection pool that Mongoose 5.x bundles dispatches a
|
|
33
|
+
// query's response from inside the pooled connection's own socket callback
|
|
34
|
+
// — whose AsyncLocalStorage context is fixed to whatever was ambient when
|
|
35
|
+
// that connection was first used, not the context of whichever query is
|
|
36
|
+
// currently awaiting a result on it. Confirmed empirically: a Mongoose
|
|
37
|
+
// post-hook loses ALS context as soon as a single prior query has run
|
|
38
|
+
// outside a captured request, which every real app does (background jobs,
|
|
39
|
+
// startup queries, connection warmup) — so relying on contextStorage in the
|
|
40
|
+
// post-hook alone silently drops footprints in production, not just in
|
|
41
|
+
// contrived tests. Pre-hooks, by contrast, run synchronously on the
|
|
42
|
+
// caller's own stack before any driver I/O, so they still see the correct
|
|
43
|
+
// context. Capture it there and thread it through to the post-hook via a
|
|
44
|
+
// WeakMap keyed on the query/document instance — Kareem (Mongoose's
|
|
45
|
+
// middleware runner) preserves that same instance as `this` across pre and
|
|
46
|
+
// post for one operation, so the lookup is exact, not a guess.
|
|
47
|
+
const ctxByHost = new WeakMap();
|
|
48
|
+
function captureCtx(host) {
|
|
49
|
+
const ctx = contextStorage.getStore();
|
|
50
|
+
if (ctx && host && typeof host === 'object')
|
|
51
|
+
ctxByHost.set(host, ctx);
|
|
52
|
+
}
|
|
53
|
+
function resolveCtx(host) {
|
|
54
|
+
return contextStorage.getStore() ?? (host && typeof host === 'object' ? ctxByHost.get(host) : undefined);
|
|
55
|
+
}
|
|
56
|
+
// Find-or-create the (collection, op) entry for this request and fold in
|
|
57
|
+
// whatever this call learned — same merge-by-(table,op) pattern mikroorm.ts
|
|
58
|
+
// uses, extended with a where_shape/count fallback for bulk ops that never
|
|
59
|
+
// expose which specific documents they touched.
|
|
60
|
+
function recordFootprint(ctx, collection, op, pks, affectedCount, whereShape) {
|
|
61
|
+
if (!ctx || !collection)
|
|
62
|
+
return;
|
|
63
|
+
let entry = ctx.footprint.find((f) => f.model === collection && f.op === op);
|
|
64
|
+
if (!entry) {
|
|
65
|
+
entry = { model: collection, op, pks: [], count: 0 };
|
|
66
|
+
ctx.footprint.push(entry);
|
|
67
|
+
}
|
|
68
|
+
for (const pk of pks)
|
|
69
|
+
if (!entry.pks.includes(pk))
|
|
70
|
+
entry.pks.push(pk);
|
|
71
|
+
entry.count = entry.pks.length > 0 ? entry.pks.length : Math.max(entry.count, affectedCount);
|
|
72
|
+
if (whereShape && !entry.where_shape)
|
|
73
|
+
entry.where_shape = whereShape;
|
|
74
|
+
}
|
|
75
|
+
function recordFromQuery(query, op, result) {
|
|
76
|
+
const ctx = resolveCtx(query);
|
|
77
|
+
const collection = query.model?.collection?.collectionName;
|
|
78
|
+
let whereShape;
|
|
79
|
+
try {
|
|
80
|
+
whereShape = query.getFilter ? shapeArgs(query.getFilter()) : undefined;
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
/* filter introspection best-effort */
|
|
84
|
+
}
|
|
85
|
+
recordFootprint(ctx, collection, op, idsOf(result), affectedCountOf(result), whereShape);
|
|
86
|
+
}
|
|
87
|
+
// Whether a document was new AT THE TIME save() was called — snapshotted in
|
|
88
|
+
// pre('save') because by the time post('save') runs, Mongoose has already
|
|
89
|
+
// reset doc.isNew to false regardless of which case this was, so isNew
|
|
90
|
+
// alone can't distinguish insert from update from inside the post hook.
|
|
91
|
+
const wasNewByDoc = new WeakMap();
|
|
92
|
+
// Installs Reprova's footprint hooks on a schema. Call BEFORE compiling any
|
|
93
|
+
// model from it — e.g. `mongoose.plugin(reprovaMongoosePlugin)` once,
|
|
94
|
+
// before any `mongoose.model(...)` calls, so every subsequently-compiled
|
|
95
|
+
// model gets it. Registers plain functions, no decorators/classes needed.
|
|
96
|
+
export function reprovaMongoosePlugin(schema) {
|
|
97
|
+
for (const opName of SELECT_QUERY_OPS) {
|
|
98
|
+
schema.pre(opName, function () {
|
|
99
|
+
captureCtx(this);
|
|
100
|
+
});
|
|
101
|
+
schema.post(opName, function (result) {
|
|
102
|
+
try {
|
|
103
|
+
recordFromQuery(this, 'select', result);
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
/* never break the host query */
|
|
107
|
+
}
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
for (const opName of UPDATE_QUERY_OPS) {
|
|
111
|
+
schema.pre(opName, function () {
|
|
112
|
+
captureCtx(this);
|
|
113
|
+
});
|
|
114
|
+
schema.post(opName, function (result) {
|
|
115
|
+
try {
|
|
116
|
+
recordFromQuery(this, 'update', result);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
/* never break the host query */
|
|
120
|
+
}
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
for (const opName of DELETE_QUERY_OPS) {
|
|
124
|
+
schema.pre(opName, function () {
|
|
125
|
+
captureCtx(this);
|
|
126
|
+
});
|
|
127
|
+
schema.post(opName, function (result) {
|
|
128
|
+
try {
|
|
129
|
+
recordFromQuery(this, 'delete', result);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
/* never break the host query */
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
schema.pre('save', function () {
|
|
137
|
+
try {
|
|
138
|
+
wasNewByDoc.set(this, !!this.isNew);
|
|
139
|
+
}
|
|
140
|
+
catch {
|
|
141
|
+
/* never break the host save */
|
|
142
|
+
}
|
|
143
|
+
captureCtx(this);
|
|
144
|
+
});
|
|
145
|
+
schema.post('save', function () {
|
|
146
|
+
try {
|
|
147
|
+
const wasNew = wasNewByDoc.get(this) ?? !!this.isNew;
|
|
148
|
+
wasNewByDoc.delete(this);
|
|
149
|
+
recordFootprint(resolveCtx(this), this.collection?.collectionName, wasNew ? 'insert' : 'update', idsOf(this), 1);
|
|
150
|
+
}
|
|
151
|
+
catch {
|
|
152
|
+
/* never break the host save */
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
// insertMany's `this` is the shared Model, not a per-call instance, so it
|
|
156
|
+
// can't be used as the WeakMap key (concurrent calls would clobber each
|
|
157
|
+
// other's captured context) — the `docs` array IS per-call and Kareem
|
|
158
|
+
// passes the same reference to both hooks, so key on that instead.
|
|
159
|
+
schema.pre('insertMany', function (docs) {
|
|
160
|
+
captureCtx(docs);
|
|
161
|
+
});
|
|
162
|
+
schema.post('insertMany', function (docs) {
|
|
163
|
+
try {
|
|
164
|
+
const ids = idsOf(docs);
|
|
165
|
+
recordFootprint(resolveCtx(docs), this.collection?.collectionName, 'insert', ids, ids.length);
|
|
166
|
+
}
|
|
167
|
+
catch {
|
|
168
|
+
/* never break the host insertMany */
|
|
169
|
+
}
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
// --- Retroactive instrumentation for already-compiled models -------------
|
|
173
|
+
//
|
|
174
|
+
// `mongoose.plugin(reprovaMongoosePlugin)` only reaches schemas compiled
|
|
175
|
+
// AFTER the call — confirmed empirically that Mongoose bakes its Kareem
|
|
176
|
+
// hook chain in at `mongoose.model(...)` time, so `schema.pre/post` added
|
|
177
|
+
// to an already-compiled model's schema afterward are simply never
|
|
178
|
+
// consulted again. That ordering requirement forces apps whose own
|
|
179
|
+
// bootstrap already compiles a model before Reprova can be wired in (e.g.
|
|
180
|
+
// a multi-file loader architecture that connects Mongoose, compiles
|
|
181
|
+
// models, THEN sets up the rest) to route `Reprova.init()` to wherever
|
|
182
|
+
// runs earliest, rather than wherever's most natural.
|
|
183
|
+
//
|
|
184
|
+
// This covers that case by wrapping each already-compiled model's own
|
|
185
|
+
// query/document methods directly instead of relying on schema hooks — a
|
|
186
|
+
// plain method override works regardless of compile order. It also
|
|
187
|
+
// sidesteps the pooled-connection ALS-loss problem the schema-hook path
|
|
188
|
+
// needs the WeakMap for (see captureCtx/resolveCtx above): the context is
|
|
189
|
+
// captured synchronously into a closure the instant the wrapped method is
|
|
190
|
+
// called, before any driver I/O, so the `.then()` continuation always has
|
|
191
|
+
// the right value on hand regardless of what AsyncLocalStorage does.
|
|
192
|
+
//
|
|
193
|
+
// Idempotent and safe to call repeatedly (e.g. instrumentMongoose() called
|
|
194
|
+
// more than once) — already-patched models are skipped via `patchedModels`.
|
|
195
|
+
const patchedModels = new WeakSet();
|
|
196
|
+
function wrapQueryReturningMethod(model, methodName, op) {
|
|
197
|
+
const original = model[methodName];
|
|
198
|
+
if (typeof original !== 'function')
|
|
199
|
+
return;
|
|
200
|
+
model[methodName] = function (...args) {
|
|
201
|
+
const ctx = contextStorage.getStore();
|
|
202
|
+
const query = original.apply(this, args);
|
|
203
|
+
if (!query || typeof query.exec !== 'function')
|
|
204
|
+
return query;
|
|
205
|
+
const originalExec = query.exec.bind(query);
|
|
206
|
+
query.exec = (...execArgs) => originalExec(...execArgs).then((result) => {
|
|
207
|
+
try {
|
|
208
|
+
const collection = model.collection?.collectionName;
|
|
209
|
+
let whereShape;
|
|
210
|
+
try {
|
|
211
|
+
whereShape = query.getFilter ? shapeArgs(query.getFilter()) : undefined;
|
|
212
|
+
}
|
|
213
|
+
catch {
|
|
214
|
+
/* filter introspection best-effort */
|
|
215
|
+
}
|
|
216
|
+
recordFootprint(ctx, collection, op, idsOf(result), affectedCountOf(result), whereShape);
|
|
217
|
+
}
|
|
218
|
+
catch {
|
|
219
|
+
/* never break the host query */
|
|
220
|
+
}
|
|
221
|
+
return result;
|
|
222
|
+
});
|
|
223
|
+
return query;
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
function patchCompiledModel(model) {
|
|
227
|
+
if (patchedModels.has(model))
|
|
228
|
+
return;
|
|
229
|
+
patchedModels.add(model);
|
|
230
|
+
for (const methodName of SELECT_QUERY_OPS)
|
|
231
|
+
wrapQueryReturningMethod(model, methodName, 'select');
|
|
232
|
+
for (const methodName of UPDATE_QUERY_OPS)
|
|
233
|
+
wrapQueryReturningMethod(model, methodName, 'update');
|
|
234
|
+
for (const methodName of DELETE_QUERY_OPS)
|
|
235
|
+
wrapQueryReturningMethod(model, methodName, 'delete');
|
|
236
|
+
const proto = model.prototype;
|
|
237
|
+
const originalSave = proto?.save;
|
|
238
|
+
if (proto && typeof originalSave === 'function') {
|
|
239
|
+
proto.save = function (...args) {
|
|
240
|
+
const ctx = contextStorage.getStore();
|
|
241
|
+
const wasNew = !!this.isNew;
|
|
242
|
+
return originalSave.apply(this, args).then((result) => {
|
|
243
|
+
try {
|
|
244
|
+
recordFootprint(ctx, this.collection?.collectionName, wasNew ? 'insert' : 'update', idsOf(this), 1);
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
/* never break the host save */
|
|
248
|
+
}
|
|
249
|
+
return result;
|
|
250
|
+
});
|
|
251
|
+
};
|
|
252
|
+
}
|
|
253
|
+
const originalInsertMany = model.insertMany;
|
|
254
|
+
if (typeof originalInsertMany === 'function') {
|
|
255
|
+
model.insertMany = function (...args) {
|
|
256
|
+
const ctx = contextStorage.getStore();
|
|
257
|
+
return originalInsertMany.apply(this, args).then((docs) => {
|
|
258
|
+
try {
|
|
259
|
+
const ids = idsOf(docs);
|
|
260
|
+
recordFootprint(ctx, model.collection?.collectionName, 'insert', ids, ids.length);
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
/* never break the host insertMany */
|
|
264
|
+
}
|
|
265
|
+
return docs;
|
|
266
|
+
});
|
|
267
|
+
};
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
// Called once from Reprova.instrumentMongoose() alongside the plugin
|
|
271
|
+
// registration above — covers every model that already exists on this
|
|
272
|
+
// mongoose instance at that moment. Any model compiled AFTER this call is
|
|
273
|
+
// still handled by reprovaMongoosePlugin via mongoose.plugin() as before.
|
|
274
|
+
export function instrumentAlreadyCompiledModels(mongooseInstance) {
|
|
275
|
+
let names = [];
|
|
276
|
+
try {
|
|
277
|
+
names = mongooseInstance.modelNames();
|
|
278
|
+
}
|
|
279
|
+
catch {
|
|
280
|
+
return;
|
|
281
|
+
}
|
|
282
|
+
for (const name of names) {
|
|
283
|
+
try {
|
|
284
|
+
patchCompiledModel(mongooseInstance.model(name));
|
|
285
|
+
}
|
|
286
|
+
catch {
|
|
287
|
+
/* one bad model shouldn't block instrumenting the rest */
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
export function discoverMongooseSchema(mongooseInstance) {
|
|
292
|
+
const models = [];
|
|
293
|
+
const edges = [];
|
|
294
|
+
let names = [];
|
|
295
|
+
try {
|
|
296
|
+
names = mongooseInstance.modelNames();
|
|
297
|
+
}
|
|
298
|
+
catch {
|
|
299
|
+
return { models, edges };
|
|
300
|
+
}
|
|
301
|
+
for (const name of names) {
|
|
302
|
+
let model;
|
|
303
|
+
try {
|
|
304
|
+
model = mongooseInstance.model(name);
|
|
305
|
+
}
|
|
306
|
+
catch {
|
|
307
|
+
continue;
|
|
308
|
+
}
|
|
309
|
+
const collection = model.collection?.collectionName;
|
|
310
|
+
if (!collection)
|
|
311
|
+
continue;
|
|
312
|
+
models.push({ model: name, collection });
|
|
313
|
+
try {
|
|
314
|
+
model.schema.eachPath((pathName, schemaType) => {
|
|
315
|
+
// Direct ref: `{ type: Schema.Types.ObjectId, ref: 'X' }`. Array ref:
|
|
316
|
+
// `[{ type: Schema.Types.ObjectId, ref: 'X' }]` — Mongoose exposes
|
|
317
|
+
// the array element's own SchemaType (with its own `.options.ref`)
|
|
318
|
+
// via `.caster` on the array path's SchemaType.
|
|
319
|
+
const ref = schemaType?.options?.ref ?? schemaType?.caster?.options?.ref;
|
|
320
|
+
if (ref) {
|
|
321
|
+
edges.push({ from_collection: collection, from_field: pathName, to_model: ref, array: !!schemaType?.caster });
|
|
322
|
+
}
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
catch {
|
|
326
|
+
/* schema introspection best-effort — one bad path shouldn't drop the whole model */
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
return { models, edges };
|
|
330
|
+
}
|
|
331
|
+
//# sourceMappingURL=mongoose.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mongoose.js","sourceRoot":"","sources":["../src/mongoose.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { FootprintQuery } from './context.js';
|
|
2
|
+
export interface NPlusOneFinding {
|
|
3
|
+
model: string;
|
|
4
|
+
op: string;
|
|
5
|
+
count: number;
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Groups a request's recorded footprint by (model, op) and returns every
|
|
9
|
+
* group whose invocation count meets or exceeds the threshold — the
|
|
10
|
+
* signature of the same query shape running as N separate round-trips
|
|
11
|
+
* instead of one batched query.
|
|
12
|
+
*
|
|
13
|
+
* This can't mistake an efficient query for N+1: a Prisma `include` (and the
|
|
14
|
+
* equivalent join/relation-load in the other adapters) produces exactly ONE
|
|
15
|
+
* footprint entry per relation per query, however many rows it returns —
|
|
16
|
+
* see prisma.ts's extractNestedFootprints, which aggregates across all rows
|
|
17
|
+
* of a single call rather than pushing one entry per row. What this counts
|
|
18
|
+
* is entries, i.e. actual separate calls into $allOperations (or the
|
|
19
|
+
* equivalent per-adapter hook) — a `for` loop firing the same
|
|
20
|
+
* findUnique/findFirst N times is exactly N entries with the same
|
|
21
|
+
* (model, op), which is the real signal.
|
|
22
|
+
*
|
|
23
|
+
* $raw queries are excluded: each one is its own distinct SQL text, not a
|
|
24
|
+
* repeatable "shape" in the same sense, so counting them together would
|
|
25
|
+
* conflate unrelated raw queries into a false positive.
|
|
26
|
+
*/
|
|
27
|
+
export declare function detectNPlusOne(footprint: FootprintQuery[], threshold: number): NPlusOneFinding[];
|
|
28
|
+
/**
|
|
29
|
+
* A stable, digit-free description of the finding, suitable as an Error
|
|
30
|
+
* message for capture. Deliberately excludes the exact count: the control
|
|
31
|
+
* plane fingerprints occurrences by error type + this message (see
|
|
32
|
+
* fingerprint.go's fallback path for stack-less errors), so two occurrences
|
|
33
|
+
* of the same underlying N+1 pattern — say 6 calls one time, 9 the next —
|
|
34
|
+
* must produce byte-identical messages to fingerprint into the same issue
|
|
35
|
+
* instead of each becoming its own issue. The actual counts are still
|
|
36
|
+
* visible in the capture's data_footprint (one entry per call), so nothing
|
|
37
|
+
* is lost by leaving them out of the message.
|
|
38
|
+
*/
|
|
39
|
+
export declare function describeNPlusOne(finding: NPlusOneFinding): string;
|
|
40
|
+
/**
|
|
41
|
+
* A real named Error subclass, not a plain `new Error()` with `.name` set
|
|
42
|
+
* afterward — `capture()` derives the payload's `error.type` (which the
|
|
43
|
+
* control plane uses verbatim to build the issue title, see ingest.go's
|
|
44
|
+
* buildTitle) from `err.constructor.name`, which for a plain Error is
|
|
45
|
+
* always "Error" regardless of what `.name` gets reassigned to. Subclassing
|
|
46
|
+
* is the only way `error.type` actually reads "PotentialNPlusOneQuery"
|
|
47
|
+
* instead of a generic "Error" in the dashboard.
|
|
48
|
+
*/
|
|
49
|
+
export declare class PotentialNPlusOneQuery extends Error {
|
|
50
|
+
constructor(finding: NPlusOneFinding);
|
|
51
|
+
}
|
|
52
|
+
//# sourceMappingURL=nPlusOne.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nPlusOne.d.ts","sourceRoot":"","sources":["../src/nPlusOne.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnD,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,CAAC,SAAS,EAAE,cAAc,EAAE,EAAE,SAAS,EAAE,MAAM,GAAG,eAAe,EAAE,CAahG;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,eAAe,GAAG,MAAM,CAEjE;AAED;;;;;;;;GAQG;AACH,qBAAa,sBAAuB,SAAQ,KAAK;gBACnC,OAAO,EAAE,eAAe;CAGrC"}
|
package/dist/nPlusOne.js
ADDED
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nPlusOne.js","sourceRoot":"","sources":["../src/nPlusOne.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,cAAc,CAAC,SAA2B,EAAE,SAAiB;IAC3E,IAAI,SAAS,IAAI,CAAC;QAAE,OAAO,EAAE,CAAC;IAE9B,MAAM,MAAM,GAAG,IAAI,GAAG,EAA2B,CAAC;IAClD,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,IAAI,CAAC,CAAC,KAAK,KAAK,MAAM;YAAE,SAAS;QACjC,MAAM,GAAG,GAAG,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,EAAE,EAAE,CAAC;QACjC,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACjC,IAAI,QAAQ;YAAE,QAAQ,CAAC,KAAK,EAAE,CAAC;;YAC1B,MAAM,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,IAAI,SAAS,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC;AACpG,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,gBAAgB,CAAC,OAAwB;IACvD,OAAO,GAAG,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,EAAE,uEAAuE,CAAC;AAC/G,CAAC;AAED;;;;;;;;GAQG;AACH,MAAM,OAAO,sBAAuB,SAAQ,KAAK;IAC/C,YAAY,OAAwB;QAClC,KAAK,CAAC,gBAAgB,CAAC,OAAO,CAAC,CAAC,CAAC;IACnC,CAAC;CACF"}
|
package/dist/nest.d.ts
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
interface HttpArgumentsHostLike {
|
|
2
|
+
getResponse(): unknown;
|
|
3
|
+
getRequest(): unknown;
|
|
4
|
+
}
|
|
5
|
+
export interface ArgumentsHostLike {
|
|
6
|
+
switchToHttp(): HttpArgumentsHostLike;
|
|
7
|
+
}
|
|
8
|
+
export interface ReprovaNestFilter {
|
|
9
|
+
catch(exception: unknown, host: ArgumentsHostLike): void;
|
|
10
|
+
}
|
|
11
|
+
export interface NestAppLike {
|
|
12
|
+
useGlobalFilters(...filters: ReprovaNestFilter[]): unknown;
|
|
13
|
+
useGlobalInterceptors(...interceptors: ReprovaNestInterceptor[]): unknown;
|
|
14
|
+
}
|
|
15
|
+
export interface CallHandlerLike {
|
|
16
|
+
handle(): unknown;
|
|
17
|
+
}
|
|
18
|
+
export interface ReprovaNestInterceptor {
|
|
19
|
+
intercept(context: ArgumentsHostLike, next: CallHandlerLike): unknown;
|
|
20
|
+
}
|
|
21
|
+
export interface NestExceptionFilterOptions {
|
|
22
|
+
capture?: (err: Error) => void;
|
|
23
|
+
}
|
|
24
|
+
export declare function createNestExceptionFilter(opts?: NestExceptionFilterOptions): ReprovaNestFilter;
|
|
25
|
+
export interface NestContextInterceptorOptions {
|
|
26
|
+
resolveContext: (req: unknown) => unknown;
|
|
27
|
+
runInContext: (ctx: unknown, fn: () => unknown) => unknown;
|
|
28
|
+
}
|
|
29
|
+
export declare function createNestContextInterceptor(opts: NestContextInterceptorOptions): ReprovaNestInterceptor;
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=nest.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nest.d.ts","sourceRoot":"","sources":["../src/nest.ts"],"names":[],"mappings":"AAgCA,UAAU,qBAAqB;IAC7B,WAAW,IAAI,OAAO,CAAC;IACvB,UAAU,IAAI,OAAO,CAAC;CACvB;AACD,MAAM,WAAW,iBAAiB;IAChC,YAAY,IAAI,qBAAqB,CAAC;CACvC;AACD,MAAM,WAAW,iBAAiB;IAChC,KAAK,CAAC,SAAS,EAAE,OAAO,EAAE,IAAI,EAAE,iBAAiB,GAAG,IAAI,CAAC;CAC1D;AAID,MAAM,WAAW,WAAW;IAC1B,gBAAgB,CAAC,GAAG,OAAO,EAAE,iBAAiB,EAAE,GAAG,OAAO,CAAC;IAC3D,qBAAqB,CAAC,GAAG,YAAY,EAAE,sBAAsB,EAAE,GAAG,OAAO,CAAC;CAC3E;AAKD,MAAM,WAAW,eAAe;IAC9B,MAAM,IAAI,OAAO,CAAC;CACnB;AACD,MAAM,WAAW,sBAAsB;IACrC,SAAS,CAAC,OAAO,EAAE,iBAAiB,EAAE,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC;CACvE;AAED,MAAM,WAAW,0BAA0B;IAIzC,OAAO,CAAC,EAAE,CAAC,GAAG,EAAE,KAAK,KAAK,IAAI,CAAC;CAChC;AAkCD,wBAAgB,yBAAyB,CAAC,IAAI,GAAE,0BAA+B,GAAG,iBAAiB,CA2DlG;AA4BD,MAAM,WAAW,6BAA6B;IAC5C,cAAc,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,OAAO,CAAC;IAC1C,YAAY,EAAE,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,OAAO,KAAK,OAAO,CAAC;CAC5D;AAuCD,wBAAgB,4BAA4B,CAAC,IAAI,EAAE,6BAA6B,GAAG,sBAAsB,CA2BxG"}
|
package/dist/nest.js
ADDED
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import { parseStack } from './stack.js';
|
|
2
|
+
// Nest's HttpException contract, detected structurally: anything with
|
|
3
|
+
// getStatus() and getResponse() is treated as an intentional HTTP response
|
|
4
|
+
// (a 404, a validation 400, ...) exactly like Nest's own default filter does.
|
|
5
|
+
function isHttpExceptionLike(e) {
|
|
6
|
+
return (typeof e === 'object' &&
|
|
7
|
+
e !== null &&
|
|
8
|
+
typeof e.getStatus === 'function' &&
|
|
9
|
+
typeof e.getResponse === 'function');
|
|
10
|
+
}
|
|
11
|
+
function toError(exception) {
|
|
12
|
+
if (exception instanceof Error)
|
|
13
|
+
return exception;
|
|
14
|
+
return new Error(typeof exception === 'string' ? exception : JSON.stringify(exception));
|
|
15
|
+
}
|
|
16
|
+
// Express: res.status(n).json(body). Fastify: reply.status(n).send(body).
|
|
17
|
+
// Both expose status(); the payload method is feature-detected. Guarded —
|
|
18
|
+
// an exception filter must never itself throw.
|
|
19
|
+
function sendJson(res, status, body) {
|
|
20
|
+
try {
|
|
21
|
+
const r = res;
|
|
22
|
+
if (typeof r.status !== 'function')
|
|
23
|
+
return;
|
|
24
|
+
const chained = r.status(status);
|
|
25
|
+
if (typeof chained.json === 'function')
|
|
26
|
+
chained.json(body);
|
|
27
|
+
else if (typeof chained.send === 'function')
|
|
28
|
+
chained.send(body);
|
|
29
|
+
}
|
|
30
|
+
catch {
|
|
31
|
+
/* never break the response path from inside the filter */
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
export function createNestExceptionFilter(opts = {}) {
|
|
35
|
+
// Same activation rule as replayErrorHandler: the CLI sets REPROVA_REPLAY=1
|
|
36
|
+
// when it boots the app for replay; checked once at construction.
|
|
37
|
+
const replay = process.env.REPROVA_REPLAY === '1';
|
|
38
|
+
return {
|
|
39
|
+
catch(exception, host) {
|
|
40
|
+
const httpEx = isHttpExceptionLike(exception);
|
|
41
|
+
let status = 500;
|
|
42
|
+
if (httpEx) {
|
|
43
|
+
try {
|
|
44
|
+
status = exception.getStatus();
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
status = 500;
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
const res = host.switchToHttp().getResponse();
|
|
51
|
+
const err = toError(exception);
|
|
52
|
+
// Replay contract (only for server-side failures — intentional 4xx
|
|
53
|
+
// responses replay as themselves): emit the structured error the CLI's
|
|
54
|
+
// verdict comparison expects, via the SAME parseStack used at capture.
|
|
55
|
+
if (replay && status >= 500) {
|
|
56
|
+
sendJson(res, 500, {
|
|
57
|
+
error: {
|
|
58
|
+
type: err.constructor?.name ?? err.name ?? 'Error',
|
|
59
|
+
message: err.message,
|
|
60
|
+
stack: parseStack(err),
|
|
61
|
+
},
|
|
62
|
+
});
|
|
63
|
+
return;
|
|
64
|
+
}
|
|
65
|
+
// Capture server-side failures with the ORIGINAL exception. 4xx
|
|
66
|
+
// HttpExceptions are intentional control flow, exactly as Nest treats
|
|
67
|
+
// them — not captured (a silent 500 from elsewhere still gets the 5xx
|
|
68
|
+
// hook as backstop).
|
|
69
|
+
if (status >= 500 && opts.capture) {
|
|
70
|
+
try {
|
|
71
|
+
opts.capture(err);
|
|
72
|
+
}
|
|
73
|
+
catch {
|
|
74
|
+
/* capture must never break the response */
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Respond the way Nest's own BaseExceptionFilter would have.
|
|
78
|
+
if (httpEx) {
|
|
79
|
+
let body;
|
|
80
|
+
try {
|
|
81
|
+
body = exception.getResponse();
|
|
82
|
+
}
|
|
83
|
+
catch {
|
|
84
|
+
body = { statusCode: status, message: err.message };
|
|
85
|
+
}
|
|
86
|
+
sendJson(res, status, typeof body === 'string' ? { statusCode: status, message: body } : body);
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
sendJson(res, 500, { statusCode: 500, message: 'Internal server error' });
|
|
90
|
+
}
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
function wrapSubscriptionWithContext(source, runInContext, ctx) {
|
|
95
|
+
if (!source || typeof source.subscribe !== 'function')
|
|
96
|
+
return source;
|
|
97
|
+
const obs = source;
|
|
98
|
+
const originalSubscribe = obs.subscribe.bind(obs);
|
|
99
|
+
obs.subscribe = (...args) => runInContext(ctx, () => originalSubscribe(...args));
|
|
100
|
+
return obs;
|
|
101
|
+
}
|
|
102
|
+
export function createNestContextInterceptor(opts) {
|
|
103
|
+
return {
|
|
104
|
+
intercept(context, next) {
|
|
105
|
+
let req;
|
|
106
|
+
try {
|
|
107
|
+
req = context.switchToHttp().getRequest();
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
req = undefined;
|
|
111
|
+
}
|
|
112
|
+
let ctx;
|
|
113
|
+
try {
|
|
114
|
+
ctx = opts.resolveContext(req);
|
|
115
|
+
}
|
|
116
|
+
catch {
|
|
117
|
+
ctx = undefined;
|
|
118
|
+
}
|
|
119
|
+
if (!ctx)
|
|
120
|
+
return next.handle();
|
|
121
|
+
// next.handle() itself must be called exactly once — on failure here
|
|
122
|
+
// there is nothing safe to retry (a second call could re-invoke the
|
|
123
|
+
// controller method, double-executing whatever it does), so this is
|
|
124
|
+
// deliberately not wrapped in a try/catch that falls back to a bare
|
|
125
|
+
// next.handle(). Constructing the Observable is cheap/lazy (no pipe or
|
|
126
|
+
// controller work happens yet); the actual context wrap lives inside
|
|
127
|
+
// wrapSubscriptionWithContext, applied to whatever subscribes to it
|
|
128
|
+
// later, whenever that turns out to be.
|
|
129
|
+
return wrapSubscriptionWithContext(next.handle(), opts.runInContext, ctx);
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
//# sourceMappingURL=nest.js.map
|
package/dist/nest.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nest.js","sourceRoot":"","sources":["../src/nest.ts"],"names":[],"mappings":"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"}
|
package/dist/nextjs.d.ts
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { ReprovaOptions } from './sdk.js';
|
|
2
|
+
export interface NextAdapterOptions extends ReprovaOptions {
|
|
3
|
+
prisma?: unknown;
|
|
4
|
+
dmmf?: unknown;
|
|
5
|
+
}
|
|
6
|
+
export interface TrpcMiddlewareResultLike {
|
|
7
|
+
ok: boolean;
|
|
8
|
+
error?: {
|
|
9
|
+
code: string;
|
|
10
|
+
cause?: unknown;
|
|
11
|
+
message?: string;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export interface TrpcMiddlewareParamsLike {
|
|
15
|
+
next: () => Promise<TrpcMiddlewareResultLike>;
|
|
16
|
+
}
|
|
17
|
+
export type ReprovaTrpcMiddleware = (opts: TrpcMiddlewareParamsLike) => Promise<TrpcMiddlewareResultLike>;
|
|
18
|
+
export interface ReprovaNextAdapter {
|
|
19
|
+
ensureInit(): Promise<void>;
|
|
20
|
+
captureError(err: unknown): void;
|
|
21
|
+
wrapRouteHandler<H extends (req: Request, ...rest: any[]) => Response | Promise<Response>>(handler: H): H;
|
|
22
|
+
withRequestContext<T>(req: Request, fn: () => T | Promise<T>): Promise<T>;
|
|
23
|
+
wrapApiHandler<Req, Res>(handler: (req: Req, res: Res) => void | Promise<void>): (req: Req, res: Res) => Promise<void>;
|
|
24
|
+
trpcMiddleware: ReprovaTrpcMiddleware;
|
|
25
|
+
}
|
|
26
|
+
export declare function createNextAdapter(opts: NextAdapterOptions): ReprovaNextAdapter;
|
|
27
|
+
//# sourceMappingURL=nextjs.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nextjs.d.ts","sourceRoot":"","sources":["../src/nextjs.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AA8C/C,MAAM,WAAW,kBAAmB,SAAQ,cAAc;IAGxD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAQD,MAAM,WAAW,wBAAwB;IACvC,EAAE,EAAE,OAAO,CAAC;IACZ,KAAK,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,CAAC,EAAE,OAAO,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;CAC7D;AACD,MAAM,WAAW,wBAAwB;IACvC,IAAI,EAAE,MAAM,OAAO,CAAC,wBAAwB,CAAC,CAAC;CAC/C;AAQD,MAAM,MAAM,qBAAqB,GAAG,CAAC,IAAI,EAAE,wBAAwB,KAAK,OAAO,CAAC,wBAAwB,CAAC,CAAC;AAE1G,MAAM,WAAW,kBAAkB;IAOjC,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAM5B,YAAY,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC;IAejC,gBAAgB,CAAC,CAAC,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC,EAAE,OAAO,EAAE,CAAC,GAAG,CAAC,CAAC;IAU1G,kBAAkB,CAAC,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;IAM1E,cAAc,CAAC,GAAG,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IAGvH,cAAc,EAAE,qBAAqB,CAAC;CACvC;AA8FD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,kBAAkB,GAAG,kBAAkB,CAoF9E"}
|