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.
@@ -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
+ [![Follow hlquery](https://img.shields.io/badge/Follow-%40hlquery-blue?logo=x&logoColor=white)](https://x.com/hlquery)
10
+ [![Commit Activity](https://img.shields.io/github/commit-activity/m/hlquery/node-api)](https://github.com/hlquery/node-api/pulse)
11
+ [![node-api](https://img.shields.io/badge/GitHub-node--api-181717?logo=github&logoColor=white)](https://github.com/hlquery/node-api/stargazers)
12
+ [![License](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](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.