@blackglory/estore-js 0.5.1 → 0.5.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.
@@ -1,8 +1,6 @@
1
1
  import { IAPI } from "../contract.js";
2
- import { ClientProxy, BatchClient, BatchClientProxy } from 'delight-rpc';
2
+ import { ClientProxy } from 'delight-rpc';
3
3
  export declare function createRPCClient(url: string, retryIntervalForReconnection?: number): Promise<{
4
4
  client: ClientProxy<IAPI>;
5
- batchClient: BatchClient<IAPI>;
6
- proxy: BatchClientProxy<IAPI, unknown>;
7
5
  close: () => Promise<void>;
8
6
  }>;
@@ -1,21 +1,15 @@
1
1
  import { expectedVersion } from "../contract.js";
2
- import { createBatchProxy } from 'delight-rpc';
3
- import { createClient, createBatchClient } from '@delight-rpc/extra-native-websocket';
2
+ import { createClient } from '@delight-rpc/extra-native-websocket';
4
3
  import { ExtraNativeWebSocket, autoReconnect } from 'extra-native-websocket';
5
4
  export async function createRPCClient(url, retryIntervalForReconnection) {
6
5
  const ws = new ExtraNativeWebSocket(() => new WebSocket(url));
7
6
  const cancelAutoReconnect = autoReconnect(ws, retryIntervalForReconnection);
8
7
  await ws.connect();
9
8
  const [client, closeClient] = createClient(ws, { expectedVersion });
10
- const [batchClient, closeBatchClient] = createBatchClient(ws, { expectedVersion });
11
- const proxy = createBatchProxy();
12
9
  return {
13
10
  client,
14
- batchClient,
15
- proxy,
16
11
  close: async () => {
17
12
  closeClient();
18
- closeBatchClient();
19
13
  cancelAutoReconnect();
20
14
  await ws.close();
21
15
  }
@@ -1 +1 @@
1
- {"version":3,"file":"rpc-client.browser.js","sourceRoot":"","sources":["../../src/utils/rpc-client.browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,eAAe,EAAE,uBAAwB;AACxD,OAAO,EAA8C,gBAAgB,EAAE,MAAM,aAAa,CAAA;AAC1F,OAAO,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,qCAAqC,CAAA;AACrF,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAE5E,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,GAAW,EACX,4BAAqC;IAOrC,MAAM,EAAE,GAAG,IAAI,oBAAoB,CAAC,GAAG,EAAE,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC,CAAA;IAC7D,MAAM,mBAAmB,GAAG,aAAa,CAAC,EAAE,EAAE,4BAA4B,CAAC,CAAA;IAC3E,MAAM,EAAE,CAAC,OAAO,EAAE,CAAA;IAElB,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,YAAY,CAAO,EAAE,EAAE,EAAE,eAAe,EAAE,CAAC,CAAA;IACzE,MAAM,CAAC,WAAW,EAAE,gBAAgB,CAAC,GAAG,iBAAiB,CAAC,EAAE,EAAE,EAAE,eAAe,EAAE,CAAC,CAAA;IAClF,MAAM,KAAK,GAAG,gBAAgB,EAAQ,CAAA;IAEtC,OAAO;QACL,MAAM;QACN,WAAW;QACX,KAAK;QACL,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,WAAW,EAAE,CAAA;YACb,gBAAgB,EAAE,CAAA;YAClB,mBAAmB,EAAE,CAAA;YACrB,MAAM,EAAE,CAAC,KAAK,EAAE,CAAA;QAClB,CAAC;KACF,CAAA;AACH,CAAC"}
1
+ {"version":3,"file":"rpc-client.browser.js","sourceRoot":"","sources":["../../src/utils/rpc-client.browser.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,eAAe,EAAE,uBAAwB;AAExD,OAAO,EAAE,YAAY,EAAE,MAAM,qCAAqC,CAAA;AAClE,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AAE5E,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,GAAW,EACX,4BAAqC;IAKrC,MAAM,EAAE,GAAG,IAAI,oBAAoB,CAAC,GAAG,EAAE,CAAC,IAAI,SAAS,CAAC,GAAG,CAAC,CAAC,CAAA;IAC7D,MAAM,mBAAmB,GAAG,aAAa,CAAC,EAAE,EAAE,4BAA4B,CAAC,CAAA;IAC3E,MAAM,EAAE,CAAC,OAAO,EAAE,CAAA;IAElB,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,GAAG,YAAY,CAAO,EAAE,EAAE,EAAE,eAAe,EAAE,CAAC,CAAA;IAEzE,OAAO;QACL,MAAM;QACN,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,WAAW,EAAE,CAAA;YACb,mBAAmB,EAAE,CAAA;YACrB,MAAM,EAAE,CAAC,KAAK,EAAE,CAAA;QAClB,CAAC;KACF,CAAA;AACH,CAAC"}
package/package.json CHANGED
@@ -1,10 +1,11 @@
1
1
  {
2
2
  "name": "@blackglory/estore-js",
3
- "version": "0.5.1",
3
+ "version": "0.5.3",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "files": [
7
- "lib"
7
+ "lib",
8
+ "src"
8
9
  ],
9
10
  "type": "module",
10
11
  "main": "lib/index.js",
@@ -0,0 +1,45 @@
1
+ import { CustomError } from '@blackglory/errors'
2
+ import { JSONValue } from 'justypes'
3
+
4
+ export const expectedVersion = '^0.4.0'
5
+
6
+ export interface INamespaceStats {
7
+ items: number
8
+ }
9
+
10
+ export interface IAPI {
11
+ getAllNamespaces(): string[]
12
+ getAllItemIds(namespace: string): string[]
13
+ getAllEvents(namespace: string, itemId: string): JSONValue[]
14
+
15
+ getNamespaceStats(namespace: string): INamespaceStats
16
+
17
+ clearItemsByNamespace(namespace: string): null
18
+
19
+ removeItem(namespace: string, itemId: string): null
20
+
21
+ /**
22
+ * 获得指定项目内包含的事件数量, 该值等同于下一个事件插入时的索引号.
23
+ * 对于不存在的项目, 它会返回0.
24
+ */
25
+ getItemSize(namespace: string, itemId: string): number
26
+
27
+ /**
28
+ * @param nextEventIndex 如果指定, 则会在eventIndex不等于下一个index时抛出EventIndexConflict错误.
29
+ * @throws {EventIndexConflict}
30
+ */
31
+ appendEvent(
32
+ namespace: string
33
+ , itemId: string
34
+ , event: JSONValue
35
+ , nextEventIndex?: number
36
+ ): null
37
+
38
+ getEvent(
39
+ namespace: string
40
+ , itemId: string
41
+ , eventIndex: number
42
+ ): JSONValue | null
43
+ }
44
+
45
+ export class EventIndexConflict extends CustomError {}
@@ -0,0 +1,143 @@
1
+ import { createRPCClient } from '@utils/rpc-client.js'
2
+ import { ClientProxy } from 'delight-rpc'
3
+ import { IAPI, INamespaceStats } from './contract.js'
4
+ import { timeoutSignal, withAbortSignal } from 'extra-abort'
5
+ import { isUndefined, JSONValue } from '@blackglory/prelude'
6
+ export { INamespaceStats } from './contract.js'
7
+ export { EventIndexConflict } from './contract.js'
8
+
9
+ export interface IEStoreClientOptions {
10
+ server: string
11
+ timeout?: number
12
+ retryIntervalForReconnection?: number
13
+ }
14
+
15
+ export class EStoreClient {
16
+ static async create(options: IEStoreClientOptions): Promise<EStoreClient> {
17
+ const { client, close } = await createRPCClient(
18
+ options.server
19
+ , options.retryIntervalForReconnection
20
+ )
21
+ return new EStoreClient(client, close, options.timeout)
22
+ }
23
+
24
+ private constructor(
25
+ private client: ClientProxy<IAPI>
26
+ , private closeClients: () => Promise<void>
27
+ , private timeout?: number
28
+ ) {}
29
+
30
+ async close(): Promise<void> {
31
+ await this.closeClients()
32
+ }
33
+
34
+ async getNamespaceStats(
35
+ namespace: string
36
+ , timeout?: number
37
+ ): Promise<INamespaceStats> {
38
+ return await this.withTimeout(
39
+ () => this.client.getNamespaceStats(namespace)
40
+ , timeout ?? this.timeout
41
+ )
42
+ }
43
+
44
+ async getAllNamespaces(timeout?: number): Promise<string[]> {
45
+ return await this.withTimeout(
46
+ () => this.client.getAllNamespaces()
47
+ , timeout ?? this.timeout
48
+ )
49
+ }
50
+
51
+ async getAllItemIds(namespace: string, timeout?: number): Promise<string[]> {
52
+ return await this.withTimeout(
53
+ () => this.client.getAllItemIds(namespace)
54
+ , timeout ?? this.timeout
55
+ )
56
+ }
57
+
58
+ async getAllEvents(
59
+ namespace: string
60
+ , itemId: string
61
+ , timeout?: number
62
+ ): Promise<JSONValue[]> {
63
+ return await this.withTimeout(
64
+ () => this.client.getAllEvents(namespace, itemId)
65
+ , timeout ?? this.timeout
66
+ )
67
+ }
68
+
69
+ async clearItemsByNamespace(namespace: string, timeout?: number): Promise<void> {
70
+ await this.withTimeout(
71
+ () => this.client.clearItemsByNamespace(namespace)
72
+ , timeout ?? this.timeout
73
+ )
74
+ }
75
+
76
+ async removeItem(
77
+ namespace: string
78
+ , itemId: string
79
+ , timeout?: number
80
+ ): Promise<void> {
81
+ await this.withTimeout(
82
+ () => this.client.removeItem(namespace, itemId)
83
+ , timeout ?? this.timeout
84
+ )
85
+ }
86
+
87
+ async getItemSize(
88
+ namespace: string
89
+ , itemId: string
90
+ , timeout?: number
91
+ ): Promise<number> {
92
+ return await this.withTimeout(
93
+ () => this.client.getItemSize(namespace, itemId)
94
+ , timeout ?? this.timeout
95
+ )
96
+ }
97
+
98
+ /**
99
+ * @param nextEventIndex 如果指定, 则会在eventIndex不等于下一个index时抛出EventIndexConflict错误.
100
+ * @throws {EventIndexConflict}
101
+ */
102
+ async appendEvent(
103
+ namespace: string
104
+ , itemId: string
105
+ , event: JSONValue
106
+ , nextEventIndex?: number
107
+ , timeout?: number
108
+ ): Promise<void> {
109
+ await this.withTimeout(
110
+ () => {
111
+ if (isUndefined(nextEventIndex)) {
112
+ return this.client.appendEvent(namespace, itemId, event)
113
+ } else {
114
+ return this.client.appendEvent(namespace, itemId, event, nextEventIndex)
115
+ }
116
+ }
117
+ , timeout ?? this.timeout
118
+ )
119
+ }
120
+
121
+ async getEvent(
122
+ namespace: string
123
+ , itemId: string
124
+ , index: number
125
+ , timeout?: number
126
+ ): Promise<JSONValue | null> {
127
+ return await this.withTimeout(
128
+ () => this.client.getEvent(namespace, itemId, index)
129
+ , timeout ?? this.timeout
130
+ )
131
+ }
132
+
133
+ private async withTimeout<T>(
134
+ fn: () => PromiseLike<T>
135
+ , timeout: number | undefined = this.timeout
136
+ ): Promise<T> {
137
+ if (timeout) {
138
+ return await withAbortSignal(timeoutSignal(timeout), fn)
139
+ } else {
140
+ return await fn()
141
+ }
142
+ }
143
+ }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from './estore-client.js'
@@ -0,0 +1,27 @@
1
+ import { IAPI, expectedVersion } from '@src/contract.js'
2
+ import { ClientProxy } from 'delight-rpc'
3
+ import { createClient } from '@delight-rpc/extra-native-websocket'
4
+ import { ExtraNativeWebSocket, autoReconnect } from 'extra-native-websocket'
5
+
6
+ export async function createRPCClient(
7
+ url: string
8
+ , retryIntervalForReconnection?: number
9
+ ): Promise<{
10
+ client: ClientProxy<IAPI>
11
+ close: () => Promise<void>
12
+ }> {
13
+ const ws = new ExtraNativeWebSocket(() => new WebSocket(url))
14
+ const cancelAutoReconnect = autoReconnect(ws, retryIntervalForReconnection)
15
+ await ws.connect()
16
+
17
+ const [client, closeClient] = createClient<IAPI>(ws, { expectedVersion })
18
+
19
+ return {
20
+ client
21
+ , close: async () => {
22
+ closeClient()
23
+ cancelAutoReconnect()
24
+ await ws.close()
25
+ }
26
+ }
27
+ }
@@ -0,0 +1,28 @@
1
+ import { IAPI, expectedVersion } from '@src/contract.js'
2
+ import { ClientProxy } from 'delight-rpc'
3
+ import { createClient } from '@delight-rpc/extra-websocket'
4
+ import { WebSocket } from 'ws'
5
+ import { ExtraWebSocket, autoReconnect } from 'extra-websocket'
6
+
7
+ export async function createRPCClient(
8
+ url: string
9
+ , retryIntervalForReconnection?: number
10
+ ): Promise<{
11
+ client: ClientProxy<IAPI>
12
+ close: () => Promise<void>
13
+ }> {
14
+ const ws = new ExtraWebSocket(() => new WebSocket(url))
15
+ const cancelAutoReconnect = autoReconnect(ws, retryIntervalForReconnection)
16
+ await ws.connect()
17
+
18
+ const [client, closeClient] = createClient<IAPI>(ws, { expectedVersion })
19
+
20
+ return {
21
+ client
22
+ , close: async () => {
23
+ closeClient()
24
+ cancelAutoReconnect()
25
+ await ws.close()
26
+ }
27
+ }
28
+ }