@geekmidas/db 10.0.0-alpha.6 → 10.0.0-alpha.61
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 +17 -0
- package/dist/errors.cjs +72 -5
- package/dist/errors.cjs.map +1 -0
- package/dist/errors.d.cts +4 -6
- package/dist/errors.d.cts.map +1 -1
- package/dist/errors.d.mts +4 -6
- package/dist/errors.d.mts.map +1 -1
- package/dist/errors.mjs +68 -2
- package/dist/errors.mjs.map +1 -0
- package/dist/introspect/DataBrowser.cjs +117 -0
- package/dist/introspect/DataBrowser.cjs.map +1 -0
- package/dist/introspect/DataBrowser.d.cts +51 -0
- package/dist/introspect/DataBrowser.d.cts.map +1 -0
- package/dist/introspect/DataBrowser.d.mts +51 -0
- package/dist/introspect/DataBrowser.d.mts.map +1 -0
- package/dist/introspect/DataBrowser.mjs +116 -0
- package/dist/introspect/DataBrowser.mjs.map +1 -0
- package/dist/introspect/errors.cjs +48 -0
- package/dist/introspect/errors.cjs.map +1 -0
- package/dist/introspect/errors.d.cts +27 -0
- package/dist/introspect/errors.d.cts.map +1 -0
- package/dist/introspect/errors.d.mts +27 -0
- package/dist/introspect/errors.d.mts.map +1 -0
- package/dist/introspect/errors.mjs +45 -0
- package/dist/introspect/errors.mjs.map +1 -0
- package/dist/introspect/filtering.cjs +101 -0
- package/dist/introspect/filtering.cjs.map +1 -0
- package/dist/introspect/filtering.d.cts +29 -0
- package/dist/introspect/filtering.d.cts.map +1 -0
- package/dist/introspect/filtering.d.mts +29 -0
- package/dist/introspect/filtering.d.mts.map +1 -0
- package/dist/introspect/filtering.mjs +98 -0
- package/dist/introspect/filtering.mjs.map +1 -0
- package/dist/introspect/handler.cjs +159 -0
- package/dist/introspect/handler.cjs.map +1 -0
- package/dist/introspect/handler.d.cts +43 -0
- package/dist/introspect/handler.d.cts.map +1 -0
- package/dist/introspect/handler.d.mts +43 -0
- package/dist/introspect/handler.d.mts.map +1 -0
- package/dist/introspect/handler.mjs +158 -0
- package/dist/introspect/handler.mjs.map +1 -0
- package/dist/introspect/index.cjs +22 -0
- package/dist/introspect/index.d.cts +8 -0
- package/dist/introspect/index.d.mts +8 -0
- package/dist/introspect/index.mjs +8 -0
- package/dist/introspect/introspection.cjs +149 -0
- package/dist/introspect/introspection.cjs.map +1 -0
- package/dist/introspect/introspection.d.cts +25 -0
- package/dist/introspect/introspection.d.cts.map +1 -0
- package/dist/introspect/introspection.d.mts +25 -0
- package/dist/introspect/introspection.d.mts.map +1 -0
- package/dist/introspect/introspection.mjs +146 -0
- package/dist/introspect/introspection.mjs.map +1 -0
- package/dist/introspect/types.cjs +24 -0
- package/dist/introspect/types.cjs.map +1 -0
- package/dist/introspect/types.d.cts +113 -0
- package/dist/introspect/types.d.cts.map +1 -0
- package/dist/introspect/types.d.mts +113 -0
- package/dist/introspect/types.d.mts.map +1 -0
- package/dist/introspect/types.mjs +23 -0
- package/dist/introspect/types.mjs.map +1 -0
- package/dist/kysely/pagination.cjs +8 -9
- package/dist/kysely/pagination.cjs.map +1 -1
- package/dist/kysely/pagination.d.cts +4 -14
- package/dist/kysely/pagination.d.cts.map +1 -1
- package/dist/kysely/pagination.d.mts +4 -14
- package/dist/kysely/pagination.d.mts.map +1 -1
- package/dist/kysely/pagination.mjs +7 -10
- package/dist/kysely/pagination.mjs.map +1 -1
- package/dist/kysely.cjs +11 -2
- package/dist/kysely.cjs.map +1 -0
- package/dist/kysely.d.cts +9 -2
- package/dist/kysely.d.cts.map +1 -0
- package/dist/kysely.d.mts +9 -2
- package/dist/kysely.d.mts.map +1 -0
- package/dist/kysely.mjs +10 -2
- package/dist/kysely.mjs.map +1 -0
- package/dist/objection/pagination.cjs +7 -7
- package/dist/objection/pagination.cjs.map +1 -1
- package/dist/objection/pagination.d.cts +4 -14
- package/dist/objection/pagination.d.cts.map +1 -1
- package/dist/objection/pagination.d.mts +4 -14
- package/dist/objection/pagination.d.mts.map +1 -1
- package/dist/objection/pagination.mjs +6 -8
- package/dist/objection/pagination.mjs.map +1 -1
- package/dist/{pagination-kv-KWS-7.d.mts → pagination-CrU89125.d.cts} +14 -4
- package/dist/pagination-CrU89125.d.cts.map +1 -0
- package/dist/{pagination-BAFX7C1I.d.cts → pagination-CrU89125.d.mts} +14 -4
- package/dist/pagination-CrU89125.d.mts.map +1 -0
- package/dist/pagination.cjs +55 -4
- package/dist/pagination.cjs.map +1 -0
- package/dist/pagination.d.cts +2 -2
- package/dist/pagination.d.mts +2 -2
- package/dist/pagination.mjs +51 -2
- package/dist/pagination.mjs.map +1 -0
- package/dist/pg/roles.cjs +26 -3
- package/dist/pg/roles.cjs.map +1 -1
- package/dist/pg/roles.d.cts +16 -8
- package/dist/pg/roles.d.cts.map +1 -1
- package/dist/pg/roles.d.mts +16 -8
- package/dist/pg/roles.d.mts.map +1 -1
- package/dist/pg/roles.mjs +25 -2
- package/dist/pg/roles.mjs.map +1 -1
- package/dist/pg/url.cjs +18 -3
- package/dist/pg/url.cjs.map +1 -1
- package/dist/pg/url.d.cts +2 -4
- package/dist/pg/url.d.cts.map +1 -1
- package/dist/pg/url.d.mts +2 -4
- package/dist/pg/url.d.mts.map +1 -1
- package/dist/pg/url.mjs +17 -3
- package/dist/pg/url.mjs.map +1 -1
- package/dist/rls.cjs +5 -29
- package/dist/rls.cjs.map +1 -1
- package/dist/rls.d.cts +6 -10
- package/dist/rls.d.cts.map +1 -1
- package/dist/rls.d.mts +6 -10
- package/dist/rls.d.mts.map +1 -1
- package/dist/rls.mjs +3 -5
- package/dist/rls.mjs.map +1 -1
- package/package.json +12 -2
- package/dist/errors-CfFCan-X.mjs +0 -69
- package/dist/errors-CfFCan-X.mjs.map +0 -1
- package/dist/errors-Cs5jlAv-.cjs +0 -93
- package/dist/errors-Cs5jlAv-.cjs.map +0 -1
- package/dist/kysely-BAedYsvn.d.mts +0 -13
- package/dist/kysely-BAedYsvn.d.mts.map +0 -1
- package/dist/kysely-Bo_Zg-D3.mjs +0 -11
- package/dist/kysely-Bo_Zg-D3.mjs.map +0 -1
- package/dist/kysely-D3eeuId4.d.cts +0 -13
- package/dist/kysely-D3eeuId4.d.cts.map +0 -1
- package/dist/kysely-LWvS2ekY.cjs +0 -17
- package/dist/kysely-LWvS2ekY.cjs.map +0 -1
- package/dist/pagination-BAFX7C1I.d.cts.map +0 -1
- package/dist/pagination-Bu1dqOy0.cjs +0 -55
- package/dist/pagination-Bu1dqOy0.cjs.map +0 -1
- package/dist/pagination-CQ8QHXaL.mjs +0 -37
- package/dist/pagination-CQ8QHXaL.mjs.map +0 -1
- package/dist/pagination-kv-KWS-7.d.mts.map +0 -1
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
import { sql } from "kysely";
|
|
2
|
+
//#region src/introspect/introspection.ts
|
|
3
|
+
/**
|
|
4
|
+
* The schemas the database has, without Postgres's own (`pg_catalog`,
|
|
5
|
+
* `pg_toast`, `information_schema`, …).
|
|
6
|
+
*/
|
|
7
|
+
async function listSchemas(db) {
|
|
8
|
+
const { rows } = await sql`
|
|
9
|
+
SELECT nspname AS name
|
|
10
|
+
FROM pg_catalog.pg_namespace
|
|
11
|
+
WHERE nspname <> 'information_schema'
|
|
12
|
+
AND nspname NOT LIKE 'pg\\_%'
|
|
13
|
+
ORDER BY nspname
|
|
14
|
+
`.execute(db);
|
|
15
|
+
return rows.map((row) => row.name);
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Every base table in the given schemas, with its columns, primary key and
|
|
19
|
+
* foreign keys. Views are left out: they have no key to page by.
|
|
20
|
+
*/
|
|
21
|
+
async function introspectSchema(db, options = {}) {
|
|
22
|
+
const schemas = options.schemas ?? ["public"];
|
|
23
|
+
const excluded = options.excludeTables ?? [];
|
|
24
|
+
const { rows } = await sql`
|
|
25
|
+
SELECT table_name AS name, table_schema AS schema
|
|
26
|
+
FROM information_schema.tables
|
|
27
|
+
WHERE table_schema = ANY(${schemas})
|
|
28
|
+
AND table_type = 'BASE TABLE'
|
|
29
|
+
AND NOT (table_name = ANY(${excluded}))
|
|
30
|
+
ORDER BY table_schema, table_name
|
|
31
|
+
`.execute(db);
|
|
32
|
+
return {
|
|
33
|
+
tables: await Promise.all(rows.map((row) => introspectTable(db, row.name, row.schema))),
|
|
34
|
+
updatedAt: /* @__PURE__ */ new Date()
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* One table's columns, primary key, foreign keys and estimated row count.
|
|
39
|
+
*/
|
|
40
|
+
async function introspectTable(db, tableName, schema = "public") {
|
|
41
|
+
const [columns, foreignKeys, estimate] = await Promise.all([
|
|
42
|
+
sql`
|
|
43
|
+
SELECT
|
|
44
|
+
c.column_name AS name,
|
|
45
|
+
c.udt_name AS udt,
|
|
46
|
+
c.is_nullable AS nullable,
|
|
47
|
+
c.column_default AS fallback,
|
|
48
|
+
EXISTS (
|
|
49
|
+
SELECT 1
|
|
50
|
+
FROM information_schema.table_constraints tc
|
|
51
|
+
JOIN information_schema.key_column_usage ku
|
|
52
|
+
ON tc.constraint_name = ku.constraint_name
|
|
53
|
+
AND tc.table_schema = ku.table_schema
|
|
54
|
+
WHERE tc.table_name = c.table_name
|
|
55
|
+
AND tc.table_schema = c.table_schema
|
|
56
|
+
AND tc.constraint_type = 'PRIMARY KEY'
|
|
57
|
+
AND ku.column_name = c.column_name
|
|
58
|
+
) AS pk
|
|
59
|
+
FROM information_schema.columns c
|
|
60
|
+
WHERE c.table_name = ${tableName}
|
|
61
|
+
AND c.table_schema = ${schema}
|
|
62
|
+
ORDER BY c.ordinal_position
|
|
63
|
+
`.execute(db),
|
|
64
|
+
sql`
|
|
65
|
+
SELECT
|
|
66
|
+
kcu.column_name AS name,
|
|
67
|
+
ccu.table_name AS target,
|
|
68
|
+
ccu.column_name AS referenced
|
|
69
|
+
FROM information_schema.table_constraints tc
|
|
70
|
+
JOIN information_schema.key_column_usage kcu
|
|
71
|
+
ON tc.constraint_name = kcu.constraint_name
|
|
72
|
+
AND tc.table_schema = kcu.table_schema
|
|
73
|
+
JOIN information_schema.constraint_column_usage ccu
|
|
74
|
+
ON tc.constraint_name = ccu.constraint_name
|
|
75
|
+
AND tc.table_schema = ccu.table_schema
|
|
76
|
+
WHERE tc.table_name = ${tableName}
|
|
77
|
+
AND tc.table_schema = ${schema}
|
|
78
|
+
AND tc.constraint_type = 'FOREIGN KEY'
|
|
79
|
+
`.execute(db),
|
|
80
|
+
sql`
|
|
81
|
+
SELECT c.reltuples::bigint AS estimate
|
|
82
|
+
FROM pg_catalog.pg_class c
|
|
83
|
+
JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
|
|
84
|
+
WHERE c.relname = ${tableName}
|
|
85
|
+
AND n.nspname = ${schema}
|
|
86
|
+
`.execute(db)
|
|
87
|
+
]);
|
|
88
|
+
const references = new Map(foreignKeys.rows.map((row) => [row.name, {
|
|
89
|
+
table: row.target,
|
|
90
|
+
column: row.referenced
|
|
91
|
+
}]));
|
|
92
|
+
const columnInfo = columns.rows.map((row) => {
|
|
93
|
+
const reference = references.get(row.name);
|
|
94
|
+
return {
|
|
95
|
+
name: row.name,
|
|
96
|
+
type: mapPostgresType(row.udt),
|
|
97
|
+
rawType: row.udt,
|
|
98
|
+
nullable: row.nullable === "YES",
|
|
99
|
+
isPrimaryKey: row.pk,
|
|
100
|
+
isForeignKey: !!reference,
|
|
101
|
+
foreignKeyTable: reference?.table,
|
|
102
|
+
foreignKeyColumn: reference?.column,
|
|
103
|
+
defaultValue: row.fallback ?? void 0
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
const rowEstimate = Number(estimate.rows[0]?.estimate ?? 0);
|
|
107
|
+
return {
|
|
108
|
+
name: tableName,
|
|
109
|
+
schema,
|
|
110
|
+
columns: columnInfo,
|
|
111
|
+
primaryKey: columnInfo.filter((c) => c.isPrimaryKey).map((c) => c.name),
|
|
112
|
+
estimatedRowCount: rowEstimate > 0 ? rowEstimate : void 0
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
const POSTGRES_TYPES = {
|
|
116
|
+
varchar: "string",
|
|
117
|
+
char: "string",
|
|
118
|
+
text: "string",
|
|
119
|
+
name: "string",
|
|
120
|
+
bpchar: "string",
|
|
121
|
+
citext: "string",
|
|
122
|
+
int2: "number",
|
|
123
|
+
int4: "number",
|
|
124
|
+
int8: "number",
|
|
125
|
+
float4: "number",
|
|
126
|
+
float8: "number",
|
|
127
|
+
numeric: "number",
|
|
128
|
+
money: "number",
|
|
129
|
+
bool: "boolean",
|
|
130
|
+
date: "date",
|
|
131
|
+
timestamp: "datetime",
|
|
132
|
+
timestamptz: "datetime",
|
|
133
|
+
time: "datetime",
|
|
134
|
+
timetz: "datetime",
|
|
135
|
+
json: "json",
|
|
136
|
+
jsonb: "json",
|
|
137
|
+
bytea: "binary",
|
|
138
|
+
uuid: "uuid"
|
|
139
|
+
};
|
|
140
|
+
function mapPostgresType(udtName) {
|
|
141
|
+
return POSTGRES_TYPES[udtName] ?? "unknown";
|
|
142
|
+
}
|
|
143
|
+
//#endregion
|
|
144
|
+
export { introspectSchema, introspectTable, listSchemas };
|
|
145
|
+
|
|
146
|
+
//# sourceMappingURL=introspection.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"introspection.mjs","names":[],"sources":["../../src/introspect/introspection.ts"],"sourcesContent":["import { type Kysely, sql } from 'kysely';\nimport type { ColumnInfo, ColumnType, SchemaInfo, TableInfo } from './types';\n\n// Every query aliases its columns to a single lower-case word. A `Kysely` built\n// with `CamelCasePlugin` rewrites result keys, so `column_name` would come back\n// as `columnName` from one client and `column_name` from another; a one-word\n// alias reads the same through both.\n\n/**\n * The schemas the database has, without Postgres's own (`pg_catalog`,\n * `pg_toast`, `information_schema`, …).\n */\nexport async function listSchemas<DB>(db: Kysely<DB>): Promise<string[]> {\n\tconst { rows } = await sql<{ name: string }>`\n\t\tSELECT nspname AS name\n\t\tFROM pg_catalog.pg_namespace\n\t\tWHERE nspname <> 'information_schema'\n\t\t\tAND nspname NOT LIKE 'pg\\\\_%'\n\t\tORDER BY nspname\n\t`.execute(db);\n\n\treturn rows.map((row) => row.name);\n}\n\nexport interface IntrospectSchemaOptions {\n\t/** The schemas to read tables from (default: `['public']`). */\n\tschemas?: string[];\n\t/** Tables to leave out, by name. */\n\texcludeTables?: string[];\n}\n\n/**\n * Every base table in the given schemas, with its columns, primary key and\n * foreign keys. Views are left out: they have no key to page by.\n */\nexport async function introspectSchema<DB>(\n\tdb: Kysely<DB>,\n\toptions: IntrospectSchemaOptions = {},\n): Promise<SchemaInfo> {\n\tconst schemas = options.schemas ?? ['public'];\n\tconst excluded = options.excludeTables ?? [];\n\n\tconst { rows } = await sql<{ name: string; schema: string }>`\n\t\tSELECT table_name AS name, table_schema AS schema\n\t\tFROM information_schema.tables\n\t\tWHERE table_schema = ANY(${schemas})\n\t\t\tAND table_type = 'BASE TABLE'\n\t\t\tAND NOT (table_name = ANY(${excluded}))\n\t\tORDER BY table_schema, table_name\n\t`.execute(db);\n\n\tconst tables = await Promise.all(\n\t\trows.map((row) => introspectTable(db, row.name, row.schema)),\n\t);\n\n\treturn { tables, updatedAt: new Date() };\n}\n\n/**\n * One table's columns, primary key, foreign keys and estimated row count.\n */\nexport async function introspectTable<DB>(\n\tdb: Kysely<DB>,\n\ttableName: string,\n\tschema = 'public',\n): Promise<TableInfo> {\n\tconst [columns, foreignKeys, estimate] = await Promise.all([\n\t\tsql<{\n\t\t\tname: string;\n\t\t\tudt: string;\n\t\t\tnullable: string;\n\t\t\tfallback: string | null;\n\t\t\tpk: boolean;\n\t\t}>`\n\t\t\tSELECT\n\t\t\t\tc.column_name AS name,\n\t\t\t\tc.udt_name AS udt,\n\t\t\t\tc.is_nullable AS nullable,\n\t\t\t\tc.column_default AS fallback,\n\t\t\t\tEXISTS (\n\t\t\t\t\tSELECT 1\n\t\t\t\t\tFROM information_schema.table_constraints tc\n\t\t\t\t\tJOIN information_schema.key_column_usage ku\n\t\t\t\t\t\tON tc.constraint_name = ku.constraint_name\n\t\t\t\t\t\tAND tc.table_schema = ku.table_schema\n\t\t\t\t\tWHERE tc.table_name = c.table_name\n\t\t\t\t\t\tAND tc.table_schema = c.table_schema\n\t\t\t\t\t\tAND tc.constraint_type = 'PRIMARY KEY'\n\t\t\t\t\t\tAND ku.column_name = c.column_name\n\t\t\t\t) AS pk\n\t\t\tFROM information_schema.columns c\n\t\t\tWHERE c.table_name = ${tableName}\n\t\t\t\tAND c.table_schema = ${schema}\n\t\t\tORDER BY c.ordinal_position\n\t\t`.execute(db),\n\t\tsql<{ name: string; target: string; referenced: string }>`\n\t\t\tSELECT\n\t\t\t\tkcu.column_name AS name,\n\t\t\t\tccu.table_name AS target,\n\t\t\t\tccu.column_name AS referenced\n\t\t\tFROM information_schema.table_constraints tc\n\t\t\tJOIN information_schema.key_column_usage kcu\n\t\t\t\tON tc.constraint_name = kcu.constraint_name\n\t\t\t\tAND tc.table_schema = kcu.table_schema\n\t\t\tJOIN information_schema.constraint_column_usage ccu\n\t\t\t\tON tc.constraint_name = ccu.constraint_name\n\t\t\t\tAND tc.table_schema = ccu.table_schema\n\t\t\tWHERE tc.table_name = ${tableName}\n\t\t\t\tAND tc.table_schema = ${schema}\n\t\t\t\tAND tc.constraint_type = 'FOREIGN KEY'\n\t\t`.execute(db),\n\t\t// The planner's estimate rather than `count(*)`, which scans the table.\n\t\t// It is -1 for a table never analysed, which is \"unknown\", not empty.\n\t\tsql<{ estimate: string | number }>`\n\t\t\tSELECT c.reltuples::bigint AS estimate\n\t\t\tFROM pg_catalog.pg_class c\n\t\t\tJOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace\n\t\t\tWHERE c.relname = ${tableName}\n\t\t\t\tAND n.nspname = ${schema}\n\t\t`.execute(db),\n\t]);\n\n\tconst references = new Map(\n\t\tforeignKeys.rows.map((row) => [\n\t\t\trow.name,\n\t\t\t{ table: row.target, column: row.referenced },\n\t\t]),\n\t);\n\n\tconst columnInfo: ColumnInfo[] = columns.rows.map((row) => {\n\t\tconst reference = references.get(row.name);\n\t\treturn {\n\t\t\tname: row.name,\n\t\t\ttype: mapPostgresType(row.udt),\n\t\t\trawType: row.udt,\n\t\t\tnullable: row.nullable === 'YES',\n\t\t\tisPrimaryKey: row.pk,\n\t\t\tisForeignKey: !!reference,\n\t\t\tforeignKeyTable: reference?.table,\n\t\t\tforeignKeyColumn: reference?.column,\n\t\t\tdefaultValue: row.fallback ?? undefined,\n\t\t};\n\t});\n\n\tconst rowEstimate = Number(estimate.rows[0]?.estimate ?? 0);\n\n\treturn {\n\t\tname: tableName,\n\t\tschema,\n\t\tcolumns: columnInfo,\n\t\tprimaryKey: columnInfo.filter((c) => c.isPrimaryKey).map((c) => c.name),\n\t\testimatedRowCount: rowEstimate > 0 ? rowEstimate : undefined,\n\t};\n}\n\nconst POSTGRES_TYPES: Record<string, ColumnType> = {\n\tvarchar: 'string',\n\tchar: 'string',\n\ttext: 'string',\n\tname: 'string',\n\tbpchar: 'string',\n\tcitext: 'string',\n\n\tint2: 'number',\n\tint4: 'number',\n\tint8: 'number',\n\tfloat4: 'number',\n\tfloat8: 'number',\n\tnumeric: 'number',\n\tmoney: 'number',\n\n\tbool: 'boolean',\n\n\tdate: 'date',\n\ttimestamp: 'datetime',\n\ttimestamptz: 'datetime',\n\ttime: 'datetime',\n\ttimetz: 'datetime',\n\n\tjson: 'json',\n\tjsonb: 'json',\n\n\tbytea: 'binary',\n\n\tuuid: 'uuid',\n};\n\nfunction mapPostgresType(udtName: string): ColumnType {\n\treturn POSTGRES_TYPES[udtName] ?? 'unknown';\n}\n"],"mappings":";;;;;;AAYA,eAAsB,YAAgB,IAAmC;CACxE,MAAM,EAAE,SAAS,MAAM,GAAqB;;;;;;GAM1C,QAAQ,EAAE;CAEZ,OAAO,KAAK,KAAK,QAAQ,IAAI,IAAI;AAClC;;;;;AAaA,eAAsB,iBACrB,IACA,UAAmC,CAAC,GACd;CACtB,MAAM,UAAU,QAAQ,WAAW,CAAC,QAAQ;CAC5C,MAAM,WAAW,QAAQ,iBAAiB,CAAC;CAE3C,MAAM,EAAE,SAAS,MAAM,GAAqC;;;6BAGhC,QAAQ;;+BAEN,SAAS;;GAErC,QAAQ,EAAE;CAMZ,OAAO;EAAE,QAAA,MAJY,QAAQ,IAC5B,KAAK,KAAK,QAAQ,gBAAgB,IAAI,IAAI,MAAM,IAAI,MAAM,CAAC,CAC5D;EAEiB,2BAAW,IAAI,KAAK;CAAE;AACxC;;;;AAKA,eAAsB,gBACrB,IACA,WACA,SAAS,UACY;CACrB,MAAM,CAAC,SAAS,aAAa,YAAY,MAAM,QAAQ,IAAI;EAC1D,GAME;;;;;;;;;;;;;;;;;;0BAkBsB,UAAU;2BACT,OAAO;;IAE9B,QAAQ,EAAE;EACZ,GAAyD;;;;;;;;;;;;2BAYhC,UAAU;4BACT,OAAO;;IAE/B,QAAQ,EAAE;EAGZ,GAAkC;;;;uBAIb,UAAU;sBACX,OAAO;IACzB,QAAQ,EAAE;CACb,CAAC;CAED,MAAM,aAAa,IAAI,IACtB,YAAY,KAAK,KAAK,QAAQ,CAC7B,IAAI,MACJ;EAAE,OAAO,IAAI;EAAQ,QAAQ,IAAI;CAAW,CAC7C,CAAC,CACF;CAEA,MAAM,aAA2B,QAAQ,KAAK,KAAK,QAAQ;EAC1D,MAAM,YAAY,WAAW,IAAI,IAAI,IAAI;EACzC,OAAO;GACN,MAAM,IAAI;GACV,MAAM,gBAAgB,IAAI,GAAG;GAC7B,SAAS,IAAI;GACb,UAAU,IAAI,aAAa;GAC3B,cAAc,IAAI;GAClB,cAAc,CAAC,CAAC;GAChB,iBAAiB,WAAW;GAC5B,kBAAkB,WAAW;GAC7B,cAAc,IAAI,YAAY,KAAA;EAC/B;CACD,CAAC;CAED,MAAM,cAAc,OAAO,SAAS,KAAK,EAAE,EAAE,YAAY,CAAC;CAE1D,OAAO;EACN,MAAM;EACN;EACA,SAAS;EACT,YAAY,WAAW,QAAQ,MAAM,EAAE,YAAY,CAAC,CAAC,KAAK,MAAM,EAAE,IAAI;EACtE,mBAAmB,cAAc,IAAI,cAAc,KAAA;CACpD;AACD;AAEA,MAAM,iBAA6C;CAClD,SAAS;CACT,MAAM;CACN,MAAM;CACN,MAAM;CACN,QAAQ;CACR,QAAQ;CAER,MAAM;CACN,MAAM;CACN,MAAM;CACN,QAAQ;CACR,QAAQ;CACR,SAAS;CACT,OAAO;CAEP,MAAM;CAEN,MAAM;CACN,WAAW;CACX,aAAa;CACb,MAAM;CACN,QAAQ;CAER,MAAM;CACN,OAAO;CAEP,OAAO;CAEP,MAAM;AACP;AAEA,SAAS,gBAAgB,SAA6B;CACrD,OAAO,eAAe,YAAY;AACnC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region src/introspect/types.ts
|
|
3
|
+
/**
|
|
4
|
+
* Filter operators a row query accepts.
|
|
5
|
+
*/
|
|
6
|
+
let FilterOperator = /* @__PURE__ */ function(FilterOperator) {
|
|
7
|
+
FilterOperator["Eq"] = "eq";
|
|
8
|
+
FilterOperator["Neq"] = "neq";
|
|
9
|
+
FilterOperator["Gt"] = "gt";
|
|
10
|
+
FilterOperator["Gte"] = "gte";
|
|
11
|
+
FilterOperator["Lt"] = "lt";
|
|
12
|
+
FilterOperator["Lte"] = "lte";
|
|
13
|
+
FilterOperator["Like"] = "like";
|
|
14
|
+
FilterOperator["Ilike"] = "ilike";
|
|
15
|
+
FilterOperator["In"] = "in";
|
|
16
|
+
FilterOperator["Nin"] = "nin";
|
|
17
|
+
FilterOperator["IsNull"] = "is_null";
|
|
18
|
+
FilterOperator["IsNotNull"] = "is_not_null";
|
|
19
|
+
return FilterOperator;
|
|
20
|
+
}({});
|
|
21
|
+
//#endregion
|
|
22
|
+
exports.FilterOperator = FilterOperator;
|
|
23
|
+
|
|
24
|
+
//# sourceMappingURL=types.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.cjs","names":[],"sources":["../../src/introspect/types.ts"],"sourcesContent":["import type { Kysely } from 'kysely';\nimport type { Direction } from '../pagination';\n\n/**\n * Filter operators a row query accepts.\n */\nexport enum FilterOperator {\n\tEq = 'eq',\n\tNeq = 'neq',\n\tGt = 'gt',\n\tGte = 'gte',\n\tLt = 'lt',\n\tLte = 'lte',\n\tLike = 'like',\n\tIlike = 'ilike',\n\tIn = 'in',\n\tNin = 'nin',\n\tIsNull = 'is_null',\n\tIsNotNull = 'is_not_null',\n}\n\n/**\n * The column a table's rows are paged by, and in which direction.\n */\nexport interface CursorConfig {\n\t/** A column whose values are unique and ordered, e.g. `id` or `created_at`. */\n\tfield: string;\n\tdirection: Direction;\n}\n\n/**\n * Options for a {@link DataBrowser}.\n */\nexport interface DataBrowserOptions<DB = unknown> {\n\tdb: Kysely<DB>;\n\t/**\n\t * The schemas to read tables from (default: `['public']`). Every schema the\n\t * database has is listed by `listSchemas` regardless; this is which of them\n\t * are browsable.\n\t */\n\tschemas?: string[];\n\t/**\n\t * The cursor every table pages by. When omitted, a table pages by its\n\t * primary key when that is a single column, ascending — the one ordering\n\t * that is unique for any table that has one.\n\t */\n\tcursor?: CursorConfig;\n\t/** Per-table cursors, by table name, for tables the default does not fit. */\n\ttableCursors?: Record<string, CursorConfig>;\n\t/** Tables left out of introspection, by name. */\n\texcludeTables?: string[];\n\t/** Rows per page when a query names none (default: 50, at most 100). */\n\tdefaultPageSize?: number;\n}\n\n/**\n * A column's type, classified independently of the engine.\n */\nexport type ColumnType =\n\t| 'string'\n\t| 'number'\n\t| 'boolean'\n\t| 'date'\n\t| 'datetime'\n\t| 'json'\n\t| 'binary'\n\t| 'uuid'\n\t| 'unknown';\n\nexport interface ColumnInfo {\n\tname: string;\n\ttype: ColumnType;\n\t/** The engine's own type name, e.g. `varchar` or `int4`. */\n\trawType: string;\n\tnullable: boolean;\n\tisPrimaryKey: boolean;\n\tisForeignKey: boolean;\n\t/** The table a foreign key references. */\n\tforeignKeyTable?: string;\n\t/** The column a foreign key references. */\n\tforeignKeyColumn?: string;\n\t/** The default value expression, as the database stores it. */\n\tdefaultValue?: string;\n}\n\nexport interface TableInfo {\n\tname: string;\n\tschema: string;\n\tcolumns: ColumnInfo[];\n\t/** Primary key column names, in key order. */\n\tprimaryKey: string[];\n\t/** Postgres's planner estimate, when it has one. */\n\testimatedRowCount?: number;\n}\n\nexport interface SchemaInfo {\n\ttables: TableInfo[];\n\t/** When the schema was introspected. */\n\tupdatedAt: Date;\n}\n\nexport interface FilterCondition {\n\tcolumn: string;\n\toperator: FilterOperator;\n\t/** Omitted for `is_null` / `is_not_null`. */\n\tvalue?: unknown;\n}\n\nexport interface SortConfig {\n\tcolumn: string;\n\tdirection: Direction;\n}\n\nexport interface QueryOptions {\n\ttable: string;\n\t/** The schema the table lives in (default: the first browsable schema). */\n\tschema?: string;\n\tfilters?: FilterCondition[];\n\tsort?: SortConfig[];\n\tcursor?: string | null;\n\tpageSize?: number;\n}\n\nexport interface QueryResult<T = Record<string, unknown>> {\n\trows: T[];\n\thasMore: boolean;\n\t/** Null when there is no next page, or the table has no cursor column. */\n\tnextCursor: string | null;\n\tprevCursor: string | null;\n}\n"],"mappings":";;;;;AAMA,IAAY,iBAAL,yBAAA,gBAAA;CACN,eAAA,QAAA;CACA,eAAA,SAAA;CACA,eAAA,QAAA;CACA,eAAA,SAAA;CACA,eAAA,QAAA;CACA,eAAA,SAAA;CACA,eAAA,UAAA;CACA,eAAA,WAAA;CACA,eAAA,QAAA;CACA,eAAA,SAAA;CACA,eAAA,YAAA;CACA,eAAA,eAAA;;AACD,EAAA,CAAA,CAAA"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { t as Direction } from "../pagination-CrU89125.cjs";
|
|
2
|
+
import { Kysely } from "kysely";
|
|
3
|
+
//#region src/introspect/types.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Filter operators a row query accepts.
|
|
6
|
+
*/
|
|
7
|
+
export declare enum FilterOperator {
|
|
8
|
+
Eq = "eq",
|
|
9
|
+
Neq = "neq",
|
|
10
|
+
Gt = "gt",
|
|
11
|
+
Gte = "gte",
|
|
12
|
+
Lt = "lt",
|
|
13
|
+
Lte = "lte",
|
|
14
|
+
Like = "like",
|
|
15
|
+
Ilike = "ilike",
|
|
16
|
+
In = "in",
|
|
17
|
+
Nin = "nin",
|
|
18
|
+
IsNull = "is_null",
|
|
19
|
+
IsNotNull = "is_not_null"
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The column a table's rows are paged by, and in which direction.
|
|
23
|
+
*/
|
|
24
|
+
export interface CursorConfig {
|
|
25
|
+
/** A column whose values are unique and ordered, e.g. `id` or `created_at`. */
|
|
26
|
+
field: string;
|
|
27
|
+
direction: Direction;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Options for a {@link DataBrowser}.
|
|
31
|
+
*/
|
|
32
|
+
export interface DataBrowserOptions<DB = unknown> {
|
|
33
|
+
db: Kysely<DB>;
|
|
34
|
+
/**
|
|
35
|
+
* The schemas to read tables from (default: `['public']`). Every schema the
|
|
36
|
+
* database has is listed by `listSchemas` regardless; this is which of them
|
|
37
|
+
* are browsable.
|
|
38
|
+
*/
|
|
39
|
+
schemas?: string[];
|
|
40
|
+
/**
|
|
41
|
+
* The cursor every table pages by. When omitted, a table pages by its
|
|
42
|
+
* primary key when that is a single column, ascending — the one ordering
|
|
43
|
+
* that is unique for any table that has one.
|
|
44
|
+
*/
|
|
45
|
+
cursor?: CursorConfig;
|
|
46
|
+
/** Per-table cursors, by table name, for tables the default does not fit. */
|
|
47
|
+
tableCursors?: Record<string, CursorConfig>;
|
|
48
|
+
/** Tables left out of introspection, by name. */
|
|
49
|
+
excludeTables?: string[];
|
|
50
|
+
/** Rows per page when a query names none (default: 50, at most 100). */
|
|
51
|
+
defaultPageSize?: number;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A column's type, classified independently of the engine.
|
|
55
|
+
*/
|
|
56
|
+
export type ColumnType = 'string' | 'number' | 'boolean' | 'date' | 'datetime' | 'json' | 'binary' | 'uuid' | 'unknown';
|
|
57
|
+
export interface ColumnInfo {
|
|
58
|
+
name: string;
|
|
59
|
+
type: ColumnType;
|
|
60
|
+
/** The engine's own type name, e.g. `varchar` or `int4`. */
|
|
61
|
+
rawType: string;
|
|
62
|
+
nullable: boolean;
|
|
63
|
+
isPrimaryKey: boolean;
|
|
64
|
+
isForeignKey: boolean;
|
|
65
|
+
/** The table a foreign key references. */
|
|
66
|
+
foreignKeyTable?: string;
|
|
67
|
+
/** The column a foreign key references. */
|
|
68
|
+
foreignKeyColumn?: string;
|
|
69
|
+
/** The default value expression, as the database stores it. */
|
|
70
|
+
defaultValue?: string;
|
|
71
|
+
}
|
|
72
|
+
export interface TableInfo {
|
|
73
|
+
name: string;
|
|
74
|
+
schema: string;
|
|
75
|
+
columns: ColumnInfo[];
|
|
76
|
+
/** Primary key column names, in key order. */
|
|
77
|
+
primaryKey: string[];
|
|
78
|
+
/** Postgres's planner estimate, when it has one. */
|
|
79
|
+
estimatedRowCount?: number;
|
|
80
|
+
}
|
|
81
|
+
export interface SchemaInfo {
|
|
82
|
+
tables: TableInfo[];
|
|
83
|
+
/** When the schema was introspected. */
|
|
84
|
+
updatedAt: Date;
|
|
85
|
+
}
|
|
86
|
+
export interface FilterCondition {
|
|
87
|
+
column: string;
|
|
88
|
+
operator: FilterOperator;
|
|
89
|
+
/** Omitted for `is_null` / `is_not_null`. */
|
|
90
|
+
value?: unknown;
|
|
91
|
+
}
|
|
92
|
+
export interface SortConfig {
|
|
93
|
+
column: string;
|
|
94
|
+
direction: Direction;
|
|
95
|
+
}
|
|
96
|
+
export interface QueryOptions {
|
|
97
|
+
table: string;
|
|
98
|
+
/** The schema the table lives in (default: the first browsable schema). */
|
|
99
|
+
schema?: string;
|
|
100
|
+
filters?: FilterCondition[];
|
|
101
|
+
sort?: SortConfig[];
|
|
102
|
+
cursor?: string | null;
|
|
103
|
+
pageSize?: number;
|
|
104
|
+
}
|
|
105
|
+
export interface QueryResult<T = Record<string, unknown>> {
|
|
106
|
+
rows: T[];
|
|
107
|
+
hasMore: boolean;
|
|
108
|
+
/** Null when there is no next page, or the table has no cursor column. */
|
|
109
|
+
nextCursor: string | null;
|
|
110
|
+
prevCursor: string | null;
|
|
111
|
+
}
|
|
112
|
+
//#endregion
|
|
113
|
+
//# sourceMappingURL=types.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.cts","names":[],"sources":["../../src/introspect/types.ts"],"mappings":";;;;;;oBAMY;EACX;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;;;iBAMgB;;EAEhB;EACA,WAAW;;;;;iBAMK,mBAAmB;EACnC,IAAI,OAAO;;;;;;EAMX;;;;;;EAMA,SAAS;;EAET,eAAe,eAAe;;EAE9B;;EAEA;;;;;YAMW;iBAWK;EAChB;EACA,MAAM;;EAEN;EACA;EACA;EACA;;EAEA;;EAEA;;EAEA;;iBAGgB;EAChB;EACA;EACA,SAAS;;EAET;;EAEA;;iBAGgB;EAChB,QAAQ;;EAER,WAAW;;iBAGK;EAChB;EACA,UAAU;;EAEV;;iBAGgB;EAChB;EACA,WAAW;;iBAGK;EAChB;;EAEA;EACA,UAAU;EACV,OAAO;EACP;EACA;;iBAGgB,YAAY,IAAI;EAChC,MAAM;EACN;;EAEA;EACA"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { t as Direction } from "../pagination-CrU89125.mjs";
|
|
2
|
+
import { Kysely } from "kysely";
|
|
3
|
+
//#region src/introspect/types.d.ts
|
|
4
|
+
/**
|
|
5
|
+
* Filter operators a row query accepts.
|
|
6
|
+
*/
|
|
7
|
+
export declare enum FilterOperator {
|
|
8
|
+
Eq = "eq",
|
|
9
|
+
Neq = "neq",
|
|
10
|
+
Gt = "gt",
|
|
11
|
+
Gte = "gte",
|
|
12
|
+
Lt = "lt",
|
|
13
|
+
Lte = "lte",
|
|
14
|
+
Like = "like",
|
|
15
|
+
Ilike = "ilike",
|
|
16
|
+
In = "in",
|
|
17
|
+
Nin = "nin",
|
|
18
|
+
IsNull = "is_null",
|
|
19
|
+
IsNotNull = "is_not_null"
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* The column a table's rows are paged by, and in which direction.
|
|
23
|
+
*/
|
|
24
|
+
export interface CursorConfig {
|
|
25
|
+
/** A column whose values are unique and ordered, e.g. `id` or `created_at`. */
|
|
26
|
+
field: string;
|
|
27
|
+
direction: Direction;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Options for a {@link DataBrowser}.
|
|
31
|
+
*/
|
|
32
|
+
export interface DataBrowserOptions<DB = unknown> {
|
|
33
|
+
db: Kysely<DB>;
|
|
34
|
+
/**
|
|
35
|
+
* The schemas to read tables from (default: `['public']`). Every schema the
|
|
36
|
+
* database has is listed by `listSchemas` regardless; this is which of them
|
|
37
|
+
* are browsable.
|
|
38
|
+
*/
|
|
39
|
+
schemas?: string[];
|
|
40
|
+
/**
|
|
41
|
+
* The cursor every table pages by. When omitted, a table pages by its
|
|
42
|
+
* primary key when that is a single column, ascending — the one ordering
|
|
43
|
+
* that is unique for any table that has one.
|
|
44
|
+
*/
|
|
45
|
+
cursor?: CursorConfig;
|
|
46
|
+
/** Per-table cursors, by table name, for tables the default does not fit. */
|
|
47
|
+
tableCursors?: Record<string, CursorConfig>;
|
|
48
|
+
/** Tables left out of introspection, by name. */
|
|
49
|
+
excludeTables?: string[];
|
|
50
|
+
/** Rows per page when a query names none (default: 50, at most 100). */
|
|
51
|
+
defaultPageSize?: number;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* A column's type, classified independently of the engine.
|
|
55
|
+
*/
|
|
56
|
+
export type ColumnType = 'string' | 'number' | 'boolean' | 'date' | 'datetime' | 'json' | 'binary' | 'uuid' | 'unknown';
|
|
57
|
+
export interface ColumnInfo {
|
|
58
|
+
name: string;
|
|
59
|
+
type: ColumnType;
|
|
60
|
+
/** The engine's own type name, e.g. `varchar` or `int4`. */
|
|
61
|
+
rawType: string;
|
|
62
|
+
nullable: boolean;
|
|
63
|
+
isPrimaryKey: boolean;
|
|
64
|
+
isForeignKey: boolean;
|
|
65
|
+
/** The table a foreign key references. */
|
|
66
|
+
foreignKeyTable?: string;
|
|
67
|
+
/** The column a foreign key references. */
|
|
68
|
+
foreignKeyColumn?: string;
|
|
69
|
+
/** The default value expression, as the database stores it. */
|
|
70
|
+
defaultValue?: string;
|
|
71
|
+
}
|
|
72
|
+
export interface TableInfo {
|
|
73
|
+
name: string;
|
|
74
|
+
schema: string;
|
|
75
|
+
columns: ColumnInfo[];
|
|
76
|
+
/** Primary key column names, in key order. */
|
|
77
|
+
primaryKey: string[];
|
|
78
|
+
/** Postgres's planner estimate, when it has one. */
|
|
79
|
+
estimatedRowCount?: number;
|
|
80
|
+
}
|
|
81
|
+
export interface SchemaInfo {
|
|
82
|
+
tables: TableInfo[];
|
|
83
|
+
/** When the schema was introspected. */
|
|
84
|
+
updatedAt: Date;
|
|
85
|
+
}
|
|
86
|
+
export interface FilterCondition {
|
|
87
|
+
column: string;
|
|
88
|
+
operator: FilterOperator;
|
|
89
|
+
/** Omitted for `is_null` / `is_not_null`. */
|
|
90
|
+
value?: unknown;
|
|
91
|
+
}
|
|
92
|
+
export interface SortConfig {
|
|
93
|
+
column: string;
|
|
94
|
+
direction: Direction;
|
|
95
|
+
}
|
|
96
|
+
export interface QueryOptions {
|
|
97
|
+
table: string;
|
|
98
|
+
/** The schema the table lives in (default: the first browsable schema). */
|
|
99
|
+
schema?: string;
|
|
100
|
+
filters?: FilterCondition[];
|
|
101
|
+
sort?: SortConfig[];
|
|
102
|
+
cursor?: string | null;
|
|
103
|
+
pageSize?: number;
|
|
104
|
+
}
|
|
105
|
+
export interface QueryResult<T = Record<string, unknown>> {
|
|
106
|
+
rows: T[];
|
|
107
|
+
hasMore: boolean;
|
|
108
|
+
/** Null when there is no next page, or the table has no cursor column. */
|
|
109
|
+
nextCursor: string | null;
|
|
110
|
+
prevCursor: string | null;
|
|
111
|
+
}
|
|
112
|
+
//#endregion
|
|
113
|
+
//# sourceMappingURL=types.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.mts","names":[],"sources":["../../src/introspect/types.ts"],"mappings":";;;;;;oBAMY;EACX;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;EACA;;;;;iBAMgB;;EAEhB;EACA,WAAW;;;;;iBAMK,mBAAmB;EACnC,IAAI,OAAO;;;;;;EAMX;;;;;;EAMA,SAAS;;EAET,eAAe,eAAe;;EAE9B;;EAEA;;;;;YAMW;iBAWK;EAChB;EACA,MAAM;;EAEN;EACA;EACA;EACA;;EAEA;;EAEA;;EAEA;;iBAGgB;EAChB;EACA;EACA,SAAS;;EAET;;EAEA;;iBAGgB;EAChB,QAAQ;;EAER,WAAW;;iBAGK;EAChB;EACA,UAAU;;EAEV;;iBAGgB;EAChB;EACA,WAAW;;iBAGK;EAChB;;EAEA;EACA,UAAU;EACV,OAAO;EACP;EACA;;iBAGgB,YAAY,IAAI;EAChC,MAAM;EACN;;EAEA;EACA"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
//#region src/introspect/types.ts
|
|
2
|
+
/**
|
|
3
|
+
* Filter operators a row query accepts.
|
|
4
|
+
*/
|
|
5
|
+
let FilterOperator = /* @__PURE__ */ function(FilterOperator) {
|
|
6
|
+
FilterOperator["Eq"] = "eq";
|
|
7
|
+
FilterOperator["Neq"] = "neq";
|
|
8
|
+
FilterOperator["Gt"] = "gt";
|
|
9
|
+
FilterOperator["Gte"] = "gte";
|
|
10
|
+
FilterOperator["Lt"] = "lt";
|
|
11
|
+
FilterOperator["Lte"] = "lte";
|
|
12
|
+
FilterOperator["Like"] = "like";
|
|
13
|
+
FilterOperator["Ilike"] = "ilike";
|
|
14
|
+
FilterOperator["In"] = "in";
|
|
15
|
+
FilterOperator["Nin"] = "nin";
|
|
16
|
+
FilterOperator["IsNull"] = "is_null";
|
|
17
|
+
FilterOperator["IsNotNull"] = "is_not_null";
|
|
18
|
+
return FilterOperator;
|
|
19
|
+
}({});
|
|
20
|
+
//#endregion
|
|
21
|
+
export { FilterOperator };
|
|
22
|
+
|
|
23
|
+
//# sourceMappingURL=types.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.mjs","names":[],"sources":["../../src/introspect/types.ts"],"sourcesContent":["import type { Kysely } from 'kysely';\nimport type { Direction } from '../pagination';\n\n/**\n * Filter operators a row query accepts.\n */\nexport enum FilterOperator {\n\tEq = 'eq',\n\tNeq = 'neq',\n\tGt = 'gt',\n\tGte = 'gte',\n\tLt = 'lt',\n\tLte = 'lte',\n\tLike = 'like',\n\tIlike = 'ilike',\n\tIn = 'in',\n\tNin = 'nin',\n\tIsNull = 'is_null',\n\tIsNotNull = 'is_not_null',\n}\n\n/**\n * The column a table's rows are paged by, and in which direction.\n */\nexport interface CursorConfig {\n\t/** A column whose values are unique and ordered, e.g. `id` or `created_at`. */\n\tfield: string;\n\tdirection: Direction;\n}\n\n/**\n * Options for a {@link DataBrowser}.\n */\nexport interface DataBrowserOptions<DB = unknown> {\n\tdb: Kysely<DB>;\n\t/**\n\t * The schemas to read tables from (default: `['public']`). Every schema the\n\t * database has is listed by `listSchemas` regardless; this is which of them\n\t * are browsable.\n\t */\n\tschemas?: string[];\n\t/**\n\t * The cursor every table pages by. When omitted, a table pages by its\n\t * primary key when that is a single column, ascending — the one ordering\n\t * that is unique for any table that has one.\n\t */\n\tcursor?: CursorConfig;\n\t/** Per-table cursors, by table name, for tables the default does not fit. */\n\ttableCursors?: Record<string, CursorConfig>;\n\t/** Tables left out of introspection, by name. */\n\texcludeTables?: string[];\n\t/** Rows per page when a query names none (default: 50, at most 100). */\n\tdefaultPageSize?: number;\n}\n\n/**\n * A column's type, classified independently of the engine.\n */\nexport type ColumnType =\n\t| 'string'\n\t| 'number'\n\t| 'boolean'\n\t| 'date'\n\t| 'datetime'\n\t| 'json'\n\t| 'binary'\n\t| 'uuid'\n\t| 'unknown';\n\nexport interface ColumnInfo {\n\tname: string;\n\ttype: ColumnType;\n\t/** The engine's own type name, e.g. `varchar` or `int4`. */\n\trawType: string;\n\tnullable: boolean;\n\tisPrimaryKey: boolean;\n\tisForeignKey: boolean;\n\t/** The table a foreign key references. */\n\tforeignKeyTable?: string;\n\t/** The column a foreign key references. */\n\tforeignKeyColumn?: string;\n\t/** The default value expression, as the database stores it. */\n\tdefaultValue?: string;\n}\n\nexport interface TableInfo {\n\tname: string;\n\tschema: string;\n\tcolumns: ColumnInfo[];\n\t/** Primary key column names, in key order. */\n\tprimaryKey: string[];\n\t/** Postgres's planner estimate, when it has one. */\n\testimatedRowCount?: number;\n}\n\nexport interface SchemaInfo {\n\ttables: TableInfo[];\n\t/** When the schema was introspected. */\n\tupdatedAt: Date;\n}\n\nexport interface FilterCondition {\n\tcolumn: string;\n\toperator: FilterOperator;\n\t/** Omitted for `is_null` / `is_not_null`. */\n\tvalue?: unknown;\n}\n\nexport interface SortConfig {\n\tcolumn: string;\n\tdirection: Direction;\n}\n\nexport interface QueryOptions {\n\ttable: string;\n\t/** The schema the table lives in (default: the first browsable schema). */\n\tschema?: string;\n\tfilters?: FilterCondition[];\n\tsort?: SortConfig[];\n\tcursor?: string | null;\n\tpageSize?: number;\n}\n\nexport interface QueryResult<T = Record<string, unknown>> {\n\trows: T[];\n\thasMore: boolean;\n\t/** Null when there is no next page, or the table has no cursor column. */\n\tnextCursor: string | null;\n\tprevCursor: string | null;\n}\n"],"mappings":";;;;AAMA,IAAY,iBAAL,yBAAA,gBAAA;CACN,eAAA,QAAA;CACA,eAAA,SAAA;CACA,eAAA,QAAA;CACA,eAAA,SAAA;CACA,eAAA,QAAA;CACA,eAAA,SAAA;CACA,eAAA,UAAA;CACA,eAAA,WAAA;CACA,eAAA,QAAA;CACA,eAAA,SAAA;CACA,eAAA,YAAA;CACA,eAAA,eAAA;;AACD,EAAA,CAAA,CAAA"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_pagination = require("../pagination.cjs");
|
|
3
3
|
//#region src/kysely/pagination.ts
|
|
4
4
|
/**
|
|
5
5
|
* Generic paginated search function that handles:
|
|
@@ -24,12 +24,11 @@ const require_pagination = require('../pagination-Bu1dqOy0.cjs');
|
|
|
24
24
|
* });
|
|
25
25
|
* ```
|
|
26
26
|
*/
|
|
27
|
-
async function paginatedSearch({ query, cursor, limit = 20, mapRow, cursorField = "id", cursorDirection =
|
|
28
|
-
const
|
|
29
|
-
const count = countResult.count;
|
|
27
|
+
async function paginatedSearch({ query, cursor, limit = 20, mapRow, cursorField = "id", cursorDirection = "asc" }) {
|
|
28
|
+
const count = (await query.clearSelect().clearOrderBy().select((eb) => eb.fn.countAll().as("count")).executeTakeFirstOrThrow()).count;
|
|
30
29
|
let paginatedQuery = query;
|
|
31
30
|
if (cursor) {
|
|
32
|
-
const operator = cursorDirection ===
|
|
31
|
+
const operator = cursorDirection === "asc" ? ">" : "<";
|
|
33
32
|
paginatedQuery = paginatedQuery.where(cursorField, operator, cursor);
|
|
34
33
|
}
|
|
35
34
|
const data = await paginatedQuery.orderBy(cursorField, cursorDirection).limit(limit + 1).execute();
|
|
@@ -38,9 +37,8 @@ async function paginatedSearch({ query, cursor, limit = 20, mapRow, cursorField
|
|
|
38
37
|
const lastRow = rows[rows.length - 1];
|
|
39
38
|
const nextCursor = hasMore && lastRow ? String(lastRow[cursorField]) : void 0;
|
|
40
39
|
const mapper = mapRow ?? ((row) => row);
|
|
41
|
-
const items = await Promise.all(rows.map(mapper));
|
|
42
40
|
return {
|
|
43
|
-
items,
|
|
41
|
+
items: await Promise.all(rows.map(mapper)),
|
|
44
42
|
pagination: {
|
|
45
43
|
total: Number(count),
|
|
46
44
|
hasMore,
|
|
@@ -48,10 +46,11 @@ async function paginatedSearch({ query, cursor, limit = 20, mapRow, cursorField
|
|
|
48
46
|
}
|
|
49
47
|
};
|
|
50
48
|
}
|
|
51
|
-
|
|
52
49
|
//#endregion
|
|
53
50
|
exports.Direction = require_pagination.Direction;
|
|
51
|
+
exports.InvalidCursor = require_pagination.InvalidCursor;
|
|
54
52
|
exports.decodeCursor = require_pagination.decodeCursor;
|
|
55
53
|
exports.encodeCursor = require_pagination.encodeCursor;
|
|
56
54
|
exports.paginatedSearch = paginatedSearch;
|
|
55
|
+
|
|
57
56
|
//# sourceMappingURL=pagination.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.cjs","names":[
|
|
1
|
+
{"version":3,"file":"pagination.cjs","names":[],"sources":["../../src/kysely/pagination.ts"],"sourcesContent":["import type { SelectQueryBuilder } from 'kysely';\nimport {\n\tDirection,\n\tdecodeCursor,\n\tencodeCursor,\n\tInvalidCursor,\n\ttype PaginationResult,\n} from '../pagination';\n\nexport {\n\tDirection,\n\tdecodeCursor,\n\tencodeCursor,\n\tInvalidCursor,\n\ttype PaginationResult,\n};\n\n/**\n * Options for paginated search.\n */\nexport interface PaginatedSearchOptions<\n\tTRow,\n\tTMapRow extends (row: TRow) => unknown = (row: TRow) => TRow,\n> {\n\t/** The base Kysely query to paginate */\n\tquery: SelectQueryBuilder<any, any, TRow>;\n\t/** Cursor value for pagination (value of cursorField from previous page) */\n\tcursor?: string;\n\t/** Maximum number of items per page (default: 20) */\n\tlimit?: number;\n\t/** Function to transform each row to the output format (default: identity) */\n\tmapRow?: TMapRow;\n\t/** Field to use for cursor pagination (default: 'id') */\n\tcursorField?: string;\n\t/** Sort direction for cursor field (default: Direction.Asc) */\n\tcursorDirection?: Direction;\n}\n\n/**\n * Generic paginated search function that handles:\n * - Total count calculation\n * - Cursor-based pagination\n * - Fetching one extra row to determine hasMore\n * - Mapping rows to output format\n *\n * @example\n * ```typescript\n * // With mapRow\n * const result = await paginatedSearch({\n * query: db.selectFrom('users').selectAll(),\n * limit: 20,\n * mapRow: (row) => ({ id: row.id, name: row.name }),\n * });\n *\n * // Without mapRow — items are the raw row type\n * const result = await paginatedSearch({\n * query: db.selectFrom('users').selectAll(),\n * limit: 20,\n * });\n * ```\n */\nexport async function paginatedSearch<\n\tTRow extends Record<string, unknown>,\n\tTMapRow extends (row: TRow) => unknown = (row: TRow) => TRow,\n>({\n\tquery,\n\tcursor,\n\tlimit = 20,\n\tmapRow,\n\tcursorField = 'id',\n\tcursorDirection = Direction.Asc,\n}: PaginatedSearchOptions<TRow, TMapRow>): Promise<\n\tPaginationResult<Awaited<ReturnType<TMapRow>>>\n> {\n\t// Get total count (without cursor)\n\tconst countResult = await query\n\t\t.clearSelect()\n\t\t.clearOrderBy()\n\t\t.select((eb) => eb.fn.countAll().as('count'))\n\t\t.executeTakeFirstOrThrow();\n\n\tconst count = countResult.count;\n\n\t// Apply cursor if provided\n\tlet paginatedQuery = query;\n\tif (cursor) {\n\t\tconst operator = cursorDirection === Direction.Asc ? '>' : '<';\n\t\tpaginatedQuery = paginatedQuery.where(\n\t\t\tcursorField as any,\n\t\t\toperator,\n\t\t\tcursor,\n\t\t) as typeof query;\n\t}\n\n\t// Fetch one extra to determine if there are more results\n\tconst data = await paginatedQuery\n\t\t.orderBy(cursorField as any, cursorDirection)\n\t\t.limit(limit + 1)\n\t\t.execute();\n\n\tconst hasMore = data.length > limit;\n\tconst rows = hasMore ? data.slice(0, limit) : data;\n\tconst lastRow = rows[rows.length - 1];\n\tconst nextCursor =\n\t\thasMore && lastRow ? String(lastRow[cursorField]) : undefined;\n\n\tconst mapper = mapRow ?? ((row: TRow) => row);\n\tconst items = (await Promise.all(rows.map(mapper))) as Awaited<\n\t\tReturnType<TMapRow>\n\t>[];\n\n\treturn {\n\t\titems,\n\t\tpagination: {\n\t\t\ttotal: Number(count),\n\t\t\thasMore,\n\t\t\tcursor: nextCursor,\n\t\t},\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AA6DA,eAAsB,gBAGpB,EACD,OACA,QACA,QAAQ,IACR,QACA,cAAc,MACd,kBAAA,SAGC;CAQD,MAAM,SAAQ,MANY,MACxB,YAAY,CAAC,CACb,aAAa,CAAC,CACd,QAAQ,OAAO,GAAG,GAAG,SAAS,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAC5C,wBAAwB,EAAA,CAEA;CAG1B,IAAI,iBAAiB;CACrB,IAAI,QAAQ;EACX,MAAM,WAAW,oBAAA,QAAoC,MAAM;EAC3D,iBAAiB,eAAe,MAC/B,aACA,UACA,MACD;CACD;CAGA,MAAM,OAAO,MAAM,eACjB,QAAQ,aAAoB,eAAe,CAAC,CAC5C,MAAM,QAAQ,CAAC,CAAC,CAChB,QAAQ;CAEV,MAAM,UAAU,KAAK,SAAS;CAC9B,MAAM,OAAO,UAAU,KAAK,MAAM,GAAG,KAAK,IAAI;CAC9C,MAAM,UAAU,KAAK,KAAK,SAAS;CACnC,MAAM,aACL,WAAW,UAAU,OAAO,QAAQ,YAAY,IAAI,KAAA;CAErD,MAAM,SAAS,YAAY,QAAc;CAKzC,OAAO;EACN,OAAA,MALoB,QAAQ,IAAI,KAAK,IAAI,MAAM,CAAC;EAMhD,YAAY;GACX,OAAO,OAAO,KAAK;GACnB;GACA,QAAQ;EACT;CACD;AACD"}
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as encodeCursor, i as decodeCursor, n as InvalidCursor, r as PaginationResult, t as Direction } from "../pagination-CrU89125.cjs";
|
|
2
2
|
import { SelectQueryBuilder } from "kysely";
|
|
3
|
-
|
|
4
3
|
//#region src/kysely/pagination.d.ts
|
|
5
|
-
|
|
6
4
|
/**
|
|
7
5
|
* Options for paginated search.
|
|
8
6
|
*/
|
|
9
|
-
interface PaginatedSearchOptions<TRow, TMapRow extends (row: TRow) => unknown = (row: TRow) => TRow> {
|
|
7
|
+
export interface PaginatedSearchOptions<TRow, TMapRow extends (row: TRow) => unknown = (row: TRow) => TRow> {
|
|
10
8
|
/** The base Kysely query to paginate */
|
|
11
9
|
query: SelectQueryBuilder<any, any, TRow>;
|
|
12
10
|
/** Cursor value for pagination (value of cursorField from previous page) */
|
|
@@ -43,15 +41,7 @@ interface PaginatedSearchOptions<TRow, TMapRow extends (row: TRow) => unknown =
|
|
|
43
41
|
* });
|
|
44
42
|
* ```
|
|
45
43
|
*/
|
|
46
|
-
declare function paginatedSearch<TRow extends Record<string, unknown>, TMapRow extends (row: TRow) => unknown = (row: TRow) => TRow>({
|
|
47
|
-
query,
|
|
48
|
-
cursor,
|
|
49
|
-
limit,
|
|
50
|
-
mapRow,
|
|
51
|
-
cursorField,
|
|
52
|
-
cursorDirection
|
|
53
|
-
}: PaginatedSearchOptions<TRow, TMapRow>): Promise<PaginationResult<Awaited<ReturnType<TMapRow>>>>;
|
|
54
|
-
//# sourceMappingURL=pagination.d.ts.map
|
|
44
|
+
export declare function paginatedSearch<TRow extends Record<string, unknown>, TMapRow extends (row: TRow) => unknown = (row: TRow) => TRow>({ query, cursor, limit, mapRow, cursorField, cursorDirection }: PaginatedSearchOptions<TRow, TMapRow>): Promise<PaginationResult<Awaited<ReturnType<TMapRow>>>>;
|
|
55
45
|
//#endregion
|
|
56
|
-
export { Direction,
|
|
46
|
+
export { Direction, InvalidCursor, type PaginationResult, decodeCursor, encodeCursor };
|
|
57
47
|
//# sourceMappingURL=pagination.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.d.cts","names":[],"sources":["../../src/kysely/pagination.ts"],"
|
|
1
|
+
{"version":3,"file":"pagination.d.cts","names":[],"sources":["../../src/kysely/pagination.ts"],"mappings":";;;;;;iBAoBiB,uBAChB,MACA,iBAAiB,KAAK,oBAAoB,KAAK,SAAS;;EAGxD,OAAO,6BAA6B;;EAEpC;;EAEA;;EAEA,SAAS;;EAET;;EAEA,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;wBA0BG,gBACrB,aAAa,yBACb,iBAAiB,KAAK,oBAAoB,KAAK,SAAS,QAExD,OACA,QACA,OACA,QACA,aACA,mBACE,uBAAuB,MAAM,WAAW,QAC1C,iBAAiB,QAAQ,WAAW"}
|
|
@@ -1,12 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a as encodeCursor, i as decodeCursor, n as InvalidCursor, r as PaginationResult, t as Direction } from "../pagination-CrU89125.mjs";
|
|
2
2
|
import { SelectQueryBuilder } from "kysely";
|
|
3
|
-
|
|
4
3
|
//#region src/kysely/pagination.d.ts
|
|
5
|
-
|
|
6
4
|
/**
|
|
7
5
|
* Options for paginated search.
|
|
8
6
|
*/
|
|
9
|
-
interface PaginatedSearchOptions<TRow, TMapRow extends (row: TRow) => unknown = (row: TRow) => TRow> {
|
|
7
|
+
export interface PaginatedSearchOptions<TRow, TMapRow extends (row: TRow) => unknown = (row: TRow) => TRow> {
|
|
10
8
|
/** The base Kysely query to paginate */
|
|
11
9
|
query: SelectQueryBuilder<any, any, TRow>;
|
|
12
10
|
/** Cursor value for pagination (value of cursorField from previous page) */
|
|
@@ -43,15 +41,7 @@ interface PaginatedSearchOptions<TRow, TMapRow extends (row: TRow) => unknown =
|
|
|
43
41
|
* });
|
|
44
42
|
* ```
|
|
45
43
|
*/
|
|
46
|
-
declare function paginatedSearch<TRow extends Record<string, unknown>, TMapRow extends (row: TRow) => unknown = (row: TRow) => TRow>({
|
|
47
|
-
query,
|
|
48
|
-
cursor,
|
|
49
|
-
limit,
|
|
50
|
-
mapRow,
|
|
51
|
-
cursorField,
|
|
52
|
-
cursorDirection
|
|
53
|
-
}: PaginatedSearchOptions<TRow, TMapRow>): Promise<PaginationResult<Awaited<ReturnType<TMapRow>>>>;
|
|
54
|
-
//# sourceMappingURL=pagination.d.ts.map
|
|
44
|
+
export declare function paginatedSearch<TRow extends Record<string, unknown>, TMapRow extends (row: TRow) => unknown = (row: TRow) => TRow>({ query, cursor, limit, mapRow, cursorField, cursorDirection }: PaginatedSearchOptions<TRow, TMapRow>): Promise<PaginationResult<Awaited<ReturnType<TMapRow>>>>;
|
|
55
45
|
//#endregion
|
|
56
|
-
export { Direction,
|
|
46
|
+
export { Direction, InvalidCursor, type PaginationResult, decodeCursor, encodeCursor };
|
|
57
47
|
//# sourceMappingURL=pagination.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.d.mts","names":[],"sources":["../../src/kysely/pagination.ts"],"
|
|
1
|
+
{"version":3,"file":"pagination.d.mts","names":[],"sources":["../../src/kysely/pagination.ts"],"mappings":";;;;;;iBAoBiB,uBAChB,MACA,iBAAiB,KAAK,oBAAoB,KAAK,SAAS;;EAGxD,OAAO,6BAA6B;;EAEpC;;EAEA;;EAEA,SAAS;;EAET;;EAEA,kBAAkB;;;;;;;;;;;;;;;;;;;;;;;;;wBA0BG,gBACrB,aAAa,yBACb,iBAAiB,KAAK,oBAAoB,KAAK,SAAS,QAExD,OACA,QACA,OACA,QACA,aACA,mBACE,uBAAuB,MAAM,WAAW,QAC1C,iBAAiB,QAAQ,WAAW"}
|