@typed-sql/postgres 1.0.0-beta.2 → 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +78 -0
- package/README.md +31 -64
- package/dist/packages/postgres/src/pg.d.ts +12 -3
- package/dist/packages/postgres/src/pg.d.ts.map +1 -1
- package/dist/packages/postgres/src/pg.js +114 -14
- package/dist/packages/postgres/src/pg.js.map +1 -1
- package/dist/packages/postgres/src/prepared.d.ts +20 -0
- package/dist/packages/postgres/src/prepared.d.ts.map +1 -0
- package/dist/packages/postgres/src/prepared.js +47 -0
- package/dist/packages/postgres/src/prepared.js.map +1 -0
- package/dist/packages/postgres/src/runtime.d.ts +21 -3
- package/dist/packages/postgres/src/runtime.d.ts.map +1 -1
- package/dist/packages/postgres/src/runtime.js +509 -20
- package/dist/packages/postgres/src/runtime.js.map +1 -1
- package/dist/packages/postgres/src/stream.d.ts +34 -0
- package/dist/packages/postgres/src/stream.d.ts.map +1 -0
- package/dist/packages/postgres/src/stream.js +124 -0
- package/dist/packages/postgres/src/stream.js.map +1 -0
- package/package.json +4 -4
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { QueryStream } from "@typed-sql/core";
|
|
2
|
+
export interface PostgresCursorLike {
|
|
3
|
+
read(rowCount: number): Promise<readonly Record<string, unknown>[]>;
|
|
4
|
+
close(): Promise<void>;
|
|
5
|
+
}
|
|
6
|
+
export interface PostgresCursorLease {
|
|
7
|
+
readonly cursor: PostgresCursorLike;
|
|
8
|
+
release?(cleanupError?: unknown): void | Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
export interface PostgresQueryStreamOptions {
|
|
11
|
+
readonly batchSize: number;
|
|
12
|
+
readonly start: () => Promise<PostgresCursorLease>;
|
|
13
|
+
readonly onError?: (error: unknown) => void;
|
|
14
|
+
readonly onStart?: () => void;
|
|
15
|
+
readonly onClose?: () => void;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* A demand-driven row iterator over a cursor lease.
|
|
19
|
+
*
|
|
20
|
+
* Operations are serialized because native PostgreSQL cursors cannot safely process overlapping
|
|
21
|
+
* reads. Cleanup always attempts both cursor close and lease release, while keeping the first
|
|
22
|
+
* operation or cleanup error as the observable failure.
|
|
23
|
+
*/
|
|
24
|
+
export declare class PostgresQueryStream<Row> implements QueryStream<Row> {
|
|
25
|
+
#private;
|
|
26
|
+
constructor(options: PostgresQueryStreamOptions);
|
|
27
|
+
[Symbol.asyncIterator](): this;
|
|
28
|
+
next(): Promise<IteratorResult<Row, undefined>>;
|
|
29
|
+
return(): Promise<IteratorResult<Row, undefined>>;
|
|
30
|
+
close(): Promise<void>;
|
|
31
|
+
[Symbol.asyncDispose](): Promise<void>;
|
|
32
|
+
}
|
|
33
|
+
export declare function validatePostgresStreamBatchSize(batchSize: number | undefined): number;
|
|
34
|
+
//# sourceMappingURL=stream.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.d.ts","sourceRoot":"","sources":["../../../../src/stream.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAEnD,MAAM,WAAW,kBAAkB;IACjC,IAAI,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,CAAC,CAAC;IACpE,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IAClC,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC,OAAO,CAAC,CAAC,YAAY,CAAC,EAAE,OAAO,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxD;AAED,MAAM,WAAW,0BAA0B;IACzC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,OAAO,CAAC,mBAAmB,CAAC,CAAC;IACnD,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAC5C,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;IAC9B,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CAC/B;AAMD;;;;;;GAMG;AACH,qBAAa,mBAAmB,CAAC,GAAG,CAAE,YAAW,WAAW,CAAC,GAAG,CAAC;;IAY/D,YAAY,OAAO,EAAE,0BAA0B,EAM9C;IAED,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,IAAI,CAE7B;IAED,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAuB9C;IAED,MAAM,IAAI,OAAO,CAAC,cAAc,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAKhD;IAED,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAErB;IAEK,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAE3C;CA8CF;AAED,wBAAgB,+BAA+B,CAAC,SAAS,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,CAMrF"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
function done() {
|
|
2
|
+
return { done: true, value: undefined };
|
|
3
|
+
}
|
|
4
|
+
/**
|
|
5
|
+
* A demand-driven row iterator over a cursor lease.
|
|
6
|
+
*
|
|
7
|
+
* Operations are serialized because native PostgreSQL cursors cannot safely process overlapping
|
|
8
|
+
* reads. Cleanup always attempts both cursor close and lease release, while keeping the first
|
|
9
|
+
* operation or cleanup error as the observable failure.
|
|
10
|
+
*/
|
|
11
|
+
export class PostgresQueryStream {
|
|
12
|
+
#batchSize;
|
|
13
|
+
#start;
|
|
14
|
+
#onClose;
|
|
15
|
+
#onError;
|
|
16
|
+
#onStart;
|
|
17
|
+
#buffer = [];
|
|
18
|
+
#bufferIndex = 0;
|
|
19
|
+
#lease;
|
|
20
|
+
#operation = Promise.resolve();
|
|
21
|
+
#terminal = false;
|
|
22
|
+
constructor(options) {
|
|
23
|
+
this.#batchSize = options.batchSize;
|
|
24
|
+
this.#start = options.start;
|
|
25
|
+
this.#onStart = options.onStart;
|
|
26
|
+
this.#onClose = options.onClose;
|
|
27
|
+
this.#onError = options.onError;
|
|
28
|
+
}
|
|
29
|
+
[Symbol.asyncIterator]() {
|
|
30
|
+
return this;
|
|
31
|
+
}
|
|
32
|
+
next() {
|
|
33
|
+
return this.#enqueue(async () => {
|
|
34
|
+
if (this.#terminal)
|
|
35
|
+
return done();
|
|
36
|
+
if (this.#bufferIndex < this.#buffer.length) {
|
|
37
|
+
return { done: false, value: this.#buffer[this.#bufferIndex++] };
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
if (this.#lease === undefined)
|
|
41
|
+
this.#onStart?.();
|
|
42
|
+
this.#lease ??= await this.#start();
|
|
43
|
+
const rows = await this.#lease.cursor.read(this.#batchSize);
|
|
44
|
+
if (rows.length === 0) {
|
|
45
|
+
await this.#terminate();
|
|
46
|
+
return done();
|
|
47
|
+
}
|
|
48
|
+
this.#buffer = rows;
|
|
49
|
+
this.#bufferIndex = 1;
|
|
50
|
+
return { done: false, value: this.#buffer[0] };
|
|
51
|
+
}
|
|
52
|
+
catch (error) {
|
|
53
|
+
await this.#terminate(error);
|
|
54
|
+
throw error;
|
|
55
|
+
}
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
return() {
|
|
59
|
+
return this.#enqueue(async () => {
|
|
60
|
+
await this.#terminate();
|
|
61
|
+
return done();
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
close() {
|
|
65
|
+
return this.#enqueue(() => this.#terminate());
|
|
66
|
+
}
|
|
67
|
+
async [Symbol.asyncDispose]() {
|
|
68
|
+
await this.close();
|
|
69
|
+
}
|
|
70
|
+
#enqueue(operation) {
|
|
71
|
+
const result = this.#operation.then(operation);
|
|
72
|
+
this.#operation = result.then(() => undefined, () => undefined);
|
|
73
|
+
return result;
|
|
74
|
+
}
|
|
75
|
+
async #terminate(primaryError) {
|
|
76
|
+
if (this.#terminal) {
|
|
77
|
+
if (primaryError !== undefined)
|
|
78
|
+
throw primaryError;
|
|
79
|
+
return;
|
|
80
|
+
}
|
|
81
|
+
this.#terminal = true;
|
|
82
|
+
const hadLease = this.#lease !== undefined;
|
|
83
|
+
this.#buffer = [];
|
|
84
|
+
this.#bufferIndex = 0;
|
|
85
|
+
let cleanupError;
|
|
86
|
+
try {
|
|
87
|
+
if (this.#lease !== undefined)
|
|
88
|
+
await this.#lease.cursor.close();
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
cleanupError = error;
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
await this.#lease?.release?.(primaryError !== undefined ? primaryError : cleanupError);
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
cleanupError ??= error;
|
|
98
|
+
}
|
|
99
|
+
finally {
|
|
100
|
+
this.#onClose?.();
|
|
101
|
+
}
|
|
102
|
+
const terminalError = primaryError ?? cleanupError;
|
|
103
|
+
if (hadLease && terminalError !== undefined) {
|
|
104
|
+
try {
|
|
105
|
+
this.#onError?.(terminalError);
|
|
106
|
+
}
|
|
107
|
+
catch {
|
|
108
|
+
/* Lifecycle observers cannot replace the stream's primary error. */
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (primaryError !== undefined)
|
|
112
|
+
throw primaryError;
|
|
113
|
+
if (cleanupError !== undefined)
|
|
114
|
+
throw cleanupError;
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
export function validatePostgresStreamBatchSize(batchSize) {
|
|
118
|
+
const resolved = batchSize ?? 100;
|
|
119
|
+
if (!Number.isSafeInteger(resolved) || resolved <= 0) {
|
|
120
|
+
throw new RangeError("PostgreSQL stream batchSize must be a positive safe integer");
|
|
121
|
+
}
|
|
122
|
+
return resolved;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=stream.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"stream.js","sourceRoot":"","sources":["../../../../src/stream.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@typed-sql/postgres",
|
|
3
|
-
"version": "1.0.0
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"description": "PostgreSQL grammar, schema introspection, type resolution, and driver-neutral runtime codecs for typed-sql.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Lojhan",
|
|
@@ -39,9 +39,9 @@
|
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"@types/pg": "8.23.1",
|
|
42
|
-
"@typed-sql/ast": "1.0.0
|
|
43
|
-
"@typed-sql/
|
|
44
|
-
"@typed-sql/
|
|
42
|
+
"@typed-sql/ast": "1.0.0",
|
|
43
|
+
"@typed-sql/core": "1.0.0",
|
|
44
|
+
"@typed-sql/schema": "1.0.0"
|
|
45
45
|
},
|
|
46
46
|
"scripts": {
|
|
47
47
|
"test": "poku test --reporter=compact --enforce",
|