querydig 0.1.0 → 0.2.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 +70 -4
- package/dist/analyzer.d.ts +13 -1
- package/dist/chunk-DZLU5MLV.js +26 -0
- package/dist/{chunk-XKXVJWL6.js → chunk-P3O2JP5S.js} +38 -13
- package/dist/{chunk-VAYEO4RI.js → chunk-YKUITQ6N.js} +150 -23
- package/dist/cli.js +13 -3
- package/dist/index.js +3 -2
- package/dist/live/correlate.d.ts +14 -0
- package/dist/live/index.d.ts +13 -0
- package/dist/live/match.d.ts +16 -0
- package/dist/live/mongo.d.ts +25 -0
- package/dist/live/postgres.d.ts +29 -0
- package/dist/live/types.d.ts +77 -0
- package/dist/live-DSIYWIT4.js +697 -0
- package/dist/scan.d.ts +4 -0
- package/dist/types.d.ts +50 -1
- package/dist/worker.js +2 -1
- package/package.json +15 -2
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { QueryShape, SortKey } from '../types.js';
|
|
2
|
+
import type { IndexInfo, SlowQuery } from './types.js';
|
|
3
|
+
/**
|
|
4
|
+
* Resolve a collection/model name seen in code to a live table/collection name.
|
|
5
|
+
* Handles Mongoose (User → users), Prisma (user → User), Django (Book → shop_book), snake/camel case.
|
|
6
|
+
*/
|
|
7
|
+
export declare function resolveTable(name: string | undefined, tables: Iterable<string>): string | undefined;
|
|
8
|
+
/** Does an index serve this filter + sort? Equality keys (any order) as the prefix, then sort keys in order. */
|
|
9
|
+
export declare function indexCovers(index: IndexInfo, filterKeys: string[], sortKeys: SortKey[]): boolean;
|
|
10
|
+
/** ESR-ordered index suggestion as a ready-to-run statement. */
|
|
11
|
+
export declare function suggestIndex(adapter: 'mongodb' | 'postgres', table: string, filterKeys: string[], sortKeys: SortKey[]): string | undefined;
|
|
12
|
+
/** Find the static shape that most likely produced a slow query seen by the database. */
|
|
13
|
+
export declare function matchSlowQuery(q: SlowQuery, shapes: QueryShape[], shapeTables: Map<string, string>): QueryShape | undefined;
|
|
14
|
+
export declare function redactUri(uri: string): string;
|
|
15
|
+
/** Replace any credential that leaked into an error message. */
|
|
16
|
+
export declare function redactText(text: string, uri: string): string;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { QueryShape } from '../types.js';
|
|
2
|
+
import type { ForeignKey, IndexInfo, LiveAdapter, LiveOptions, PlanSummary, SlowQuery, TableInfo } from './types.js';
|
|
3
|
+
type Doc = Record<string, any>;
|
|
4
|
+
/** Top-level field names of a filter, flattening $and / $or and skipping operators. */
|
|
5
|
+
export declare function filterFields(filter: Doc | undefined): string[];
|
|
6
|
+
/** Walk a winning plan (classic or SBE `queryPlan`) and summarise it. */
|
|
7
|
+
export declare function summarisePlan(plan: Doc | undefined, table: string): Omit<PlanSummary, 'estRows' | 'docsExamined' | 'ms'>;
|
|
8
|
+
export declare class MongoAdapter implements LiveAdapter {
|
|
9
|
+
private opts;
|
|
10
|
+
readonly name: "mongodb";
|
|
11
|
+
database: string;
|
|
12
|
+
private client;
|
|
13
|
+
private db;
|
|
14
|
+
constructor(opts: LiveOptions);
|
|
15
|
+
connect(): Promise<void>;
|
|
16
|
+
private get t();
|
|
17
|
+
tables(): Promise<TableInfo[]>;
|
|
18
|
+
indexes(tables: string[]): Promise<IndexInfo[]>;
|
|
19
|
+
foreignKeys(): Promise<ForeignKey[]>;
|
|
20
|
+
explain(shape: QueryShape, table: string): Promise<PlanSummary | null>;
|
|
21
|
+
slowQueries(slowMs: number): Promise<SlowQuery[]>;
|
|
22
|
+
warnings(): Promise<string[]>;
|
|
23
|
+
close(): Promise<void>;
|
|
24
|
+
}
|
|
25
|
+
export {};
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { QueryShape } from '../types.js';
|
|
2
|
+
import type { ForeignKey, IndexInfo, LiveAdapter, LiveOptions, PlanSummary, SlowQuery, TableInfo } from './types.js';
|
|
3
|
+
type Row = Record<string, any>;
|
|
4
|
+
/** Summarise an EXPLAIN (FORMAT JSON) plan tree. */
|
|
5
|
+
export declare function summarisePgPlan(root: Row | undefined, table: string): PlanSummary;
|
|
6
|
+
export declare class PostgresAdapter implements LiveAdapter {
|
|
7
|
+
private opts;
|
|
8
|
+
readonly name: "postgres";
|
|
9
|
+
database: string;
|
|
10
|
+
private client;
|
|
11
|
+
private version;
|
|
12
|
+
private columns;
|
|
13
|
+
constructor(opts: LiveOptions);
|
|
14
|
+
connect(): Promise<void>;
|
|
15
|
+
private q;
|
|
16
|
+
tables(): Promise<TableInfo[]>;
|
|
17
|
+
indexes(): Promise<IndexInfo[]>;
|
|
18
|
+
foreignKeys(): Promise<ForeignKey[]>;
|
|
19
|
+
/** SQL to explain for a shape, or null when it can't be explained safely. */
|
|
20
|
+
explainSql(shape: QueryShape, table: string): {
|
|
21
|
+
sql: string;
|
|
22
|
+
generic: boolean;
|
|
23
|
+
} | null;
|
|
24
|
+
explain(shape: QueryShape, table: string): Promise<PlanSummary | null>;
|
|
25
|
+
slowQueries(slowMs: number): Promise<SlowQuery[]>;
|
|
26
|
+
warnings(): Promise<string[]>;
|
|
27
|
+
close(): Promise<void>;
|
|
28
|
+
}
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import type { QueryShape, SortKey } from '../types.js';
|
|
2
|
+
export type AdapterName = 'mongodb' | 'postgres';
|
|
3
|
+
export interface TableInfo {
|
|
4
|
+
name: string;
|
|
5
|
+
rows: number;
|
|
6
|
+
sizeBytes?: number;
|
|
7
|
+
}
|
|
8
|
+
export interface IndexInfo {
|
|
9
|
+
table: string;
|
|
10
|
+
name: string;
|
|
11
|
+
keys: SortKey[];
|
|
12
|
+
unique: boolean;
|
|
13
|
+
primary: boolean;
|
|
14
|
+
/** number of recorded uses; undefined when the database does not expose it */
|
|
15
|
+
usage?: number;
|
|
16
|
+
definition?: string;
|
|
17
|
+
}
|
|
18
|
+
export interface PlanSummary {
|
|
19
|
+
table: string;
|
|
20
|
+
fullScan: boolean;
|
|
21
|
+
inMemorySort: boolean;
|
|
22
|
+
indexUsed?: string;
|
|
23
|
+
estRows?: number;
|
|
24
|
+
docsExamined?: number;
|
|
25
|
+
ms?: number;
|
|
26
|
+
/** short human readable plan, e.g. "COLLSCAN" or "IXSCAN status_1 → FETCH" */
|
|
27
|
+
text: string;
|
|
28
|
+
}
|
|
29
|
+
export interface SlowQuery {
|
|
30
|
+
table?: string;
|
|
31
|
+
filterKeys: string[];
|
|
32
|
+
sortKeys: SortKey[];
|
|
33
|
+
meanMs: number;
|
|
34
|
+
calls: number;
|
|
35
|
+
text: string;
|
|
36
|
+
plan?: string;
|
|
37
|
+
docsExamined?: number;
|
|
38
|
+
}
|
|
39
|
+
export interface ForeignKey {
|
|
40
|
+
table: string;
|
|
41
|
+
column: string;
|
|
42
|
+
refTable: string;
|
|
43
|
+
}
|
|
44
|
+
export interface LiveData {
|
|
45
|
+
adapter: AdapterName;
|
|
46
|
+
database: string;
|
|
47
|
+
tables: Map<string, TableInfo>;
|
|
48
|
+
indexes: IndexInfo[];
|
|
49
|
+
/** plan per static shape id */
|
|
50
|
+
plans: Map<string, PlanSummary>;
|
|
51
|
+
/** static shape id -> resolved live table name */
|
|
52
|
+
shapeTables: Map<string, string>;
|
|
53
|
+
slow: SlowQuery[];
|
|
54
|
+
fks: ForeignKey[];
|
|
55
|
+
explained: number;
|
|
56
|
+
warnings: string[];
|
|
57
|
+
}
|
|
58
|
+
export interface LiveOptions {
|
|
59
|
+
uri: string;
|
|
60
|
+
db?: string;
|
|
61
|
+
slowMs: number;
|
|
62
|
+
explainExecute: boolean;
|
|
63
|
+
maxExplain: number;
|
|
64
|
+
timeoutMs: number;
|
|
65
|
+
}
|
|
66
|
+
export interface LiveAdapter {
|
|
67
|
+
readonly name: AdapterName;
|
|
68
|
+
readonly database: string;
|
|
69
|
+
connect(): Promise<void>;
|
|
70
|
+
tables(): Promise<TableInfo[]>;
|
|
71
|
+
indexes(tables: string[]): Promise<IndexInfo[]>;
|
|
72
|
+
foreignKeys(): Promise<ForeignKey[]>;
|
|
73
|
+
explain(shape: QueryShape, table: string): Promise<PlanSummary | null>;
|
|
74
|
+
slowQueries(slowMs: number): Promise<SlowQuery[]>;
|
|
75
|
+
warnings(): Promise<string[]>;
|
|
76
|
+
close(): Promise<void>;
|
|
77
|
+
}
|