@ouim/vectoriadb-server 0.1.4 → 0.1.6
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/package.json +3 -2
- package/test/filter-deserialize.test.js +46 -0
- package/vectoriadb-server.js +22 -4
package/package.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@ouim/vectoriadb-server",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"start": "node index.js",
|
|
8
|
-
"demo": "node demo.js"
|
|
8
|
+
"demo": "node demo.js",
|
|
9
|
+
"test": "node --test"
|
|
9
10
|
},
|
|
10
11
|
"dependencies": {
|
|
11
12
|
"@huggingface/transformers": "^3.8.1",
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import test from 'node:test'
|
|
2
|
+
import assert from 'node:assert/strict'
|
|
3
|
+
import VectoriaDBServer from '../vectoriadb-server.js'
|
|
4
|
+
|
|
5
|
+
test('server deserializes serialized options.filter (object form) into a function', async () => {
|
|
6
|
+
const server = new VectoriaDBServer()
|
|
7
|
+
|
|
8
|
+
// stub the underlying VectoriaDB method (`search`) to inspect received args
|
|
9
|
+
server._vectoria = {
|
|
10
|
+
async search(...args) {
|
|
11
|
+
// find an arg that contains a `filter` property
|
|
12
|
+
const opt = args.find(a => a && typeof a === 'object' && Object.prototype.hasOwnProperty.call(a, 'filter'))
|
|
13
|
+
assert(opt, 'expected an options object containing `filter`')
|
|
14
|
+
assert.equal(typeof opt.filter, 'function', 'options.filter should be a function after deserialization')
|
|
15
|
+
|
|
16
|
+
// sanity-check the deserialized function works
|
|
17
|
+
const sample = { owner: 'team' }
|
|
18
|
+
assert.equal(opt.filter(sample), true)
|
|
19
|
+
|
|
20
|
+
return { ok: true }
|
|
21
|
+
},
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// capture emitted responses from the "socket"
|
|
25
|
+
let emitted = null
|
|
26
|
+
const mockSocket = { emit: (evt, payload) => (emitted = { evt, payload }) }
|
|
27
|
+
|
|
28
|
+
const payload = {
|
|
29
|
+
id: 't-filter-1',
|
|
30
|
+
method: 'search',
|
|
31
|
+
params: [
|
|
32
|
+
{
|
|
33
|
+
// serialized filter object as sent by the client SDK
|
|
34
|
+
filter: { __isFnString: true, fn: 'function(m){ return !!(m && m.owner === "team") }' },
|
|
35
|
+
},
|
|
36
|
+
],
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
await server._handleRequest(mockSocket, payload)
|
|
40
|
+
|
|
41
|
+
assert(emitted, 'expected socket.emit to be called')
|
|
42
|
+
assert.equal(emitted.evt, 'response')
|
|
43
|
+
assert.equal(emitted.payload.id, payload.id)
|
|
44
|
+
assert.deepEqual(emitted.payload.result, { ok: true })
|
|
45
|
+
assert.equal(emitted.payload.error, null)
|
|
46
|
+
})
|
package/vectoriadb-server.js
CHANGED
|
@@ -24,7 +24,19 @@ export default class VectoriaDBServer {
|
|
|
24
24
|
this.minSaveIntervalMs = Number(opts.minSaveIntervalMs) || 10 * 1000 // minimum time between auto-saves
|
|
25
25
|
|
|
26
26
|
// internal mutation-tracking state
|
|
27
|
-
this._mutationMethods = new Set([
|
|
27
|
+
this._mutationMethods = new Set([
|
|
28
|
+
'add',
|
|
29
|
+
'addMany',
|
|
30
|
+
'update',
|
|
31
|
+
'remove',
|
|
32
|
+
'removeMany',
|
|
33
|
+
'clear',
|
|
34
|
+
'insert',
|
|
35
|
+
'upsert',
|
|
36
|
+
'replace',
|
|
37
|
+
'put',
|
|
38
|
+
'delete',
|
|
39
|
+
])
|
|
28
40
|
this._mutationTimestamps = []
|
|
29
41
|
this._inactivityTimer = null
|
|
30
42
|
this._lastBurstAt = 0
|
|
@@ -136,15 +148,21 @@ export default class VectoriaDBServer {
|
|
|
136
148
|
// Allow passing serialized functions from client: convert stringified functions back to real functions
|
|
137
149
|
const reparsedParams = params.map(p => {
|
|
138
150
|
if (p && typeof p === 'object') {
|
|
139
|
-
//
|
|
151
|
+
// Top-level serialized function (client forwarded a function as a param)
|
|
140
152
|
if (p.__isFnString && typeof p.fn === 'string') {
|
|
141
153
|
// create function from string - executed in server process (trusted usage only)
|
|
142
154
|
// eslint-disable-next-line no-new-func
|
|
143
155
|
const fn = new Function('return (' + p.fn + ')')()
|
|
144
156
|
return fn
|
|
145
157
|
}
|
|
146
|
-
|
|
147
|
-
|
|
158
|
+
|
|
159
|
+
// Support serialized `filter` nested inside an `options` object:
|
|
160
|
+
// - { filter: { __isFnString: true, fn: 'function(m) { ... }' } }
|
|
161
|
+
// - or `filter` as a raw function string
|
|
162
|
+
if (p.filter && typeof p.filter === 'object' && p.filter.__isFnString && typeof p.filter.fn === 'string') {
|
|
163
|
+
// eslint-disable-next-line no-new-func
|
|
164
|
+
p.filter = new Function('return (' + p.filter.fn + ')')()
|
|
165
|
+
} else if (typeof p.filter === 'string' && p.filter.trim().startsWith('function')) {
|
|
148
166
|
// eslint-disable-next-line no-new-func
|
|
149
167
|
p.filter = new Function('return (' + p.filter + ')')()
|
|
150
168
|
}
|