@mblaney/holster 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.
Files changed (46) hide show
  1. package/.github/workflows/node.js.yml +31 -0
  2. package/LICENSE.md +55 -0
  3. package/README.md +24 -0
  4. package/build/holster.js +4 -0
  5. package/build/holster.js.map +7 -0
  6. package/examples/index.html +33 -0
  7. package/examples/index.js +49 -0
  8. package/examples/user.html +31 -0
  9. package/examples/user.js +88 -0
  10. package/examples/wire.html +27 -0
  11. package/examples/wire.js +55 -0
  12. package/package.json +44 -0
  13. package/src/array.js +34 -0
  14. package/src/buffer.js +83 -0
  15. package/src/dup.js +23 -0
  16. package/src/get.js +19 -0
  17. package/src/ham.js +151 -0
  18. package/src/holster.js +502 -0
  19. package/src/index.js +21 -0
  20. package/src/radisk.js +438 -0
  21. package/src/radix.js +106 -0
  22. package/src/sea-utils.js +65 -0
  23. package/src/sea.js +224 -0
  24. package/src/store.js +225 -0
  25. package/src/user.js +330 -0
  26. package/src/utils.js +124 -0
  27. package/src/wire.js +290 -0
  28. package/test/holster.get.test.js +60 -0
  29. package/test/holster.lex.test.js +196 -0
  30. package/test/holster.off.test.js +53 -0
  31. package/test/holster.on.test.js +168 -0
  32. package/test/holster.put.test.js +278 -0
  33. package/test/holster.secure.test.js +210 -0
  34. package/test/holster.user.get.test.js +86 -0
  35. package/test/holster.user.lex.test.js +148 -0
  36. package/test/holster.user.off.test.js +72 -0
  37. package/test/holster.user.on.test.js +185 -0
  38. package/test/holster.user.put.test.js +381 -0
  39. package/test/kitty/! +9 -0
  40. package/test/names.js +225 -0
  41. package/test/radisk.test.js +191 -0
  42. package/test/radix.test.js +117 -0
  43. package/test/sea.test.js +284 -0
  44. package/test/store.test.js +316 -0
  45. package/test/user.test.js +173 -0
  46. package/test/wire.test.js +159 -0
