@ouim/vectoriadb-server 0.1.2 → 0.1.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.
package/README.md CHANGED
@@ -189,15 +189,6 @@ A: The client SDK stringifies your filter function. The server then reconstructs
189
189
 
190
190
  ---
191
191
 
192
- ## Future Roadmap
193
-
194
- - [ ] **JWT Authentication**: Add more robust auth options.
195
- - [ ] **Data Encryption**: Support for end-to-end encryption of metadata.
196
- - [ ] **Multi-Instance**: Support for multiple VectoriaDB instances managed by one server.
197
- - [ ] **Python Client**: A compatible SDK for Python applications.
198
-
199
- ---
200
-
201
192
  ## Credits
202
193
 
203
194
  This SDK builds on and integrates with [VectoriaDB](https://github.com/agentfront/vectoriadb). See the Vectoria product website at [https://agentfront.dev/vectoria](https://agentfront.dev/vectoria) for more information and additional resources.
package/index.js CHANGED
@@ -1,23 +1,23 @@
1
1
  import VectoriaDBServer from './vectoriadb-server.js'
2
2
  import { FileStorageAdapter } from 'vectoriadb'
3
3
 
4
- // If run directly, start a demo server
5
- if (process.argv[1] && process.argv[1].endsWith('index.js')) {
6
- const server = new VectoriaDBServer({
7
- port: process.env.PORT ? Number(process.env.PORT) : 3001,
8
- host: '0.0.0.0',
9
- vectoriadbConfig: {
10
- // default storage / model - user should override for production
11
- storageAdapter: new FileStorageAdapter({ cacheDir: '/data/vectoriadb', namespace: 'default' }),
12
- },
13
- cors: ['http://localhost:3000'],
14
- })
4
+ // // If run directly, start a demo server
5
+ // if (process.argv[1] && process.argv[1].endsWith('index.js')) {
6
+ // const server = new VectoriaDBServer({
7
+ // port: process.env.PORT ? Number(process.env.PORT) : 3001,
8
+ // host: '0.0.0.0',
9
+ // vectoriadbConfig: {
10
+ // // default storage / model - user should override for production
11
+ // storageAdapter: new FileStorageAdapter({ cacheDir: '/data/vectoriadb', namespace: 'default' }),
12
+ // },
13
+ // cors: ['http://localhost:3000'],
14
+ // })
15
15
 
16
- server.listen().catch(err => {
17
- console.error(err)
18
- process.exit(1)
19
- })
20
- }
16
+ // server.listen().catch(err => {
17
+ // console.error(err)
18
+ // process.exit(1)
19
+ // })
20
+ // }
21
21
 
22
- export { VectoriaDBServer }
22
+ export { VectoriaDBServer, FileStorageAdapter }
23
23
  export default VectoriaDBServer
@@ -0,0 +1,28 @@
1
+ import VectoriaDBServer from './vectoriadb-server.js'
2
+ import { FileStorageAdapter } from 'vectoriadb'
3
+
4
+ async function run() {
5
+ const server = new VectoriaDBServer({
6
+ port: 3002,
7
+ vectoriadbConfig: {
8
+ storageAdapter: new FileStorageAdapter({ cacheDir: './.cache/test-vectoriadb', namespace: 'test' }),
9
+ },
10
+ })
11
+
12
+ try {
13
+ // call listen() twice concurrently to reproduce the race if present
14
+ const results = await Promise.all([server.listen(), server.listen()])
15
+ console.log('listen() calls resolved, same instance:', results[0] === results[1])
16
+ console.log('server._started =', server._started)
17
+ } catch (err) {
18
+ console.error('concurrent listen failed:', err)
19
+ process.exitCode = 1
20
+ } finally {
21
+ await server.close()
22
+ }
23
+ }
24
+
25
+ run().catch(err => {
26
+ console.error(err)
27
+ process.exit(1)
28
+ })
package/package.json CHANGED
@@ -1,12 +1,11 @@
1
1
  {
2
2
  "name": "@ouim/vectoriadb-server",
3
- "version": "0.1.2",
3
+ "version": "0.1.3",
4
4
  "type": "module",
5
5
  "main": "index.js",
6
6
  "scripts": {
7
7
  "start": "node index.js",
8
- "demo": "node demo.js",
9
- "publish": "npm publish --access public"
8
+ "demo": "node demo.js"
10
9
  },
11
10
  "dependencies": {
12
11
  "@huggingface/transformers": "^3.8.1",
@@ -19,63 +19,89 @@ export default class VectoriaDBServer {
19
19
  this._vectoria = null
20
20
  this._sockets = new Set()
21
21
  this._started = false
22
+ this._startPromise = null
22
23
  }
23
24
 
24
25
  async listen() {
25
- if (this._started) return
26
- // Initialize VectoriaDB (loads models / storage as configured)
27
- this._vectoria = new VectoriaDB(this.vectoriadbConfig)
28
- if (typeof this._vectoria.initialize === 'function') {
29
- await this._vectoria.initialize()
30
- }
31
-
32
- this._http = http.createServer((req, res) => {
33
- res.writeHead(200, { 'Content-Type': 'text/plain' })
34
- res.end('VectoriaDB Server')
35
- })
36
-
37
- this._io = new IOServer(this._http, {
38
- cors: { origin: this.cors.length ? this.cors : '*', methods: ['GET', 'POST'] },
39
- maxHttpBufferSize: 1e7,
40
- })
26
+ // fast-path: already started
27
+ if (this._started) return this
41
28
 
42
- const nsp = this._io.of('/vectoriadb')
29
+ // if a start is already in progress, return the same promise
30
+ if (this._startPromise) return this._startPromise
43
31
 
44
- nsp.use((socket, next) => {
45
- // simple API key auth if configured
46
- if (this.apiKey) {
47
- const provided = socket.handshake.auth?.apiKey || socket.handshake.query?.apiKey
48
- if (!provided || provided !== this.apiKey) {
49
- return next(new Error('Unauthorized'))
32
+ this._startPromise = (async () => {
33
+ try {
34
+ // Initialize VectoriaDB (loads models / storage as configured)
35
+ this._vectoria = new VectoriaDB(this.vectoriadbConfig)
36
+ if (typeof this._vectoria.initialize === 'function') {
37
+ await this._vectoria.initialize()
50
38
  }
51
- }
52
- next()
53
- })
54
-
55
- nsp.on('connection', socket => {
56
- this._sockets.add(socket)
57
- socket.on('disconnect', () => this._sockets.delete(socket))
58
39
 
59
- socket.on('request', async payload => {
60
- // payload: { id, method, params, collection, timestamp }
40
+ this._http = http.createServer((req, res) => {
41
+ res.writeHead(200, { 'Content-Type': 'text/plain' })
42
+ res.end('VectoriaDB Server')
43
+ })
44
+
45
+ this._io = new IOServer(this._http, {
46
+ cors: { origin: this.cors.length ? this.cors : '*', methods: ['GET', 'POST'] },
47
+ maxHttpBufferSize: 1e7,
48
+ })
49
+
50
+ const nsp = this._io.of('/vectoriadb')
51
+
52
+ nsp.use((socket, next) => {
53
+ // simple API key auth if configured
54
+ if (this.apiKey) {
55
+ const provided = socket.handshake.auth?.apiKey || socket.handshake.query?.apiKey
56
+ if (!provided || provided !== this.apiKey) {
57
+ return next(new Error('Unauthorized'))
58
+ }
59
+ }
60
+ next()
61
+ })
62
+
63
+ nsp.on('connection', socket => {
64
+ this._sockets.add(socket)
65
+ socket.on('disconnect', () => this._sockets.delete(socket))
66
+
67
+ socket.on('request', async payload => {
68
+ // payload: { id, method, params, collection, timestamp }
69
+ try {
70
+ await this._handleRequest(socket, payload)
71
+ } catch (err) {
72
+ socket.emit('response', { id: payload?.id ?? null, result: null, error: { message: err.message }, took: 0 })
73
+ }
74
+ })
75
+
76
+ // allow ping from client
77
+ socket.on('health', cb => cb && cb({ ok: true, ts: Date.now() }))
78
+ })
79
+
80
+ await new Promise((res, rej) => {
81
+ this._http.listen(this.port, this.host, err => (err ? rej(err) : res()))
82
+ })
83
+
84
+ this._started = true
85
+ console.log(`VectoriaDB Server listening on ${this.host}:${this.port}`)
86
+ return this
87
+ } catch (err) {
88
+ // cleanup partial resources on failure
61
89
  try {
62
- await this._handleRequest(socket, payload)
63
- } catch (err) {
64
- socket.emit('response', { id: payload?.id ?? null, result: null, error: { message: err.message }, took: 0 })
65
- }
66
- })
67
-
68
- // allow ping from client
69
- socket.on('health', cb => cb && cb({ ok: true, ts: Date.now() }))
70
- })
71
-
72
- await new Promise((res, rej) => {
73
- this._http.listen(this.port, this.host, err => (err ? rej(err) : res()))
74
- })
90
+ if (this._io) await this._io.close()
91
+ } catch (e) {}
92
+ try {
93
+ if (this._http) this._http.close(() => {})
94
+ } catch (e) {}
95
+ throw err
96
+ }
97
+ })()
75
98
 
76
- this._started = true
77
- console.log(`VectoriaDB Server listening on ${this.host}:${this.port}`)
78
- return this
99
+ try {
100
+ return await this._startPromise
101
+ } finally {
102
+ // ensure the in-progress marker is cleared after attempt completes
103
+ this._startPromise = null
104
+ }
79
105
  }
80
106
 
81
107
  async _handleRequest(socket, payload) {