unikvs 0.0.2 → 0.0.3
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/LICENSE +21 -0
- package/dist/src/core/_assign-context.d.ts +3 -0
- package/dist/src/core/_assign-context.d.ts.map +1 -0
- package/dist/src/core/_assign-context.js +3 -0
- package/dist/src/core/_combine-signals.d.ts +3 -0
- package/dist/src/core/_combine-signals.d.ts.map +1 -0
- package/dist/src/core/_combine-signals.js +34 -0
- package/dist/src/core/_is-iterable.d.ts +2 -0
- package/dist/src/core/_is-iterable.d.ts.map +1 -0
- package/dist/src/core/_is-iterable.js +3 -0
- package/dist/src/core/_is-plain-object.d.ts +2 -0
- package/dist/src/core/_is-plain-object.d.ts.map +1 -0
- package/dist/src/core/_is-plain-object.js +7 -0
- package/dist/src/core/_logger.d.ts +3 -0
- package/dist/src/core/_logger.d.ts.map +1 -0
- package/dist/src/core/_logger.js +3 -0
- package/dist/src/core/_merge-context.d.ts +3 -0
- package/dist/src/core/_merge-context.d.ts.map +1 -0
- package/dist/src/core/_merge-context.js +4 -0
- package/dist/src/core/_to-context.d.ts +7 -0
- package/dist/src/core/_to-context.d.ts.map +1 -0
- package/dist/src/core/_to-context.js +42 -0
- package/dist/src/core/_to-value-stream.d.ts +4 -0
- package/dist/src/core/_to-value-stream.d.ts.map +1 -0
- package/dist/src/core/_to-value-stream.js +38 -0
- package/dist/src/core/_with-readable-stream-from.d.ts +6 -0
- package/dist/src/core/_with-readable-stream-from.d.ts.map +1 -0
- package/dist/src/core/_with-readable-stream-from.js +58 -0
- package/dist/src/core/context.types.d.ts +5 -0
- package/dist/src/core/context.types.d.ts.map +1 -0
- package/dist/src/core/context.types.js +1 -0
- package/dist/src/core/errors.d.ts +13 -0
- package/dist/src/core/errors.d.ts.map +1 -0
- package/dist/src/core/errors.js +20 -0
- package/dist/src/core/index.d.ts +15 -0
- package/dist/src/core/index.d.ts.map +1 -0
- package/dist/src/core/index.js +4 -0
- package/dist/src/core/plugin.types.d.ts +8 -0
- package/dist/src/core/plugin.types.d.ts.map +1 -0
- package/dist/src/core/plugin.types.js +1 -0
- package/dist/src/core/storage.types.d.ts +22 -0
- package/dist/src/core/storage.types.d.ts.map +1 -0
- package/dist/src/core/storage.types.js +1 -0
- package/dist/src/core/to-readable-stream.d.ts +2 -0
- package/dist/src/core/to-readable-stream.d.ts.map +1 -0
- package/dist/src/core/to-readable-stream.js +4 -0
- package/dist/src/core/transformer.types.d.ts +18 -0
- package/dist/src/core/transformer.types.d.ts.map +1 -0
- package/dist/src/core/transformer.types.js +1 -0
- package/dist/src/core/unikvs-config.d.ts +82 -0
- package/dist/src/core/unikvs-config.d.ts.map +1 -0
- package/dist/src/core/unikvs-config.js +49 -0
- package/dist/src/core/unikvs.d.ts +73 -0
- package/dist/src/core/unikvs.d.ts.map +1 -0
- package/dist/src/core/unikvs.js +678 -0
- package/dist/src/core/utils.types.d.ts +3 -0
- package/dist/src/core/utils.types.d.ts.map +1 -0
- package/dist/src/core/utils.types.js +1 -0
- package/dist/src/core/value-stream.types.d.ts +4 -0
- package/dist/src/core/value-stream.types.d.ts.map +1 -0
- package/dist/src/core/value-stream.types.js +1 -0
- package/dist/src/destinations/memory-storage.d.ts +17 -0
- package/dist/src/destinations/memory-storage.d.ts.map +1 -0
- package/dist/src/destinations/memory-storage.js +113 -0
- package/dist/src/types/storage.d.ts +5 -0
- package/dist/src/types/storage.d.ts.map +1 -0
- package/dist/src/types/storage.js +1 -0
- package/dist/src/types/transformer.d.ts +5 -0
- package/dist/src/types/transformer.d.ts.map +1 -0
- package/dist/src/types/transformer.js +1 -0
- package/package.json +69 -6
- package/src/core/_assign-context.ts +5 -0
- package/src/core/_combine-signals.ts +40 -0
- package/src/core/_is-iterable.ts +3 -0
- package/src/core/_is-plain-object.ts +11 -0
- package/src/core/_logger.ts +5 -0
- package/src/core/_merge-context.ts +9 -0
- package/src/core/_to-context.ts +59 -0
- package/src/core/_to-value-stream.ts +41 -0
- package/src/core/_with-readable-stream-from.ts +70 -0
- package/src/core/context.types.ts +7 -0
- package/src/core/errors.ts +37 -0
- package/src/core/index.ts +23 -0
- package/src/core/plugin.types.ts +10 -0
- package/src/core/storage.types.ts +53 -0
- package/src/core/to-readable-stream.ts +7 -0
- package/src/core/transformer.types.ts +110 -0
- package/src/core/unikvs-config.ts +230 -0
- package/src/core/unikvs.ts +740 -0
- package/src/core/utils.types.ts +3 -0
- package/src/core/value-stream.types.ts +3 -0
- package/src/destinations/memory-storage.ts +160 -0
- package/src/types/storage.ts +5 -0
- package/src/types/transformer.ts +5 -0
- package/README.md +0 -45
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"value-stream.types.d.ts","sourceRoot":"","sources":["../../../src/core/value-stream.types.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW,CAAC,CAAC,CAAE,SAAQ,cAAc,CAAC,CAAC,CAAC;IACvD,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,mBAAmB,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,CAAC;CACtE"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import type { IStorage, Key } from "../core/storage.types.js";
|
|
2
|
+
type TypedArray = Int8Array | Uint8Array | Uint8ClampedArray | Int16Array | Uint16Array | Int32Array | Uint32Array | Float32Array | Float64Array | BigInt64Array | BigUint64Array;
|
|
3
|
+
type Chunk = ArrayBuffer | TypedArray;
|
|
4
|
+
export default class MemoryStorage implements IStorage {
|
|
5
|
+
readonly isOpen: boolean;
|
|
6
|
+
private store;
|
|
7
|
+
constructor();
|
|
8
|
+
write(key: Key, data: any): void;
|
|
9
|
+
getWritable(key: Key): WritableStream<Chunk>;
|
|
10
|
+
read(key: Key): any;
|
|
11
|
+
getReadable(key: Key): ReadableStream;
|
|
12
|
+
exists(key: Key): boolean;
|
|
13
|
+
delete(key: Key): void;
|
|
14
|
+
clear(): void;
|
|
15
|
+
}
|
|
16
|
+
export {};
|
|
17
|
+
//# sourceMappingURL=memory-storage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory-storage.d.ts","sourceRoot":"","sources":["../../../src/destinations/memory-storage.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,MAAM,0BAA0B,CAAC;AAG9D,KAAK,UAAU,GACX,SAAS,GACT,UAAU,GACV,iBAAiB,GACjB,UAAU,GACV,WAAW,GACX,UAAU,GACV,WAAW,GACX,YAAY,GACZ,YAAY,GACZ,aAAa,GACb,cAAc,CAAC;AAEnB,KAAK,KAAK,GAAG,WAAW,GAAG,UAAU,CAAC;AAYtC,MAAM,CAAC,OAAO,OAAO,aAAc,YAAW,QAAQ;IACpD,SAAgB,MAAM,EAAE,OAAO,CAAQ;IAEvC,OAAO,CAAC,KAAK,CAAgB;;IAMtB,KAAK,CAAC,GAAG,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,GAAG,IAAI;IAIhC,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,cAAc,CAAC,KAAK,CAAC;IA8B5C,IAAI,CAAC,GAAG,EAAE,GAAG,GAAG,GAAG;IAkDnB,WAAW,CAAC,GAAG,EAAE,GAAG,GAAG,cAAc;IAoBrC,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,OAAO;IAQzB,MAAM,CAAC,GAAG,EAAE,GAAG,GAAG,IAAI;IAItB,KAAK,IAAI,IAAI;CAGrB"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import getType from "type-name";
|
|
2
|
+
import { TypeError } from "../core/errors.js";
|
|
3
|
+
class Chunks extends Array {
|
|
4
|
+
}
|
|
5
|
+
function isTypedArray(x) {
|
|
6
|
+
return ArrayBuffer.isView(x) && !(x instanceof DataView);
|
|
7
|
+
}
|
|
8
|
+
function isArrayBuffer(x) {
|
|
9
|
+
return x instanceof ArrayBuffer;
|
|
10
|
+
}
|
|
11
|
+
export default class MemoryStorage {
|
|
12
|
+
constructor() {
|
|
13
|
+
this.isOpen = true;
|
|
14
|
+
this.store = new Map();
|
|
15
|
+
}
|
|
16
|
+
write(key, data) {
|
|
17
|
+
this.store.set(key, data);
|
|
18
|
+
}
|
|
19
|
+
getWritable(key) {
|
|
20
|
+
const chunks = new Chunks();
|
|
21
|
+
let firstChunk = null;
|
|
22
|
+
return new WritableStream({
|
|
23
|
+
write: (chunk) => {
|
|
24
|
+
if (!isTypedArray(chunk) && !isArrayBuffer(chunk)) {
|
|
25
|
+
throw new TypeError({
|
|
26
|
+
actualValue: chunk,
|
|
27
|
+
expectedType: "ArrayBuffer | TypedArray",
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
if (firstChunk === null) {
|
|
31
|
+
firstChunk = chunk;
|
|
32
|
+
}
|
|
33
|
+
else if (!(chunk instanceof firstChunk.constructor)) {
|
|
34
|
+
throw new TypeError({
|
|
35
|
+
actualValue: chunk,
|
|
36
|
+
expectedType: getType(firstChunk),
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
chunks.push(chunk);
|
|
40
|
+
},
|
|
41
|
+
close: () => {
|
|
42
|
+
this.store.set(key, chunks);
|
|
43
|
+
},
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
read(key) {
|
|
47
|
+
const data = this.store.get(key);
|
|
48
|
+
if (data instanceof Chunks) {
|
|
49
|
+
if (data.length === 0) {
|
|
50
|
+
return null;
|
|
51
|
+
}
|
|
52
|
+
const firstChunk = data[0];
|
|
53
|
+
if (isTypedArray(firstChunk)) {
|
|
54
|
+
const chunks = data;
|
|
55
|
+
const Constructor = firstChunk.constructor;
|
|
56
|
+
const totalLength = chunks.reduce((len, chunk) => len + chunk.length, 0);
|
|
57
|
+
const mergedArray = new Constructor(totalLength);
|
|
58
|
+
let offset = 0;
|
|
59
|
+
for (const chunk of chunks) {
|
|
60
|
+
mergedArray.set(chunk, offset);
|
|
61
|
+
offset += chunk.length;
|
|
62
|
+
}
|
|
63
|
+
return mergedArray;
|
|
64
|
+
}
|
|
65
|
+
if (isArrayBuffer(firstChunk)) {
|
|
66
|
+
const chunks = data;
|
|
67
|
+
const totalLength = data.reduce((len, chunk) => len + chunk.byteLength, 0);
|
|
68
|
+
const mergedArray = new Uint8Array(totalLength);
|
|
69
|
+
let offset = 0;
|
|
70
|
+
for (const chunk of chunks) {
|
|
71
|
+
mergedArray.set(new Uint8Array(chunk), offset);
|
|
72
|
+
offset += chunk.byteLength;
|
|
73
|
+
}
|
|
74
|
+
return mergedArray.buffer;
|
|
75
|
+
}
|
|
76
|
+
throw new TypeError({
|
|
77
|
+
actualValue: firstChunk,
|
|
78
|
+
expectedType: "ArrayBuffer | TypedArray",
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
return data;
|
|
82
|
+
}
|
|
83
|
+
getReadable(key) {
|
|
84
|
+
const data = this.store.get(key);
|
|
85
|
+
return new ReadableStream({
|
|
86
|
+
start(controller) {
|
|
87
|
+
if (data !== undefined) {
|
|
88
|
+
if (data instanceof Chunks) {
|
|
89
|
+
for (const chunk of data) {
|
|
90
|
+
controller.enqueue(chunk);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
controller.enqueue(data);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
controller.close();
|
|
98
|
+
},
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
exists(key) {
|
|
102
|
+
return this.store.has(key);
|
|
103
|
+
}
|
|
104
|
+
// public keys(): Iterable<Key> {
|
|
105
|
+
// return this.store.keys();
|
|
106
|
+
// }
|
|
107
|
+
delete(key) {
|
|
108
|
+
this.store.delete(key);
|
|
109
|
+
}
|
|
110
|
+
clear() {
|
|
111
|
+
this.store.clear();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/types/storage.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACxD,YAAY,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AACvD,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,mBAAmB,0BAA0B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
export type { Context } from "../core/context.types.js";
|
|
2
|
+
export type { IPlugin } from "../core/plugin.types.js";
|
|
3
|
+
export type { MaybePromise } from "../core/utils.types.js";
|
|
4
|
+
export type * from "../core/transformer.types.js";
|
|
5
|
+
//# sourceMappingURL=transformer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transformer.d.ts","sourceRoot":"","sources":["../../../src/types/transformer.ts"],"names":[],"mappings":"AAAA,YAAY,EAAE,OAAO,EAAE,MAAM,0BAA0B,CAAC;AACxD,YAAY,EAAE,OAAO,EAAE,MAAM,yBAAyB,CAAC;AACvD,YAAY,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,mBAAmB,8BAA8B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,10 +1,73 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "unikvs",
|
|
3
|
-
"version": "0.0.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.0.3",
|
|
4
|
+
"description": "",
|
|
5
5
|
"keywords": [
|
|
6
|
-
"
|
|
7
|
-
"
|
|
8
|
-
|
|
9
|
-
|
|
6
|
+
"kv",
|
|
7
|
+
"kvs"
|
|
8
|
+
],
|
|
9
|
+
"homepage": "https://github.com/tai-kun/unikvs",
|
|
10
|
+
"license": "MIT",
|
|
11
|
+
"author": "tai-kun",
|
|
12
|
+
"repository": {
|
|
13
|
+
"url": "https://github.com/tai-kun/unikvs"
|
|
14
|
+
},
|
|
15
|
+
"files": [
|
|
16
|
+
"dist",
|
|
17
|
+
"src",
|
|
18
|
+
"package.json",
|
|
19
|
+
"LICENSE"
|
|
20
|
+
],
|
|
21
|
+
"type": "module",
|
|
22
|
+
"sideEffects": false,
|
|
23
|
+
"main": "./dist/src/core/index.js",
|
|
24
|
+
"module": "./dist/src/core/index.js",
|
|
25
|
+
"types": "./dist/src/core/index.d.ts",
|
|
26
|
+
"exports": {
|
|
27
|
+
".": {
|
|
28
|
+
"types": "./dist/src/core/index.d.ts",
|
|
29
|
+
"import": "./dist/src/core/index.js",
|
|
30
|
+
"require": "./dist/src/core/index.js"
|
|
31
|
+
},
|
|
32
|
+
"./storage/memory": {
|
|
33
|
+
"types": "./dist/src/destinations/memory-storage.d.ts",
|
|
34
|
+
"import": "./dist/src/destinations/memory-storage.js",
|
|
35
|
+
"require": "./dist/src/destinations/memory-storage.js"
|
|
36
|
+
},
|
|
37
|
+
"./types/storage": {
|
|
38
|
+
"types": "./dist/src/types/storage.d.ts",
|
|
39
|
+
"import": "./dist/src/types/storage.js",
|
|
40
|
+
"require": "./dist/src/types/storage.js"
|
|
41
|
+
},
|
|
42
|
+
"./types/transformer": {
|
|
43
|
+
"types": "./dist/src/types/transformer.d.ts",
|
|
44
|
+
"import": "./dist/src/types/transformer.js",
|
|
45
|
+
"require": "./dist/src/types/transformer.js"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
"scripts": {
|
|
49
|
+
"build": "tsc --project ./.config/tsconfig.build.json"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"@logtape/logtape": "^2.0.5",
|
|
53
|
+
"asyncmux": "^0.0.5",
|
|
54
|
+
"i18n-error-base": "^0.0.3",
|
|
55
|
+
"type-name": "^2.0.2"
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@tsconfig/node22": "^22.0.5",
|
|
59
|
+
"@tsconfig/strictest": "^2.0.8",
|
|
60
|
+
"@types/filename-reserved-regex": "^3.0.0",
|
|
61
|
+
"@types/node": "^22.19.17",
|
|
62
|
+
"@types/type-name": "^1.0.32",
|
|
63
|
+
"@vitest/browser": "^4.1.2",
|
|
64
|
+
"@vitest/browser-playwright": "^4.1.2",
|
|
65
|
+
"npm-check-updates": "^20.0.0",
|
|
66
|
+
"oxfmt": "^0.44.0",
|
|
67
|
+
"oxlint": "^1.59.0",
|
|
68
|
+
"oxlint-tsgolint": "^0.20.0",
|
|
69
|
+
"playwright": "^1.59.1",
|
|
70
|
+
"typescript": "^6.0.2",
|
|
71
|
+
"vitest": "^4.1.2"
|
|
72
|
+
}
|
|
10
73
|
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
let combineSignals: (signals: readonly (AbortSignal | null | undefined)[]) => AbortSignal;
|
|
2
|
+
|
|
3
|
+
if ("any" in AbortSignal && typeof AbortSignal.any === "function") {
|
|
4
|
+
const AbortSignalAny = AbortSignal.any.bind(AbortSignal);
|
|
5
|
+
combineSignals = function combineSignals(inputSignals) {
|
|
6
|
+
const signals = inputSignals.filter((s) => s != null);
|
|
7
|
+
return AbortSignalAny(signals);
|
|
8
|
+
};
|
|
9
|
+
} else {
|
|
10
|
+
combineSignals = function combineSignals(inputSignals) {
|
|
11
|
+
const ac = new AbortController();
|
|
12
|
+
const signals: AbortSignal[] = [];
|
|
13
|
+
|
|
14
|
+
for (const signal of inputSignals) {
|
|
15
|
+
if (signal?.aborted) {
|
|
16
|
+
ac.abort(signal.reason);
|
|
17
|
+
return ac.signal;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (signal) {
|
|
21
|
+
signals.push(signal);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
function handleAbort(this: AbortSignal): void {
|
|
26
|
+
ac.abort(this.reason);
|
|
27
|
+
for (const signal of signals) {
|
|
28
|
+
signal.removeEventListener("abort", handleAbort);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
for (const signal of signals) {
|
|
33
|
+
signal.addEventListener("abort", handleAbort, { once: true });
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return ac.signal;
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
export default combineSignals;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
const ObjectConstructor = Object;
|
|
2
|
+
|
|
3
|
+
// oxlint-disable typescript-eslint/unbound-method
|
|
4
|
+
const ObjectToString = ObjectConstructor.prototype.toString;
|
|
5
|
+
|
|
6
|
+
export default function isPlainObject(value: any): value is Record<keyof any, unknown> {
|
|
7
|
+
return (
|
|
8
|
+
ObjectToString.call(value) === "[object Object]" &&
|
|
9
|
+
(value.constructor === ObjectConstructor || value.constructor === undefined)
|
|
10
|
+
);
|
|
11
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import toContext from "./_to-context.js";
|
|
2
|
+
import type { Context, ContextSource } from "./context.types.js";
|
|
3
|
+
|
|
4
|
+
export default function mergeContext(
|
|
5
|
+
a: Readonly<Context>,
|
|
6
|
+
b: Readonly<Context> | ContextSource | undefined,
|
|
7
|
+
): Context {
|
|
8
|
+
return b ? { ...a, ...toContext(b) } : a;
|
|
9
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import isIterable from "./_is-iterable.js";
|
|
2
|
+
import isPlainObject from "./_is-plain-object.js";
|
|
3
|
+
import type { Context, ContextKeyValuePair, ContextSource } from "./context.types.js";
|
|
4
|
+
import { TypeError } from "./errors.js";
|
|
5
|
+
|
|
6
|
+
function isValidKeyValuePair(x: unknown): x is ContextKeyValuePair {
|
|
7
|
+
return (
|
|
8
|
+
Array.isArray(x) &&
|
|
9
|
+
x.length === 2 &&
|
|
10
|
+
(typeof x[0] === "string" || typeof x[0] === "number" || typeof x[0] === "symbol") &&
|
|
11
|
+
1 in x
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
function iterableToContext(iterable: Iterable<ContextKeyValuePair>): Context {
|
|
16
|
+
const ctx: Context = {};
|
|
17
|
+
for (const item of iterable) {
|
|
18
|
+
if (!isValidKeyValuePair(item)) {
|
|
19
|
+
throw new TypeError({
|
|
20
|
+
actualValue: item satisfies never,
|
|
21
|
+
expectedType: "ContextKeyValuePair",
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
const [key, value] = item;
|
|
26
|
+
ctx[key] = value;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
return ctx;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function contextToContext(ctx: Readonly<Context>, copy: boolean): Readonly<Context> {
|
|
33
|
+
if (copy) {
|
|
34
|
+
ctx = { ...ctx };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return ctx;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function toContext(source: ContextSource, options: { copy: true }): Context;
|
|
41
|
+
|
|
42
|
+
function toContext(source: ContextSource): Readonly<Context>;
|
|
43
|
+
|
|
44
|
+
function toContext(source: ContextSource, options: { copy: boolean } = { copy: false }) {
|
|
45
|
+
if (isIterable(source)) {
|
|
46
|
+
return iterableToContext(source);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (isPlainObject(source)) {
|
|
50
|
+
return contextToContext(source, options.copy);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
throw new TypeError({
|
|
54
|
+
actualValue: source satisfies never,
|
|
55
|
+
expectedType: "ContextSource",
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export default toContext;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import log from "./_logger.js";
|
|
2
|
+
import type { IReadableStream } from "./storage.types.js";
|
|
3
|
+
import type { ValueStream } from "./value-stream.types.js";
|
|
4
|
+
|
|
5
|
+
export default function toValueStream<T>(r: IReadableStream<T>): ValueStream<T> {
|
|
6
|
+
if (Symbol.asyncIterator in r) {
|
|
7
|
+
return r;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
return Object.assign(r, {
|
|
11
|
+
async *[Symbol.asyncIterator](this: IReadableStream<T>) {
|
|
12
|
+
const r = this.getReader();
|
|
13
|
+
try {
|
|
14
|
+
while (true) {
|
|
15
|
+
const { done, value } = await r.read();
|
|
16
|
+
if (done) {
|
|
17
|
+
break;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
yield value;
|
|
21
|
+
}
|
|
22
|
+
} catch (ex) {
|
|
23
|
+
try {
|
|
24
|
+
await r.cancel(ex);
|
|
25
|
+
} catch (ex) {
|
|
26
|
+
log.error`Failed to cancel reader: ${ex}`;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
throw ex;
|
|
30
|
+
} finally {
|
|
31
|
+
try {
|
|
32
|
+
r.releaseLock();
|
|
33
|
+
} catch (ex) {
|
|
34
|
+
log.error`Failed to release reader's lock: ${ex}`;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return undefined;
|
|
39
|
+
},
|
|
40
|
+
});
|
|
41
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import isIterable from "./_is-iterable.js";
|
|
2
|
+
import log from "./_logger.js";
|
|
3
|
+
import { TypeError } from "./errors.js";
|
|
4
|
+
|
|
5
|
+
interface ReadableStreamWithFrom extends ReadableStream {
|
|
6
|
+
from<T>(iterable: Iterable<T> | AsyncIterable<T>): ReadableStream<T>;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
export default function withReadableStreamFrom<T>(
|
|
10
|
+
cb: (ReadableStream: ReadableStreamWithFrom) => T,
|
|
11
|
+
): T {
|
|
12
|
+
if ("from" in ReadableStream) {
|
|
13
|
+
return cb(ReadableStream as any);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
(ReadableStream as any).from = function ReadableStreamFrom<T>(
|
|
18
|
+
iterable: Iterable<T> | AsyncIterable<T>,
|
|
19
|
+
): ReadableStream<T> {
|
|
20
|
+
if (!isIterable(iterable)) {
|
|
21
|
+
throw new TypeError({
|
|
22
|
+
actualValue: iterable satisfies never,
|
|
23
|
+
expectedType: "(Iterable | AsyncIterable)",
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const iter: AsyncIterator<T> =
|
|
28
|
+
Symbol.asyncIterator in iterable
|
|
29
|
+
? iterable[Symbol.asyncIterator]()
|
|
30
|
+
: (async function* (iterable) {
|
|
31
|
+
yield* iterable;
|
|
32
|
+
})(iterable);
|
|
33
|
+
|
|
34
|
+
let done = false;
|
|
35
|
+
|
|
36
|
+
return new ReadableStream<T>({
|
|
37
|
+
async pull(controller) {
|
|
38
|
+
if (done) {
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
try {
|
|
43
|
+
const result = await iter.next();
|
|
44
|
+
if (result.done) {
|
|
45
|
+
done = true;
|
|
46
|
+
controller.close();
|
|
47
|
+
} else {
|
|
48
|
+
controller.enqueue(result.value);
|
|
49
|
+
}
|
|
50
|
+
} catch (ex) {
|
|
51
|
+
done = true;
|
|
52
|
+
controller.error(ex);
|
|
53
|
+
}
|
|
54
|
+
},
|
|
55
|
+
async cancel(reason) {
|
|
56
|
+
done = true;
|
|
57
|
+
try {
|
|
58
|
+
await iter.return?.(reason);
|
|
59
|
+
} catch (ex) {
|
|
60
|
+
log.error`Failed to close iterator: ${ex}`;
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
});
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
return cb(ReadableStream as any);
|
|
67
|
+
} finally {
|
|
68
|
+
delete (ReadableStream as any).from;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { ValueOf } from "./utils.types.js";
|
|
2
|
+
|
|
3
|
+
export type Context = Record<keyof any, unknown>;
|
|
4
|
+
|
|
5
|
+
export type ContextKeyValuePair = readonly [key: keyof Context, value: ValueOf<Context>];
|
|
6
|
+
|
|
7
|
+
export type ContextSource = Readonly<Context> | Iterable<ContextKeyValuePair>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type ErrorMeta, I18nErrorBase, setErrorMessage } from "i18n-error-base";
|
|
2
|
+
import getTypeName from "type-name";
|
|
3
|
+
|
|
4
|
+
export { setErrorMessage };
|
|
5
|
+
|
|
6
|
+
export class ErrorBase<
|
|
7
|
+
TMeta extends ErrorMeta | undefined = ErrorMeta | undefined,
|
|
8
|
+
> extends I18nErrorBase<TMeta> {}
|
|
9
|
+
|
|
10
|
+
export type TypeErrorMeta = {
|
|
11
|
+
expectedType: string;
|
|
12
|
+
actualValue: unknown;
|
|
13
|
+
actualType: string;
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
export class TypeError extends ErrorBase<TypeErrorMeta> {
|
|
17
|
+
static {
|
|
18
|
+
this.prototype.name = "UniKvsTypeError";
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public constructor(meta: Readonly<Pick<TypeErrorMeta, "expectedType" | "actualValue">>) {
|
|
22
|
+
super(
|
|
23
|
+
{
|
|
24
|
+
actualType: getTypeName(meta.actualValue),
|
|
25
|
+
actualValue: meta.actualValue,
|
|
26
|
+
expectedType: meta.expectedType,
|
|
27
|
+
},
|
|
28
|
+
({ expectedType, actualType }) => `Expected type ${expectedType}, but got ${actualType}`,
|
|
29
|
+
);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/*#__PURE__*/ setErrorMessage(
|
|
34
|
+
TypeError,
|
|
35
|
+
({ expectedType, actualType }) => `型 ${expectedType} を期待しましたが、${actualType} を得ました`,
|
|
36
|
+
"ja",
|
|
37
|
+
);
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
export type * from "./context.types.js";
|
|
2
|
+
|
|
3
|
+
export type { TypeErrorMeta } from "./errors.js";
|
|
4
|
+
export { setErrorMessage, TypeError, ErrorBase } from "./errors.js";
|
|
5
|
+
|
|
6
|
+
export type * from "./plugin.types.js";
|
|
7
|
+
|
|
8
|
+
export type * from "./storage.types.js";
|
|
9
|
+
|
|
10
|
+
export type * from "./to-readable-stream.js";
|
|
11
|
+
export { default as toReadableStream } from "./to-readable-stream.js";
|
|
12
|
+
|
|
13
|
+
export type * from "./transformer.types.js";
|
|
14
|
+
|
|
15
|
+
export type * from "./unikvs-config.js";
|
|
16
|
+
export { default as UniKvsConfig } from "./unikvs-config.js";
|
|
17
|
+
|
|
18
|
+
export type * from "./unikvs.js";
|
|
19
|
+
export { default as UniKvs } from "./unikvs.js";
|
|
20
|
+
|
|
21
|
+
export type * from "./utils.types.js";
|
|
22
|
+
|
|
23
|
+
export type * from "./value-stream.types.js";
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { Context } from "./context.types.js";
|
|
2
|
+
import type { MaybePromise } from "./utils.types.js";
|
|
3
|
+
|
|
4
|
+
export interface IPlugin {
|
|
5
|
+
readonly isOpen: boolean;
|
|
6
|
+
|
|
7
|
+
open?(signal: AbortSignal, context: Context): MaybePromise<void>;
|
|
8
|
+
|
|
9
|
+
close?(signal: AbortSignal, context: Context): MaybePromise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import type { Context } from "./context.types.js";
|
|
2
|
+
import type { IPlugin } from "./plugin.types.js";
|
|
3
|
+
import type { MaybePromise } from "./utils.types.js";
|
|
4
|
+
|
|
5
|
+
export type Key = string;
|
|
6
|
+
|
|
7
|
+
export interface IWritableStream<TData = any> extends WritableStream<TData> {}
|
|
8
|
+
|
|
9
|
+
export interface IWritableStreamStorage<TData = any> {
|
|
10
|
+
getWritable(
|
|
11
|
+
key: Key,
|
|
12
|
+
signal: AbortSignal,
|
|
13
|
+
context: Context,
|
|
14
|
+
): MaybePromise<IWritableStream<TData>>;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface IReadableStream<TData = any> extends ReadableStream<TData> {}
|
|
18
|
+
|
|
19
|
+
export interface IReadableStreamStorage<TData = any> {
|
|
20
|
+
getReadable(
|
|
21
|
+
key: Key,
|
|
22
|
+
signal: AbortSignal,
|
|
23
|
+
context: Context,
|
|
24
|
+
): MaybePromise<IReadableStream<TData>>;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export interface IStorage<
|
|
28
|
+
TWriteDataInput = any,
|
|
29
|
+
TReadDataOutput = TWriteDataInput,
|
|
30
|
+
TWriteChunkInput = TWriteDataInput extends ArrayBufferLike | ArrayBufferView
|
|
31
|
+
? TWriteDataInput
|
|
32
|
+
: any,
|
|
33
|
+
TReadChunkOutput = TWriteChunkInput,
|
|
34
|
+
>
|
|
35
|
+
extends
|
|
36
|
+
IPlugin,
|
|
37
|
+
Partial<IWritableStreamStorage<TWriteChunkInput>>,
|
|
38
|
+
Partial<IReadableStreamStorage<TReadChunkOutput>> {
|
|
39
|
+
write(key: Key, data: TWriteDataInput, signal: AbortSignal, context: Context): MaybePromise<void>;
|
|
40
|
+
|
|
41
|
+
read(key: Key, signal: AbortSignal, context: Context): MaybePromise<TReadDataOutput>;
|
|
42
|
+
|
|
43
|
+
exists(key: Key, signal: AbortSignal, context: Context): MaybePromise<boolean>;
|
|
44
|
+
|
|
45
|
+
// keys(
|
|
46
|
+
// signal: AbortSignal,
|
|
47
|
+
// context: Context,
|
|
48
|
+
// ): MaybePromise<AsyncIterable<Key> | Iterable<MaybePromise<Key>> | ArrayLike<MaybePromise<Key>>>;
|
|
49
|
+
|
|
50
|
+
delete(key: Key, signal: AbortSignal, context: Context): MaybePromise<void>;
|
|
51
|
+
|
|
52
|
+
clear(signal: AbortSignal, context: Context): MaybePromise<void>;
|
|
53
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import withReadableStreamFrom from "./_with-readable-stream-from.js";
|
|
2
|
+
|
|
3
|
+
export default function toReadableStream<T>(
|
|
4
|
+
iterable: Iterable<T> | AsyncIterable<T>,
|
|
5
|
+
): ReadableStream<T> {
|
|
6
|
+
return withReadableStreamFrom((ReadableStream) => ReadableStream.from(iterable));
|
|
7
|
+
}
|