@reprova/sdk 0.5.0 → 0.6.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +75 -0
- 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 +101 -0
- package/dist/cjs/invariantInference.js +90 -0
- package/dist/cjs/invariantRules.js +142 -0
- package/dist/cjs/knex.js +105 -0
- package/dist/cjs/kysely.js +201 -0
- package/dist/cjs/legacyPrisma.js +130 -0
- package/dist/cjs/mikroorm.js +107 -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 +146 -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 +231 -0
- package/dist/context.d.ts +18 -0
- package/dist/context.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/drizzle.js +10 -4
- 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 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +20 -6
- 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 +1 -0
- package/dist/knex.d.ts.map +1 -1
- package/dist/knex.js +19 -0
- package/dist/knex.js.map +1 -1
- package/dist/kysely.d.ts +1 -0
- package/dist/kysely.d.ts.map +1 -1
- package/dist/kysely.js +27 -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 +3 -0
- package/dist/mikroorm.d.ts.map +1 -0
- package/dist/mikroorm.js +104 -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 +13 -0
- package/dist/nest.d.ts.map +1 -1
- package/dist/nest.js +39 -0
- package/dist/nest.js.map +1 -1
- 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 +10 -2
- 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 +48 -7
- package/dist/sdk.d.ts.map +1 -1
- package/dist/sdk.js +619 -47
- package/dist/sdk.js.map +1 -1
- package/dist/sequelize.d.ts +1 -0
- package/dist/sequelize.d.ts.map +1 -1
- package/dist/sequelize.js +41 -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 +2 -0
- package/dist/typeorm.d.ts.map +1 -1
- package/dist/typeorm.js +163 -1
- package/dist/typeorm.js.map +1 -1
- package/package.json +14 -5
package/dist/nextjs.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { contextStorage } from './context.js';
|
|
2
|
+
import { Reprova } from './sdk.js';
|
|
3
|
+
import { registerContext, completeContext, findContextByTraceId } from './registry.js';
|
|
4
|
+
import { generateTraceId } from './stack.js';
|
|
5
|
+
function toError(value) {
|
|
6
|
+
if (value instanceof Error)
|
|
7
|
+
return value;
|
|
8
|
+
return new Error(typeof value === 'string' ? value : JSON.stringify(value));
|
|
9
|
+
}
|
|
10
|
+
function headersToRecord(headers) {
|
|
11
|
+
const out = {};
|
|
12
|
+
headers.forEach((value, key) => {
|
|
13
|
+
out[key] = value;
|
|
14
|
+
});
|
|
15
|
+
return out;
|
|
16
|
+
}
|
|
17
|
+
// Builds a brand-new, self-contained context directly from a Fetch API
|
|
18
|
+
// Request — used when there is no ambient ALS context AND no outer context
|
|
19
|
+
// could be recovered by traceId (instrumentHttp disabled, an edge runtime
|
|
20
|
+
// with no Node http.Server underneath, or any other setup with no "outer"
|
|
21
|
+
// context to begin with). Registered/completed by the caller, same lifecycle
|
|
22
|
+
// runWithContext/runJob already give background work with no HTTP layer at
|
|
23
|
+
// all.
|
|
24
|
+
function contextFromFetchRequest(req) {
|
|
25
|
+
let path = '/';
|
|
26
|
+
try {
|
|
27
|
+
path = new URL(req.url).pathname;
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
// keep the default
|
|
31
|
+
}
|
|
32
|
+
const traceId = req.headers.get('traceparent') ?? generateTraceId();
|
|
33
|
+
return {
|
|
34
|
+
traceId,
|
|
35
|
+
capturedAt: new Date(),
|
|
36
|
+
request: {
|
|
37
|
+
method: req.method,
|
|
38
|
+
path,
|
|
39
|
+
headers: headersToRecord(req.headers),
|
|
40
|
+
body: '',
|
|
41
|
+
},
|
|
42
|
+
footprint: [],
|
|
43
|
+
outboundCalls: [],
|
|
44
|
+
businessInvariantHits: [],
|
|
45
|
+
writeCountDriftHits: [],
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
// The core of wrapRouteHandler's universality: never assumes ambient ALS
|
|
49
|
+
// context survived whatever dispatch mechanism called into this route.
|
|
50
|
+
// Three cases, in order:
|
|
51
|
+
// 1. Ambient context is present — the common case for Pages Router/tRPC,
|
|
52
|
+
// and for any future Next.js version where App Router propagation
|
|
53
|
+
// works. Used as-is; nothing to register/complete, that's already
|
|
54
|
+
// owned by whoever established it.
|
|
55
|
+
// 2. No ambient context, but the request carries the SAME traceparent
|
|
56
|
+
// value contextFromIncoming wrote onto the raw connection — recovers
|
|
57
|
+
// the REAL outer context (the one instrumentHttpServers's res 'finish'
|
|
58
|
+
// handler already closes over for its own http_5xx fallback), so
|
|
59
|
+
// running the handler inside it and capturing marks that SAME ctx as
|
|
60
|
+
// captured, suppressing the fallback with zero coordination beyond the
|
|
61
|
+
// header. This is the case that fixes Next.js App Router: Next
|
|
62
|
+
// constructs its own Fetch Request rather than reusing the
|
|
63
|
+
// IncomingMessage, so object-identity recovery (ctxByRequest) can't
|
|
64
|
+
// work there, but the header survives regardless of what request
|
|
65
|
+
// object Next builds.
|
|
66
|
+
// 3. Neither — genuinely nothing to recover (instrumentHttp disabled, an
|
|
67
|
+
// edge runtime). Build a fresh context from the Request itself so a
|
|
68
|
+
// real capture still happens instead of silently deferring to a
|
|
69
|
+
// fallback that, in this case, doesn't exist either.
|
|
70
|
+
function resolveRequestContext(req) {
|
|
71
|
+
const existing = contextStorage.getStore();
|
|
72
|
+
if (existing)
|
|
73
|
+
return { ctx: existing, isFresh: false };
|
|
74
|
+
const traceId = req.headers.get('traceparent');
|
|
75
|
+
const recovered = traceId ? findContextByTraceId(traceId) : undefined;
|
|
76
|
+
if (recovered)
|
|
77
|
+
return { ctx: recovered, isFresh: false };
|
|
78
|
+
const fresh = contextFromFetchRequest(req);
|
|
79
|
+
registerContext(fresh);
|
|
80
|
+
return { ctx: fresh, isFresh: true };
|
|
81
|
+
}
|
|
82
|
+
// Shared by wrapRouteHandler and withRequestContext: resolves the context
|
|
83
|
+
// once, runs fn() inside it via ALS, and tears down a freshly-built one
|
|
84
|
+
// (never a recovered or already-ambient one — those are owned by whoever
|
|
85
|
+
// created them).
|
|
86
|
+
async function runInResolvedContext(req, fn) {
|
|
87
|
+
const { ctx, isFresh } = resolveRequestContext(req);
|
|
88
|
+
try {
|
|
89
|
+
return await contextStorage.run(ctx, () => fn(ctx));
|
|
90
|
+
}
|
|
91
|
+
finally {
|
|
92
|
+
if (isFresh)
|
|
93
|
+
completeContext(ctx);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
export function createNextAdapter(opts) {
|
|
97
|
+
const { prisma, dmmf, ...reprovaOpts } = opts;
|
|
98
|
+
const sdk = Reprova.init(reprovaOpts);
|
|
99
|
+
// Not caught here deliberately: a Prisma instrumentation failure is a real
|
|
100
|
+
// setup bug (bad dmmf, a client shape instrumentPrisma doesn't recognize),
|
|
101
|
+
// not something to silently swallow — every ensureInit() caller sees the
|
|
102
|
+
// same rejection instrumentPrisma itself produced, same as the original
|
|
103
|
+
// cal.diy wiring this replaces (`await reprovaSdk.instrumentPrisma(...)`,
|
|
104
|
+
// no try/catch).
|
|
105
|
+
const initPromise = prisma !== undefined ? sdk.instrumentPrisma(prisma, { dmmf }) : Promise.resolve();
|
|
106
|
+
function ensureInit() {
|
|
107
|
+
return initPromise;
|
|
108
|
+
}
|
|
109
|
+
// Used by wrapApiHandler and trpcMiddleware — both reliably see the
|
|
110
|
+
// ambient context established further up the stack (Pages Router's
|
|
111
|
+
// apiResolver mutates the SAME req object instrumentHttpServers already
|
|
112
|
+
// saw; tRPC procedures run inside whatever context wrapped the HTTP
|
|
113
|
+
// handler that dispatches them). Confirmed live: only App Router's own
|
|
114
|
+
// internal dispatch loses the ALS store (see wrapRouteHandler below for
|
|
115
|
+
// the fix) — Pages Router and tRPC carry it through fine, so they don't
|
|
116
|
+
// need the recovery dance.
|
|
117
|
+
function captureUnhandled(err) {
|
|
118
|
+
const ctx = contextStorage.getStore();
|
|
119
|
+
if (!ctx || ctx.captured)
|
|
120
|
+
return;
|
|
121
|
+
sdk.capture('unhandled_exception', toError(err), ctx);
|
|
122
|
+
}
|
|
123
|
+
return {
|
|
124
|
+
ensureInit,
|
|
125
|
+
captureError(err) {
|
|
126
|
+
const ctx = contextStorage.getStore();
|
|
127
|
+
if (!ctx || ctx.captured)
|
|
128
|
+
return;
|
|
129
|
+
sdk.captureError(toError(err));
|
|
130
|
+
},
|
|
131
|
+
wrapRouteHandler(handler) {
|
|
132
|
+
return (async (req, ...rest) => {
|
|
133
|
+
await ensureInit();
|
|
134
|
+
// Establishing ALS directly around this call — rather than
|
|
135
|
+
// depending on whatever context Next's own dispatch may or may not
|
|
136
|
+
// have carried through to get here — is what makes this work
|
|
137
|
+
// regardless of Next.js version, App Router internals, or
|
|
138
|
+
// Turbopack vs. webpack: there is no dispatch layer left between
|
|
139
|
+
// this contextStorage.run() and the handler for anything to lose.
|
|
140
|
+
return runInResolvedContext(req, async (ctx) => {
|
|
141
|
+
try {
|
|
142
|
+
return await handler(req, ...rest);
|
|
143
|
+
}
|
|
144
|
+
catch (err) {
|
|
145
|
+
if (!ctx.captured)
|
|
146
|
+
sdk.capture('unhandled_exception', toError(err), ctx);
|
|
147
|
+
throw err;
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
});
|
|
151
|
+
},
|
|
152
|
+
async withRequestContext(req, fn) {
|
|
153
|
+
await ensureInit();
|
|
154
|
+
return runInResolvedContext(req, () => Promise.resolve(fn()));
|
|
155
|
+
},
|
|
156
|
+
wrapApiHandler(handler) {
|
|
157
|
+
return async (req, res) => {
|
|
158
|
+
await ensureInit();
|
|
159
|
+
try {
|
|
160
|
+
await handler(req, res);
|
|
161
|
+
}
|
|
162
|
+
catch (err) {
|
|
163
|
+
captureUnhandled(err);
|
|
164
|
+
throw err;
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
},
|
|
168
|
+
trpcMiddleware: async ({ next }) => {
|
|
169
|
+
await ensureInit();
|
|
170
|
+
const result = await next();
|
|
171
|
+
if (!result.ok && result.error?.code === 'INTERNAL_SERVER_ERROR') {
|
|
172
|
+
captureUnhandled(result.error.cause ?? result.error);
|
|
173
|
+
}
|
|
174
|
+
return result;
|
|
175
|
+
},
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=nextjs.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nextjs.js","sourceRoot":"","sources":["../src/nextjs.ts"],"names":[],"mappings":"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"}
|
package/dist/prisma.d.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
|
-
|
|
1
|
+
import type { ReprovaContext } from './context.js';
|
|
2
|
+
import type { InvariantRule } from './invariantRules.js';
|
|
3
|
+
import type { InferenceReporter } from './invariantInference.js';
|
|
4
|
+
import type { DistributionDriftReporter } from './distributionDrift.js';
|
|
5
|
+
import type { DistributionBaselinePoller } from './distributionBaselinePoller.js';
|
|
6
|
+
export interface DMMFField {
|
|
2
7
|
name: string;
|
|
3
8
|
kind: string;
|
|
4
9
|
type: string;
|
|
@@ -6,19 +11,31 @@ interface DMMFField {
|
|
|
6
11
|
isList: boolean;
|
|
7
12
|
relationName?: string;
|
|
8
13
|
}
|
|
9
|
-
interface DMMFModel {
|
|
14
|
+
export interface DMMFModel {
|
|
10
15
|
name: string;
|
|
11
16
|
fields: DMMFField[];
|
|
12
17
|
primaryKey?: {
|
|
13
18
|
fields: string[];
|
|
14
19
|
} | null;
|
|
15
20
|
}
|
|
16
|
-
interface DMMF {
|
|
21
|
+
export interface DMMF {
|
|
17
22
|
datamodel: {
|
|
18
23
|
models: DMMFModel[];
|
|
19
24
|
};
|
|
20
25
|
}
|
|
21
|
-
export declare function
|
|
26
|
+
export declare function getPkFields(dmmf: DMMF, modelName: string): string[];
|
|
27
|
+
export declare function extractPks(result: unknown, pkFields: string[]): string[];
|
|
28
|
+
export interface PrismaRecordHooks {
|
|
29
|
+
dmmf?: DMMF;
|
|
30
|
+
getRules?: () => InvariantRule[];
|
|
31
|
+
inferenceReporter?: InferenceReporter;
|
|
32
|
+
writeCountDriftReporter?: DistributionDriftReporter;
|
|
33
|
+
writeCountBaselinePoller?: DistributionBaselinePoller;
|
|
34
|
+
}
|
|
35
|
+
export declare function isWriteOperation(operation: string): boolean;
|
|
36
|
+
export declare function recordFailedWrite(ctx: ReprovaContext, model: string, operation: string, args: Record<string, unknown>): void;
|
|
37
|
+
export declare function recordPrismaOperation(ctx: ReprovaContext, model: string, operation: string, args: Record<string, unknown>, result: unknown, hooks: PrismaRecordHooks): Promise<void>;
|
|
38
|
+
export declare function createPrismaExtension(dmmf: DMMF, getRules?: () => InvariantRule[], inferenceReporter?: InferenceReporter, writeCountDriftReporter?: DistributionDriftReporter, writeCountBaselinePoller?: DistributionBaselinePoller): {
|
|
22
39
|
name: string;
|
|
23
40
|
query: {
|
|
24
41
|
$allOperations({ model, operation, args, query }: {
|
|
@@ -29,5 +46,4 @@ export declare function createPrismaExtension(dmmf: DMMF): {
|
|
|
29
46
|
}): Promise<unknown>;
|
|
30
47
|
};
|
|
31
48
|
};
|
|
32
|
-
export {};
|
|
33
49
|
//# sourceMappingURL=prisma.d.ts.map
|
package/dist/prisma.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prisma.d.ts","sourceRoot":"","sources":["../src/prisma.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"prisma.d.ts","sourceRoot":"","sources":["../src/prisma.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAkB,cAAc,EAAE,MAAM,cAAc,CAAC;AAEnE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjE,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,wBAAwB,CAAC;AACxE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,iCAAiC,CAAC;AAQlF,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;IACd,MAAM,EAAE,OAAO,CAAC;IAChB,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AACD,MAAM,WAAW,SAAS;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,SAAS,EAAE,CAAC;IACpB,UAAU,CAAC,EAAE;QAAE,MAAM,EAAE,MAAM,EAAE,CAAA;KAAE,GAAG,IAAI,CAAC;CAC1C;AACD,MAAM,WAAW,IAAI;IACnB,SAAS,EAAE;QAAE,MAAM,EAAE,SAAS,EAAE,CAAA;KAAE,CAAC;CACpC;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,IAAI,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,EAAE,CAQnE;AA0BD,wBAAgB,UAAU,CAAC,MAAM,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAoBxE;AAgMD,MAAM,WAAW,iBAAiB;IAChC,IAAI,CAAC,EAAE,IAAI,CAAC;IACZ,QAAQ,CAAC,EAAE,MAAM,aAAa,EAAE,CAAC;IACjC,iBAAiB,CAAC,EAAE,iBAAiB,CAAC;IACtC,uBAAuB,CAAC,EAAE,yBAAyB,CAAC;IACpD,wBAAwB,CAAC,EAAE,0BAA0B,CAAC;CACvD;AAQD,wBAAgB,gBAAgB,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAE3D;AAYD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,cAAc,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAY5H;AAYD,wBAAsB,qBAAqB,CACzC,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,MAAM,EACjB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC7B,MAAM,EAAE,OAAO,EACf,KAAK,EAAE,iBAAiB,GACvB,OAAO,CAAC,IAAI,CAAC,CAgCf;AAOD,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,IAAI,EACV,QAAQ,CAAC,EAAE,MAAM,aAAa,EAAE,EAChC,iBAAiB,CAAC,EAAE,iBAAiB,EACrC,uBAAuB,CAAC,EAAE,yBAAyB,EACnD,wBAAwB,CAAC,EAAE,0BAA0B;;;0DAKC;YAChD,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;YAC1B,SAAS,EAAE,MAAM,CAAC;YAClB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;YAC9B,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;SAC5D;;EA8CN"}
|
package/dist/prisma.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { contextStorage } from './context.js';
|
|
2
2
|
import { shapeArgs } from './shape.js';
|
|
3
|
-
|
|
3
|
+
import { compileInvariant, evaluateInvariant, operationMatchesHook } from './invariantRules.js';
|
|
4
|
+
import { isDrift } from './distributionDrift.js';
|
|
5
|
+
export function getPkFields(dmmf, modelName) {
|
|
4
6
|
const model = dmmf.datamodel.models.find(m => m.name === modelName);
|
|
5
7
|
if (!model)
|
|
6
8
|
return ['id'];
|
|
@@ -17,13 +19,25 @@ function getRelationFields(dmmf, modelName) {
|
|
|
17
19
|
return [];
|
|
18
20
|
return model.fields.filter(f => f.kind === 'object' && !!f.relationName);
|
|
19
21
|
}
|
|
22
|
+
const NUMERIC_SCALAR_TYPES = new Set(['Int', 'Float', 'Decimal', 'BigInt']);
|
|
23
|
+
function getNumericFieldNames(dmmf, modelName) {
|
|
24
|
+
const model = dmmf.datamodel.models.find(m => m.name === modelName);
|
|
25
|
+
if (!model)
|
|
26
|
+
return new Set();
|
|
27
|
+
const out = new Set();
|
|
28
|
+
for (const f of model.fields) {
|
|
29
|
+
if (f.kind === 'scalar' && NUMERIC_SCALAR_TYPES.has(f.type))
|
|
30
|
+
out.add(f.name);
|
|
31
|
+
}
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
20
34
|
function extractFromRow(row, pkFields) {
|
|
21
35
|
const vals = pkFields.map(f => row[f]);
|
|
22
36
|
if (vals.some(v => v === undefined))
|
|
23
37
|
return null;
|
|
24
38
|
return vals.map(v => String(v)).join(':');
|
|
25
39
|
}
|
|
26
|
-
function extractPks(result, pkFields) {
|
|
40
|
+
export function extractPks(result, pkFields) {
|
|
27
41
|
if (result === null || result === undefined)
|
|
28
42
|
return [];
|
|
29
43
|
if (Array.isArray(result)) {
|
|
@@ -80,20 +94,228 @@ function extractNestedFootprints(dmmf, modelName, result) {
|
|
|
80
94
|
}
|
|
81
95
|
return entries;
|
|
82
96
|
}
|
|
83
|
-
//
|
|
97
|
+
// Evaluates every enabled rule matching this model/operation against the
|
|
98
|
+
// query result, recording at most one hit per rule per request (see
|
|
99
|
+
// context.ts's businessInvariantHits). Evaluation only sees relation data
|
|
100
|
+
// the app's own query already `include`d — a rule referencing anything else
|
|
101
|
+
// is silently inapplicable (evaluateInvariant returns undefined), never a
|
|
102
|
+
// false violation. Must run here, inside the extension: this is the only
|
|
103
|
+
// place actual field values are available — the footprint pushed above only
|
|
104
|
+
// ever carries PKs/counts, never row content.
|
|
105
|
+
async function applyInvariantRules(ctx, rules, model, operation, result, pkFields) {
|
|
106
|
+
if (rules.length === 0)
|
|
107
|
+
return;
|
|
108
|
+
const rows = Array.isArray(result)
|
|
109
|
+
? result.filter((r) => r && typeof r === 'object')
|
|
110
|
+
: result && typeof result === 'object'
|
|
111
|
+
? [result]
|
|
112
|
+
: [];
|
|
113
|
+
if (rows.length === 0)
|
|
114
|
+
return;
|
|
115
|
+
for (const rule of rules) {
|
|
116
|
+
if (rule.model !== model)
|
|
117
|
+
continue;
|
|
118
|
+
if (!operationMatchesHook(operation, rule.when_hook))
|
|
119
|
+
continue;
|
|
120
|
+
if (ctx.businessInvariantHits.some((h) => h.ruleId === rule.id))
|
|
121
|
+
continue; // one hit per rule per request
|
|
122
|
+
const compiled = await compileInvariant(rule);
|
|
123
|
+
if (!compiled)
|
|
124
|
+
continue; // invalid CEL syntax (or CEL engine unavailable on this runtime) — never crash, never fire
|
|
125
|
+
for (const row of rows) {
|
|
126
|
+
if (evaluateInvariant(compiled, row) === false) {
|
|
127
|
+
ctx.businessInvariantHits.push({ ruleId: rule.id, message: rule.message, pks: extractPks(row, pkFields) });
|
|
128
|
+
break; // first offending row is enough evidence for this rule
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// Invariant inference, v1 slice: passively observes whether a same-named
|
|
134
|
+
// numeric field on the parent equals the sum of that same field across an
|
|
135
|
+
// already-included to-many relation (Invoice.total vs
|
|
136
|
+
// sum(lineItems.total)), reporting pass/fail counts — never capturing or
|
|
137
|
+
// altering behavior on its own. Same-field-name only, not every numeric-
|
|
138
|
+
// field-pair combination: that keeps candidate volume bounded (at most one
|
|
139
|
+
// candidate per shared field name per relation, not N×M) and the heuristic
|
|
140
|
+
// legible. Runs unconditionally whenever a reporter is configured; see
|
|
141
|
+
// invariantInference.ts's module doc for the fuller design this is a first
|
|
142
|
+
// slice of.
|
|
143
|
+
function observeInferredInvariants(dmmf, modelName, result, reporter) {
|
|
144
|
+
if (!dmmf)
|
|
145
|
+
return;
|
|
146
|
+
const rows = Array.isArray(result)
|
|
147
|
+
? result.filter(r => r && typeof r === 'object')
|
|
148
|
+
: result && typeof result === 'object'
|
|
149
|
+
? [result]
|
|
150
|
+
: [];
|
|
151
|
+
if (rows.length === 0)
|
|
152
|
+
return;
|
|
153
|
+
const parentNumeric = getNumericFieldNames(dmmf, modelName);
|
|
154
|
+
if (parentNumeric.size === 0)
|
|
155
|
+
return;
|
|
156
|
+
for (const field of getRelationFields(dmmf, modelName)) {
|
|
157
|
+
if (!field.isList)
|
|
158
|
+
continue; // sum only makes sense over a to-many relation
|
|
159
|
+
if (!rows.some(row => field.name in row))
|
|
160
|
+
continue; // relation wasn't included
|
|
161
|
+
const childNumeric = getNumericFieldNames(dmmf, field.type);
|
|
162
|
+
const sharedFields = [...parentNumeric].filter(f => childNumeric.has(f));
|
|
163
|
+
if (sharedFields.length === 0)
|
|
164
|
+
continue;
|
|
165
|
+
for (const row of rows) {
|
|
166
|
+
const relVal = row[field.name];
|
|
167
|
+
if (!Array.isArray(relVal))
|
|
168
|
+
continue; // relation not included on this specific row
|
|
169
|
+
for (const fieldName of sharedFields) {
|
|
170
|
+
const parentVal = row[fieldName];
|
|
171
|
+
if (typeof parentVal !== 'number')
|
|
172
|
+
continue;
|
|
173
|
+
let sum = 0;
|
|
174
|
+
let allNumeric = true;
|
|
175
|
+
for (const item of relVal) {
|
|
176
|
+
const v = item && typeof item === 'object' ? item[fieldName] : undefined;
|
|
177
|
+
if (typeof v !== 'number') {
|
|
178
|
+
allNumeric = false;
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
sum += v;
|
|
182
|
+
}
|
|
183
|
+
if (!allNumeric)
|
|
184
|
+
continue; // partial/missing data — never guess, same principle as evaluateCondition
|
|
185
|
+
// Float-tolerant: Decimal fields commonly arrive as floating-point
|
|
186
|
+
// numbers, where exact equality would misreport ordinary rounding
|
|
187
|
+
// as a "violation" on every single request.
|
|
188
|
+
const held = Math.abs(parentVal - sum) < 1e-6 * Math.max(1, Math.abs(parentVal));
|
|
189
|
+
reporter.record(modelName, fieldName, field.name, held);
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
const BULK_WRITE_OPS = new Set(['updateMany', 'deleteMany', 'createMany']);
|
|
195
|
+
// Write-pattern anomalies, row-count-drift slice: baselines the
|
|
196
|
+
// affected-row count of a bulk write (updateMany/deleteMany/createMany —
|
|
197
|
+
// a single update/delete/create always affects exactly 1 row or throws,
|
|
198
|
+
// nothing to baseline there) per (route, operation:model), and flags a
|
|
199
|
+
// live count implausibly far from it — "0 rows where normally ~3" and
|
|
200
|
+
// "50,000 rows where normally ~5" are the same phenomenon, just opposite
|
|
201
|
+
// ends of one baseline. Reuses isDrift and the DistributionDriftReporter/
|
|
202
|
+
// DistributionBaselinePoller classes directly from distributionDrift.ts —
|
|
203
|
+
// see that module's doc comment on WriteCountDrift for why this needs no
|
|
204
|
+
// new statistical machinery, only a new observation site and a second
|
|
205
|
+
// pair of instances pointed at a separate endpoint. Recording is
|
|
206
|
+
// unconditional (same reasoning as observeInferredInvariants/
|
|
207
|
+
// checkDistributionDriftIfAny — the baseline must already be populated by
|
|
208
|
+
// the time an admin opts in); only the CAPTURE side gates on the polled
|
|
209
|
+
// enabled flag, and hits push onto ctx for wrapResponse to drain and
|
|
210
|
+
// capture at response time (the same deferred-capture shape
|
|
211
|
+
// applyInvariantRules already uses via businessInvariantHits) rather than
|
|
212
|
+
// capturing directly from inside the Prisma extension.
|
|
213
|
+
function observeWriteCountDrift(ctx, model, operation, result, reporter, poller) {
|
|
214
|
+
if (!BULK_WRITE_OPS.has(operation))
|
|
215
|
+
return;
|
|
216
|
+
if (!result || typeof result !== 'object' || Array.isArray(result))
|
|
217
|
+
return;
|
|
218
|
+
const count = result.count;
|
|
219
|
+
if (typeof count !== 'number')
|
|
220
|
+
return;
|
|
221
|
+
const req = ctx.rawRequest;
|
|
222
|
+
const routePattern = req?.route?.path;
|
|
223
|
+
if (!routePattern)
|
|
224
|
+
return; // no stable key to group on
|
|
225
|
+
const route = `${ctx.request.method} ${routePattern}`;
|
|
226
|
+
const key = `${operation}:${model}`;
|
|
227
|
+
reporter.record(route, key, count);
|
|
228
|
+
if (!poller.isEnabled())
|
|
229
|
+
return;
|
|
230
|
+
const baseline = poller.getBaseline(route, key);
|
|
231
|
+
if (!baseline || !isDrift(count, baseline))
|
|
232
|
+
return;
|
|
233
|
+
if (ctx.writeCountDriftHits.some((h) => h.route === route && h.model === model && h.operation === operation))
|
|
234
|
+
return;
|
|
235
|
+
ctx.writeCountDriftHits.push({ route, model, operation });
|
|
236
|
+
}
|
|
237
|
+
// Shared with legacyPrisma.ts's instrumentLegacyPrismaClient, which has its
|
|
238
|
+
// own copy of this same set for the exact same reason: a rejected read has
|
|
239
|
+
// no "what would have been written" story, so only writes get a footprint
|
|
240
|
+
// entry when the database rejects them.
|
|
241
|
+
const WRITE_OPS = new Set(['create', 'createMany', 'update', 'updateMany', 'upsert', 'delete', 'deleteMany']);
|
|
242
|
+
export function isWriteOperation(operation) {
|
|
243
|
+
return WRITE_OPS.has(operation);
|
|
244
|
+
}
|
|
245
|
+
// Column NAMES only — never the bound values (the too-long username, the
|
|
246
|
+
// duplicate email), which are row data and must never enter a footprint per
|
|
247
|
+
// the metadata-only rule. Mirrors typeorm.ts's parseFailedWrite and
|
|
248
|
+
// legacyPrisma.ts's recordFailedWrite; this is the version createPrismaExtension's
|
|
249
|
+
// $allOperations uses for modern ($extends-capable) clients, whose failed
|
|
250
|
+
// queries previously left no trace at all — `$allOperations` only had a
|
|
251
|
+
// `.then()`, no rejection handler, so a write the database rejected (a
|
|
252
|
+
// unique-constraint violation, a length-limited column, a FK violation)
|
|
253
|
+
// silently vanished from the footprint even though it's often exactly the
|
|
254
|
+
// query that explains the bug.
|
|
255
|
+
export function recordFailedWrite(ctx, model, operation, args) {
|
|
256
|
+
const data = args.data;
|
|
257
|
+
const where = args.where;
|
|
258
|
+
const columns = [...new Set([...(data ? Object.keys(data) : []), ...(where ? Object.keys(where) : [])])];
|
|
259
|
+
ctx.footprint.push({
|
|
260
|
+
model,
|
|
261
|
+
op: `${operation}_failed`,
|
|
262
|
+
pks: [],
|
|
263
|
+
count: 0,
|
|
264
|
+
where_shape: columns.length ? columns.join(',') : undefined,
|
|
265
|
+
note: 'rejected by database — see error for reason',
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
// The one place a completed Prisma operation (result in hand, whatever
|
|
269
|
+
// hooked into its lifecycle) gets turned into a footprint entry and run
|
|
270
|
+
// through every detector. Shared by BOTH createPrismaExtension's
|
|
271
|
+
// $allOperations (clients with $extends) and legacyPrisma.ts's
|
|
272
|
+
// instrumentLegacyPrismaClient (clients with neither $extends nor $use —
|
|
273
|
+
// confirmed live against a real @prisma/client@2.0.0-beta.4, which has
|
|
274
|
+
// none of Prisma's query-lifecycle hooks at all) — same recording logic
|
|
275
|
+
// regardless of how the installed client exposes its queries. `args` here
|
|
276
|
+
// is whatever the model delegate method itself was called with (where/data/
|
|
277
|
+
// select/include), same shape on every Prisma version.
|
|
278
|
+
export async function recordPrismaOperation(ctx, model, operation, args, result, hooks) {
|
|
279
|
+
const { dmmf, getRules, inferenceReporter, writeCountDriftReporter, writeCountBaselinePoller } = hooks;
|
|
280
|
+
const pkFields = dmmf ? getPkFields(dmmf, model) : ['id'];
|
|
281
|
+
const pks = extractPks(result, pkFields);
|
|
282
|
+
const count = Array.isArray(result) ? result.length : (result !== null && result !== undefined ? 1 : 0);
|
|
283
|
+
const whereShape = args.where ? shapeArgs(args.where) : undefined;
|
|
284
|
+
ctx.footprint.push({
|
|
285
|
+
model,
|
|
286
|
+
op: operation,
|
|
287
|
+
pks,
|
|
288
|
+
where_shape: whereShape,
|
|
289
|
+
count,
|
|
290
|
+
note: count === 0 ? 'returned 0 rows' : undefined,
|
|
291
|
+
});
|
|
292
|
+
for (const nested of extractNestedFootprints(dmmf, model, result)) {
|
|
293
|
+
ctx.footprint.push(nested);
|
|
294
|
+
}
|
|
295
|
+
if (getRules) {
|
|
296
|
+
await applyInvariantRules(ctx, getRules(), model, operation, result, pkFields);
|
|
297
|
+
}
|
|
298
|
+
if (inferenceReporter) {
|
|
299
|
+
observeInferredInvariants(dmmf, model, result, inferenceReporter);
|
|
300
|
+
}
|
|
301
|
+
if (writeCountDriftReporter && writeCountBaselinePoller) {
|
|
302
|
+
observeWriteCountDrift(ctx, model, operation, result, writeCountDriftReporter, writeCountBaselinePoller);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
// Creates the Reprova Prisma client extension. getRules returns the SDK's
|
|
306
|
+
// live-cached business-invariant rules (RulesPoller) — read on every query
|
|
307
|
+
// rather than captured once, so a rule enabled/edited in the dashboard
|
|
308
|
+
// takes effect on the next poll without touching this extension.
|
|
84
309
|
// Usage: const prisma = new PrismaClient().$extends(reprova.prismaExtension())
|
|
85
|
-
export function createPrismaExtension(dmmf) {
|
|
310
|
+
export function createPrismaExtension(dmmf, getRules, inferenceReporter, writeCountDriftReporter, writeCountBaselinePoller) {
|
|
86
311
|
return {
|
|
87
312
|
name: 'reprova-footprint',
|
|
88
313
|
query: {
|
|
89
314
|
$allOperations({ model, operation, args, query }) {
|
|
90
315
|
const ctx = contextStorage.getStore();
|
|
91
|
-
|
|
92
|
-
return query(args).then((result) => {
|
|
316
|
+
return query(args).then(async (result) => {
|
|
93
317
|
if (!ctx)
|
|
94
318
|
return result;
|
|
95
|
-
const elapsed = performance.now() - start;
|
|
96
|
-
void elapsed; // used for bench
|
|
97
319
|
// Handle raw queries
|
|
98
320
|
if (model === undefined || operation === '$queryRaw' || operation === '$executeRaw') {
|
|
99
321
|
const sqlText = Array.isArray(args) ? String(args[0]) : '[raw]';
|
|
@@ -107,22 +329,25 @@ export function createPrismaExtension(dmmf) {
|
|
|
107
329
|
});
|
|
108
330
|
return result;
|
|
109
331
|
}
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
op: operation,
|
|
117
|
-
pks,
|
|
118
|
-
where_shape: whereShape,
|
|
119
|
-
count,
|
|
120
|
-
note: count === 0 ? 'returned 0 rows' : undefined,
|
|
332
|
+
await recordPrismaOperation(ctx, model, operation, args, result, {
|
|
333
|
+
dmmf,
|
|
334
|
+
getRules,
|
|
335
|
+
inferenceReporter,
|
|
336
|
+
writeCountDriftReporter,
|
|
337
|
+
writeCountBaselinePoller,
|
|
121
338
|
});
|
|
122
|
-
for (const nested of extractNestedFootprints(dmmf, model, result)) {
|
|
123
|
-
ctx.footprint.push(nested);
|
|
124
|
-
}
|
|
125
339
|
return result;
|
|
340
|
+
},
|
|
341
|
+
// The two-argument form of .then (not a chained .catch) so a
|
|
342
|
+
// throw from the success branch above never gets mistaken for a
|
|
343
|
+
// rejected query. Only writes get a footprint entry here — same
|
|
344
|
+
// "no what-would-have-been-read story" reasoning as the legacy
|
|
345
|
+
// adapters — and the original error is always rethrown unchanged.
|
|
346
|
+
(err) => {
|
|
347
|
+
if (ctx && model !== undefined && isWriteOperation(operation)) {
|
|
348
|
+
recordFailedWrite(ctx, model, operation, args);
|
|
349
|
+
}
|
|
350
|
+
throw err;
|
|
126
351
|
});
|
|
127
352
|
},
|
|
128
353
|
},
|
package/dist/prisma.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"prisma.js","sourceRoot":"","sources":["../src/prisma.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAqBvC,SAAS,WAAW,CAAC,IAAU,EAAE,SAAiB;IAChD,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;IACpE,IAAI,CAAC,KAAK;QAAE,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,eAAe;IACf,IAAI,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,MAAM;QAAE,OAAO,KAAK,CAAC,UAAU,CAAC,MAAM,CAAC;IACrE,mBAAmB;IACnB,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC/C,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AAC3C,CAAC;AAED,SAAS,iBAAiB,CAAC,IAAU,EAAE,SAAiB;IACtD,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC;IACpE,IAAI,CAAC,KAAK;QAAE,OAAO,EAAE,CAAC;IACtB,OAAO,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;AAC3E,CAAC;AAED,SAAS,cAAc,CAAC,GAA4B,EAAE,QAAkB;IACtE,MAAM,IAAI,GAAG,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC;QAAE,OAAO,IAAI,CAAC;IACjD,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,UAAU,CAAC,MAAe,EAAE,QAAkB;IACrD,IAAI,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS;QAAE,OAAO,EAAE,CAAC;IAEvD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;QAC1B,MAAM,GAAG,GAAa,EAAE,CAAC;QACzB,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;YAC1B,IAAI,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACrC,MAAM,EAAE,GAAG,cAAc,CAAC,IAA+B,EAAE,QAAQ,CAAC,CAAC;gBACrE,IAAI,EAAE,KAAK,IAAI;oBAAE,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;QACD,OAAO,GAAG,CAAC;IACb,CAAC;IAED,IAAI,OAAO,MAAM,KAAK,QAAQ,EAAE,CAAC;QAC/B,MAAM,EAAE,GAAG,cAAc,CAAC,MAAiC,EAAE,QAAQ,CAAC,CAAC;QACvE,OAAO,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACjC,CAAC;IAED,OAAO,EAAE,CAAC;AACZ,CAAC;AAED,gFAAgF;AAChF,gFAAgF;AAChF,sDAAsD;AACtD,SAAS,uBAAuB,CAAC,IAAsB,EAAE,SAAiB,EAAE,MAAe;IACzF,IAAI,CAAC,IAAI;QAAE,OAAO,EAAE,CAAC;IACrB,MAAM,IAAI,GAA8B,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAC3D,CAAC,CAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,CAA+B;QAC/E,CAAC,CAAC,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ;YACpC,CAAC,CAAC,CAAC,MAAiC,CAAC;YACrC,CAAC,CAAC,EAAE,CAAC;IACT,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,EAAE,CAAC;IAEjC,MAAM,OAAO,GAAqB,EAAE,CAAC;IACrC,KAAK,MAAM,KAAK,IAAI,iBAAiB,CAAC,IAAI,EAAE,SAAS,CAAC,EAAE,CAAC;QACvD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,IAAI,GAAG,CAAC;YAAE,SAAS,CAAC,2BAA2B;QAE/E,MAAM,cAAc,GAAG,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACrD,MAAM,WAAW,GAAc,EAAE,CAAC;QAClC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE,CAAC;YACvB,MAAM,GAAG,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC5B,IAAI,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;gBAAE,WAAW,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC;iBAC5C,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,KAAK,SAAS;gBAAE,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QACpE,CAAC;QAED,MAAM,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,cAAc,CAAC,CAAC;QAC5F,OAAO,CAAC,IAAI,CAAC;YACX,KAAK,EAAE,KAAK,CAAC,IAAI;YACjB,EAAE,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,YAAY;YAC5C,GAAG;YACH,KAAK,EAAE,WAAW,CAAC,MAAM;YACzB,IAAI,EAAE,WAAW,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS;SAC/D,CAAC,CAAC;IACL,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,+CAA+C;AAC/C,+EAA+E;AAC/E,MAAM,UAAU,qBAAqB,CAAC,IAAU;IAC9C,OAAO;QACL,IAAI,EAAE,mBAAmB;QACzB,KAAK,EAAE;YACL,cAAc,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAK7C;gBACC,MAAM,GAAG,GAAG,cAAc,CAAC,QAAQ,EAAE,CAAC;gBACtC,MAAM,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC;gBAEhC,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,MAAe,EAAE,EAAE;oBAC1C,IAAI,CAAC,GAAG;wBAAE,OAAO,MAAM,CAAC;oBAExB,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE,GAAG,KAAK,CAAC;oBAC1C,KAAK,OAAO,CAAC,CAAC,iBAAiB;oBAE/B,qBAAqB;oBACrB,IAAI,KAAK,KAAK,SAAS,IAAI,SAAS,KAAK,WAAW,IAAI,SAAS,KAAK,aAAa,EAAE,CAAC;wBACpF,MAAM,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC;wBAChE,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC;4BACjB,KAAK,EAAE,MAAM;4BACb,EAAE,EAAE,SAAS;4BACb,GAAG,EAAE,EAAE;4BACP,KAAK,EAAE,CAAC;4BACR,IAAI,EAAE,8BAA8B;4BACpC,WAAW,EAAE,OAAO,CAAC,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;yBAC5C,CAAC,CAAC;wBACH,OAAO,MAAM,CAAC;oBAChB,CAAC;oBAED,MAAM,QAAQ,GAAG,IAAI,CAAC,CAAC,CAAC,WAAW,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;oBAC1D,MAAM,GAAG,GAAG,UAAU,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;oBACzC,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,KAAK,IAAI,IAAI,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;oBACxG,MAAM,UAAU,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;oBAElE,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC;wBACjB,KAAK;wBACL,EAAE,EAAE,SAAS;wBACb,GAAG;wBACH,WAAW,EAAE,UAAU;wBACvB,KAAK;wBACL,IAAI,EAAE,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,SAAS;qBAClD,CAAC,CAAC;oBAEH,KAAK,MAAM,MAAM,IAAI,uBAAuB,CAAC,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,CAAC;wBAClE,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;oBAC7B,CAAC;oBAED,OAAO,MAAM,CAAC;gBAChB,CAAC,CAAC,CAAC;YACL,CAAC;SACF;KACF,CAAC;AACJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"prisma.js","sourceRoot":"","sources":["../src/prisma.ts"],"names":[],"mappings":"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"}
|
package/dist/proto.gen.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export interface CapturePayload {
|
|
2
|
-
trigger: 'unhandled_exception' | 'http_5xx' | 'manual_capture' | 'orm_error' | 'job_failure' | 'frontend_error';
|
|
2
|
+
trigger: 'unhandled_exception' | 'http_5xx' | 'manual_capture' | 'orm_error' | 'job_failure' | 'frontend_error' | 'n_plus_one_query' | 'retry_storm' | 'business_invariant' | 'idempotency_key_mismatch' | 'duplicate_read_mismatch' | 'value_distribution_drift' | 'write_count_drift';
|
|
3
3
|
trace_id: string;
|
|
4
4
|
timestamp: string;
|
|
5
5
|
release: string;
|
|
@@ -29,6 +29,7 @@ export interface CapturePayload {
|
|
|
29
29
|
where_shape?: string;
|
|
30
30
|
count: number;
|
|
31
31
|
note?: string;
|
|
32
|
+
resolved?: boolean;
|
|
32
33
|
}>;
|
|
33
34
|
};
|
|
34
35
|
outbound_calls: Array<{
|
|
@@ -87,6 +88,7 @@ export interface CapturePayload {
|
|
|
87
88
|
where_shape?: string;
|
|
88
89
|
count: number;
|
|
89
90
|
note?: string;
|
|
91
|
+
resolved?: boolean;
|
|
90
92
|
}>;
|
|
91
93
|
};
|
|
92
94
|
}>;
|
|
@@ -137,6 +139,12 @@ export interface JobPlan {
|
|
|
137
139
|
rows_per_table: number;
|
|
138
140
|
include_audit_findings: boolean;
|
|
139
141
|
};
|
|
142
|
+
reference_edges?: Array<{
|
|
143
|
+
from_collection: string;
|
|
144
|
+
from_field: string;
|
|
145
|
+
to_collection: string;
|
|
146
|
+
array: boolean;
|
|
147
|
+
}>;
|
|
140
148
|
}
|
|
141
149
|
export interface Manifest {
|
|
142
150
|
package_id: string;
|
|
@@ -145,7 +153,7 @@ export interface Manifest {
|
|
|
145
153
|
migration_id: string;
|
|
146
154
|
created_at: string;
|
|
147
155
|
anonymization_ruleset_id: string;
|
|
148
|
-
dialect?: 'postgres' | 'mysql' | 'mssql';
|
|
156
|
+
dialect?: 'postgres' | 'mysql' | 'mssql' | 'mongo';
|
|
149
157
|
table_order: Array<string>;
|
|
150
158
|
row_counts: Record<string, number>;
|
|
151
159
|
row_count: number;
|