@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 CHANGED
@@ -1,11 +1,12 @@
1
1
  {
2
2
  "name": "@ouim/vectoriadb-server",
3
- "version": "0.1.4",
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
+ })
@@ -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(['add', 'addMany', 'update', 'remove', 'clear', 'insert', 'upsert', 'replace', 'put', 'delete'])
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
- // detect serialized function marker
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
- // also support options.filter as a string directly
147
- if (typeof p.filter === 'string' && p.filter.trim().startsWith('function')) {
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
  }