presidium-db-client-server 0.0.0-stage → 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.
@@ -0,0 +1,224 @@
1
+ /**
2
+ * Presidium DB Client and Server may be freely distributed under the CFOSS license.
3
+ */
4
+
5
+ require("rubico/global")
6
+ const HTTP = require("presidium/HTTP")
7
+ const Readable = require("presidium/Readable")
8
+ const handleServerResponse = require("./handleServerResponse")
9
+ const buffersToEntry = require("./buffersToEntry")
10
+
11
+ /**
12
+ * @name DiskHashTableClient
13
+ *
14
+ * @docs
15
+ * ```specscript
16
+ * new DiskHashTableClient(options {
17
+ * serverUrl: string,
18
+ * tableName: string,
19
+ * delimiter: string,
20
+ * }) -> DiskHashTableClient
21
+ * ```
22
+ */
23
+ class DiskHashTableClient {
24
+ constructor(options) {
25
+ this.serverUrl = options.serverUrl
26
+ this.tableName = options.tableName
27
+ this.delimiter = options.delimiter ?? ""
28
+ this.http = new HTTP(this.serverUrl)
29
+ }
30
+
31
+ /**
32
+ * @name clear
33
+ *
34
+ * @docs
35
+ * ```specscript
36
+ * module DiskHashTable "https://presidium.services/docs/DiskHashTable"
37
+ *
38
+ * clear DiskHashTable.clear
39
+ * ```
40
+ */
41
+ async clear() {
42
+ const response = await this.http.POST(`/${this.tableName}/clear`, {
43
+ headers: {
44
+ "Client-Name": "DiskHashTableClient",
45
+ },
46
+ })
47
+ return handleServerResponse(response)
48
+ }
49
+
50
+ /**
51
+ * @name set
52
+ *
53
+ * @docs
54
+ * ```specscript
55
+ * module DiskHashTable "https://presidium.services/docs/DiskHashTable"
56
+ *
57
+ * set DiskHashTable.set
58
+ * ```
59
+ */
60
+ async set(key, value) {
61
+ const response = await this.http.POST(`/${this.tableName}/set`, {
62
+ headers: {
63
+ "Content-Type": "application/json",
64
+ "Client-Name": "DiskHashTableClient",
65
+ },
66
+ body: JSON.stringify({ key, value }),
67
+ })
68
+ await handleServerResponse(response)
69
+ }
70
+
71
+ /**
72
+ * @name get
73
+ *
74
+ * @docs
75
+ * ```specscript
76
+ * module DiskHashTable "https://presidium.services/docs/DiskHashTable"
77
+ *
78
+ * get DiskHashTable.get
79
+ * ```
80
+ */
81
+ async get(key) {
82
+ const response = await this.http.POST(`/${this.tableName}/get`, {
83
+ headers: {
84
+ "Content-Type": "application/json",
85
+ "Client-Name": "DiskHashTableClient",
86
+ },
87
+ body: JSON.stringify({ key }),
88
+ })
89
+ if (response.status == 499) {
90
+ return undefined
91
+ }
92
+ return handleServerResponse(response)
93
+ }
94
+
95
+ /**
96
+ * @name getBinary
97
+ *
98
+ * @docs
99
+ * ```specscript
100
+ * module DiskHashTable "https://presidium.services/docs/DiskHashTable"
101
+ *
102
+ * getBinary DiskHashTable.getBinary
103
+ * ```
104
+ */
105
+ async getBinary(key) {
106
+ const response = await this.http.POST(`/${this.tableName}/getBinary`, {
107
+ headers: {
108
+ "Content-Type": "application/json",
109
+ "Client-Name": "DiskHashTableClient",
110
+ },
111
+ body: JSON.stringify({ key }),
112
+ })
113
+ return handleServerResponse(response)
114
+ }
115
+
116
+ /**
117
+ * @name delete
118
+ *
119
+ * @docs
120
+ * ```specscript
121
+ * module DiskHashTable "https://presidium.services/docs/DiskHashTable"
122
+ *
123
+ * delete DiskHashTable.delete
124
+ * ```
125
+ */
126
+ async delete(key) {
127
+ const response = await this.http.POST(`/${this.tableName}/delete`, {
128
+ headers: {
129
+ "Content-Type": "application/json",
130
+ "Client-Name": "DiskHashTableClient",
131
+ },
132
+ body: JSON.stringify({ key }),
133
+ })
134
+ const didDeleteText = await handleServerResponse(response)
135
+ return didDeleteText == "true"
136
+ }
137
+
138
+ /**
139
+ * @name count
140
+ *
141
+ * @docs
142
+ * ```specscript
143
+ * count() -> Promise<number>
144
+ * ```
145
+ */
146
+ async count() {
147
+ const response = await this.http.POST(`/${this.tableName}/count`, {
148
+ headers: {
149
+ "Client-Name": "DiskHashTableClient",
150
+ },
151
+ })
152
+ const scount = await handleServerResponse(response)
153
+ return Number(scount)
154
+ }
155
+
156
+ /**
157
+ * @name iterator
158
+ *
159
+ * @docs
160
+ * ```specscript
161
+ * iterator(options {
162
+ * valueType: "string"|"binary",
163
+ * }) -> values AsyncIterator<string|Buffer>
164
+ * ```
165
+ */
166
+ async iterator(options = {}) {
167
+ const { valueType } = options
168
+ const response = await this.http.POST(`/${this.tableName}/iterator`, {
169
+ headers: {
170
+ "Content-Type": "application/json",
171
+ "Client-Name": "DiskHashTableClient",
172
+ },
173
+ body: JSON.stringify(options),
174
+ })
175
+ if (valueType == "binary") {
176
+ return handleServerResponse(response, {
177
+ binaryStream: true,
178
+ delimiter: this.delimiter,
179
+ })
180
+ }
181
+ return handleServerResponse(response, {
182
+ textStream: true,
183
+ delimiter: this.delimiter,
184
+ })
185
+ }
186
+
187
+ /**
188
+ * @name entriesIterator
189
+ *
190
+ * @docs
191
+ * ```specscript
192
+ * entriesIterator(options {
193
+ * valueType: 'string'|'binary',
194
+ * }) -> entries AsyncIterator<[key string, value string|Buffer]>
195
+ * ```
196
+ */
197
+ async entriesIterator(options = {}) {
198
+ const { valueType } = options
199
+ const response = await this.http.POST(`/${this.tableName}/entriesIterator`, {
200
+ headers: {
201
+ "Content-Type": "application/json",
202
+ "Client-Name": "DiskHashTableClient",
203
+ },
204
+ body: JSON.stringify({ valueType }),
205
+ })
206
+
207
+ if (valueType == "binary") {
208
+ const iter = await handleServerResponse(response, {
209
+ binaryEntriesStream: true,
210
+ delimiter: this.delimiter,
211
+ entryLength: 2,
212
+ })
213
+ return map(iter, curry.arity(4, buffersToEntry, __, 2, "utf8", valueType))
214
+ }
215
+ const iter = await handleServerResponse(response, {
216
+ textEntriesStream: true,
217
+ delimiter: this.delimiter,
218
+ entryLength: 2,
219
+ })
220
+ return map(iter, curry.arity(4, buffersToEntry, __, 2, "utf8", valueType))
221
+ }
222
+ }
223
+
224
+ module.exports = DiskHashTableClient
@@ -0,0 +1,321 @@
1
+ /**
2
+ * Presidium DB Client and Server may be freely distributed under the CFOSS license.
3
+ */
4
+
5
+ require("rubico/global")
6
+ const HTTP = require("presidium/HTTP")
7
+ const handleServerResponse = require("./handleServerResponse")
8
+ const buffersToEntry = require("./buffersToEntry")
9
+
10
+ /**
11
+ * @name DiskSortedHashTableClient
12
+ *
13
+ * @docs
14
+ * ```specscript
15
+ * new DiskSortedHashTableClient(options {
16
+ * serverUrl: string,
17
+ * tableName: string,
18
+ * sortValueType: "string"|"number",
19
+ * degree: number,
20
+ * delimiter: string,
21
+ * }) -> DiskSortedHashTableClient
22
+ * ```
23
+ */
24
+ class DiskSortedHashTableClient {
25
+ constructor(options) {
26
+ this.serverUrl = options.serverUrl
27
+ this.tableName = options.tableName
28
+ this.sortValueType = options.sortValueType
29
+ this.degree = options.degree ?? 2
30
+ this.delimiter = options.delimiter ?? ""
31
+ this.http = new HTTP(this.serverUrl)
32
+ }
33
+
34
+ /**
35
+ * @name clear
36
+ *
37
+ * @docs
38
+ * ```specscript
39
+ * module DiskSortedHashTable "https://presidium.services/docs/DiskSortedHashTable"
40
+ *
41
+ * clear DiskSortedHashTable.clear
42
+ * ```
43
+ */
44
+ async clear() {
45
+ const response = await this.http.POST(`/${this.tableName}/clear`, {
46
+ headers: {
47
+ "Client-Name": "DiskSortedHashTableClient",
48
+ "Sort-Value-Type": this.sortValueType,
49
+ "Degree": Number(this.degree),
50
+ },
51
+ })
52
+ return handleServerResponse(response)
53
+ }
54
+
55
+ /**
56
+ * @name set
57
+ *
58
+ * @docs
59
+ * ```specscript
60
+ * module DiskSortedHashTable "https://presidium.services/docs/DiskSortedHashTable"
61
+ *
62
+ * set DiskSortedHashTable.set
63
+ * ```
64
+ */
65
+ async set(key, value, sortValue) {
66
+ const response = await this.http.POST(`/${this.tableName}/set`, {
67
+ headers: {
68
+ "Content-Type": "application/json",
69
+ "Client-Name": "DiskSortedHashTableClient",
70
+ "Sort-Value-Type": this.sortValueType,
71
+ "Degree": Number(this.degree),
72
+ },
73
+ body: JSON.stringify({ key, value, sortValue }),
74
+ })
75
+ await handleServerResponse(response)
76
+ }
77
+
78
+ /**
79
+ * @name get
80
+ *
81
+ * @docs
82
+ * ```specscript
83
+ * module DiskSortedHashTable "https://presidium.services/docs/DiskSortedHashTable"
84
+ *
85
+ * get DiskSortedHashTable.get
86
+ * ```
87
+ */
88
+ async get(key) {
89
+ const response = await this.http.POST(`/${this.tableName}/get`, {
90
+ headers: {
91
+ "Content-Type": "application/json",
92
+ "Client-Name": "DiskSortedHashTableClient",
93
+ "Sort-Value-Type": this.sortValueType,
94
+ "Degree": Number(this.degree),
95
+ },
96
+ body: JSON.stringify({ key }),
97
+ })
98
+ if (response.status == 499) {
99
+ return undefined
100
+ }
101
+ return handleServerResponse(response)
102
+ }
103
+
104
+ /**
105
+ * @name getBinary
106
+ *
107
+ * @docs
108
+ * ```specscript
109
+ * module DiskSortedHashTable "https://presidium.services/docs/DiskSortedHashTable"
110
+ *
111
+ * getBinary DiskSortedHashTable.getBinary
112
+ * ```
113
+ */
114
+ async getBinary(key) {
115
+ const response = await this.http.POST(`/${this.tableName}/getBinary`, {
116
+ headers: {
117
+ "Content-Type": "application/json",
118
+ "Client-Name": "DiskSortedHashTableClient",
119
+ "Sort-Value-Type": this.sortValueType,
120
+ "Degree": Number(this.degree),
121
+ },
122
+ body: JSON.stringify({ key }),
123
+ })
124
+ return handleServerResponse(response)
125
+ }
126
+
127
+ /**
128
+ * @name forwardIterator
129
+ *
130
+ * @docs
131
+ * ```specscript
132
+ * forwardIterator(options {
133
+ * exclusiveStartKey: string,
134
+ * startingSortValue: string|number,
135
+ * endingSortValue: string|number,
136
+ * valueType: 'string'|'binary',
137
+ * }) -> values AsyncIterator<string|Buffer>
138
+ * ```
139
+ */
140
+ async forwardIterator(options = {}) {
141
+ const { valueType } = options
142
+ const response = await this.http.POST(`/${this.tableName}/forwardIterator`, {
143
+ headers: {
144
+ "Content-Type": "application/json",
145
+ "Client-Name": "DiskSortedHashTableClient",
146
+ "Sort-Value-Type": this.sortValueType,
147
+ "Degree": Number(this.degree),
148
+ },
149
+ body: JSON.stringify(options),
150
+ })
151
+ if (valueType == "binary") {
152
+ return handleServerResponse(response, {
153
+ binaryStream: true,
154
+ delimiter: this.delimiter,
155
+ })
156
+ }
157
+ return handleServerResponse(response, {
158
+ textStream: true,
159
+ delimiter: this.delimiter,
160
+ })
161
+ }
162
+
163
+ /**
164
+ * @name reverseIterator
165
+ *
166
+ * @docs
167
+ * ```specscript
168
+ * reverseIterator(options {
169
+ * exclusiveStartKey: string,
170
+ * startingSortValue: string|number,
171
+ * endingSortValue: string|number,
172
+ * valueType: 'string'|'binary',
173
+ * }) -> values AsyncIterator<string|Buffer>
174
+ * ```
175
+ */
176
+ async reverseIterator(options = {}) {
177
+ const { valueType } = options
178
+ const response = await this.http.POST(`/${this.tableName}/reverseIterator`, {
179
+ headers: {
180
+ "Content-Type": "application/json",
181
+ "Client-Name": "DiskSortedHashTableClient",
182
+ "Sort-Value-Type": this.sortValueType,
183
+ "Degree": Number(this.degree),
184
+ },
185
+ body: JSON.stringify(options),
186
+ })
187
+ if (valueType == "binary") {
188
+ return handleServerResponse(response, {
189
+ binaryStream: true,
190
+ delimiter: this.delimiter,
191
+ })
192
+ }
193
+ return handleServerResponse(response, {
194
+ textStream: true,
195
+ delimiter: this.delimiter,
196
+ })
197
+ }
198
+
199
+ /**
200
+ * @name forwardEntriesIterator
201
+ *
202
+ * @docs
203
+ * ```specscript
204
+ * forwardEntriesIterator(options {
205
+ * exclusiveStartKey: string,
206
+ * startingSortValue: string|number,
207
+ * endingSortValue: string|number,
208
+ * valueType: 'string'|'binary',
209
+ * }) -> values AsyncIterator<string|Buffer>
210
+ * ```
211
+ */
212
+ async forwardEntriesIterator(options = {}) {
213
+ const { valueType } = options
214
+ const response = await this.http.POST(`/${this.tableName}/forwardEntriesIterator`, {
215
+ headers: {
216
+ "Content-Type": "application/json",
217
+ "Client-Name": "DiskSortedHashTableClient",
218
+ "Sort-Value-Type": this.sortValueType,
219
+ "Degree": Number(this.degree),
220
+ },
221
+ body: JSON.stringify(options),
222
+ })
223
+ if (valueType == "binary") {
224
+ const iter = await handleServerResponse(response, {
225
+ binaryEntriesStream: true,
226
+ delimiter: this.delimiter,
227
+ entryLength: 3,
228
+ })
229
+ return map(iter, curry(buffersToEntry, __, 3, "utf8", valueType, this.sortValueType))
230
+ }
231
+ const iter = await handleServerResponse(response, {
232
+ textEntriesStream: true,
233
+ delimiter: this.delimiter,
234
+ entryLength: 3,
235
+ })
236
+ return map(iter, curry(buffersToEntry, __, 3, "utf8", valueType, this.sortValueType))
237
+ }
238
+
239
+ /**
240
+ * @name reverseEntriesIterator
241
+ *
242
+ * @docs
243
+ * ```specscript
244
+ * module DiskSortedHashTable "https://presidium.services/docs/DiskSortedHashTable"
245
+ *
246
+ * reverseEntriesIterator DiskSortedHashTable.reverseEntriesIterator
247
+ * ```
248
+ */
249
+ async reverseEntriesIterator(options = {}) {
250
+ const { valueType } = options
251
+ const response = await this.http.POST(`/${this.tableName}/reverseEntriesIterator`, {
252
+ headers: {
253
+ "Content-Type": "application/json",
254
+ "Client-Name": "DiskSortedHashTableClient",
255
+ "Sort-Value-Type": this.sortValueType,
256
+ "Degree": Number(this.degree),
257
+ },
258
+ body: JSON.stringify(options),
259
+ })
260
+
261
+ if (valueType == "binary") {
262
+ const iter = await handleServerResponse(response, {
263
+ binaryEntriesStream: true,
264
+ delimiter: this.delimiter,
265
+ entryLength: 3,
266
+ })
267
+ return map(iter, curry(buffersToEntry, __, 3, "utf8", valueType, this.sortValueType))
268
+ }
269
+ const iter = await handleServerResponse(response, {
270
+ textEntriesStream: true,
271
+ delimiter: this.delimiter,
272
+ entryLength: 3,
273
+ })
274
+ return map(iter, curry(buffersToEntry, __, 3, "utf8", valueType, this.sortValueType))
275
+ }
276
+
277
+ /**
278
+ * @name delete
279
+ *
280
+ * @docs
281
+ * ```specscript
282
+ * module DiskSortedHashTable "https://presidium.services/docs/DiskSortedHashTable"
283
+ *
284
+ * delete DiskSortedHashTable.delete
285
+ * ```
286
+ */
287
+ async delete(key) {
288
+ const response = await this.http.POST(`/${this.tableName}/delete`, {
289
+ headers: {
290
+ "Content-Type": "application/json",
291
+ "Client-Name": "DiskSortedHashTableClient",
292
+ "Sort-Value-Type": this.sortValueType,
293
+ "Degree": Number(this.degree),
294
+ },
295
+ body: JSON.stringify({ key }),
296
+ })
297
+ const didDeleteText = await handleServerResponse(response)
298
+ return didDeleteText == "true"
299
+ }
300
+
301
+ /**
302
+ * @name count
303
+ *
304
+ * @docs
305
+ * ```specscript
306
+ * count() -> Promise<number>
307
+ * ```
308
+ */
309
+ async count() {
310
+ const response = await this.http.POST(`/${this.tableName}/count`, {
311
+ headers: {
312
+ "Client-Name": "DiskSortedHashTableClient",
313
+ "Sort-Value-Type": this.sortValueType,
314
+ "Degree": Number(this.degree),
315
+ },
316
+ })
317
+ return Number(await handleServerResponse(response))
318
+ }
319
+ }
320
+
321
+ module.exports = DiskSortedHashTableClient
package/README.md CHANGED
@@ -1,3 +1,55 @@
1
- # Temporary Holding Version
1
+ # Presidium DB Client and Server
2
+ ![presidium](https://rubico.land/assets/presidium-logo-3-w200.jpg)
2
3
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
4
+ Source code: [GitHub](https://github.com/richytong/presidium-websocket) |
5
+ License: [CFOSS](https://cloutsworld.com/en-us/legal/license/cfoss)
6
+
7
+ ![Node.js CI](https://github.com/richytong/presidium-db-client-server/workflows/Node.js%20CI/badge.svg)
8
+ [![codecov](https://codecov.io/gh/richytong/presidium-db-client-server/graph/badge.svg?token=07P6G8GIOQ)](https://codecov.io/gh/richytong/presidium-db-client-server)
9
+ [![npm version](https://img.shields.io/npm/v/presidium-db-client-server.svg?style=flat)](https://www.npmjs.com/package/presidium-db-client-server)
10
+
11
+ Presidium DB Client and Server.
12
+
13
+ ```javascript
14
+ const DatabaseServer = require("presidium-db-client-server/DatabaseServer")
15
+ const DiskHashTableClient = require("presidium-db-client-server/DiskHashTableClient")
16
+
17
+ const server = new DatabaseServer({
18
+ databasePath: `${__dirname}/database`,
19
+ })
20
+ await server.init()
21
+
22
+ server.listen(5000, () => {
23
+ console.log("Database server listening on port 5000")
24
+ })
25
+
26
+ const sessionHt = new DiskHashTableClient({
27
+ serverUrl: "http://localhost:7357",
28
+ tableName: "Session",
29
+ })
30
+
31
+ const accessToken = "token"
32
+ const session = { accessToken }
33
+
34
+ await sessionHt.set(accessToken, JSON.stringify(session))
35
+
36
+ const sessionJson = await sessionHt.get(accessToken)
37
+
38
+ await sessionHt.delete(accessToken)
39
+ ```
40
+
41
+ ## Docs
42
+ Coming soon.
43
+
44
+ ## Installation
45
+
46
+ with [npm](https://docs.npmjs.com/downloading-and-installing-node-js-and-npm):
47
+ ```bash
48
+ npm i presidium-db-client-server
49
+ ```
50
+
51
+ ## License
52
+ Presidium DB Client and Server is distributed under the [CFOSS License](https://cloutsworld.com/en-us/legal/license/cfoss).
53
+
54
+ ## Support
55
+ * minimum Node.js version: 16
@@ -0,0 +1,73 @@
1
+ /**
2
+ * Presidium DB Client and Server may be freely distributed under the CFOSS license.
3
+ */
4
+
5
+ const EventEmitter = require("events")
6
+
7
+ /**
8
+ * @name TextEntriesStream
9
+ *
10
+ * @docs
11
+ * ```coffeescript [specscript]
12
+ * module EventEmitter "./specscript/EventEmitter.ss"
13
+ *
14
+ * TextEntriesStream(
15
+ * readable stream.Readable,
16
+ * entryLength number,
17
+ * delimiter string
18
+ * ) -> textEntriesStream EventEmitter
19
+ *
20
+ * textEntriesStream.on("entry", (entry Array<string>, keyEncoding string) -> ())
21
+ *
22
+ * textEntriesStream.on("end", () -> ())
23
+ * ```
24
+ */
25
+ class TextEntriesStream extends EventEmitter {
26
+ constructor(readable, entryLength, delimiter, encoding) {
27
+ super()
28
+
29
+ delimiter ??= ""
30
+ encoding ??= "utf8"
31
+
32
+ let s = ""
33
+ let entry = []
34
+ readable.on('data', (chunk, encoding) => {
35
+ if (typeof chunk == 'string') {
36
+ s += Buffer.from(chunk, encoding).toString(encoding)
37
+ } else {
38
+ s += chunk.toString(encoding)
39
+ }
40
+
41
+ let delimiterIndex = s.indexOf(delimiter)
42
+ while (delimiterIndex > -1) {
43
+ const text = s.slice(0, delimiterIndex)
44
+ entry.push(text)
45
+ if (entry.length == entryLength) {
46
+ this.emit("entry", entry, encoding)
47
+ entry = []
48
+ }
49
+ s = s.slice(delimiterIndex + 1)
50
+ delimiterIndex = s.indexOf(delimiter)
51
+ }
52
+ })
53
+
54
+ readable.on("end", () => {
55
+ if (s.length > 0) {
56
+ entry.push(s)
57
+ }
58
+ if (entry.length == entryLength) {
59
+ this.emit("entry", entry, encoding)
60
+ this.emit("end")
61
+ entry = []
62
+ } else if (entry.length > 0) {
63
+ const error = new Error("last entry")
64
+ error.entry = entry
65
+ this.emit("error", error)
66
+ } else {
67
+ this.emit("end")
68
+ }
69
+ })
70
+ }
71
+ }
72
+
73
+ module.exports = TextEntriesStream