@lossless.org/client 0.1.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/.smartconfig.json +37 -0
- package/dist_ts/00_commitinfo_data.d.ts +8 -0
- package/dist_ts/00_commitinfo_data.js +9 -0
- package/dist_ts/classes.losslessorgclient.d.ts +32 -0
- package/dist_ts/classes.losslessorgclient.js +103 -0
- package/dist_ts/core/classes.error.d.ts +16 -0
- package/dist_ts/core/classes.error.js +29 -0
- package/dist_ts/core/classes.operation.d.ts +17 -0
- package/dist_ts/core/classes.operation.js +70 -0
- package/dist_ts/core/interfaces.d.ts +18 -0
- package/dist_ts/core/interfaces.js +2 -0
- package/dist_ts/index.d.ts +4 -0
- package/dist_ts/index.js +3 -0
- package/dist_ts/nosqldb/classes.atomicdelete.d.ts +26 -0
- package/dist_ts/nosqldb/classes.atomicdelete.js +44 -0
- package/dist_ts/nosqldb/classes.atomicfindoneandupdate.d.ts +27 -0
- package/dist_ts/nosqldb/classes.atomicfindoneandupdate.js +86 -0
- package/dist_ts/nosqldb/classes.atomicupdate.d.ts +26 -0
- package/dist_ts/nosqldb/classes.atomicupdate.js +55 -0
- package/dist_ts/nosqldb/classes.bootstraprecord.d.ts +14 -0
- package/dist_ts/nosqldb/classes.bootstraprecord.js +80 -0
- package/dist_ts/nosqldb/classes.bsonassertion.d.ts +2 -0
- package/dist_ts/nosqldb/classes.bsonassertion.js +29 -0
- package/dist_ts/nosqldb/classes.bsonobjectid.d.ts +2 -0
- package/dist_ts/nosqldb/classes.bsonobjectid.js +50 -0
- package/dist_ts/nosqldb/classes.bsonsnapshot.d.ts +3 -0
- package/dist_ts/nosqldb/classes.bsonsnapshot.js +126 -0
- package/dist_ts/nosqldb/classes.cached-document.d.ts +27 -0
- package/dist_ts/nosqldb/classes.cached-document.js +112 -0
- package/dist_ts/nosqldb/classes.collection.d.ts +302 -0
- package/dist_ts/nosqldb/classes.collection.js +1568 -0
- package/dist_ts/nosqldb/classes.collectionfactory.d.ts +30 -0
- package/dist_ts/nosqldb/classes.collectionfactory.js +65 -0
- package/dist_ts/nosqldb/classes.collectionlifecycle.d.ts +4 -0
- package/dist_ts/nosqldb/classes.collectionlifecycle.js +15 -0
- package/dist_ts/nosqldb/classes.collectionpreparation.d.ts +34 -0
- package/dist_ts/nosqldb/classes.collectionpreparation.js +134 -0
- package/dist_ts/nosqldb/classes.collectiontopology.d.ts +47 -0
- package/dist_ts/nosqldb/classes.collectiontopology.js +388 -0
- package/dist_ts/nosqldb/classes.connection.d.ts +18 -0
- package/dist_ts/nosqldb/classes.connection.js +23 -0
- package/dist_ts/nosqldb/classes.convenience.d.ts +1 -0
- package/dist_ts/nosqldb/classes.convenience.js +5 -0
- package/dist_ts/nosqldb/classes.cursor.d.ts +15 -0
- package/dist_ts/nosqldb/classes.cursor.js +82 -0
- package/dist_ts/nosqldb/classes.cursoroperation.d.ts +7 -0
- package/dist_ts/nosqldb/classes.cursoroperation.js +36 -0
- package/dist_ts/nosqldb/classes.db.d.ts +98 -0
- package/dist_ts/nosqldb/classes.db.js +434 -0
- package/dist_ts/nosqldb/classes.distributedcoordinator.d.ts +52 -0
- package/dist_ts/nosqldb/classes.distributedcoordinator.js +314 -0
- package/dist_ts/nosqldb/classes.doc.d.ts +722 -0
- package/dist_ts/nosqldb/classes.doc.js +2976 -0
- package/dist_ts/nosqldb/classes.easystore.d.ts +42 -0
- package/dist_ts/nosqldb/classes.easystore.js +199 -0
- package/dist_ts/nosqldb/classes.exactpersistence.d.ts +141 -0
- package/dist_ts/nosqldb/classes.exactpersistence.js +1110 -0
- package/dist_ts/nosqldb/classes.lucene.adapter.d.ts +173 -0
- package/dist_ts/nosqldb/classes.lucene.adapter.js +623 -0
- package/dist_ts/nosqldb/classes.mongoadministration.d.ts +73 -0
- package/dist_ts/nosqldb/classes.mongoadministration.js +497 -0
- package/dist_ts/nosqldb/classes.namespaceinspection.d.ts +42 -0
- package/dist_ts/nosqldb/classes.namespaceinspection.js +138 -0
- package/dist_ts/nosqldb/classes.operationbudget.d.ts +22 -0
- package/dist_ts/nosqldb/classes.operationbudget.js +65 -0
- package/dist_ts/nosqldb/classes.ordinarypersistence.d.ts +18 -0
- package/dist_ts/nosqldb/classes.ordinarypersistence.js +71 -0
- package/dist_ts/nosqldb/classes.persistence.d.ts +14 -0
- package/dist_ts/nosqldb/classes.persistence.js +34 -0
- package/dist_ts/nosqldb/classes.session.d.ts +28 -0
- package/dist_ts/nosqldb/classes.session.js +246 -0
- package/dist_ts/nosqldb/classes.storedinspection.d.ts +44 -0
- package/dist_ts/nosqldb/classes.storedinspection.js +100 -0
- package/dist_ts/nosqldb/classes.testdatabase.d.ts +56 -0
- package/dist_ts/nosqldb/classes.testdatabase.js +250 -0
- package/dist_ts/nosqldb/classes.watcher.d.ts +37 -0
- package/dist_ts/nosqldb/classes.watcher.js +98 -0
- package/dist_ts/nosqldb/index.d.ts +27 -0
- package/dist_ts/nosqldb/index.js +18 -0
- package/dist_ts/nosqldb/logging.d.ts +2 -0
- package/dist_ts/nosqldb/logging.js +3 -0
- package/dist_ts/nosqldb/plugins.d.ts +17 -0
- package/dist_ts/nosqldb/plugins.js +20 -0
- package/dist_ts/nosqldb/shim.d.ts +1 -0
- package/dist_ts/nosqldb/shim.js +8 -0
- package/dist_ts/nosqldb/testsupport.d.ts +3 -0
- package/dist_ts/nosqldb/testsupport.js +3 -0
- package/dist_ts/objectstorage/classes.bucket.d.ts +227 -0
- package/dist_ts/objectstorage/classes.bucket.js +939 -0
- package/dist_ts/objectstorage/classes.connection.d.ts +21 -0
- package/dist_ts/objectstorage/classes.connection.js +27 -0
- package/dist_ts/objectstorage/classes.directory.d.ts +124 -0
- package/dist_ts/objectstorage/classes.directory.js +335 -0
- package/dist_ts/objectstorage/classes.exactpathpurgeerror.d.ts +5 -0
- package/dist_ts/objectstorage/classes.exactpathpurgeerror.js +18 -0
- package/dist_ts/objectstorage/classes.exactuploaderror.d.ts +5 -0
- package/dist_ts/objectstorage/classes.exactuploaderror.js +19 -0
- package/dist_ts/objectstorage/classes.file.d.ts +91 -0
- package/dist_ts/objectstorage/classes.file.js +255 -0
- package/dist_ts/objectstorage/classes.listcursor.d.ts +41 -0
- package/dist_ts/objectstorage/classes.listcursor.js +67 -0
- package/dist_ts/objectstorage/classes.metadata.d.ts +57 -0
- package/dist_ts/objectstorage/classes.metadata.js +113 -0
- package/dist_ts/objectstorage/classes.smartbucket.d.ts +57 -0
- package/dist_ts/objectstorage/classes.smartbucket.js +357 -0
- package/dist_ts/objectstorage/classes.trash.d.ts +11 -0
- package/dist_ts/objectstorage/classes.trash.js +22 -0
- package/dist_ts/objectstorage/classes.watcher.d.ts +79 -0
- package/dist_ts/objectstorage/classes.watcher.js +249 -0
- package/dist_ts/objectstorage/helpers.d.ts +25 -0
- package/dist_ts/objectstorage/helpers.js +215 -0
- package/dist_ts/objectstorage/index.d.ts +13 -0
- package/dist_ts/objectstorage/index.js +13 -0
- package/dist_ts/objectstorage/interfaces.d.ts +276 -0
- package/dist_ts/objectstorage/interfaces.js +2 -0
- package/dist_ts/objectstorage/internal.exactpathpurge.operations.d.ts +11 -0
- package/dist_ts/objectstorage/internal.exactpathpurge.operations.js +1069 -0
- package/dist_ts/objectstorage/internal.exactupload.capability.d.ts +40 -0
- package/dist_ts/objectstorage/internal.exactupload.capability.js +382 -0
- package/dist_ts/objectstorage/internal.exactupload.operations.d.ts +11 -0
- package/dist_ts/objectstorage/internal.exactupload.operations.js +1104 -0
- package/dist_ts/objectstorage/internal.multipart.planner.d.ts +8 -0
- package/dist_ts/objectstorage/internal.multipart.planner.js +63 -0
- package/dist_ts/objectstorage/internal.multipart.stream.d.ts +17 -0
- package/dist_ts/objectstorage/internal.multipart.stream.js +440 -0
- package/dist_ts/objectstorage/internal.multipart.types.d.ts +82 -0
- package/dist_ts/objectstorage/internal.multipart.types.js +2 -0
- package/dist_ts/objectstorage/plugins.d.ts +17 -0
- package/dist_ts/objectstorage/plugins.js +23 -0
- package/dist_ts/plugins.d.ts +4 -0
- package/dist_ts/plugins.js +5 -0
- package/dist_ts/sqldb/classes.clickhouseconnection.d.ts +39 -0
- package/dist_ts/sqldb/classes.clickhouseconnection.js +225 -0
- package/dist_ts/sqldb/classes.sqlconnection.d.ts +50 -0
- package/dist_ts/sqldb/classes.sqlconnection.js +376 -0
- package/dist_ts/sqldb/classes.sqltable.d.ts +29 -0
- package/dist_ts/sqldb/classes.sqltable.js +70 -0
- package/dist_ts/sqldb/clickhouse/classes.metricwriter.d.ts +27 -0
- package/dist_ts/sqldb/clickhouse/classes.metricwriter.js +89 -0
- package/dist_ts/sqldb/clickhouse/index.d.ts +9 -0
- package/dist_ts/sqldb/clickhouse/index.js +13 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.clickhousetable.d.ts +88 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.clickhousetable.js +304 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.httpclient.d.ts +28 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.httpclient.js +46 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.querybuilder.d.ts +43 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.querybuilder.js +155 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.resultset.d.ts +13 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.resultset.js +36 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.smartclickhouse.d.ts +49 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.smartclickhouse.js +106 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.timedatatable.d.ts +51 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.classes.timedatatable.js +96 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.plugins.d.ts +5 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.plugins.js +6 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.types.d.ts +53 -0
- package/dist_ts/sqldb/clickhouse/smartclickhouse.types.js +41 -0
- package/dist_ts/sqldb/index.d.ts +6 -0
- package/dist_ts/sqldb/index.js +6 -0
- package/dist_ts/sqldb/interfaces.d.ts +53 -0
- package/dist_ts/sqldb/interfaces.js +19 -0
- package/dist_ts/sqldb/internal.sqlpool.d.ts +51 -0
- package/dist_ts/sqldb/internal.sqlpool.js +214 -0
- package/dist_ts/sqldb/plugins.clickhouse.d.ts +4 -0
- package/dist_ts/sqldb/plugins.clickhouse.js +5 -0
- package/dist_ts/sqldb/plugins.mariadb.d.ts +4 -0
- package/dist_ts/sqldb/plugins.mariadb.js +5 -0
- package/docs/source/smartbucket/license.md +19 -0
- package/docs/source/smartclickhouse/license.md +19 -0
- package/license.md +21 -0
- package/package.json +101 -0
- package/readme.md +157 -0
- package/ts/00_commitinfo_data.ts +8 -0
- package/ts/classes.losslessorgclient.ts +104 -0
- package/ts/core/classes.error.ts +31 -0
- package/ts/core/classes.operation.ts +60 -0
- package/ts/core/interfaces.ts +24 -0
- package/ts/index.ts +4 -0
- package/ts/nosqldb/classes.atomicdelete.ts +81 -0
- package/ts/nosqldb/classes.atomicfindoneandupdate.ts +152 -0
- package/ts/nosqldb/classes.atomicupdate.ts +99 -0
- package/ts/nosqldb/classes.bootstraprecord.ts +107 -0
- package/ts/nosqldb/classes.bsonassertion.ts +25 -0
- package/ts/nosqldb/classes.bsonobjectid.ts +45 -0
- package/ts/nosqldb/classes.bsonsnapshot.ts +105 -0
- package/ts/nosqldb/classes.cached-document.ts +67 -0
- package/ts/nosqldb/classes.collection.ts +2399 -0
- package/ts/nosqldb/classes.collectionfactory.ts +87 -0
- package/ts/nosqldb/classes.collectionlifecycle.ts +24 -0
- package/ts/nosqldb/classes.collectionpreparation.ts +164 -0
- package/ts/nosqldb/classes.collectiontopology.ts +645 -0
- package/ts/nosqldb/classes.connection.ts +31 -0
- package/ts/nosqldb/classes.convenience.ts +5 -0
- package/ts/nosqldb/classes.cursor.ts +88 -0
- package/ts/nosqldb/classes.cursoroperation.ts +38 -0
- package/ts/nosqldb/classes.db.ts +637 -0
- package/ts/nosqldb/classes.distributedcoordinator.ts +305 -0
- package/ts/nosqldb/classes.doc.ts +4928 -0
- package/ts/nosqldb/classes.easystore.ts +154 -0
- package/ts/nosqldb/classes.exactpersistence.ts +1974 -0
- package/ts/nosqldb/classes.lucene.adapter.ts +780 -0
- package/ts/nosqldb/classes.mongoadministration.ts +867 -0
- package/ts/nosqldb/classes.namespaceinspection.ts +199 -0
- package/ts/nosqldb/classes.operationbudget.ts +75 -0
- package/ts/nosqldb/classes.ordinarypersistence.ts +84 -0
- package/ts/nosqldb/classes.persistence.ts +62 -0
- package/ts/nosqldb/classes.session.ts +389 -0
- package/ts/nosqldb/classes.storedinspection.ts +151 -0
- package/ts/nosqldb/classes.testdatabase.ts +272 -0
- package/ts/nosqldb/classes.watcher.ts +96 -0
- package/ts/nosqldb/index.ts +51 -0
- package/ts/nosqldb/logging.ts +3 -0
- package/ts/nosqldb/plugins.ts +37 -0
- package/ts/nosqldb/shim.ts +6 -0
- package/ts/nosqldb/testsupport.ts +13 -0
- package/ts/objectstorage/classes.bucket.ts +1114 -0
- package/ts/objectstorage/classes.connection.ts +36 -0
- package/ts/objectstorage/classes.directory.ts +425 -0
- package/ts/objectstorage/classes.exactpathpurgeerror.ts +24 -0
- package/ts/objectstorage/classes.exactuploaderror.ts +25 -0
- package/ts/objectstorage/classes.file.ts +303 -0
- package/ts/objectstorage/classes.listcursor.ts +89 -0
- package/ts/objectstorage/classes.metadata.ts +134 -0
- package/ts/objectstorage/classes.smartbucket.ts +445 -0
- package/ts/objectstorage/classes.trash.ts +30 -0
- package/ts/objectstorage/classes.watcher.ts +289 -0
- package/ts/objectstorage/helpers.ts +254 -0
- package/ts/objectstorage/index.ts +13 -0
- package/ts/objectstorage/interfaces.ts +389 -0
- package/ts/objectstorage/internal.exactpathpurge.operations.ts +1936 -0
- package/ts/objectstorage/internal.exactupload.capability.ts +580 -0
- package/ts/objectstorage/internal.exactupload.operations.ts +1715 -0
- package/ts/objectstorage/internal.multipart.planner.ts +90 -0
- package/ts/objectstorage/internal.multipart.stream.ts +606 -0
- package/ts/objectstorage/internal.multipart.types.ts +106 -0
- package/ts/objectstorage/plugins.ts +35 -0
- package/ts/plugins.ts +4 -0
- package/ts/sqldb/classes.clickhouseconnection.ts +189 -0
- package/ts/sqldb/classes.sqlconnection.ts +350 -0
- package/ts/sqldb/classes.sqltable.ts +70 -0
- package/ts/sqldb/clickhouse/classes.metricwriter.ts +72 -0
- package/ts/sqldb/clickhouse/index.ts +16 -0
- package/ts/sqldb/clickhouse/smartclickhouse.classes.clickhousetable.ts +372 -0
- package/ts/sqldb/clickhouse/smartclickhouse.classes.httpclient.ts +52 -0
- package/ts/sqldb/clickhouse/smartclickhouse.classes.querybuilder.ts +120 -0
- package/ts/sqldb/clickhouse/smartclickhouse.classes.resultset.ts +44 -0
- package/ts/sqldb/clickhouse/smartclickhouse.classes.smartclickhouse.ts +123 -0
- package/ts/sqldb/clickhouse/smartclickhouse.classes.timedatatable.ts +114 -0
- package/ts/sqldb/clickhouse/smartclickhouse.plugins.ts +5 -0
- package/ts/sqldb/clickhouse/smartclickhouse.types.ts +134 -0
- package/ts/sqldb/index.ts +6 -0
- package/ts/sqldb/interfaces.ts +61 -0
- package/ts/sqldb/internal.sqlpool.ts +179 -0
- package/ts/sqldb/plugins.clickhouse.ts +4 -0
- package/ts/sqldb/plugins.mariadb.ts +4 -0
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
export interface IMultipartPlanningOptions {
|
|
2
|
+
objectSize: number;
|
|
3
|
+
requestedPartSize?: number;
|
|
4
|
+
requestedConcurrency?: number;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
interface IMultipartUploadPlanBase {
|
|
8
|
+
objectSize: number;
|
|
9
|
+
concurrency: number;
|
|
10
|
+
maximumBufferedBytes: number;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface IMultipartZeroUploadPlan extends IMultipartUploadPlanBase {
|
|
14
|
+
classification: 'zero';
|
|
15
|
+
objectSize: 0;
|
|
16
|
+
partSize: 0;
|
|
17
|
+
partCount: 0;
|
|
18
|
+
maximumBufferedBytes: 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface IMultipartDataUploadPlan extends IMultipartUploadPlanBase {
|
|
22
|
+
classification: 'multipart';
|
|
23
|
+
partSize: number;
|
|
24
|
+
partCount: number;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export type TMultipartUploadPlan = IMultipartZeroUploadPlan | IMultipartDataUploadPlan;
|
|
28
|
+
|
|
29
|
+
export interface IMultipartStreamPart {
|
|
30
|
+
partNumber: number;
|
|
31
|
+
byteOffset: number;
|
|
32
|
+
isLastPart: boolean;
|
|
33
|
+
/**
|
|
34
|
+
* An exact, exclusively owned copy. The consumer never mutates or reuses it.
|
|
35
|
+
*/
|
|
36
|
+
data: Uint8Array;
|
|
37
|
+
signal: AbortSignal;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export interface IConsumeExactMultipartStreamOptions {
|
|
41
|
+
readableStream: ReadableStream<Uint8Array>;
|
|
42
|
+
plan: TMultipartUploadPlan;
|
|
43
|
+
onPart: (part: IMultipartStreamPart) => Promise<void>;
|
|
44
|
+
signal?: AbortSignal;
|
|
45
|
+
/** Internal failure-teardown bound (default and maximum: 30000ms). */
|
|
46
|
+
failureSettlementTimeoutMs?: number;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
export interface IMultipartStreamConsumptionResult {
|
|
50
|
+
completionAuthorized: true;
|
|
51
|
+
bytesConsumed: number;
|
|
52
|
+
partsConsumed: number;
|
|
53
|
+
peakBufferedBytes: number;
|
|
54
|
+
maximumBufferedBytes: number;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export type TMultipartStreamFailureKind =
|
|
58
|
+
| 'aborted'
|
|
59
|
+
| 'source-read'
|
|
60
|
+
| 'source-buffer-limit'
|
|
61
|
+
| 'source-empty-chunk-limit'
|
|
62
|
+
| 'source-short'
|
|
63
|
+
| 'source-extra'
|
|
64
|
+
| 'part-callback';
|
|
65
|
+
|
|
66
|
+
export type TMultipartOwnedReaderCleanup =
|
|
67
|
+
| {
|
|
68
|
+
status: 'closed';
|
|
69
|
+
}
|
|
70
|
+
| {
|
|
71
|
+
status: 'cancelled';
|
|
72
|
+
}
|
|
73
|
+
| {
|
|
74
|
+
status: 'cancel-failed';
|
|
75
|
+
cause: unknown;
|
|
76
|
+
}
|
|
77
|
+
| {
|
|
78
|
+
status: 'cancel-detached';
|
|
79
|
+
};
|
|
80
|
+
|
|
81
|
+
export interface IMultipartOwnedCleanupState {
|
|
82
|
+
callbacks: 'settled' | 'detached';
|
|
83
|
+
reader: TMultipartOwnedReaderCleanup;
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
export type TMultipartRetryState =
|
|
87
|
+
| {
|
|
88
|
+
disposition: 'safe-to-retry';
|
|
89
|
+
requiresMultipartAbort: false;
|
|
90
|
+
}
|
|
91
|
+
| {
|
|
92
|
+
disposition: 'abort-multipart-first';
|
|
93
|
+
requiresMultipartAbort: true;
|
|
94
|
+
};
|
|
95
|
+
|
|
96
|
+
export interface IMultipartStreamFailureState {
|
|
97
|
+
completionAuthorized: false;
|
|
98
|
+
kind: TMultipartStreamFailureKind;
|
|
99
|
+
cause?: unknown;
|
|
100
|
+
expectedBytes: number;
|
|
101
|
+
observedBytes: number;
|
|
102
|
+
partCallbacksStarted: number;
|
|
103
|
+
completedPartNumbers: number[];
|
|
104
|
+
cleanup: IMultipartOwnedCleanupState;
|
|
105
|
+
retry: TMultipartRetryState;
|
|
106
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// plugins.ts
|
|
2
|
+
|
|
3
|
+
// node native
|
|
4
|
+
import * as crypto from 'node:crypto';
|
|
5
|
+
import * as path from 'node:path';
|
|
6
|
+
import * as stream from 'node:stream';
|
|
7
|
+
|
|
8
|
+
export { crypto, path, stream };
|
|
9
|
+
|
|
10
|
+
// @push.rocks scope
|
|
11
|
+
import * as smartmime from '@push.rocks/smartmime';
|
|
12
|
+
import * as smartpath from '@push.rocks/smartpath';
|
|
13
|
+
import * as smartpromise from '@push.rocks/smartpromise';
|
|
14
|
+
import * as smartrx from '@push.rocks/smartrx';
|
|
15
|
+
import * as smartstream from '@push.rocks/smartstream';
|
|
16
|
+
import * as smartstring from '@push.rocks/smartstring';
|
|
17
|
+
import * as smartunique from '@push.rocks/smartunique';
|
|
18
|
+
|
|
19
|
+
export { smartmime, smartpath, smartpromise, smartrx, smartstream, smartstring, smartunique };
|
|
20
|
+
|
|
21
|
+
// @tsclass
|
|
22
|
+
import * as tsclass from '@tsclass/tsclass';
|
|
23
|
+
|
|
24
|
+
export {
|
|
25
|
+
tsclass,
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// third party scope
|
|
29
|
+
import * as s3 from '@aws-sdk/client-s3';
|
|
30
|
+
import { Minimatch } from 'minimatch';
|
|
31
|
+
|
|
32
|
+
export {
|
|
33
|
+
s3,
|
|
34
|
+
Minimatch,
|
|
35
|
+
}
|
package/ts/plugins.ts
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
export const loadNoSql = () => import('./nosqldb/classes.connection.js');
|
|
2
|
+
export const loadObjects = () => import('./objectstorage/classes.connection.js');
|
|
3
|
+
export const loadSql = () => import('./sqldb/classes.sqlconnection.js');
|
|
4
|
+
export const loadClickHouse = () => import('./sqldb/classes.clickhouseconnection.js');
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import * as plugins from './plugins.clickhouse.js';
|
|
2
|
+
import { Operation } from '../core/classes.operation.js';
|
|
3
|
+
import { LosslessClientError, backendError } from '../core/classes.error.js';
|
|
4
|
+
import type { ICapabilities, IOperationOptions, IReadiness } from '../core/interfaces.js';
|
|
5
|
+
import { quoteClickHouseIdentifier as quoteIdentifier, resultLimits, valueBytes } from './interfaces.js';
|
|
6
|
+
import type { IClickHouseConnectionOptions, IClickHouseStatement, IInsertOptions, IQueryOptions } from './interfaces.js';
|
|
7
|
+
import { SmartClickHouseDb } from './clickhouse/smartclickhouse.classes.smartclickhouse.js';
|
|
8
|
+
|
|
9
|
+
/** ClickHouse HTTP connection. The server executes filtering, projection and aggregation. */
|
|
10
|
+
export class ClickHouseConnection {
|
|
11
|
+
public readonly backend = 'clickhouse' as const;
|
|
12
|
+
public readonly metrics: SmartClickHouseDb;
|
|
13
|
+
public readonly capabilities: ICapabilities = Object.freeze({ backend: 'clickhouse',
|
|
14
|
+
transactions: 'unsupported', changeStreams: 'unsupported', objectMetrics: 'unsupported', diskResidentScans: 'available' });
|
|
15
|
+
private client?: plugins.clickhouse.ClickHouseClient;
|
|
16
|
+
private readonly operations = new Map<Operation, () => void>();
|
|
17
|
+
private readonly tasks = new Set<Promise<unknown>>();
|
|
18
|
+
private closed = false;
|
|
19
|
+
private closing?: Promise<void>;
|
|
20
|
+
private connecting?: Promise<void>;
|
|
21
|
+
private readonly writerCleanup = new plugins.asyncHooks.AsyncLocalStorage<boolean>();
|
|
22
|
+
|
|
23
|
+
constructor(public readonly options: IClickHouseConnectionOptions) {
|
|
24
|
+
const url = new URL(options.url);
|
|
25
|
+
if (!['http:', 'https:'].includes(url.protocol) || !options.database || url.username || url.password ||
|
|
26
|
+
url.search || url.hash || url.pathname !== '/') {
|
|
27
|
+
throw new LosslessClientError('invalid_argument', 'ClickHouse requires an HTTP(S) URL, separate credentials and a database.');
|
|
28
|
+
}
|
|
29
|
+
const limit = options.connectionLimit ?? 10;
|
|
30
|
+
if (!Number.isSafeInteger(limit) || limit < 1 || limit > 1024) {
|
|
31
|
+
throw new LosslessClientError('invalid_argument', 'connectionLimit must be between 1 and 1024.');
|
|
32
|
+
}
|
|
33
|
+
const budget = new Operation({ timeoutMs: options.timeoutMs }); budget.dispose();
|
|
34
|
+
this.metrics = new SmartClickHouseDb(options, this);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
public connect(options: IOperationOptions = {}): Promise<void> {
|
|
38
|
+
if (this.closed || this.closing) return Promise.reject(new LosslessClientError('closed', 'ClickHouse connection is closed.'));
|
|
39
|
+
if (this.connecting) return this.connecting;
|
|
40
|
+
if (this.client) return Promise.resolve();
|
|
41
|
+
this.client = plugins.clickhouse.createClient({ url: this.options.url,
|
|
42
|
+
database: this.options.database, username: this.options.username, password: this.options.password,
|
|
43
|
+
log: { level: plugins.clickhouse.ClickHouseLogLevel.OFF },
|
|
44
|
+
max_open_connections: this.options.connectionLimit ?? 10, request_timeout: this.options.timeoutMs ?? 30_000 });
|
|
45
|
+
this.connecting = (async () => {
|
|
46
|
+
try { await this.query({ sql: 'SELECT 1 AS ready' }, { ...options, maxRows: 1 }); }
|
|
47
|
+
catch (error) { const client = this.client; this.client = undefined; await client?.close(); throw error; }
|
|
48
|
+
finally { this.connecting = undefined; }
|
|
49
|
+
})();
|
|
50
|
+
return this.connecting;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
private begin(options: IOperationOptions): { client: plugins.clickhouse.ClickHouseClient; operation: Operation } {
|
|
54
|
+
if (!this.client || this.closed || (this.closing && !this.writerCleanup.getStore())) {
|
|
55
|
+
throw new LosslessClientError(this.closed || this.closing ? 'closed' : 'not_connected', 'ClickHouse connection is not open.');
|
|
56
|
+
}
|
|
57
|
+
const operation = new Operation(options, this.options.timeoutMs);
|
|
58
|
+
this.operations.set(operation, () => {});
|
|
59
|
+
try { operation.check(); }
|
|
60
|
+
catch (error) { this.end(operation); throw error; }
|
|
61
|
+
return { client: this.client, operation };
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
private end(operation: Operation): void {
|
|
65
|
+
operation.dispose();
|
|
66
|
+
this.operations.delete(operation);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
private track<Result>(task: Promise<Result>): Promise<Result> {
|
|
70
|
+
this.tasks.add(task);
|
|
71
|
+
void task.finally(() => this.tasks.delete(task)).catch(() => {});
|
|
72
|
+
return task;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
public async ready(options: IOperationOptions = {}): Promise<IReadiness> {
|
|
76
|
+
try { await this.query({ sql: 'SELECT 1 AS ready' }, { ...options, maxRows: 1 }); return { ready: true }; }
|
|
77
|
+
catch (error) { return { ready: false, reason: error instanceof LosslessClientError ? error.code : 'unavailable' }; }
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public execute(statement: IClickHouseStatement, options: IOperationOptions = {}): Promise<{ queryId: string; completion: 'acknowledged' }> {
|
|
81
|
+
this.validate(statement);
|
|
82
|
+
return this.track((async () => {
|
|
83
|
+
const { client, operation } = this.begin(options);
|
|
84
|
+
try {
|
|
85
|
+
const result = await client.command({ query: statement.sql, query_params: statement.values,
|
|
86
|
+
abort_signal: operation.signal, clickhouse_settings: { wait_end_of_query: 1, mutations_sync: '2' } });
|
|
87
|
+
return { queryId: result.query_id, completion: 'acknowledged' as const };
|
|
88
|
+
} catch (error) {
|
|
89
|
+
// HTTP transport loss does not establish whether the server committed a mutation.
|
|
90
|
+
if (operation.signal.aborted || !(error instanceof Error && 'code' in error && /^\d+$/.test(String(error.code)))) {
|
|
91
|
+
throw new LosslessClientError('ambiguous_write', 'ClickHouse mutation outcome is unknown.', { cause: error });
|
|
92
|
+
}
|
|
93
|
+
throw backendError(error);
|
|
94
|
+
} finally { this.end(operation); }
|
|
95
|
+
})());
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
public async *stream<Row = Record<string, unknown>>(statement: IClickHouseStatement,
|
|
99
|
+
options: IOperationOptions = {}): AsyncGenerator<Row> {
|
|
100
|
+
this.validate(statement);
|
|
101
|
+
const { client, operation } = this.begin(options);
|
|
102
|
+
let result: Awaited<ReturnType<typeof client.query<'JSONEachRow'>>> | undefined;
|
|
103
|
+
try {
|
|
104
|
+
result = await this.track(client.query({ query: statement.sql, query_params: statement.values,
|
|
105
|
+
format: 'JSONEachRow', abort_signal: operation.signal,
|
|
106
|
+
clickhouse_settings: { output_format_json_quote_64bit_integers: 1, output_format_json_quote_decimals: 1 } }));
|
|
107
|
+
const current = result;
|
|
108
|
+
this.operations.set(operation, () => current.close());
|
|
109
|
+
const stream = result.stream<Row>();
|
|
110
|
+
stream.on('error', () => {});
|
|
111
|
+
stream.once('close', () => this.end(operation));
|
|
112
|
+
for await (const batch of stream) {
|
|
113
|
+
operation.check();
|
|
114
|
+
for (const row of batch) { operation.check(); yield row.json(); }
|
|
115
|
+
}
|
|
116
|
+
operation.check();
|
|
117
|
+
} catch (error) { throw operation.signal.aborted ? operation.signal.reason : backendError(error); }
|
|
118
|
+
finally { result?.close(); this.end(operation); }
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
public async query<Row = Record<string, unknown>>(statement: IClickHouseStatement,
|
|
122
|
+
options: IQueryOptions = {}): Promise<Row[]> {
|
|
123
|
+
const limits = resultLimits(options), rows: Row[] = [];
|
|
124
|
+
let bytes = 0;
|
|
125
|
+
for await (const row of this.stream<Row>(statement, options)) {
|
|
126
|
+
bytes += valueBytes(row);
|
|
127
|
+
if (rows.length >= limits.rows || bytes > limits.bytes) {
|
|
128
|
+
throw new LosslessClientError('result_limit', 'ClickHouse result exceeded its materialization limit. Use stream().');
|
|
129
|
+
}
|
|
130
|
+
rows.push(row);
|
|
131
|
+
}
|
|
132
|
+
return rows;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
public insert(table: string, rows: AsyncIterable<Record<string, unknown>> | Iterable<Record<string, unknown>>,
|
|
136
|
+
options: IInsertOptions = {}): Promise<{ queryId: string; completion: 'acknowledged' }> {
|
|
137
|
+
return this.insertQualified(this.options.database, table, rows, options);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
public insertQualified(database: string, table: string,
|
|
141
|
+
rows: AsyncIterable<Record<string, unknown>> | Iterable<Record<string, unknown>>,
|
|
142
|
+
options: IInsertOptions = {}): Promise<{ queryId: string; completion: 'acknowledged' }> {
|
|
143
|
+
const target = `${quoteIdentifier(database)}.${quoteIdentifier(table)}`;
|
|
144
|
+
const maxBytes = options.maxBatchBytes ?? 4 * 1024 * 1024;
|
|
145
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes < 1) throw new LosslessClientError('invalid_argument', 'maxBatchBytes must be a positive integer.');
|
|
146
|
+
return this.track((async () => {
|
|
147
|
+
const { client, operation } = this.begin(options);
|
|
148
|
+
const source = plugins.stream.Readable.from((async function* () {
|
|
149
|
+
for await (const row of operation.iterate(rows)) {
|
|
150
|
+
operation.check();
|
|
151
|
+
if (valueBytes(row) > maxBytes) throw new LosslessClientError('invalid_argument', 'ClickHouse row exceeds maxBatchBytes.');
|
|
152
|
+
yield row;
|
|
153
|
+
}
|
|
154
|
+
})(), { objectMode: true, highWaterMark: 1 });
|
|
155
|
+
source.on('error', () => {});
|
|
156
|
+
this.operations.set(operation, () => source.destroy());
|
|
157
|
+
try {
|
|
158
|
+
const result = await client.insert({ table: target, values: source, format: 'JSONEachRow',
|
|
159
|
+
abort_signal: operation.signal, clickhouse_settings: { async_insert: 0, wait_end_of_query: 1 } });
|
|
160
|
+
return { queryId: result.query_id, completion: 'acknowledged' as const };
|
|
161
|
+
} catch (error) {
|
|
162
|
+
throw new LosslessClientError('ambiguous_write', 'ClickHouse insert may have stored part or all of the input.', { cause: error });
|
|
163
|
+
} finally { source.destroy(); this.end(operation); }
|
|
164
|
+
})());
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
public close(): Promise<void> {
|
|
168
|
+
return this.closing ??= (async () => {
|
|
169
|
+
let writerError: unknown;
|
|
170
|
+
try { await this.writerCleanup.run(true, () => this.metrics.closeWriters()); } catch (error) { writerError = error; }
|
|
171
|
+
this.closed = true;
|
|
172
|
+
for (const [operation, dispose] of this.operations) { operation.cancel(); dispose(); }
|
|
173
|
+
await Promise.allSettled([...this.tasks]);
|
|
174
|
+
if (this.connecting) await Promise.allSettled([this.connecting]);
|
|
175
|
+
const client = this.client;
|
|
176
|
+
this.client = undefined;
|
|
177
|
+
await client?.close();
|
|
178
|
+
for (const operation of this.operations.keys()) this.end(operation);
|
|
179
|
+
if (writerError) throw writerError;
|
|
180
|
+
})();
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
private validate(statement: IClickHouseStatement): void {
|
|
184
|
+
if (!statement || typeof statement.sql !== 'string' || !statement.sql.trim() ||
|
|
185
|
+
(statement.values !== undefined && (!statement.values || typeof statement.values !== 'object' || Array.isArray(statement.values)))) {
|
|
186
|
+
throw new LosslessClientError('invalid_argument', 'ClickHouse requires SQL text and a named parameter object.');
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
}
|