@@ -0,0 +1,316 @@
1
+ import {describe, test} from "node:test"
2
+ import assert from "node:assert/strict"
3
+ import Store from "../src/store.js"
4
+ import fs from "fs"
5
+
6
+ describe("store", () => {
7
+ const kitty = Store({file: "test/kitty"})
8
+ const multiple = Store({file: "test/multiple", size: 100})
9
+ const special = Store({file: "test/special"})
10
+ const newFileValue =
11
+ "file size is only 100 bytes so writing this value requires calling slice"
12
+
13
+ test("get graph", (t, done) => {
14
+ kitty.get({"#": "FDSA"}, (err, value) => {
15
+ assert.deepEqual(value, {
16
+ FDSA: {
17
+ _: {
18
+ "#": "FDSA",
19
+ ">": {
20
+ color: 3,
21
+ name: 2,
22
+ slave: 2,
23
+ species: 2,
24
+ },
25
+ },
26
+ color: "ginger",
27
+ name: "Fluffy",
28
+ slave: {
29
+ "#": "ASDF",
30
+ },
31
+ species: "felis silvestris",
32
+ },
33
+ })
34
+ done()
35
+ })
36
+ })
37
+
38
+ test("get item", (t, done) => {
39
+ kitty.get({"#": "FDSA", ".": "species"}, (err, value) => {
40
+ assert.deepEqual(value, {
41
+ FDSA: {
42
+ _: {
43
+ "#": "FDSA",
44
+ ">": {
45
+ species: 2,
46
+ },
47
+ },
48
+ species: "felis silvestris",
49
+ },
50
+ })
51
+ done()
52
+ })
53
+ })
54
+
55
+ test("put keys to multiple files", (t, done) => {
56
+ multiple.put(
57
+ {
58
+ keyA: {
59
+ _: {"#": "keyA", ">": {value: 1}},
60
+ value: "valueA",
61
+ },
62
+ keyB: {
63
+ _: {"#": "keyB", ">": {value: 1}},
64
+ value: "valueB",
65
+ },
66
+ keyC: {
67
+ _: {"#": "keyC", ">": {value: 1, extraField: 1}},
68
+ value: "valueC",
69
+ extraField: true,
70
+ },
71
+ newFile: {
72
+ _: {"#": "newFile", ">": {value: 1}},
73
+ value: newFileValue,
74
+ },
75
+ },
76
+ err => {
77
+ assert.equal(err, null)
78
+ fs.access("test/multiple/keyC", err => {
79
+ assert.equal(err, null)
80
+ fs.access("test/multiple/newFile", err => {
81
+ assert.equal(err, null)
82
+ done()
83
+ })
84
+ })
85
+ },
86
+ )
87
+ })
88
+
89
+ test("get key from first file", (t, done) => {
90
+ multiple.get({"#": "keyA"}, (err, value) => {
91
+ assert.deepEqual(value, {
92
+ keyA: {
93
+ _: {
94
+ "#": "keyA",
95
+ ">": {
96
+ value: 1,
97
+ },
98
+ },
99
+ value: "valueA",
100
+ },
101
+ })
102
+ done()
103
+ })
104
+ })
105
+
106
+ test("get keys from second file", (t, done) => {
107
+ multiple.get({"#": "keyC"}, (err, value) => {
108
+ assert.deepEqual(value, {
109
+ keyC: {
110
+ _: {
111
+ "#": "keyC",
112
+ ">": {
113
+ extraField: 1,
114
+ value: 1,
115
+ },
116
+ },
117
+ extraField: true,
118
+ value: "valueC",
119
+ },
120
+ })
121
+ })
122
+ multiple.get({"#": "keyC", ".": "value"}, (err, value) => {
123
+ assert.deepEqual(value, {
124
+ keyC: {
125
+ _: {
126
+ "#": "keyC",
127
+ ">": {
128
+ value: 1,
129
+ },
130
+ },
131
+ value: "valueC",
132
+ },
133
+ })
134
+ done()
135
+ })
136
+ })
137
+
138
+ test("get key from third file", (t, done) => {
139
+ multiple.get({"#": "newFile"}, (err, value) => {
140
+ assert.deepEqual(value, {
141
+ newFile: {
142
+ _: {
143
+ "#": "newFile",
144
+ ">": {
145
+ value: 1,
146
+ },
147
+ },
148
+ value: newFileValue,
149
+ },
150
+ })
151
+ fs.rm("test/multiple", {recursive: true, force: true}, err => {
152
+ assert.equal(err, null)
153
+ done()
154
+ })
155
+ })
156
+ })
157
+
158
+ test("put keys with special characters", (t, done) => {
159
+ special.put(
160
+ {
161
+ "#": {
162
+ _: {"#": "#", ">": {value: 1}},
163
+ value: "ok got #",
164
+ },
165
+ ">": {
166
+ _: {"#": ">", ">": {value: 1, extraField: 1}},
167
+ value: "ok got >",
168
+ extraField: true,
169
+ },
170
+ ".": {
171
+ _: {"#": ".", ">": {value: 1, extraField: 1}},
172
+ value: "ok got .",
173
+ extraField: true,
174
+ },
175
+ "+": {
176
+ _: {"#": "+", ">": {value: 1}},
177
+ value: "ok got +",
178
+ },
179
+ "[": {
180
+ _: {"#": "[", ">": {value: 1}},
181
+ value: "ok got [",
182
+ },
183
+ ",": {
184
+ _: {"#": ",", ">": {value: 1}},
185
+ value: "ok got ,",
186
+ },
187
+ '"': {
188
+ _: {"#": '"', ">": {value: 1}},
189
+ value: 'ok got "',
190
+ },
191
+ _: {
192
+ _: {"#": "_", ">": {value: 1}},
193
+ value: "ok got _",
194
+ },
195
+ },
196
+ err => {
197
+ assert.equal(err, null)
198
+ fs.access("test/special/!", err => {
199
+ assert.equal(err, null)
200
+ done()
201
+ })
202
+ },
203
+ )
204
+ })
205
+
206
+ test("get keys with special characters", (t, done) => {
207
+ special.get({"#": "#"}, (err, value) => {
208
+ assert.deepEqual(value, {
209
+ "#": {
210
+ _: {
211
+ "#": "#",
212
+ ">": {
213
+ value: 1,
214
+ },
215
+ },
216
+ value: "ok got #",
217
+ },
218
+ })
219
+ })
220
+ special.get({"#": ">", ".": "value"}, (err, value) => {
221
+ assert.deepEqual(value, {
222
+ ">": {
223
+ _: {
224
+ "#": ">",
225
+ ">": {
226
+ value: 1,
227
+ },
228
+ },
229
+ value: "ok got >",
230
+ },
231
+ })
232
+ })
233
+ special.get({"#": ".", ".": "value"}, (err, value) => {
234
+ assert.deepEqual(value, {
235
+ ".": {
236
+ _: {
237
+ "#": ".",
238
+ ">": {
239
+ value: 1,
240
+ },
241
+ },
242
+ value: "ok got .",
243
+ },
244
+ })
245
+ })
246
+ special.get({"#": "+"}, (err, value) => {
247
+ assert.deepEqual(value, {
248
+ "+": {
249
+ _: {
250
+ "#": "+",
251
+ ">": {
252
+ value: 1,
253
+ },
254
+ },
255
+ value: "ok got +",
256
+ },
257
+ })
258
+ })
259
+ special.get({"#": "["}, (err, value) => {
260
+ assert.deepEqual(value, {
261
+ "[": {
262
+ _: {
263
+ "#": "[",
264
+ ">": {
265
+ value: 1,
266
+ },
267
+ },
268
+ value: "ok got [",
269
+ },
270
+ })
271
+ })
272
+ special.get({"#": ","}, (err, value) => {
273
+ assert.deepEqual(value, {
274
+ ",": {
275
+ _: {
276
+ "#": ",",
277
+ ">": {
278
+ value: 1,
279
+ },
280
+ },
281
+ value: "ok got ,",
282
+ },
283
+ })
284
+ })
285
+ special.get({"#": '"'}, (err, value) => {
286
+ assert.deepEqual(value, {
287
+ '"': {
288
+ _: {
289
+ "#": '"',
290
+ ">": {
291
+ value: 1,
292
+ },
293
+ },
294
+ value: 'ok got "',
295
+ },
296
+ })
297
+ })
298
+ special.get({"#": "_"}, (err, value) => {
299
+ assert.deepEqual(value, {
300
+ _: {
301
+ _: {
302
+ "#": "_",
303
+ ">": {
304
+ value: 1,
305
+ },
306
+ },
307
+ value: "ok got _",
308
+ },
309
+ })
310
+ fs.rm("test/special", {recursive: true, force: true}, err => {
311
+ assert.equal(err, null)
312
+ done()
313
+ })
314
+ })
315
+ })
316
+ })
@@ -0,0 +1,173 @@
1
+ import fs from "fs"
2
+ import {Server} from "mock-socket"
3
+ import {describe, test} from "node:test"
4
+ import assert from "node:assert/strict"
5
+ import User from "../src/user.js"
6
+
7
+ describe("user", () => {
8
+ const wss = new Server("ws://localhost:1234")
9
+ const user = User({file: "test/user", wss: wss, maxAge: 100})
10
+
11
+ test("create", (t, done) => {
12
+ user.create("alice", "password", err => {
13
+ assert.equal(err, null)
14
+ done()
15
+ })
16
+ })
17
+
18
+ test("create no username", (t, done) => {
19
+ user.create("", "password", err => {
20
+ assert.equal(err, "Please provide a username")
21
+ done()
22
+ })
23
+ })
24
+
25
+ test("create no password", (t, done) => {
26
+ user.create("alice", "", err => {
27
+ assert.equal(err, "Please provide a password")
28
+ done()
29
+ })
30
+ })
31
+
32
+ test("username already exists", (t, done) => {
33
+ user.create("alice", "password", err => {
34
+ assert.equal(err, "Username already exists")
35
+ done()
36
+ })
37
+ })
38
+
39
+ test("user is already being created", (t, done) => {
40
+ user.create("bob", "password", err => {
41
+ assert.equal(err, null)
42
+ done()
43
+ })
44
+ user.create("bob", "password", err => {
45
+ assert.equal(err, "User is already being created")
46
+ })
47
+ })
48
+
49
+ test("auth", (t, done) => {
50
+ user.auth("alice", "password", err => {
51
+ assert.equal(err, null)
52
+ assert.equal(user.is.username, "alice")
53
+ done()
54
+ })
55
+ })
56
+
57
+ test("auth no username", (t, done) => {
58
+ user.auth("", "password", err => {
59
+ assert.equal(err, "Please provide a username")
60
+ assert.equal(user.is, null)
61
+ done()
62
+ })
63
+ })
64
+
65
+ test("auth no password", (t, done) => {
66
+ user.auth("alice", "", err => {
67
+ assert.equal(err, "Please provide a password")
68
+ assert.equal(user.is, null)
69
+ done()
70
+ })
71
+ })
72
+
73
+ test("auth wrong username", (t, done) => {
74
+ user.auth("wrong", "password", err => {
75
+ assert.equal(err, "Wrong username or password")
76
+ assert.equal(user.is, null)
77
+ done()
78
+ })
79
+ })
80
+
81
+ test("auth wrong password", (t, done) => {
82
+ user.auth("alice", "wrong", err => {
83
+ assert.equal(err, "Wrong username or password")
84
+ assert.equal(user.is, null)
85
+ done()
86
+ })
87
+ })
88
+
89
+ test("user is already authenticating", (t, done) => {
90
+ user.auth("bob", "password", err => {
91
+ assert.equal(err, null)
92
+ assert.equal(user.is.username, "bob")
93
+ done()
94
+ })
95
+ user.auth("bob", "password", err => {
96
+ assert.equal(err, "User is already authenticating")
97
+ assert.equal(user.is, null)
98
+ })
99
+ })
100
+
101
+ test("change", (t, done) => {
102
+ user.change("alice", "password", "new password", err => {
103
+ assert.equal(err, null)
104
+ assert.equal(user.is.username, "alice")
105
+ done()
106
+ })
107
+ })
108
+
109
+ test("change no username", (t, done) => {
110
+ user.change("", "password", "new password", err => {
111
+ assert.equal(err, "Please provide a username")
112
+ assert.equal(user.is, null)
113
+ done()
114
+ })
115
+ })
116
+
117
+ test("change no password", (t, done) => {
118
+ user.change("alice", "", "new password", err => {
119
+ assert.equal(err, "Please provide a password")
120
+ assert.equal(user.is, null)
121
+ done()
122
+ })
123
+ })
124
+
125
+ test("change no new password", (t, done) => {
126
+ user.change("alice", "password", "", err => {
127
+ assert.equal(err, "Please provide a new password")
128
+ assert.equal(user.is, null)
129
+ done()
130
+ })
131
+ })
132
+
133
+ test("check password change and leave", (t, done) => {
134
+ user.auth("alice", "new password", err => {
135
+ assert.equal(err, null)
136
+ assert.equal(user.is.username, "alice")
137
+ user.leave()
138
+ assert.equal(user.is, null)
139
+ done()
140
+ })
141
+ })
142
+
143
+ test("delete wrong password", (t, done) => {
144
+ user.delete("alice", "password", err => {
145
+ assert.equal(err, "Wrong username or password")
146
+ assert.equal(user.is, null)
147
+ done()
148
+ })
149
+ })
150
+
151
+ test("delete", (t, done) => {
152
+ user.delete("alice", "new password", err => {
153
+ assert.equal(err, null)
154
+ assert.equal(user.is, null)
155
+ done()
156
+ })
157
+ })
158
+
159
+ test("auth after delete", (t, done) => {
160
+ user.auth("alice", "new password", err => {
161
+ assert.equal(err, "Wrong username or password")
162
+ assert.equal(user.is, null)
163
+ done()
164
+ })
165
+ })
166
+
167
+ test("cleanup", (t, done) => {
168
+ fs.rm("test/user", {recursive: true, force: true}, err => {
169
+ assert.equal(err, null)
170
+ done()
171
+ })
172
+ })
173
+ })
@@ -0,0 +1,159 @@
1
+ import fs from "fs"
2
+ import {Server} from "mock-socket"
3
+ import {describe, test} from "node:test"
4
+ import assert from "node:assert/strict"
5
+ import Wire from "../src/wire.js"
6
+
7
+ describe("wire", () => {
8
+ // Need different websocket servers otherwise data on file will sync up.
9
+ const wss1 = new Server("ws://localhost:1234")
10
+ const kitty = Wire({file: "test/kitty", wss: wss1, maxAge: 10})
11
+
12
+ const wss2 = new Server("ws://localhost:1235")
13
+ const wire = Wire({file: "test/wire", wss: wss2, maxAge: 10})
14
+
15
+ const ws = new WebSocket("ws://localhost:1235")
16
+ ws.onmessage = m => {
17
+ const msg = JSON.parse(m.data)
18
+ if (msg.get) {
19
+ const soul = msg.get["#"]
20
+ const put = {
21
+ [soul]: {
22
+ _: {"#": soul, ">": {test: 1}},
23
+ test: "property",
24
+ },
25
+ }
26
+ let track = "item"
27
+ if (!msg.get["."]) {
28
+ put[soul]._[">"].other = 2
29
+ put[soul].other = "value"
30
+ track = "node"
31
+ }
32
+ ws.send(
33
+ JSON.stringify({
34
+ "#": track,
35
+ "@": msg["#"],
36
+ put: put,
37
+ }),
38
+ )
39
+ }
40
+ }
41
+
42
+ test("get node", (t, done) => {
43
+ kitty.get({"#": "FDSA"}, msg => {
44
+ assert.deepEqual(msg, {
45
+ err: undefined,
46
+ put: {
47
+ FDSA: {
48
+ _: {
49
+ "#": "FDSA",
50
+ ">": {
51
+ color: 3,
52
+ name: 2,
53
+ slave: 2,
54
+ species: 2,
55
+ },
56
+ },
57
+ color: "ginger",
58
+ name: "Fluffy",
59
+ slave: {"#": "ASDF"},
60
+ species: "felis silvestris",
61
+ },
62
+ },
63
+ })
64
+ done()
65
+ })
66
+ })
67
+
68
+ test("get item", (t, done) => {
69
+ kitty.get({"#": "FDSA", ".": "species"}, msg => {
70
+ assert.deepEqual(msg, {
71
+ err: undefined,
72
+ put: {
73
+ FDSA: {
74
+ _: {
75
+ "#": "FDSA",
76
+ ">": {species: 2},
77
+ },
78
+ species: "felis silvestris",
79
+ },
80
+ },
81
+ })
82
+ done()
83
+ })
84
+ })
85
+
86
+ test("get node from wire", (t, done) => {
87
+ wire.get({"#": "not on disk"}, msg => {
88
+ assert.deepEqual(msg, {
89
+ put: {
90
+ "not on disk": {
91
+ _: {
92
+ "#": "not on disk",
93
+ ">": {test: 1, other: 2},
94
+ },
95
+ test: "property",
96
+ other: "value",
97
+ },
98
+ },
99
+ })
100
+ done()
101
+ })
102
+ })
103
+
104
+ test("get item from wire", (t, done) => {
105
+ wire.get({"#": "not on disk", ".": "test"}, msg => {
106
+ assert.deepEqual(msg, {
107
+ put: {
108
+ "not on disk": {
109
+ _: {
110
+ "#": "not on disk",
111
+ ">": {test: 1},
112
+ p: undefined,
113
+ s: undefined,
114
+ },
115
+ test: "property",
116
+ },
117
+ },
118
+ })
119
+ done()
120
+ })
121
+ })
122
+
123
+ test("put and get new node", (t, done) => {
124
+ const update = {
125
+ key: {
126
+ _: {"#": "key", ">": {value: 1, otherValue: 1}},
127
+ value: "wire test",
128
+ otherValue: false,
129
+ },
130
+ }
131
+ wire.put(update, err => {
132
+ assert.deepEqual(err, null)
133
+
134
+ wire.get({"#": "key", ".": "value"}, msg => {
135
+ assert.deepEqual(msg, {
136
+ put: {
137
+ key: {
138
+ _: {
139
+ "#": "key",
140
+ ">": {value: 1},
141
+ p: undefined,
142
+ s: undefined,
143
+ },
144
+ value: "wire test",
145
+ },
146
+ },
147
+ })
148
+ done()
149
+ })
150
+ })
151
+ })
152
+
153
+ test("cleanup", (t, done) => {
154
+ fs.rm("test/wire", {recursive: true, force: true}, err => {
155
+ assert.equal(err, null)
156
+ done()
157
+ })
158
+ })
159
+ })