hlquery-node-client 1.0.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.
- package/.github/workflows/ci.yml +37 -0
- package/LICENSE +29 -0
- package/README.md +316 -0
- package/example.js +636 -0
- package/examples/basic_usage.js +35 -0
- package/examples/collections.js +40 -0
- package/examples/csv.js +39 -0
- package/examples/documents.js +54 -0
- package/examples/flush.js +128 -0
- package/examples/keys.js +58 -0
- package/examples/pdf.js +40 -0
- package/examples/search.js +101 -0
- package/examples/vector.js +465 -0
- package/index.js +39 -0
- package/lib/Aliases.js +48 -0
- package/lib/Client.js +623 -0
- package/lib/Collections.js +159 -0
- package/lib/Documents.js +244 -0
- package/lib/Exceptions.js +101 -0
- package/lib/Keys.js +85 -0
- package/lib/Overrides.js +53 -0
- package/lib/Request.js +147 -0
- package/lib/Response.js +54 -0
- package/lib/Search.js +350 -0
- package/lib/Stopwords.js +60 -0
- package/lib/Synonyms.js +85 -0
- package/lib/System.js +110 -0
- package/lib/conformance.js +74 -0
- package/package.json +42 -0
- package/test/offline-smoke.js +86 -0
- package/utils/Auth.js +34 -0
- package/utils/CSVParser.js +160 -0
- package/utils/Config.js +57 -0
- package/utils/PDFParser.js +196 -0
- package/utils/Validator.js +143 -0
- package/utils/ranker.js +51 -0
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
name: Node API CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main, master, unstable ]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [ main, master, unstable ]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
test:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
env:
|
|
14
|
+
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
|
|
15
|
+
strategy:
|
|
16
|
+
matrix:
|
|
17
|
+
node-version: [18, 20, 22]
|
|
18
|
+
|
|
19
|
+
steps:
|
|
20
|
+
- name: Checkout
|
|
21
|
+
uses: actions/checkout@v5
|
|
22
|
+
|
|
23
|
+
- name: Setup Node.js
|
|
24
|
+
uses: actions/setup-node@v6
|
|
25
|
+
with:
|
|
26
|
+
node-version: ${{ matrix.node-version }}
|
|
27
|
+
cache: npm
|
|
28
|
+
cache-dependency-path: ./package-lock.json
|
|
29
|
+
|
|
30
|
+
- name: Install dependencies
|
|
31
|
+
run: npm ci
|
|
32
|
+
|
|
33
|
+
- name: Run offline smoke tests
|
|
34
|
+
run: npm run test:offline
|
|
35
|
+
|
|
36
|
+
- name: Validate package entry point
|
|
37
|
+
run: node -e "const sdk=require('./'); if (typeof sdk !== 'function') process.exit(1); console.log('entry point OK')"
|
package/LICENSE
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2021-2026, Carlos F. Ferry <carlos.ferry@gmail.com>
|
|
4
|
+
All rights reserved.
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
ADDED
|
@@ -0,0 +1,316 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
<img src="https://docs.hlquery.com/img/hlquery/2.png" alt="hlquery logo" width="200">
|
|
3
|
+
</div>
|
|
4
|
+
|
|
5
|
+
<div align="center">
|
|
6
|
+
|
|
7
|
+
**A modular Node.js client library for hlquery.**
|
|
8
|
+
|
|
9
|
+
[](https://x.com/hlquery)
|
|
10
|
+
[](https://github.com/hlquery/node-api/pulse)
|
|
11
|
+
[](https://github.com/hlquery/node-api/stargazers)
|
|
12
|
+
[](https://opensource.org/licenses/BSD-3-Clause)
|
|
13
|
+
|
|
14
|
+
</div>
|
|
15
|
+
|
|
16
|
+
# hlquery Node.js API Client
|
|
17
|
+
|
|
18
|
+
### Installation
|
|
19
|
+
|
|
20
|
+
Core client usage has no external dependencies. CSV support is built in.
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
npm install hlquery-node-client
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
```javascript
|
|
27
|
+
const Client = require('hlquery-node-client');
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
For local development in this repository:
|
|
31
|
+
|
|
32
|
+
```javascript
|
|
33
|
+
const Client = require('./lib/Client');
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Quick Start
|
|
37
|
+
|
|
38
|
+
```javascript
|
|
39
|
+
const Client = require('hlquery-node-client');
|
|
40
|
+
|
|
41
|
+
const client = new Client(process.env.HLQ_BASE_URL || 'http://localhost:9200', {
|
|
42
|
+
token: process.env.HLQ_TOKEN,
|
|
43
|
+
auth_method: 'bearer' // or 'api-key'
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
const health = await client.system().health();
|
|
47
|
+
console.log('status:', health.getStatusCode());
|
|
48
|
+
|
|
49
|
+
const collections = await client.collections().list(0, 10);
|
|
50
|
+
console.log(collections.getBody());
|
|
51
|
+
|
|
52
|
+
await client.collections().create('books', {
|
|
53
|
+
fields: [
|
|
54
|
+
{ name: 'title', type: 'string' },
|
|
55
|
+
{ name: 'content', type: 'string' }
|
|
56
|
+
]
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
await client.documents().add('books', {
|
|
60
|
+
id: 'book-1',
|
|
61
|
+
title: 'Designing Data-Intensive Applications',
|
|
62
|
+
content: 'Distributed systems, data models, replication, and indexing.'
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
const results = await client.searchApi().search('books', {
|
|
66
|
+
q: 'distributed systems',
|
|
67
|
+
query_by: 'title,content',
|
|
68
|
+
limit: 10
|
|
69
|
+
});
|
|
70
|
+
console.log(results.getBody());
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
You can also set authentication later:
|
|
74
|
+
|
|
75
|
+
```javascript
|
|
76
|
+
client.setAuthToken('your_token_here', 'bearer');
|
|
77
|
+
client.setAuthToken('your_api_key_here', 'api-key');
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
### API Surface
|
|
81
|
+
|
|
82
|
+
Use nested API objects: `client -> resource -> action`, for example `client.collections().create(...)`.
|
|
83
|
+
|
|
84
|
+
```javascript
|
|
85
|
+
client.system().health();
|
|
86
|
+
client.system().stats();
|
|
87
|
+
client.system().info();
|
|
88
|
+
client.system().status();
|
|
89
|
+
client.system().metrics();
|
|
90
|
+
client.system().connections();
|
|
91
|
+
client.system().rocksdb();
|
|
92
|
+
|
|
93
|
+
client.collections().list(offset, limit);
|
|
94
|
+
client.collections().get(name);
|
|
95
|
+
client.collections().create(name, schema);
|
|
96
|
+
client.collections().update(name, schema);
|
|
97
|
+
client.collections().delete(name);
|
|
98
|
+
client.collections().getFields(name);
|
|
99
|
+
|
|
100
|
+
client.documents().list(collection, params);
|
|
101
|
+
client.documents().get(collection, id);
|
|
102
|
+
client.documents().add(collection, document);
|
|
103
|
+
client.documents().update(collection, id, document);
|
|
104
|
+
client.documents().delete(collection, id);
|
|
105
|
+
client.documents().import(collection, documents);
|
|
106
|
+
client.documents().export(collection, params);
|
|
107
|
+
client.documents().facetCounts(collection, params);
|
|
108
|
+
client.documents().addCSV(collection, filePath, options);
|
|
109
|
+
|
|
110
|
+
client.searchApi().search(collection, params);
|
|
111
|
+
client.searchApi().vectorSearch(collection, params);
|
|
112
|
+
client.searchApi().multiSearch(searches);
|
|
113
|
+
client.searchApi().globalSearch(params);
|
|
114
|
+
client.searchApi().sql(collection, sql);
|
|
115
|
+
|
|
116
|
+
client.aliases().create(name, params);
|
|
117
|
+
client.aliases().update(name, params);
|
|
118
|
+
client.aliases().delete(name);
|
|
119
|
+
client.synonyms().create(collection, id, synonym);
|
|
120
|
+
client.stopwords().create(collection, params);
|
|
121
|
+
client.overrides().create(collection, id, override);
|
|
122
|
+
client.keys().create(params);
|
|
123
|
+
client.executeRequest(method, path, body, query);
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Collections
|
|
127
|
+
|
|
128
|
+
```javascript
|
|
129
|
+
const collections = client.collections();
|
|
130
|
+
|
|
131
|
+
await collections.create('books', {
|
|
132
|
+
fields: [
|
|
133
|
+
{ name: 'title', type: 'string' },
|
|
134
|
+
{ name: 'content', type: 'string' },
|
|
135
|
+
{ name: 'category', type: 'string', facet: true }
|
|
136
|
+
]
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
await collections.get('books');
|
|
140
|
+
await collections.getFields('books');
|
|
141
|
+
await collections.update('books', schema);
|
|
142
|
+
await collections.delete('books');
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Documents
|
|
146
|
+
|
|
147
|
+
```javascript
|
|
148
|
+
const documents = client.documents();
|
|
149
|
+
|
|
150
|
+
await documents.add('books', {
|
|
151
|
+
id: 'book-1',
|
|
152
|
+
title: 'Designing Data-Intensive Applications',
|
|
153
|
+
content: 'Distributed systems, data models, replication, and indexing.'
|
|
154
|
+
});
|
|
155
|
+
|
|
156
|
+
await documents.update('books', 'book-1', { title: 'DDIA' });
|
|
157
|
+
await documents.delete('books', 'book-1');
|
|
158
|
+
|
|
159
|
+
await documents.import('books', [
|
|
160
|
+
{ id: 'book-2', title: 'Database Internals', content: 'Storage engines and indexes.' }
|
|
161
|
+
]);
|
|
162
|
+
|
|
163
|
+
await documents.addCSV('reports', './files/metrics.csv', {
|
|
164
|
+
id: 'metrics_q1',
|
|
165
|
+
document: { source_type: 'csv' }
|
|
166
|
+
});
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
`addCSV()` parses a local CSV file, flattens rows into text, and indexes the generated document. It does not require extra packages.
|
|
170
|
+
|
|
171
|
+
### Search
|
|
172
|
+
|
|
173
|
+
```javascript
|
|
174
|
+
const search = client.searchApi();
|
|
175
|
+
|
|
176
|
+
await search.search('books', {
|
|
177
|
+
q: 'title:database OR content:index*',
|
|
178
|
+
query_by: 'title,content',
|
|
179
|
+
filter_by: 'category:technical',
|
|
180
|
+
sort_by: '_text_match:desc',
|
|
181
|
+
facet_by: 'category',
|
|
182
|
+
limit: 10,
|
|
183
|
+
offset: 0
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
await search.multiSearch([
|
|
187
|
+
{ collection: 'books', q: 'database', query_by: 'title,content' },
|
|
188
|
+
{ collection: 'articles', q: 'database', query_by: 'title,body' }
|
|
189
|
+
]);
|
|
190
|
+
|
|
191
|
+
await search.vectorSearch('books', {
|
|
192
|
+
vector_query: [0.12, 0.34, 0.56],
|
|
193
|
+
vector_by: 'embedding',
|
|
194
|
+
limit: 10
|
|
195
|
+
});
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
Common search parameters:
|
|
199
|
+
|
|
200
|
+
- `q`: query string, including field clauses, phrases, boolean operators, and wildcards.
|
|
201
|
+
- `query_by`: searchable fields as a string or array.
|
|
202
|
+
- `filter_by`: filter expression.
|
|
203
|
+
- `sort_by`: sort expression.
|
|
204
|
+
- `facet_by`: facet fields.
|
|
205
|
+
- `limit` / `offset`: pagination.
|
|
206
|
+
- `page` / `per_page`: alternate pagination.
|
|
207
|
+
|
|
208
|
+
### SQL
|
|
209
|
+
|
|
210
|
+
SQL queries are supported through the search API and through the interactive talk shell.
|
|
211
|
+
|
|
212
|
+
```javascript
|
|
213
|
+
const response = await client.searchApi().sql(
|
|
214
|
+
'products',
|
|
215
|
+
'SELECT id, title, price FROM products ORDER BY price DESC LIMIT 5;'
|
|
216
|
+
);
|
|
217
|
+
|
|
218
|
+
const rows = response.getBody().rows || [];
|
|
219
|
+
|
|
220
|
+
await client.sql('SHOW COLLECTIONS;');
|
|
221
|
+
await client.execSql("INSERT INTO products (id, title) VALUES ('sku-9', 'Camp Stove');");
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
Talk shell example:
|
|
225
|
+
|
|
226
|
+
```text
|
|
227
|
+
localhost:9200> sql: select title,id from music LIMIT 2;
|
|
228
|
+
|
|
229
|
+
SQL rows for `select title,id from music LIMIT 2;`:
|
|
230
|
+
+--------------------------------+------------------------------------------+
|
|
231
|
+
| id | title |
|
|
232
|
+
+--------------------------------+------------------------------------------+
|
|
233
|
+
| music_artist-profile-beyonce | Artist Profile: Beyonce |
|
|
234
|
+
| music_artist-profile-kendrick- | Artist Profile: Kendrick Lamar |
|
|
235
|
+
| lamar | |
|
|
236
|
+
+--------------------------------+------------------------------------------+
|
|
237
|
+
2 results shown.
|
|
238
|
+
Search completed in 19 ms.
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Search Management
|
|
242
|
+
|
|
243
|
+
```javascript
|
|
244
|
+
const aliases = client.aliases();
|
|
245
|
+
const synonyms = client.synonyms();
|
|
246
|
+
const stopwords = client.stopwords();
|
|
247
|
+
const overrides = client.overrides();
|
|
248
|
+
|
|
249
|
+
await aliases.create('books_current', { collection_name: 'books_v2' });
|
|
250
|
+
|
|
251
|
+
await synonyms.create('books', 'cars', {
|
|
252
|
+
root: 'car',
|
|
253
|
+
synonyms: ['auto', 'automobile']
|
|
254
|
+
});
|
|
255
|
+
|
|
256
|
+
await stopwords.create('books', { word: 'the' });
|
|
257
|
+
|
|
258
|
+
await overrides.create('books', 'boost_featured', {
|
|
259
|
+
rule: { query: 'featured', match: 'exact' },
|
|
260
|
+
includes: [{ id: 'doc-1', position: 1 }],
|
|
261
|
+
excludes: []
|
|
262
|
+
});
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
### Responses
|
|
266
|
+
|
|
267
|
+
All API methods return a `Response` object.
|
|
268
|
+
|
|
269
|
+
```javascript
|
|
270
|
+
const response = await client.system().health();
|
|
271
|
+
|
|
272
|
+
response.getStatusCode();
|
|
273
|
+
response.getBody();
|
|
274
|
+
response.isSuccess();
|
|
275
|
+
response.isError();
|
|
276
|
+
response.getError();
|
|
277
|
+
response.toArray();
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Errors
|
|
281
|
+
|
|
282
|
+
```javascript
|
|
283
|
+
const { RequestException, AuthenticationException, ValidationException } = require('./lib/Exceptions');
|
|
284
|
+
|
|
285
|
+
try {
|
|
286
|
+
const result = await client.searchApi().search('books', { q: 'test' });
|
|
287
|
+
if (result.isError()) {
|
|
288
|
+
console.log(result.getError());
|
|
289
|
+
}
|
|
290
|
+
} catch (error) {
|
|
291
|
+
if (error instanceof RequestException) {
|
|
292
|
+
console.log('request failed:', error.message, error.statusCode);
|
|
293
|
+
} else if (error instanceof AuthenticationException) {
|
|
294
|
+
console.log('auth failed:', error.message);
|
|
295
|
+
} else if (error instanceof ValidationException) {
|
|
296
|
+
console.log('validation failed:', error.message);
|
|
297
|
+
} else {
|
|
298
|
+
throw error;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
### Requirements
|
|
304
|
+
|
|
305
|
+
- Node.js >= 12.0.0
|
|
306
|
+
- No external dependencies required for core client usage
|
|
307
|
+
|
|
308
|
+
### Features
|
|
309
|
+
|
|
310
|
+
- Modular classes for collections, documents, search, aliases, overrides, synonyms, stopwords, and system APIs.
|
|
311
|
+
- Bearer token and X-API-Key authentication.
|
|
312
|
+
- Flexible parameter formats.
|
|
313
|
+
- Automatic searchable-field detection when fields are not specified.
|
|
314
|
+
- SQL helpers for collection-bound and top-level SQL execution.
|
|
315
|
+
- Response wrapper with status, body, and error helpers.
|
|
316
|
+
- Built-in validation and async/await support.
|