@synapcores/sdk 0.2.1 → 0.4.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/CHANGELOG.md +108 -0
- package/README.md +10 -0
- package/dist/index.d.mts +172 -2
- package/dist/index.d.ts +172 -2
- package/dist/index.js +278 -33
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +277 -33
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -2
package/dist/index.js
CHANGED
|
@@ -62,6 +62,7 @@ __export(index_exports, {
|
|
|
62
62
|
Tx: () => Tx,
|
|
63
63
|
VERSION: () => VERSION,
|
|
64
64
|
ValidationError: () => ValidationError,
|
|
65
|
+
VectorCollection: () => VectorCollection,
|
|
65
66
|
VectorError: () => VectorError,
|
|
66
67
|
z: () => import_zod.z
|
|
67
68
|
});
|
|
@@ -316,20 +317,20 @@ var Collection = class {
|
|
|
316
317
|
}
|
|
317
318
|
async vectorSearch(options) {
|
|
318
319
|
const { data } = await this.client._getHttpClient().post(
|
|
319
|
-
|
|
320
|
+
`/vectors/collections/${this.name}/search`,
|
|
320
321
|
{
|
|
321
322
|
vector: options.vector,
|
|
322
|
-
|
|
323
|
-
top_k: options.topK || 10,
|
|
323
|
+
k: options.topK || 10,
|
|
324
324
|
filter: options.filter,
|
|
325
|
-
|
|
326
|
-
include_metadata: options.includeMetadata
|
|
325
|
+
include_metadata: options.includeMetadata !== false
|
|
327
326
|
}
|
|
328
327
|
);
|
|
328
|
+
const inner = data?.data ?? data;
|
|
329
|
+
const matches = Array.isArray(inner) ? inner : inner?.matches ?? inner?.results ?? inner?.documents ?? data?.matches ?? data?.results ?? data?.documents ?? [];
|
|
329
330
|
return {
|
|
330
|
-
documents:
|
|
331
|
-
total:
|
|
332
|
-
tookMs:
|
|
331
|
+
documents: matches,
|
|
332
|
+
total: (inner && !Array.isArray(inner) ? inner.total : void 0) ?? matches.length,
|
|
333
|
+
tookMs: (inner && !Array.isArray(inner) ? inner.took_ms : void 0) ?? data?.took_ms
|
|
333
334
|
};
|
|
334
335
|
}
|
|
335
336
|
async query(options = {}) {
|
|
@@ -394,6 +395,125 @@ var Collection = class {
|
|
|
394
395
|
}
|
|
395
396
|
};
|
|
396
397
|
|
|
398
|
+
// src/vector_collection.ts
|
|
399
|
+
var VectorCollection = class {
|
|
400
|
+
constructor(client, name) {
|
|
401
|
+
this.client = client;
|
|
402
|
+
this.name = name;
|
|
403
|
+
}
|
|
404
|
+
get basePath() {
|
|
405
|
+
return `/vectors/collections/${encodeURIComponent(this.name)}`;
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Insert one or more vectors.
|
|
409
|
+
*
|
|
410
|
+
* Wire: `POST /v1/vectors/collections/{name}/vectors` with
|
|
411
|
+
* `{ vectors: [{ id, values, metadata }] }`.
|
|
412
|
+
*
|
|
413
|
+
* Accepts either a single record or an array — the SDK always sends
|
|
414
|
+
* the wrapped `{ vectors: [...] }` envelope the gateway expects.
|
|
415
|
+
*/
|
|
416
|
+
async insert(records) {
|
|
417
|
+
const vectors = Array.isArray(records) ? records : [records];
|
|
418
|
+
const { data } = await this.client._getHttpClient().post(
|
|
419
|
+
`${this.basePath}/vectors`,
|
|
420
|
+
{ vectors }
|
|
421
|
+
);
|
|
422
|
+
return data?.data ?? data;
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* k-NN search over the vector collection.
|
|
426
|
+
*
|
|
427
|
+
* Wire: `POST /v1/vectors/collections/{name}/search` with
|
|
428
|
+
* `{ vector, k, include_metadata, filter? }`.
|
|
429
|
+
*
|
|
430
|
+
* Returns the bare array of hits — gateway envelope (`{data: [...]}`) is
|
|
431
|
+
* unwrapped automatically for parity with `Collection.vectorSearch`.
|
|
432
|
+
*/
|
|
433
|
+
async search(options) {
|
|
434
|
+
const k = options.k ?? options.topK ?? 10;
|
|
435
|
+
const body = {
|
|
436
|
+
vector: options.vector,
|
|
437
|
+
k,
|
|
438
|
+
include_metadata: options.includeMetadata !== false
|
|
439
|
+
};
|
|
440
|
+
if (options.filter !== void 0) body.filter = options.filter;
|
|
441
|
+
const { data } = await this.client._getHttpClient().post(
|
|
442
|
+
`${this.basePath}/search`,
|
|
443
|
+
body
|
|
444
|
+
);
|
|
445
|
+
const inner = data?.data ?? data;
|
|
446
|
+
if (Array.isArray(inner)) return inner;
|
|
447
|
+
return inner?.matches ?? inner?.results ?? inner?.hits ?? [];
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Fetch a single vector by id.
|
|
451
|
+
*
|
|
452
|
+
* Wire: `GET /v1/vectors/collections/{name}/vectors/{id}`. Returns the
|
|
453
|
+
* gateway payload `{ id, values, metadata }` (envelope unwrapped) or
|
|
454
|
+
* `null` on 404.
|
|
455
|
+
*/
|
|
456
|
+
async get(id) {
|
|
457
|
+
try {
|
|
458
|
+
const { data } = await this.client._getHttpClient().get(
|
|
459
|
+
`${this.basePath}/vectors/${encodeURIComponent(id)}`
|
|
460
|
+
);
|
|
461
|
+
return data?.data ?? data;
|
|
462
|
+
} catch (err) {
|
|
463
|
+
if (err?.code === "NOT_FOUND" || err?.status === 404) return null;
|
|
464
|
+
throw err;
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
/**
|
|
468
|
+
* Delete one or more vectors by id.
|
|
469
|
+
*
|
|
470
|
+
* Single-id wire: `DELETE /v1/vectors/collections/{name}/vectors/{id}`.
|
|
471
|
+
* Bulk wire: `DELETE /v1/vectors/collections/{name}/vectors` with
|
|
472
|
+
* `{ ids: [...] }` body.
|
|
473
|
+
*/
|
|
474
|
+
async delete(ids) {
|
|
475
|
+
if (typeof ids === "string") {
|
|
476
|
+
const { data: data2 } = await this.client._getHttpClient().delete(
|
|
477
|
+
`${this.basePath}/vectors/${encodeURIComponent(ids)}`
|
|
478
|
+
);
|
|
479
|
+
return data2?.data ?? data2;
|
|
480
|
+
}
|
|
481
|
+
const { data } = await this.client._getHttpClient().request({
|
|
482
|
+
method: "DELETE",
|
|
483
|
+
url: `${this.basePath}/vectors`,
|
|
484
|
+
data: { ids }
|
|
485
|
+
});
|
|
486
|
+
return data?.data ?? data;
|
|
487
|
+
}
|
|
488
|
+
/**
|
|
489
|
+
* Vector count.
|
|
490
|
+
*
|
|
491
|
+
* Wire: `GET /v1/vectors/collections/{name}/count` if the gateway
|
|
492
|
+
* exposes it, otherwise falls back to `info().vector_count`.
|
|
493
|
+
*/
|
|
494
|
+
async count() {
|
|
495
|
+
try {
|
|
496
|
+
const { data } = await this.client._getHttpClient().get(`${this.basePath}/count`);
|
|
497
|
+
const inner = data?.data ?? data;
|
|
498
|
+
const n = typeof inner === "number" ? inner : inner?.count ?? inner?.vector_count;
|
|
499
|
+
if (typeof n === "number") return n;
|
|
500
|
+
} catch {
|
|
501
|
+
}
|
|
502
|
+
const info = await this.info();
|
|
503
|
+
return typeof info?.vector_count === "number" ? info.vector_count : 0;
|
|
504
|
+
}
|
|
505
|
+
/**
|
|
506
|
+
* Collection metadata.
|
|
507
|
+
*
|
|
508
|
+
* Wire: `GET /v1/vectors/collections/{name}` returning
|
|
509
|
+
* `{ name, dimensions, vector_count, distance_metric, index_type }`.
|
|
510
|
+
*/
|
|
511
|
+
async info() {
|
|
512
|
+
const { data } = await this.client._getHttpClient().get(this.basePath);
|
|
513
|
+
return data?.data ?? data;
|
|
514
|
+
}
|
|
515
|
+
};
|
|
516
|
+
|
|
397
517
|
// src/automl.ts
|
|
398
518
|
var AutoMLModel = class {
|
|
399
519
|
constructor(client, info) {
|
|
@@ -467,27 +587,48 @@ var AutoMLClient = class {
|
|
|
467
587
|
return new AutoMLModel(this, modelInfo);
|
|
468
588
|
}
|
|
469
589
|
async getModel(modelId) {
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
590
|
+
try {
|
|
591
|
+
const { data } = await this.synapCores._getHttpClient().get(
|
|
592
|
+
`/automl/models/${modelId}`
|
|
593
|
+
);
|
|
594
|
+
const m = data?.data ?? data;
|
|
595
|
+
const modelInfo = {
|
|
596
|
+
id: m.id ?? modelId,
|
|
597
|
+
name: m.name ?? modelId,
|
|
598
|
+
task: m.task,
|
|
599
|
+
status: m.status,
|
|
600
|
+
accuracy: m.accuracy,
|
|
601
|
+
createdAt: new Date(m.created_at ?? Date.now()),
|
|
602
|
+
updatedAt: m.updated_at ? new Date(m.updated_at) : void 0,
|
|
603
|
+
config: m.config ?? {}
|
|
604
|
+
};
|
|
605
|
+
return new AutoMLModel(this, modelInfo);
|
|
606
|
+
} catch (err) {
|
|
607
|
+
const status = err?.statusCode ?? err?.response?.status;
|
|
608
|
+
const code = err?.code;
|
|
609
|
+
if (status === 404 || code === "NOT_FOUND") {
|
|
610
|
+
const modelInfo = {
|
|
611
|
+
id: modelId,
|
|
612
|
+
name: modelId,
|
|
613
|
+
task: void 0,
|
|
614
|
+
status: "unknown",
|
|
615
|
+
accuracy: void 0,
|
|
616
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
617
|
+
updatedAt: void 0,
|
|
618
|
+
config: {}
|
|
619
|
+
};
|
|
620
|
+
return new AutoMLModel(this, modelInfo);
|
|
621
|
+
}
|
|
622
|
+
throw err;
|
|
623
|
+
}
|
|
484
624
|
}
|
|
485
625
|
async listModels(filters) {
|
|
486
626
|
const { data } = await this.synapCores._getHttpClient().get("/automl/models", {
|
|
487
627
|
params: filters
|
|
488
628
|
});
|
|
489
|
-
|
|
490
|
-
|
|
629
|
+
const list = Array.isArray(data) ? data : Array.isArray(data?.data) ? data.data : Array.isArray(data?.models) ? data.models : Array.isArray(data?.data?.items) ? data.data.items : [];
|
|
630
|
+
return list.map((model) => ({
|
|
631
|
+
id: model.id ?? model.name,
|
|
491
632
|
name: model.name,
|
|
492
633
|
task: model.task,
|
|
493
634
|
status: model.status,
|
|
@@ -1998,23 +2139,24 @@ var GraphsApi = class {
|
|
|
1998
2139
|
constructor(synapCores) {
|
|
1999
2140
|
this.synapCores = synapCores;
|
|
2000
2141
|
}
|
|
2142
|
+
// v0.3.0: gateway routes live under /graph/graphs, not /graphs.
|
|
2001
2143
|
async list() {
|
|
2002
|
-
const { data } = await this.synapCores._getHttpClient().get("/graphs");
|
|
2144
|
+
const { data } = await this.synapCores._getHttpClient().get("/graph/graphs");
|
|
2003
2145
|
return (data.graphs ?? data ?? []).map((g) => this.normalize(g));
|
|
2004
2146
|
}
|
|
2005
2147
|
async create(name, opts = {}) {
|
|
2006
|
-
const { data } = await this.synapCores._getHttpClient().post("/graphs", {
|
|
2148
|
+
const { data } = await this.synapCores._getHttpClient().post("/graph/graphs", {
|
|
2007
2149
|
name,
|
|
2008
2150
|
description: opts.description
|
|
2009
2151
|
});
|
|
2010
2152
|
return this.normalize(data);
|
|
2011
2153
|
}
|
|
2012
2154
|
async get(name) {
|
|
2013
|
-
const { data } = await this.synapCores._getHttpClient().get(`/graphs/${name}`);
|
|
2155
|
+
const { data } = await this.synapCores._getHttpClient().get(`/graph/graphs/${name}`);
|
|
2014
2156
|
return this.normalize(data);
|
|
2015
2157
|
}
|
|
2016
2158
|
async delete(name) {
|
|
2017
|
-
await this.synapCores._getHttpClient().delete(`/graphs/${name}`);
|
|
2159
|
+
await this.synapCores._getHttpClient().delete(`/graph/graphs/${name}`);
|
|
2018
2160
|
}
|
|
2019
2161
|
normalize(data) {
|
|
2020
2162
|
return {
|
|
@@ -2813,6 +2955,20 @@ var SynapCores = class {
|
|
|
2813
2955
|
this.collectionsCache = /* @__PURE__ */ new Map();
|
|
2814
2956
|
this.currentTransaction = null;
|
|
2815
2957
|
this.preparedStatements = /* @__PURE__ */ new Map();
|
|
2958
|
+
// =================================================================
|
|
2959
|
+
// VECTOR COLLECTIONS — /v1/vectors/collections/{name}
|
|
2960
|
+
//
|
|
2961
|
+
// The gateway exposes two parallel "collection" worlds:
|
|
2962
|
+
// (a) document-store collections under /v1/collections (above), and
|
|
2963
|
+
// (b) vector collections under /v1/vectors/collections (below).
|
|
2964
|
+
//
|
|
2965
|
+
// v0.3.0 only wrapped (a) so vector-first users had to drop down to
|
|
2966
|
+
// `_getHttpClient()` to call (b) directly. v0.4.0 adds first-class
|
|
2967
|
+
// helpers — `createVectorCollection`, `vectorCollection(name)`,
|
|
2968
|
+
// `listVectorCollections`, `deleteVectorCollection` — that target (b)
|
|
2969
|
+
// and return a typed `VectorCollection` handle.
|
|
2970
|
+
// =================================================================
|
|
2971
|
+
this.vectorCollectionsCache = /* @__PURE__ */ new Map();
|
|
2816
2972
|
this.config = {
|
|
2817
2973
|
host: config.host || "localhost",
|
|
2818
2974
|
port: config.port || 8080,
|
|
@@ -2835,14 +2991,14 @@ var SynapCores = class {
|
|
|
2835
2991
|
if (this.config.jwtToken) {
|
|
2836
2992
|
authHeader["Authorization"] = `Bearer ${this.config.jwtToken}`;
|
|
2837
2993
|
} else if (this.config.apiKey) {
|
|
2838
|
-
authHeader["
|
|
2994
|
+
authHeader["Authorization"] = `Bearer ${this.config.apiKey}`;
|
|
2839
2995
|
}
|
|
2840
2996
|
this.httpClient = import_axios.default.create({
|
|
2841
2997
|
baseURL,
|
|
2842
2998
|
timeout: this.config.timeout,
|
|
2843
2999
|
headers: {
|
|
2844
3000
|
"Content-Type": "application/json",
|
|
2845
|
-
"User-Agent": "synapcores-nodejs/0.
|
|
3001
|
+
"User-Agent": "synapcores-nodejs/0.4.0",
|
|
2846
3002
|
...authHeader
|
|
2847
3003
|
},
|
|
2848
3004
|
...httpsAgent && { httpsAgent }
|
|
@@ -3008,15 +3164,35 @@ var SynapCores = class {
|
|
|
3008
3164
|
this.collectionsCache.set(name, collection);
|
|
3009
3165
|
return collection;
|
|
3010
3166
|
}
|
|
3167
|
+
/**
|
|
3168
|
+
* Synchronous accessor that returns a Collection handle without round-tripping
|
|
3169
|
+
* to the gateway. Use this when you already know the collection exists and just
|
|
3170
|
+
* want to issue a vectorSearch / search / insert against it.
|
|
3171
|
+
*
|
|
3172
|
+
* v0.3.0: added so `client.collection(name).vectorSearch(...)` works without
|
|
3173
|
+
* a preceding await on getCollection().
|
|
3174
|
+
*/
|
|
3175
|
+
collection(name) {
|
|
3176
|
+
if (this.collectionsCache.has(name)) {
|
|
3177
|
+
return this.collectionsCache.get(name);
|
|
3178
|
+
}
|
|
3179
|
+
const c = new Collection(this, name);
|
|
3180
|
+
this.collectionsCache.set(name, c);
|
|
3181
|
+
return c;
|
|
3182
|
+
}
|
|
3011
3183
|
/**
|
|
3012
3184
|
* List collections (legacy method for backward compatibility)
|
|
3013
3185
|
*/
|
|
3014
3186
|
async listCollections() {
|
|
3015
3187
|
const result = await this.listCollectionsDetailed();
|
|
3016
|
-
return result.collections.map((c) => c.name);
|
|
3188
|
+
return (result.collections ?? []).map((c) => c.name);
|
|
3017
3189
|
}
|
|
3018
3190
|
/**
|
|
3019
3191
|
* List collections with detailed information matching the database integration guide format
|
|
3192
|
+
*
|
|
3193
|
+
* v0.3.0: gateway returns an envelope { data: { items, total, page, page_size, ... }, meta }.
|
|
3194
|
+
* We normalise that into the SDK's { collections, total, page, pageSize } shape and also
|
|
3195
|
+
* accept legacy { collections: [...] } / bare arrays for forward-compat.
|
|
3020
3196
|
*/
|
|
3021
3197
|
async listCollectionsDetailed(options) {
|
|
3022
3198
|
const params = new URLSearchParams();
|
|
@@ -3028,7 +3204,14 @@ var SynapCores = class {
|
|
|
3028
3204
|
const { data } = await this.httpClient.get(
|
|
3029
3205
|
`/collections${params.toString() ? `?${params.toString()}` : ""}`
|
|
3030
3206
|
);
|
|
3031
|
-
|
|
3207
|
+
const inner = data?.data ?? data;
|
|
3208
|
+
const items = Array.isArray(inner) ? inner : inner?.items ?? inner?.collections ?? [];
|
|
3209
|
+
return {
|
|
3210
|
+
collections: items,
|
|
3211
|
+
total: inner?.total ?? items.length,
|
|
3212
|
+
page: inner?.page ?? 1,
|
|
3213
|
+
pageSize: inner?.page_size ?? inner?.pageSize ?? items.length
|
|
3214
|
+
};
|
|
3032
3215
|
}
|
|
3033
3216
|
async getDocuments(collectionName, page, pageSize) {
|
|
3034
3217
|
const { data } = await this.httpClient.get(
|
|
@@ -3040,6 +3223,67 @@ var SynapCores = class {
|
|
|
3040
3223
|
await this.httpClient.delete(`/collections/${name}`);
|
|
3041
3224
|
this.collectionsCache.delete(name);
|
|
3042
3225
|
}
|
|
3226
|
+
/**
|
|
3227
|
+
* Create a vector collection.
|
|
3228
|
+
*
|
|
3229
|
+
* Wire: `POST /v1/vectors/collections` with
|
|
3230
|
+
* `{ name, dimensions, distance_metric }`. Distinct from
|
|
3231
|
+
* `createCollection`, which targets the document-store subsystem.
|
|
3232
|
+
*
|
|
3233
|
+
* @example
|
|
3234
|
+
* const coll = await client.createVectorCollection({
|
|
3235
|
+
* name: 'memory_v1', dimensions: 1536, distance_metric: 'cosine',
|
|
3236
|
+
* });
|
|
3237
|
+
* await coll.insert({ id: 'v1', values: [...], metadata: { ... } });
|
|
3238
|
+
*/
|
|
3239
|
+
async createVectorCollection(options) {
|
|
3240
|
+
await this.httpClient.post("/vectors/collections", {
|
|
3241
|
+
name: options.name,
|
|
3242
|
+
dimensions: options.dimensions,
|
|
3243
|
+
distance_metric: options.distance_metric ?? "cosine"
|
|
3244
|
+
});
|
|
3245
|
+
const coll = new VectorCollection(this, options.name);
|
|
3246
|
+
this.vectorCollectionsCache.set(options.name, coll);
|
|
3247
|
+
return coll;
|
|
3248
|
+
}
|
|
3249
|
+
/**
|
|
3250
|
+
* Synchronous accessor for an existing vector collection. Does not
|
|
3251
|
+
* round-trip to the gateway — use `createVectorCollection` if you
|
|
3252
|
+
* need to provision the collection first, or `listVectorCollections`
|
|
3253
|
+
* to confirm existence.
|
|
3254
|
+
*
|
|
3255
|
+
* v0.4.0 split: this targets the **vector subsystem**
|
|
3256
|
+
* (`/v1/vectors/collections/{name}`). `client.collection(name)` still
|
|
3257
|
+
* returns a document-store `Collection` for the legacy subsystem.
|
|
3258
|
+
*/
|
|
3259
|
+
vectorCollection(name) {
|
|
3260
|
+
const cached = this.vectorCollectionsCache.get(name);
|
|
3261
|
+
if (cached) return cached;
|
|
3262
|
+
const coll = new VectorCollection(this, name);
|
|
3263
|
+
this.vectorCollectionsCache.set(name, coll);
|
|
3264
|
+
return coll;
|
|
3265
|
+
}
|
|
3266
|
+
/**
|
|
3267
|
+
* List vector collections.
|
|
3268
|
+
*
|
|
3269
|
+
* Wire: `GET /v1/vectors/collections`. Returns the bare array of
|
|
3270
|
+
* collection-info objects (envelope unwrapped).
|
|
3271
|
+
*/
|
|
3272
|
+
async listVectorCollections() {
|
|
3273
|
+
const { data } = await this.httpClient.get("/vectors/collections");
|
|
3274
|
+
const inner = data?.data ?? data;
|
|
3275
|
+
if (Array.isArray(inner)) return inner;
|
|
3276
|
+
return inner?.items ?? inner?.collections ?? [];
|
|
3277
|
+
}
|
|
3278
|
+
/**
|
|
3279
|
+
* Delete a vector collection.
|
|
3280
|
+
*
|
|
3281
|
+
* Wire: `DELETE /v1/vectors/collections/{name}`.
|
|
3282
|
+
*/
|
|
3283
|
+
async deleteVectorCollection(name) {
|
|
3284
|
+
await this.httpClient.delete(`/vectors/collections/${encodeURIComponent(name)}`);
|
|
3285
|
+
this.vectorCollectionsCache.delete(name);
|
|
3286
|
+
}
|
|
3043
3287
|
/**
|
|
3044
3288
|
* Execute SQL query (legacy method for backward compatibility)
|
|
3045
3289
|
* @deprecated Use executeQuery for new code
|
|
@@ -3954,7 +4198,7 @@ var SynapCores = class {
|
|
|
3954
4198
|
|
|
3955
4199
|
// src/index.ts
|
|
3956
4200
|
var import_zod = require("zod");
|
|
3957
|
-
var VERSION = "0.
|
|
4201
|
+
var VERSION = "0.4.0";
|
|
3958
4202
|
// Annotate the CommonJS export names for ESM import in node:
|
|
3959
4203
|
0 && (module.exports = {
|
|
3960
4204
|
AuthenticationError,
|
|
@@ -3989,6 +4233,7 @@ var VERSION = "0.2.0";
|
|
|
3989
4233
|
Tx,
|
|
3990
4234
|
VERSION,
|
|
3991
4235
|
ValidationError,
|
|
4236
|
+
VectorCollection,
|
|
3992
4237
|
VectorError,
|
|
3993
4238
|
z
|
|
3994
4239
|
});
|