@juit/pgproxy-persister 1.3.7 → 1.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,211 @@
1
+ import type { ColumnDefinition, InferSelectType } from './model';
2
+ import type { Persister } from './persister';
3
+ /**
4
+ * Definition for a simple (straight) join in a {@link Search}
5
+ */
6
+ export interface SearchJoin<Schema> {
7
+ /**
8
+ * The column in _the search table_ (passed to the constructor of
9
+ * {@link Search}) referencing the specified `refTable` (defined here).
10
+ *
11
+ * ```sql
12
+ * ... LEFT JOIN "refTable" ON "table"."column" = "refTable"."refColumn"
13
+ * ^^^^^^
14
+ * ```
15
+ */
16
+ column: string;
17
+ /**
18
+ * The name of the table to _left join_.
19
+ *
20
+ * ```sql
21
+ * ... LEFT JOIN "refTable" ON "table"."column" = "refTable"."refColumn"
22
+ * ^^^^^^^^ ^^^^^^^^
23
+ * ```
24
+ */
25
+ refTable: string & keyof Schema;
26
+ /**
27
+ * The column in the `refTable` referenced by the _the search table_.
28
+ *
29
+ * ```sql
30
+ * ... LEFT JOIN "refTable" ON "table"."column" = "refTable"."refColumn"
31
+ * ^^^^^^^^^
32
+ * ```
33
+ */
34
+ refColumn: string;
35
+ /**
36
+ * The column in the referenced table to use as default sort column, when
37
+ * sorting by this join.
38
+ */
39
+ sortColumn?: string;
40
+ }
41
+ /**
42
+ * Definition for joins in a {@link Search}
43
+ *
44
+ * Each key is the name of the join as it will appear in the results, and the
45
+ * value defines how to perform the join.
46
+ *
47
+ * See {@link StraightJoin} and {@link LinkedJoin} for details on the fields.
48
+ */
49
+ export interface SearchJoins<Schema> {
50
+ [key: string]: SearchJoin<Schema>;
51
+ }
52
+ /** Internal interface defining operators available to *single values* */
53
+ interface ValueSearchFilter<Schema, Table extends string & keyof Schema> {
54
+ name: string & keyof Schema[Table];
55
+ field?: string;
56
+ op?: '=' | '!=' | '>' | '>=' | '<' | '<=' | '~' | 'like' | 'ilike';
57
+ value: string | number | Date | boolean | null;
58
+ }
59
+ /** Internal interface defining operators available to *array values* */
60
+ interface ArraySearchFilter<Schema, Table extends string & keyof Schema> {
61
+ name: string & keyof Schema[Table];
62
+ field?: string;
63
+ op: 'in' | 'not in';
64
+ value: (string | number | Date | boolean | null)[];
65
+ }
66
+ /** Internal interface defining operators available to *json values* */
67
+ interface JsonSearchFilter<Schema, Table extends string & keyof Schema> {
68
+ name: string & keyof Schema[Table];
69
+ field?: never;
70
+ op: '@>' | '<@';
71
+ value: any;
72
+ }
73
+ /**
74
+ * A filter for a search that matches a single value
75
+ *
76
+ * - `name` is the column name to filter on
77
+ * - `field` is a field to filter on when the column is a complex type (JSONB)
78
+ * - `op` is the operator to use for the filter (default: `=`)
79
+ * - `value` is the value to filter for
80
+ *
81
+ * All operators are defined as per PostgreSQL documentation, with few notable
82
+ * exceptions:
83
+ *
84
+ * - `~` is an alias to the `ilike` operator
85
+ * - `in` and `not in` are used to match a value against an array of possible
86
+ * values using the `... = ANY(...)` or `... != ALL(...)` constructs
87
+ * - `@>` and `<@` will accept single values as well as arrays.
88
+ * - `!=` and `=` will use the PostgreSQL `IS (NOT) DISTINCT FROM` semantics
89
+ * to properly handle `NULL` comparisons.
90
+ */
91
+ export type SearchFilter<Schema, Table extends string & keyof Schema> = ValueSearchFilter<Schema, Table> | ArraySearchFilter<Schema, Table> | JsonSearchFilter<Schema, Table>;
92
+ /**
93
+ * Base interface for querying results via our {@link Search}.
94
+ */
95
+ export interface SearchQuery<Schema, Table extends string & keyof Schema, Joins extends SearchJoins<Schema> = {}> {
96
+ /** An optional set of filters to apply */
97
+ filters?: SearchFilter<Schema, Table>[];
98
+ /** An optional column to sort by */
99
+ sort?: string & (keyof Schema[Table] | keyof Joins);
100
+ /** The order to sort by (if `sort` is specified, default: 'asc') */
101
+ order?: 'asc' | 'desc';
102
+ /** An optional full-text search query, available for full-text search */
103
+ q?: string;
104
+ }
105
+ /**
106
+ * Full options for querying a limited set of results via our {@link Search}.
107
+ */
108
+ export interface SearchOptions<Schema, Table extends string & keyof Schema, Joins extends SearchJoins<Schema> = {}> extends SearchQuery<Schema, Table, Joins> {
109
+ /** Offset to start returning rows from (default: 0) */
110
+ offset?: number;
111
+ /** Maximum number of rows to return (default: 20, unlimited if 0) */
112
+ limit?: number;
113
+ }
114
+ /**
115
+ * Extra (manual) SQL to further customize our {@link Search} queries.
116
+ */
117
+ export interface SearchExtra {
118
+ /** Extra `WHERE` clause to add to our search */
119
+ where: string;
120
+ /** Parameters for the extra `WHERE` clause */
121
+ params: any[];
122
+ }
123
+ /** A single search result row (with joins) */
124
+ export type SearchResult<Schema, Table extends string & keyof Schema, Joins extends SearchJoins<Schema> = {}> = Schema[Table] extends Record<string, ColumnDefinition> ? InferSelectType<Schema[Table]> & {
125
+ [key in keyof Joins]: Joins[key]['refTable'] extends keyof Schema ? Schema[Joins[key]['refTable']] extends Record<string, ColumnDefinition> ? Schema[Table][Joins[key]['column']]['isNullable'] extends true ? InferSelectType<Schema[Joins[key]['refTable']]> | null : InferSelectType<Schema[Joins[key]['refTable']]> : unknown : unknown;
126
+ } : never;
127
+ /** What's being returned by our `search` */
128
+ export interface SearchResults<Schema, Table extends string & keyof Schema, Joins extends SearchJoins<Schema> = {}> {
129
+ /** The total length of all available results (without offset or limit) */
130
+ total: number;
131
+ /** The lines queried (truncated by offset and limit) */
132
+ rows: SearchResult<Schema, Table, Joins>[];
133
+ }
134
+ /**
135
+ * An object to perform searches on a given table in our {@link Persister}
136
+ */
137
+ export interface Search<Schema, Table extends string & keyof Schema, Joins extends SearchJoins<Schema>> {
138
+ /**
139
+ * Return the first result (if any) matching the specified query.
140
+ *
141
+ * This will intrinsically limit the search to 1 result.
142
+ *
143
+ * @param query The query to filter results by
144
+ * @param extra Optional extra SQL to customize the search
145
+ * @returns The first matching result, or `undefined` if no results matched
146
+ */
147
+ find(query: SearchQuery<Schema, Table, Joins>, extra?: SearchExtra): Promise<SearchResult<Schema, Table, Joins> | undefined>;
148
+ /**
149
+ * Return the raw SQL query and parameters for the specified options.
150
+ *
151
+ * @param options The search options to generate SQL for
152
+ * @param extra Optional extra SQL to customize the search
153
+ * @returns A tuple containing the SQL string and its parameters
154
+ */
155
+ query(options: SearchOptions<Schema, Table, Joins>, extra?: SearchExtra): [sql: string, params: any[]];
156
+ /**
157
+ * Perform a search with the specified options.
158
+ *
159
+ * @param options The search options to use
160
+ * @param extra Optional extra SQL to customize the search
161
+ * @returns The search results
162
+ */
163
+ search(options: SearchOptions<Schema, Table, Joins>, extra?: SearchExtra): Promise<SearchResults<Schema, Table, Joins>>;
164
+ }
165
+ /**
166
+ * A constructor for our {@link Search} object
167
+ */
168
+ export interface SearchConstructor {
169
+ /**
170
+ * Construct a {@link Search} object using the specified {@link Persister},
171
+ * operating on the specified table.
172
+ *
173
+ * @param persister The {@link Persister} instance to use
174
+ * @param table The table to perform searches on
175
+ */
176
+ new <P extends Persister, T extends string & (P extends Persister<infer S> ? keyof S : never)>(persister: P, table: T): Search<P extends Persister<infer S> ? S : never, T, {}>;
177
+ /**
178
+ * Construct a {@link Search} object using the specified {@link Persister},
179
+ * operating on the specified table, and using the specified full-text search
180
+ * column (TSVECTOR) to perform `q` searches.
181
+ *
182
+ * @param persister The {@link Persister} instance to use
183
+ * @param table The table to perform searches on
184
+ * @param fullTextSearchColumn The column to use for full-text searches
185
+ */
186
+ new <P extends Persister, T extends string & (P extends Persister<infer S> ? keyof S : never)>(persister: P, table: T, fullTextSearchColumn: string): Search<P extends Persister<infer S> ? S : never, T, {}>;
187
+ /**
188
+ * Construct a {@link Search} object using the specified {@link Persister},
189
+ * operating on the specified table, joining external tables.
190
+ *
191
+ * @param persister The {@link Persister} instance to use
192
+ * @param table The table to perform searches on
193
+ * @param joins The joins to perform
194
+ */
195
+ new <P extends Persister, T extends string & (P extends Persister<infer S> ? keyof S : never), J extends SearchJoins<P extends Persister<infer S> ? S : never>>(persister: P, table: T, joins: J): Search<P extends Persister<infer S> ? S : never, T, J>;
196
+ /**
197
+ * Construct a {@link Search} object using the specified {@link Persister},
198
+ * operating on the specified table, joining external tables, and using the
199
+ * specified full-text search column (TSVECTOR) to perform `q` searches.
200
+ *
201
+ * @param persister The {@link Persister} instance to use
202
+ * @param table The table to perform searches on
203
+ * @param joins The joins to perform
204
+ * @param fullTextSearchColumn The column to use for full-text searches
205
+ */
206
+ new <P extends Persister, T extends string & (P extends Persister<infer S> ? keyof S : never), J extends SearchJoins<P extends Persister<infer S> ? S : never>>(persister: P, table: T, joins: J, fullTextSearchColumn: string): Search<P extends Persister<infer S> ? S : never, T, J>;
207
+ }
208
+ /** Revive a JSON, parsing ISO dates as {@link Date} objects */
209
+ export declare function reviver(_key: string, data: any): any;
210
+ export declare const Search: SearchConstructor;
211
+ export {};
@@ -0,0 +1,189 @@
1
+ // search.ts
2
+ import { escape } from "@juit/pgproxy-client";
3
+ import { assert, encodeSchemaAndName } from "./utils.mjs";
4
+ var ISO_RE = /^(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d\.\d+([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))|(\d{4}-[01]\d-[0-3]\dT[0-2]\d:[0-5]\d([+-][0-2]\d:[0-5]\d|Z))$/;
5
+ function reviver(_key, data) {
6
+ if (typeof data === "string" && ISO_RE.test(data)) return new Date(data);
7
+ return data;
8
+ }
9
+ var SearchImpl = class {
10
+ /** Our persister instance */
11
+ #persister;
12
+ /** The escaped table name */
13
+ #eTable;
14
+ /** The escaped joins */
15
+ #eJoins;
16
+ /** The full-text search column (if any) */
17
+ #fullTextSearchColumn;
18
+ constructor(persister, table, joinsOrFullTextSearchColumn, maybeFullTextSearchColumn) {
19
+ this.#persister = persister;
20
+ this.#eTable = encodeSchemaAndName(table);
21
+ let joins = {};
22
+ let fullTextSearchColumn = void 0;
23
+ if (typeof joinsOrFullTextSearchColumn === "string") {
24
+ fullTextSearchColumn = joinsOrFullTextSearchColumn;
25
+ } else if (joinsOrFullTextSearchColumn) {
26
+ joins = joinsOrFullTextSearchColumn;
27
+ fullTextSearchColumn = maybeFullTextSearchColumn;
28
+ }
29
+ this.#fullTextSearchColumn = fullTextSearchColumn || void 0;
30
+ this.#eJoins = Object.fromEntries(Object.entries(joins).map(([key, def]) => {
31
+ return [key, {
32
+ column: escape(def.column),
33
+ refTable: encodeSchemaAndName(def.refTable),
34
+ refColumn: escape(def.refColumn),
35
+ sortColumn: def.sortColumn ? escape(def.sortColumn) : void 0
36
+ }];
37
+ }));
38
+ }
39
+ #query(count, options, extra) {
40
+ const {
41
+ offset = 0,
42
+ limit = 20,
43
+ filters = [],
44
+ sort,
45
+ order,
46
+ q
47
+ } = options;
48
+ const etable = this.#eTable;
49
+ const ejoins = this.#eJoins;
50
+ const fields = [];
51
+ const where = [];
52
+ const orderby = [];
53
+ const params = [];
54
+ if (extra) {
55
+ where.push(extra.where);
56
+ params.push(...extra.params);
57
+ }
58
+ let esearch = "";
59
+ if (count === "only") {
60
+ if (this.#fullTextSearchColumn) esearch = escape(this.#fullTextSearchColumn);
61
+ } else if (this.#fullTextSearchColumn) {
62
+ fields.push(`(TO_JSONB(${etable}.*) - $${params.push(this.#fullTextSearchColumn)})`);
63
+ esearch = escape(this.#fullTextSearchColumn);
64
+ } else {
65
+ fields.push(`TO_JSONB(${etable}.*)`);
66
+ }
67
+ const from = [etable];
68
+ let joinIndex = 0;
69
+ const joinedTables = {};
70
+ Object.entries(ejoins).forEach(([as, { column, refTable, refColumn }]) => {
71
+ const ealias = escape(`__$${(++joinIndex).toString(16).padStart(4, "0")}$__`);
72
+ joinedTables[as] ??= ealias;
73
+ if (count !== "only") {
74
+ const index = params.push(as);
75
+ fields.push(`JSONB_BUILD_OBJECT($${index}::TEXT, TO_JSONB(${ealias}))`);
76
+ }
77
+ from.push(`LEFT JOIN ${refTable} ${ealias} ON ${etable}.${column} = ${ealias}.${refColumn}`);
78
+ });
79
+ if (sort) {
80
+ const joinedOrder = order?.toLocaleLowerCase() === "desc" ? " DESC" : "";
81
+ if (ejoins[sort]) {
82
+ assert(ejoins[sort].sortColumn, `Sort column for joined field "${sort}" not defined`);
83
+ const joinedTableAlias = joinedTables[sort];
84
+ const joinedColumn = ejoins[sort].sortColumn;
85
+ orderby.push(`${joinedTableAlias}.${joinedColumn}${joinedOrder} NULLS LAST`);
86
+ } else {
87
+ orderby.push(`${etable}.${escape(sort)}${joinedOrder}`);
88
+ }
89
+ }
90
+ if (q) {
91
+ assert(esearch, "Full-text search column not defined");
92
+ if (q.match(/^[\w][-@\w]*$/)) {
93
+ from.push(`CROSS JOIN LATERAL CAST(LOWER($${params.push(q + ":*")}) AS tsquery) AS "__query"`);
94
+ } else {
95
+ from.push(`CROSS JOIN LATERAL websearch_to_tsquery($${params.push(q)}) AS "__query"`);
96
+ }
97
+ orderby.push(`ts_rank(${etable}.${esearch}, "__query") DESC`);
98
+ where.push(`"__query" @@ ${etable}.${esearch}`);
99
+ }
100
+ for (const { name, field, op = "=", value } of filters) {
101
+ const [ecolumn, evalue] = field && ["like", "ilike", "~"].includes(op) ? [`${escape(name)}->>$${params.push(field)}`, value] : field ? [`${escape(name)}->$${params.push(field)}`, JSON.stringify(value)] : [escape(name), value];
102
+ if (op === "in") {
103
+ const evalue2 = field && Array.isArray(value) ? value.map((v) => JSON.stringify(v)) : value;
104
+ where.push(`${etable}.${ecolumn} = ANY($${params.push(evalue2)})`);
105
+ continue;
106
+ } else if (op === "not in") {
107
+ const evalue2 = field && Array.isArray(value) ? value.map((v) => JSON.stringify(v)) : value;
108
+ where.push(`${etable}.${ecolumn} != ALL($${params.push(evalue2)})`);
109
+ continue;
110
+ } else if (op === "@>" || op === "<@") {
111
+ assert(!field, `Field "${field}" cannot be specified when using JSONB operator "${op}" for column "${name}"`);
112
+ where.push(`${etable}.${ecolumn} ${op} ($${params.push(JSON.stringify(value))})::JSONB`);
113
+ continue;
114
+ }
115
+ let operator;
116
+ switch (op) {
117
+ case ">":
118
+ operator = ">";
119
+ break;
120
+ case ">=":
121
+ operator = ">=";
122
+ break;
123
+ case "<":
124
+ operator = "<";
125
+ break;
126
+ case "<=":
127
+ operator = "<=";
128
+ break;
129
+ case "like":
130
+ operator = "LIKE";
131
+ break;
132
+ case "ilike":
133
+ operator = "ILIKE";
134
+ break;
135
+ case "~":
136
+ operator = "ILIKE";
137
+ break;
138
+ case "!=":
139
+ operator = "IS DISTINCT FROM";
140
+ break;
141
+ case "=":
142
+ operator = "IS NOT DISTINCT FROM";
143
+ break;
144
+ default:
145
+ throw new Error(`Unsupported operator "${op}" for column "${name}"`);
146
+ }
147
+ where.push(`${etable}.${ecolumn} ${operator} $${params.push(evalue)}`);
148
+ }
149
+ const result = `(${fields.join(" || ")})::TEXT AS "result"`;
150
+ const clauses = count === "only" ? 'COUNT(*) AS "total"' : count ? `COUNT(*) OVER() AS "total", ${result}` : result;
151
+ let sql = `SELECT ${clauses} FROM ${from.join(" ")}`;
152
+ if (where.length) sql += ` WHERE ${where.join(" AND ")}`;
153
+ if (orderby.length && count !== "only") sql += ` ORDER BY ${orderby.join(", ")}`;
154
+ if (offset) sql += ` OFFSET $${params.push(offset)}`;
155
+ if (limit) sql += ` LIMIT $${params.push(limit)}`;
156
+ return [sql, params];
157
+ }
158
+ query(options, extra) {
159
+ return this.#query(false, options, extra);
160
+ }
161
+ async find(options, extra) {
162
+ const [sql, params] = this.#query(false, { ...options, offset: 0, limit: 1 }, extra);
163
+ const result = await this.#persister.query(sql, params);
164
+ if (result.rows[0]) return JSON.parse(result.rows[0].result, reviver);
165
+ return void 0;
166
+ }
167
+ async search(options, extra) {
168
+ const [sql, params] = this.#query(true, options, extra);
169
+ const result = await this.#persister.query(sql, params).catch((error) => {
170
+ throw new Error(`Error executing search query: ${error.message}`, { cause: { sql, params, error } });
171
+ });
172
+ if (result.rows.length === 0 && (options.offset || 0) > 0) {
173
+ const [sql2, params2] = this.#query("only", { ...options, offset: 0, limit: void 0 }, extra);
174
+ const result2 = await this.#persister.query(sql2, params2);
175
+ assert(result2.rows[0], "Expected total row in count query");
176
+ const total2 = Number(result2.rows[0].total);
177
+ return { total: total2, rows: [] };
178
+ }
179
+ const rows = result.rows.map((row) => JSON.parse(row.result, reviver));
180
+ const total = Number(result.rows[0]?.total) || 0;
181
+ return { total, rows };
182
+ }
183
+ };
184
+ var Search = SearchImpl;
185
+ export {
186
+ Search,
187
+ reviver
188
+ };
189
+ //# sourceMappingURL=search.mjs.map
@@ -0,0 +1,6 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/search.ts"],
4
+ "mappings": "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",
5
+ "names": ["evalue", "sql", "params", "result", "total"]
6
+ }
package/dist/utils.cjs ADDED
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // utils.ts
21
+ var utils_exports = {};
22
+ __export(utils_exports, {
23
+ assert: () => assert,
24
+ assertArray: () => assertArray,
25
+ assertObject: () => assertObject,
26
+ encodeSchemaAndName: () => encodeSchemaAndName
27
+ });
28
+ module.exports = __toCommonJS(utils_exports);
29
+ var import_pgproxy_client = require("@juit/pgproxy-client");
30
+ function assert(assertion, message) {
31
+ if (!assertion) throw new Error(message);
32
+ }
33
+ function assertArray(value, message) {
34
+ assert(Array.isArray(value), message);
35
+ }
36
+ function assertObject(value, message) {
37
+ assert(value && typeof value === "object", message);
38
+ }
39
+ function encodeSchemaAndName(name) {
40
+ const [schemaOrTable, maybeTable, ...extra] = name.split(".");
41
+ assert(extra.length === 0, `Invalid table name "${name}"`);
42
+ const [schema, table] = maybeTable ? [schemaOrTable, maybeTable] : ["public", schemaOrTable];
43
+ assert(table, `Invalid table name "${name}"`);
44
+ return `${(0, import_pgproxy_client.escape)(schema || "public")}.${(0, import_pgproxy_client.escape)(table)}`;
45
+ }
46
+ // Annotate the CommonJS export names for ESM import in node:
47
+ 0 && (module.exports = {
48
+ assert,
49
+ assertArray,
50
+ assertObject,
51
+ encodeSchemaAndName
52
+ });
53
+ //# sourceMappingURL=utils.cjs.map
@@ -0,0 +1,6 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/utils.ts"],
4
+ "mappings": ";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,4BAAuB;AAMhB,SAAS,OAAO,WAAgB,SAAoC;AACzE,MAAI,CAAE,UAAW,OAAM,IAAI,MAAM,OAAO;AAC1C;AAEO,SAAS,YAAY,OAAY,SAAyC;AAC/E,SAAO,MAAM,QAAQ,KAAK,GAAG,OAAO;AACtC;AAEO,SAAS,aAAa,OAAY,SAA0C;AACjF,SAAO,SAAU,OAAO,UAAU,UAAW,OAAO;AACtD;AAMO,SAAS,oBAAoB,MAAsB;AACxD,QAAM,CAAE,eAAe,YAAY,GAAG,KAAM,IAAI,KAAK,MAAM,GAAG;AAC9D,SAAO,MAAM,WAAW,GAAG,uBAAuB,IAAI,GAAG;AAEzD,QAAM,CAAE,QAAQ,KAAM,IAAI,aACxB,CAAE,eAAe,UAAW,IAC5B,CAAE,UAAU,aAAc;AAC5B,SAAO,OAAO,uBAAuB,IAAI,GAAG;AAE5C,SAAO,OAAG,8BAAO,UAAU,QAAQ,CAAC,QAAI,8BAAO,KAAK,CAAC;AACvD;",
5
+ "names": []
6
+ }
@@ -0,0 +1,4 @@
1
+ export declare function assert(assertion: any, message: string): asserts assertion;
2
+ export declare function assertArray(value: any, message: string): asserts value is any[];
3
+ export declare function assertObject(value: any, message: string): asserts value is object;
4
+ export declare function encodeSchemaAndName(name: string): string;
package/dist/utils.mjs ADDED
@@ -0,0 +1,25 @@
1
+ // utils.ts
2
+ import { escape } from "@juit/pgproxy-client";
3
+ function assert(assertion, message) {
4
+ if (!assertion) throw new Error(message);
5
+ }
6
+ function assertArray(value, message) {
7
+ assert(Array.isArray(value), message);
8
+ }
9
+ function assertObject(value, message) {
10
+ assert(value && typeof value === "object", message);
11
+ }
12
+ function encodeSchemaAndName(name) {
13
+ const [schemaOrTable, maybeTable, ...extra] = name.split(".");
14
+ assert(extra.length === 0, `Invalid table name "${name}"`);
15
+ const [schema, table] = maybeTable ? [schemaOrTable, maybeTable] : ["public", schemaOrTable];
16
+ assert(table, `Invalid table name "${name}"`);
17
+ return `${escape(schema || "public")}.${escape(table)}`;
18
+ }
19
+ export {
20
+ assert,
21
+ assertArray,
22
+ assertObject,
23
+ encodeSchemaAndName
24
+ };
25
+ //# sourceMappingURL=utils.mjs.map
@@ -0,0 +1,6 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/utils.ts"],
4
+ "mappings": ";AAAA,SAAS,cAAc;AAMhB,SAAS,OAAO,WAAgB,SAAoC;AACzE,MAAI,CAAE,UAAW,OAAM,IAAI,MAAM,OAAO;AAC1C;AAEO,SAAS,YAAY,OAAY,SAAyC;AAC/E,SAAO,MAAM,QAAQ,KAAK,GAAG,OAAO;AACtC;AAEO,SAAS,aAAa,OAAY,SAA0C;AACjF,SAAO,SAAU,OAAO,UAAU,UAAW,OAAO;AACtD;AAMO,SAAS,oBAAoB,MAAsB;AACxD,QAAM,CAAE,eAAe,YAAY,GAAG,KAAM,IAAI,KAAK,MAAM,GAAG;AAC9D,SAAO,MAAM,WAAW,GAAG,uBAAuB,IAAI,GAAG;AAEzD,QAAM,CAAE,QAAQ,KAAM,IAAI,aACxB,CAAE,eAAe,UAAW,IAC5B,CAAE,UAAU,aAAc;AAC5B,SAAO,OAAO,uBAAuB,IAAI,GAAG;AAE5C,SAAO,GAAG,OAAO,UAAU,QAAQ,CAAC,IAAI,OAAO,KAAK,CAAC;AACvD;",
5
+ "names": []
6
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juit/pgproxy-persister",
3
- "version": "1.3.7",
3
+ "version": "1.4.0",
4
4
  "main": "./dist/index.cjs",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",
@@ -53,7 +53,7 @@
53
53
  "src/"
54
54
  ],
55
55
  "dependencies": {
56
- "@juit/pgproxy-client": "1.3.7",
57
- "@juit/pgproxy-types": "1.3.7"
56
+ "@juit/pgproxy-client": "1.4.0",
57
+ "@juit/pgproxy-types": "1.4.0"
58
58
  }
59
59
  }
package/src/index.ts CHANGED
@@ -2,3 +2,4 @@
2
2
  export { escape, SQL } from '@juit/pgproxy-client'
3
3
  export * from './model'
4
4
  export * from './persister'
5
+ export * from './search'