@geekmidas/db 10.0.0-alpha.16 → 10.0.0-alpha.161
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/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 +1 -0
- package/dist/kysely/pagination.cjs.map +1 -1
- package/dist/kysely/pagination.d.cts +2 -2
- package/dist/kysely/pagination.d.cts.map +1 -1
- package/dist/kysely/pagination.d.mts +2 -2
- package/dist/kysely/pagination.d.mts.map +1 -1
- package/dist/kysely/pagination.mjs +2 -2
- package/dist/kysely/pagination.mjs.map +1 -1
- package/dist/objection/pagination.cjs +1 -0
- package/dist/objection/pagination.cjs.map +1 -1
- package/dist/objection/pagination.d.cts +2 -2
- package/dist/objection/pagination.d.cts.map +1 -1
- package/dist/objection/pagination.d.mts +2 -2
- package/dist/objection/pagination.d.mts.map +1 -1
- package/dist/objection/pagination.mjs +2 -2
- package/dist/objection/pagination.mjs.map +1 -1
- package/dist/pagination-CrU89125.d.cts +42 -0
- package/dist/pagination-CrU89125.d.cts.map +1 -0
- package/dist/pagination-CrU89125.d.mts +42 -0
- package/dist/pagination-CrU89125.d.mts.map +1 -0
- package/dist/pagination.cjs +17 -1
- package/dist/pagination.cjs.map +1 -1
- package/dist/pagination.d.cts +2 -30
- package/dist/pagination.d.mts +2 -30
- package/dist/pagination.mjs +17 -2
- package/dist/pagination.mjs.map +1 -1
- package/dist/pg/roles.cjs +42 -4
- package/dist/pg/roles.cjs.map +1 -1
- package/dist/pg/roles.d.cts +19 -0
- package/dist/pg/roles.d.cts.map +1 -1
- package/dist/pg/roles.d.mts +19 -0
- package/dist/pg/roles.d.mts.map +1 -1
- package/dist/pg/roles.mjs +42 -4
- package/dist/pg/roles.mjs.map +1 -1
- package/package.json +13 -2
- package/dist/pagination.d.cts.map +0 -1
- package/dist/pagination.d.mts.map +0 -1
|
@@ -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"}
|
|
@@ -48,6 +48,7 @@ async function paginatedSearch({ query, cursor, limit = 20, mapRow, cursorField
|
|
|
48
48
|
}
|
|
49
49
|
//#endregion
|
|
50
50
|
exports.Direction = require_pagination.Direction;
|
|
51
|
+
exports.InvalidCursor = require_pagination.InvalidCursor;
|
|
51
52
|
exports.decodeCursor = require_pagination.decodeCursor;
|
|
52
53
|
exports.encodeCursor = require_pagination.encodeCursor;
|
|
53
54
|
exports.paginatedSearch = paginatedSearch;
|
|
@@ -1 +1 @@
|
|
|
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\ttype PaginationResult,\n} from '../pagination';\n\nexport {
|
|
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,4 +1,4 @@
|
|
|
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
3
|
//#region src/kysely/pagination.d.ts
|
|
4
4
|
/**
|
|
@@ -43,5 +43,5 @@ export interface PaginatedSearchOptions<TRow, TMapRow extends (row: TRow) => unk
|
|
|
43
43
|
*/
|
|
44
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>>>>;
|
|
45
45
|
//#endregion
|
|
46
|
-
export { Direction, type PaginationResult, decodeCursor, encodeCursor };
|
|
46
|
+
export { Direction, InvalidCursor, type PaginationResult, decodeCursor, encodeCursor };
|
|
47
47
|
//# sourceMappingURL=pagination.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.d.cts","names":[],"sources":["../../src/kysely/pagination.ts"],"mappings":";;;;;;
|
|
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,4 +1,4 @@
|
|
|
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
3
|
//#region src/kysely/pagination.d.ts
|
|
4
4
|
/**
|
|
@@ -43,5 +43,5 @@ export interface PaginatedSearchOptions<TRow, TMapRow extends (row: TRow) => unk
|
|
|
43
43
|
*/
|
|
44
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>>>>;
|
|
45
45
|
//#endregion
|
|
46
|
-
export { Direction, type PaginationResult, decodeCursor, encodeCursor };
|
|
46
|
+
export { Direction, InvalidCursor, type PaginationResult, decodeCursor, encodeCursor };
|
|
47
47
|
//# sourceMappingURL=pagination.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.d.mts","names":[],"sources":["../../src/kysely/pagination.ts"],"mappings":";;;;;;
|
|
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"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Direction, decodeCursor, encodeCursor } from "../pagination.mjs";
|
|
1
|
+
import { Direction, InvalidCursor, decodeCursor, encodeCursor } from "../pagination.mjs";
|
|
2
2
|
//#region src/kysely/pagination.ts
|
|
3
3
|
/**
|
|
4
4
|
* Generic paginated search function that handles:
|
|
@@ -46,6 +46,6 @@ async function paginatedSearch({ query, cursor, limit = 20, mapRow, cursorField
|
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
48
|
//#endregion
|
|
49
|
-
export { Direction, decodeCursor, encodeCursor, paginatedSearch };
|
|
49
|
+
export { Direction, InvalidCursor, decodeCursor, encodeCursor, paginatedSearch };
|
|
50
50
|
|
|
51
51
|
//# sourceMappingURL=pagination.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.mjs","names":[],"sources":["../../src/kysely/pagination.ts"],"sourcesContent":["import type { SelectQueryBuilder } from 'kysely';\nimport {\n\tDirection,\n\tdecodeCursor,\n\tencodeCursor,\n\ttype PaginationResult,\n} from '../pagination';\n\nexport {
|
|
1
|
+
{"version":3,"file":"pagination.mjs","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"}
|
|
@@ -42,6 +42,7 @@ async function paginatedSearch({ query, cursor, limit = 20, mapRow, cursorField
|
|
|
42
42
|
}
|
|
43
43
|
//#endregion
|
|
44
44
|
exports.Direction = require_pagination.Direction;
|
|
45
|
+
exports.InvalidCursor = require_pagination.InvalidCursor;
|
|
45
46
|
exports.decodeCursor = require_pagination.decodeCursor;
|
|
46
47
|
exports.encodeCursor = require_pagination.encodeCursor;
|
|
47
48
|
exports.paginatedSearch = paginatedSearch;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.cjs","names":[],"sources":["../../src/objection/pagination.ts"],"sourcesContent":["import type { Model, QueryBuilder } from 'objection';\nimport {\n\tDirection,\n\tdecodeCursor,\n\tencodeCursor,\n\ttype PaginationResult,\n} from '../pagination';\n\nexport {
|
|
1
|
+
{"version":3,"file":"pagination.cjs","names":[],"sources":["../../src/objection/pagination.ts"],"sourcesContent":["import type { Model, QueryBuilder } from 'objection';\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 with Objection.js models.\n */\nexport interface ObjectionPaginatedSearchOptions<\n\tTModel extends Model,\n\tTMapRow extends (row: TModel) => unknown = (row: TModel) => TModel,\n> {\n\t/** The Objection QueryBuilder to paginate (e.g. User.query(trx).where(...)) */\n\tquery: QueryBuilder<TModel>;\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 * Cursor-based paginated search for Objection.js models.\n *\n * Accepts a pre-built QueryBuilder so callers can apply filters,\n * eager loading, and scopes before pagination is layered on top.\n *\n * @example\n * ```typescript\n * const result = await paginatedSearch({\n * query: User.query(trx).where('orgId', orgId).withGraphFetched('roles'),\n * cursor: previousCursor,\n * limit: 20,\n * cursorField: 'createdAt',\n * cursorDirection: Direction.Desc,\n * });\n * ```\n */\nexport async function paginatedSearch<\n\tTModel extends Model,\n\tTMapRow extends (row: TModel) => unknown = (row: TModel) => TModel,\n>({\n\tquery,\n\tcursor,\n\tlimit = 20,\n\tmapRow,\n\tcursorField = 'id',\n\tcursorDirection = Direction.Asc,\n}: ObjectionPaginatedSearchOptions<TModel, TMapRow>): Promise<\n\tPaginationResult<Awaited<ReturnType<TMapRow>>>\n> {\n\t// Get total count (without cursor filtering)\n\tconst total = await query.resultSize();\n\n\t// Apply cursor if provided\n\tlet paginatedQuery = query.clone();\n\tif (cursor) {\n\t\tconst operator = cursorDirection === Direction.Asc ? '>' : '<';\n\t\tpaginatedQuery = paginatedQuery.where(cursorField, operator, cursor);\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, cursorDirection)\n\t\t.limit(limit + 1);\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\n\t\t\t? String((lastRow as Record<string, unknown>)[cursorField])\n\t\t\t: undefined;\n\n\tconst mapper = mapRow ?? ((row: TModel) => 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,\n\t\t\thasMore,\n\t\t\tcursor: nextCursor,\n\t\t},\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAuDA,eAAsB,gBAGpB,EACD,OACA,QACA,QAAQ,IACR,QACA,cAAc,MACd,kBAAA,SAGC;CAED,MAAM,QAAQ,MAAM,MAAM,WAAW;CAGrC,IAAI,iBAAiB,MAAM,MAAM;CACjC,IAAI,QAAQ;EACX,MAAM,WAAW,oBAAA,QAAoC,MAAM;EAC3D,iBAAiB,eAAe,MAAM,aAAa,UAAU,MAAM;CACpE;CAGA,MAAM,OAAO,MAAM,eACjB,QAAQ,aAAa,eAAe,CAAC,CACrC,MAAM,QAAQ,CAAC;CAEjB,MAAM,UAAU,KAAK,SAAS;CAC9B,MAAM,OAAO,UAAU,KAAK,MAAM,GAAG,KAAK,IAAI;CAC9C,MAAM,UAAU,KAAK,KAAK,SAAS;CACnC,MAAM,aACL,WAAW,UACR,OAAQ,QAAoC,YAAY,IACxD,KAAA;CAEJ,MAAM,SAAS,YAAY,QAAgB;CAK3C,OAAO;EACN,OAAA,MALoB,QAAQ,IAAI,KAAK,IAAI,MAAM,CAAC;EAMhD,YAAY;GACX;GACA;GACA,QAAQ;EACT;CACD;AACD"}
|
|
@@ -1,4 +1,4 @@
|
|
|
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 { Model, QueryBuilder } from "objection";
|
|
3
3
|
//#region src/objection/pagination.d.ts
|
|
4
4
|
/**
|
|
@@ -37,5 +37,5 @@ export interface ObjectionPaginatedSearchOptions<TModel extends Model, TMapRow e
|
|
|
37
37
|
*/
|
|
38
38
|
export declare function paginatedSearch<TModel extends Model, TMapRow extends (row: TModel) => unknown = (row: TModel) => TModel>({ query, cursor, limit, mapRow, cursorField, cursorDirection }: ObjectionPaginatedSearchOptions<TModel, TMapRow>): Promise<PaginationResult<Awaited<ReturnType<TMapRow>>>>;
|
|
39
39
|
//#endregion
|
|
40
|
-
export { Direction, type PaginationResult, decodeCursor, encodeCursor };
|
|
40
|
+
export { Direction, InvalidCursor, type PaginationResult, decodeCursor, encodeCursor };
|
|
41
41
|
//# sourceMappingURL=pagination.d.cts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.d.cts","names":[],"sources":["../../src/objection/pagination.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"pagination.d.cts","names":[],"sources":["../../src/objection/pagination.ts"],"mappings":";;;;;;iBAoBiB,gCAChB,eAAe,OACf,iBAAiB,KAAK,sBAAsB,KAAK,WAAW;;EAG5D,OAAO,aAAa;;EAEpB;;EAEA;;EAEA,SAAS;;EAET;;EAEA,kBAAkB;;;;;;;;;;;;;;;;;;;wBAoBG,gBACrB,eAAe,OACf,iBAAiB,KAAK,sBAAsB,KAAK,WAAW,UAE5D,OACA,QACA,OACA,QACA,aACA,mBACE,gCAAgC,QAAQ,WAAW,QACrD,iBAAiB,QAAQ,WAAW"}
|
|
@@ -1,4 +1,4 @@
|
|
|
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 { Model, QueryBuilder } from "objection";
|
|
3
3
|
//#region src/objection/pagination.d.ts
|
|
4
4
|
/**
|
|
@@ -37,5 +37,5 @@ export interface ObjectionPaginatedSearchOptions<TModel extends Model, TMapRow e
|
|
|
37
37
|
*/
|
|
38
38
|
export declare function paginatedSearch<TModel extends Model, TMapRow extends (row: TModel) => unknown = (row: TModel) => TModel>({ query, cursor, limit, mapRow, cursorField, cursorDirection }: ObjectionPaginatedSearchOptions<TModel, TMapRow>): Promise<PaginationResult<Awaited<ReturnType<TMapRow>>>>;
|
|
39
39
|
//#endregion
|
|
40
|
-
export { Direction, type PaginationResult, decodeCursor, encodeCursor };
|
|
40
|
+
export { Direction, InvalidCursor, type PaginationResult, decodeCursor, encodeCursor };
|
|
41
41
|
//# sourceMappingURL=pagination.d.mts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.d.mts","names":[],"sources":["../../src/objection/pagination.ts"],"mappings":";;;;;;
|
|
1
|
+
{"version":3,"file":"pagination.d.mts","names":[],"sources":["../../src/objection/pagination.ts"],"mappings":";;;;;;iBAoBiB,gCAChB,eAAe,OACf,iBAAiB,KAAK,sBAAsB,KAAK,WAAW;;EAG5D,OAAO,aAAa;;EAEpB;;EAEA;;EAEA,SAAS;;EAET;;EAEA,kBAAkB;;;;;;;;;;;;;;;;;;;wBAoBG,gBACrB,eAAe,OACf,iBAAiB,KAAK,sBAAsB,KAAK,WAAW,UAE5D,OACA,QACA,OACA,QACA,aACA,mBACE,gCAAgC,QAAQ,WAAW,QACrD,iBAAiB,QAAQ,WAAW"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Direction, decodeCursor, encodeCursor } from "../pagination.mjs";
|
|
1
|
+
import { Direction, InvalidCursor, decodeCursor, encodeCursor } from "../pagination.mjs";
|
|
2
2
|
//#region src/objection/pagination.ts
|
|
3
3
|
/**
|
|
4
4
|
* Cursor-based paginated search for Objection.js models.
|
|
@@ -40,6 +40,6 @@ async function paginatedSearch({ query, cursor, limit = 20, mapRow, cursorField
|
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
42
|
//#endregion
|
|
43
|
-
export { Direction, decodeCursor, encodeCursor, paginatedSearch };
|
|
43
|
+
export { Direction, InvalidCursor, decodeCursor, encodeCursor, paginatedSearch };
|
|
44
44
|
|
|
45
45
|
//# sourceMappingURL=pagination.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.mjs","names":[],"sources":["../../src/objection/pagination.ts"],"sourcesContent":["import type { Model, QueryBuilder } from 'objection';\nimport {\n\tDirection,\n\tdecodeCursor,\n\tencodeCursor,\n\ttype PaginationResult,\n} from '../pagination';\n\nexport {
|
|
1
|
+
{"version":3,"file":"pagination.mjs","names":[],"sources":["../../src/objection/pagination.ts"],"sourcesContent":["import type { Model, QueryBuilder } from 'objection';\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 with Objection.js models.\n */\nexport interface ObjectionPaginatedSearchOptions<\n\tTModel extends Model,\n\tTMapRow extends (row: TModel) => unknown = (row: TModel) => TModel,\n> {\n\t/** The Objection QueryBuilder to paginate (e.g. User.query(trx).where(...)) */\n\tquery: QueryBuilder<TModel>;\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 * Cursor-based paginated search for Objection.js models.\n *\n * Accepts a pre-built QueryBuilder so callers can apply filters,\n * eager loading, and scopes before pagination is layered on top.\n *\n * @example\n * ```typescript\n * const result = await paginatedSearch({\n * query: User.query(trx).where('orgId', orgId).withGraphFetched('roles'),\n * cursor: previousCursor,\n * limit: 20,\n * cursorField: 'createdAt',\n * cursorDirection: Direction.Desc,\n * });\n * ```\n */\nexport async function paginatedSearch<\n\tTModel extends Model,\n\tTMapRow extends (row: TModel) => unknown = (row: TModel) => TModel,\n>({\n\tquery,\n\tcursor,\n\tlimit = 20,\n\tmapRow,\n\tcursorField = 'id',\n\tcursorDirection = Direction.Asc,\n}: ObjectionPaginatedSearchOptions<TModel, TMapRow>): Promise<\n\tPaginationResult<Awaited<ReturnType<TMapRow>>>\n> {\n\t// Get total count (without cursor filtering)\n\tconst total = await query.resultSize();\n\n\t// Apply cursor if provided\n\tlet paginatedQuery = query.clone();\n\tif (cursor) {\n\t\tconst operator = cursorDirection === Direction.Asc ? '>' : '<';\n\t\tpaginatedQuery = paginatedQuery.where(cursorField, operator, cursor);\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, cursorDirection)\n\t\t.limit(limit + 1);\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\n\t\t\t? String((lastRow as Record<string, unknown>)[cursorField])\n\t\t\t: undefined;\n\n\tconst mapper = mapRow ?? ((row: TModel) => 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,\n\t\t\thasMore,\n\t\t\tcursor: nextCursor,\n\t\t},\n\t};\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAuDA,eAAsB,gBAGpB,EACD,OACA,QACA,QAAQ,IACR,QACA,cAAc,MACd,kBAAA,SAGC;CAED,MAAM,QAAQ,MAAM,MAAM,WAAW;CAGrC,IAAI,iBAAiB,MAAM,MAAM;CACjC,IAAI,QAAQ;EACX,MAAM,WAAW,oBAAA,QAAoC,MAAM;EAC3D,iBAAiB,eAAe,MAAM,aAAa,UAAU,MAAM;CACpE;CAGA,MAAM,OAAO,MAAM,eACjB,QAAQ,aAAa,eAAe,CAAC,CACrC,MAAM,QAAQ,CAAC;CAEjB,MAAM,UAAU,KAAK,SAAS;CAC9B,MAAM,OAAO,UAAU,KAAK,MAAM,GAAG,KAAK,IAAI;CAC9C,MAAM,UAAU,KAAK,KAAK,SAAS;CACnC,MAAM,aACL,WAAW,UACR,OAAQ,QAAoC,YAAY,IACxD,KAAA;CAEJ,MAAM,SAAS,YAAY,QAAgB;CAK3C,OAAO;EACN,OAAA,MALoB,QAAQ,IAAI,KAAK,IAAI,MAAM,CAAC;EAMhD,YAAY;GACX;GACA;GACA,QAAQ;EACT;CACD;AACD"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
//#region src/pagination.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Sort direction for cursor-based pagination.
|
|
4
|
+
*/
|
|
5
|
+
declare enum Direction {
|
|
6
|
+
Asc = "asc",
|
|
7
|
+
Desc = "desc"
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Result of a paginated query.
|
|
11
|
+
*/
|
|
12
|
+
interface PaginationResult<TItem> {
|
|
13
|
+
items: TItem[];
|
|
14
|
+
pagination: {
|
|
15
|
+
total: number;
|
|
16
|
+
hasMore: boolean;
|
|
17
|
+
cursor?: string;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Encode a cursor value for safe URL transmission.
|
|
22
|
+
* Supports various types: string, number, Date, etc.
|
|
23
|
+
*/
|
|
24
|
+
declare function encodeCursor(value: unknown): string;
|
|
25
|
+
/**
|
|
26
|
+
* Decode a cursor string back to its original value.
|
|
27
|
+
*/
|
|
28
|
+
declare function decodeCursor(cursor: string): unknown;
|
|
29
|
+
/**
|
|
30
|
+
* A cursor that did not come from `encodeCursor`.
|
|
31
|
+
*
|
|
32
|
+
* Usually a cursor from a different page size or sort that was edited by hand,
|
|
33
|
+
* or truncated on its way through a URL. The fix is the same either way: start
|
|
34
|
+
* again from the first page.
|
|
35
|
+
*/
|
|
36
|
+
declare class InvalidCursor extends Error {
|
|
37
|
+
readonly cursor: string;
|
|
38
|
+
constructor(cursor: string);
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { encodeCursor as a, decodeCursor as i, InvalidCursor as n, PaginationResult as r, Direction as t };
|
|
42
|
+
//# sourceMappingURL=pagination-CrU89125.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination-CrU89125.d.cts","names":[],"sources":["../src/pagination.ts"],"mappings":";;;;aAGY;EACX;EACA;;;;;UAMgB,iBAAiB;EACjC,OAAO;EACP;IACC;IACA;IACA;;;;;;;iBAQc,aAAa;;;;iBAWb,aAAa;;;;;;;;cAsBhB,sBAAsB;WACb;EAArB,YAAqB"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
//#region src/pagination.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* Sort direction for cursor-based pagination.
|
|
4
|
+
*/
|
|
5
|
+
declare enum Direction {
|
|
6
|
+
Asc = "asc",
|
|
7
|
+
Desc = "desc"
|
|
8
|
+
}
|
|
9
|
+
/**
|
|
10
|
+
* Result of a paginated query.
|
|
11
|
+
*/
|
|
12
|
+
interface PaginationResult<TItem> {
|
|
13
|
+
items: TItem[];
|
|
14
|
+
pagination: {
|
|
15
|
+
total: number;
|
|
16
|
+
hasMore: boolean;
|
|
17
|
+
cursor?: string;
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Encode a cursor value for safe URL transmission.
|
|
22
|
+
* Supports various types: string, number, Date, etc.
|
|
23
|
+
*/
|
|
24
|
+
declare function encodeCursor(value: unknown): string;
|
|
25
|
+
/**
|
|
26
|
+
* Decode a cursor string back to its original value.
|
|
27
|
+
*/
|
|
28
|
+
declare function decodeCursor(cursor: string): unknown;
|
|
29
|
+
/**
|
|
30
|
+
* A cursor that did not come from `encodeCursor`.
|
|
31
|
+
*
|
|
32
|
+
* Usually a cursor from a different page size or sort that was edited by hand,
|
|
33
|
+
* or truncated on its way through a URL. The fix is the same either way: start
|
|
34
|
+
* again from the first page.
|
|
35
|
+
*/
|
|
36
|
+
declare class InvalidCursor extends Error {
|
|
37
|
+
readonly cursor: string;
|
|
38
|
+
constructor(cursor: string);
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
export { encodeCursor as a, decodeCursor as i, InvalidCursor as n, PaginationResult as r, Direction as t };
|
|
42
|
+
//# sourceMappingURL=pagination-CrU89125.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pagination-CrU89125.d.mts","names":[],"sources":["../src/pagination.ts"],"mappings":";;;;aAGY;EACX;EACA;;;;;UAMgB,iBAAiB;EACjC,OAAO;EACP;IACC;IACA;IACA;;;;;;;iBAQc,aAAa;;;;iBAWb,aAAa;;;;;;;;cAsBhB,sBAAsB;WACb;EAArB,YAAqB"}
|
package/dist/pagination.cjs
CHANGED
|
@@ -29,11 +29,27 @@ function decodeCursor(cursor) {
|
|
|
29
29
|
if (payload.t === "date") return new Date(payload.v);
|
|
30
30
|
return payload.v;
|
|
31
31
|
} catch {
|
|
32
|
-
throw new
|
|
32
|
+
throw new InvalidCursor(cursor);
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* A cursor that did not come from `encodeCursor`.
|
|
37
|
+
*
|
|
38
|
+
* Usually a cursor from a different page size or sort that was edited by hand,
|
|
39
|
+
* or truncated on its way through a URL. The fix is the same either way: start
|
|
40
|
+
* again from the first page.
|
|
41
|
+
*/
|
|
42
|
+
var InvalidCursor = class extends Error {
|
|
43
|
+
cursor;
|
|
44
|
+
constructor(cursor) {
|
|
45
|
+
super("This cursor was not produced by encodeCursor. Drop it and request the first page again.");
|
|
46
|
+
this.cursor = cursor;
|
|
47
|
+
this.name = "InvalidCursor";
|
|
48
|
+
}
|
|
49
|
+
};
|
|
35
50
|
//#endregion
|
|
36
51
|
exports.Direction = Direction;
|
|
52
|
+
exports.InvalidCursor = InvalidCursor;
|
|
37
53
|
exports.decodeCursor = decodeCursor;
|
|
38
54
|
exports.encodeCursor = encodeCursor;
|
|
39
55
|
|
package/dist/pagination.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pagination.cjs","names":[],"sources":["../src/pagination.ts"],"sourcesContent":["/**\n * Sort direction for cursor-based pagination.\n */\nexport enum Direction {\n\tAsc = 'asc',\n\tDesc = 'desc',\n}\n\n/**\n * Result of a paginated query.\n */\nexport interface PaginationResult<TItem> {\n\titems: TItem[];\n\tpagination: {\n\t\ttotal: number;\n\t\thasMore: boolean;\n\t\tcursor?: string;\n\t};\n}\n\n/**\n * Encode a cursor value for safe URL transmission.\n * Supports various types: string, number, Date, etc.\n */\nexport function encodeCursor(value: unknown): string {\n\tconst payload = {\n\t\tv: value instanceof Date ? value.toISOString() : value,\n\t\tt: value instanceof Date ? 'date' : typeof value,\n\t};\n\treturn Buffer.from(JSON.stringify(payload)).toString('base64url');\n}\n\n/**\n * Decode a cursor string back to its original value.\n */\nexport function decodeCursor(cursor: string): unknown {\n\ttry {\n\t\tconst json = Buffer.from(cursor, 'base64url').toString('utf-8');\n\t\tconst payload = JSON.parse(json);\n\n\t\tif (payload.t === 'date') {\n\t\t\treturn new Date(payload.v);\n\t\t}\n\n\t\treturn payload.v;\n\t} catch {\n\t\tthrow new Error('
|
|
1
|
+
{"version":3,"file":"pagination.cjs","names":[],"sources":["../src/pagination.ts"],"sourcesContent":["/**\n * Sort direction for cursor-based pagination.\n */\nexport enum Direction {\n\tAsc = 'asc',\n\tDesc = 'desc',\n}\n\n/**\n * Result of a paginated query.\n */\nexport interface PaginationResult<TItem> {\n\titems: TItem[];\n\tpagination: {\n\t\ttotal: number;\n\t\thasMore: boolean;\n\t\tcursor?: string;\n\t};\n}\n\n/**\n * Encode a cursor value for safe URL transmission.\n * Supports various types: string, number, Date, etc.\n */\nexport function encodeCursor(value: unknown): string {\n\tconst payload = {\n\t\tv: value instanceof Date ? value.toISOString() : value,\n\t\tt: value instanceof Date ? 'date' : typeof value,\n\t};\n\treturn Buffer.from(JSON.stringify(payload)).toString('base64url');\n}\n\n/**\n * Decode a cursor string back to its original value.\n */\nexport function decodeCursor(cursor: string): unknown {\n\ttry {\n\t\tconst json = Buffer.from(cursor, 'base64url').toString('utf-8');\n\t\tconst payload = JSON.parse(json);\n\n\t\tif (payload.t === 'date') {\n\t\t\treturn new Date(payload.v);\n\t\t}\n\n\t\treturn payload.v;\n\t} catch {\n\t\tthrow new InvalidCursor(cursor);\n\t}\n}\n\n/**\n * A cursor that did not come from `encodeCursor`.\n *\n * Usually a cursor from a different page size or sort that was edited by hand,\n * or truncated on its way through a URL. The fix is the same either way: start\n * again from the first page.\n */\nexport class InvalidCursor extends Error {\n\tconstructor(readonly cursor: string) {\n\t\tsuper(\n\t\t\t'This cursor was not produced by encodeCursor. Drop it and request the first page again.',\n\t\t);\n\t\tthis.name = 'InvalidCursor';\n\t}\n}\n"],"mappings":";;;;;AAGA,IAAY,YAAL,yBAAA,WAAA;CACN,UAAA,SAAA;CACA,UAAA,UAAA;;AACD,EAAA,CAAA,CAAA;;;;;AAkBA,SAAgB,aAAa,OAAwB;CACpD,MAAM,UAAU;EACf,GAAG,iBAAiB,OAAO,MAAM,YAAY,IAAI;EACjD,GAAG,iBAAiB,OAAO,SAAS,OAAO;CAC5C;CACA,OAAO,OAAO,KAAK,KAAK,UAAU,OAAO,CAAC,CAAC,CAAC,SAAS,WAAW;AACjE;;;;AAKA,SAAgB,aAAa,QAAyB;CACrD,IAAI;EACH,MAAM,OAAO,OAAO,KAAK,QAAQ,WAAW,CAAC,CAAC,SAAS,OAAO;EAC9D,MAAM,UAAU,KAAK,MAAM,IAAI;EAE/B,IAAI,QAAQ,MAAM,QACjB,OAAO,IAAI,KAAK,QAAQ,CAAC;EAG1B,OAAO,QAAQ;CAChB,QAAQ;EACP,MAAM,IAAI,cAAc,MAAM;CAC/B;AACD;;;;;;;;AASA,IAAa,gBAAb,cAAmC,MAAM;CACnB;CAArB,YAAY,QAAyB;EACpC,MACC,yFACD;EAHoB,KAAA,SAAA;EAIpB,KAAK,OAAO;CACb;AACD"}
|