@synapseone/sdk 0.0.0-stage → 0.7.0-dev.43
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/LICENSE +199 -0
- package/README.md +64 -2
- package/dist/_http.d.ts +42 -0
- package/dist/_http.js +108 -0
- package/dist/ai.d.ts +30 -0
- package/dist/ai.js +36 -0
- package/dist/base.d.ts +253 -0
- package/dist/base.js +339 -0
- package/dist/client.test.d.ts +1 -0
- package/dist/client.test.js +292 -0
- package/dist/example.d.ts +1 -0
- package/dist/example.js +16 -0
- package/dist/faststore.d.ts +108 -0
- package/dist/faststore.js +201 -0
- package/dist/iam.d.ts +88 -0
- package/dist/iam.js +149 -0
- package/dist/index.d.ts +66 -0
- package/dist/index.js +143 -0
- package/dist/inference.d.ts +110 -0
- package/dist/inference.js +62 -0
- package/dist/lds.d.ts +82 -0
- package/dist/lds.js +77 -0
- package/dist/queue.d.ts +72 -0
- package/dist/queue.js +129 -0
- package/dist/services.test.d.ts +1 -0
- package/dist/services.test.js +666 -0
- package/dist/stream.d.ts +99 -0
- package/dist/stream.js +117 -0
- package/dist/workflow.d.ts +82 -0
- package/dist/workflow.js +185 -0
- package/package.json +81 -4
package/dist/base.d.ts
ADDED
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
import { HttpClient } from './_http';
|
|
2
|
+
export type BaseMappingType = 'string' | 'number' | 'boolean' | 'date' | 'array' | 'object' | 'vector' | 'any';
|
|
3
|
+
export type BaseVectorMetric = 'cosine' | 'l2' | 'ip';
|
|
4
|
+
export interface BaseMappingField {
|
|
5
|
+
/** Dot path inside the stored document. */
|
|
6
|
+
path: string;
|
|
7
|
+
/** Validation type (default: any). */
|
|
8
|
+
type?: BaseMappingType;
|
|
9
|
+
/** Required on full writes (create/replace), not on partial patches. */
|
|
10
|
+
required?: boolean;
|
|
11
|
+
/** Vector dimension (optional, verified if provided). */
|
|
12
|
+
dimension?: number;
|
|
13
|
+
/** Distance metric for similarity queries (default: cosine). */
|
|
14
|
+
metric?: BaseVectorMetric;
|
|
15
|
+
}
|
|
16
|
+
export interface BaseMapping {
|
|
17
|
+
/** Allow logical keys that are not declared in `fields` (default: false). */
|
|
18
|
+
additional?: boolean;
|
|
19
|
+
fields: Record<string, BaseMappingField>;
|
|
20
|
+
}
|
|
21
|
+
/** Canonical `{fields: ...}` mapping or the shorthand `{logical: 'dot.path'}` form. */
|
|
22
|
+
export type BaseMappingInput = BaseMapping | Record<string, string | BaseMappingField>;
|
|
23
|
+
export type BaseQueryOp = 'eq' | 'ne' | 'gt' | 'gte' | 'lt' | 'lte' | 'in' | 'nin' | 'contains' | 'startsWith' | 'endsWith' | 'exists';
|
|
24
|
+
export interface BaseFilter {
|
|
25
|
+
field?: string;
|
|
26
|
+
op?: BaseQueryOp;
|
|
27
|
+
value?: unknown;
|
|
28
|
+
and?: BaseFilter[];
|
|
29
|
+
or?: BaseFilter[];
|
|
30
|
+
not?: BaseFilter;
|
|
31
|
+
}
|
|
32
|
+
export interface BaseOrderBy {
|
|
33
|
+
field: string;
|
|
34
|
+
direction?: 'asc' | 'desc';
|
|
35
|
+
}
|
|
36
|
+
export interface BaseQuery {
|
|
37
|
+
where?: BaseFilter | BaseFilter[] | Record<string, unknown>;
|
|
38
|
+
orderBy?: BaseOrderBy | string | Array<BaseOrderBy | string>;
|
|
39
|
+
limit?: number;
|
|
40
|
+
offset?: number;
|
|
41
|
+
cursor?: string;
|
|
42
|
+
select?: string[];
|
|
43
|
+
as?: 'data' | 'object';
|
|
44
|
+
}
|
|
45
|
+
export interface BaseDocument<T = Record<string, unknown>> {
|
|
46
|
+
id: string;
|
|
47
|
+
data?: T;
|
|
48
|
+
object?: T;
|
|
49
|
+
version: number;
|
|
50
|
+
createdAt: string;
|
|
51
|
+
updatedAt: string;
|
|
52
|
+
collection?: string;
|
|
53
|
+
}
|
|
54
|
+
export interface BaseCollectionInfo {
|
|
55
|
+
id: string;
|
|
56
|
+
name: string;
|
|
57
|
+
description?: string;
|
|
58
|
+
mapping?: BaseMapping;
|
|
59
|
+
orgId?: string;
|
|
60
|
+
accountId?: string;
|
|
61
|
+
createdAt: string;
|
|
62
|
+
updatedAt: string;
|
|
63
|
+
stats?: Record<string, unknown>;
|
|
64
|
+
}
|
|
65
|
+
export interface BaseQueryResult<T = Record<string, unknown>> {
|
|
66
|
+
items: T[];
|
|
67
|
+
total: number;
|
|
68
|
+
limit: number;
|
|
69
|
+
offset: number;
|
|
70
|
+
nextCursor: string | null;
|
|
71
|
+
}
|
|
72
|
+
export interface BaseVectorSearchOptions {
|
|
73
|
+
vector: number[];
|
|
74
|
+
limit?: number;
|
|
75
|
+
k?: number;
|
|
76
|
+
field?: string;
|
|
77
|
+
metric?: BaseVectorMetric;
|
|
78
|
+
where?: BaseFilter | BaseFilter[] | Record<string, unknown>;
|
|
79
|
+
filter?: BaseFilter | BaseFilter[] | Record<string, unknown>;
|
|
80
|
+
select?: string[];
|
|
81
|
+
as?: 'data' | 'object';
|
|
82
|
+
}
|
|
83
|
+
export interface BaseVectorSearchItem<T = Record<string, unknown>> {
|
|
84
|
+
id: string;
|
|
85
|
+
similarity: number;
|
|
86
|
+
distance: number;
|
|
87
|
+
version: number;
|
|
88
|
+
createdAt: string;
|
|
89
|
+
updatedAt: string;
|
|
90
|
+
data?: T;
|
|
91
|
+
object?: T;
|
|
92
|
+
}
|
|
93
|
+
export interface BaseVectorSearchResult<T = Record<string, unknown>> {
|
|
94
|
+
items: BaseVectorSearchItem<T>[];
|
|
95
|
+
total: number;
|
|
96
|
+
limit: number;
|
|
97
|
+
metric: string;
|
|
98
|
+
}
|
|
99
|
+
export declare function normalizeMapping(input?: BaseMappingInput | null): Record<string, BaseMappingField>;
|
|
100
|
+
/** Project stored `data` onto logical field names (empty mapping = copy). */
|
|
101
|
+
export declare function dataToObject(data: Record<string, unknown> | null | undefined, mapping?: BaseMappingInput | null): Record<string, unknown>;
|
|
102
|
+
/** Project a logical object onto stored `data` (empty mapping = copy). */
|
|
103
|
+
export declare function objectToData(obj: Record<string, unknown> | null | undefined, mapping?: BaseMappingInput | null): Record<string, unknown>;
|
|
104
|
+
export declare class BaseService {
|
|
105
|
+
private readonly http;
|
|
106
|
+
constructor(http: HttpClient);
|
|
107
|
+
/** Bind a collection name (plus optional model/mapping) for typed use. */
|
|
108
|
+
collection<T = Record<string, unknown>>(name: string, opts?: BaseCollectionOptions<T>): BaseCollection<T>;
|
|
109
|
+
listCollections(query?: {
|
|
110
|
+
orgId?: string;
|
|
111
|
+
accountId?: string;
|
|
112
|
+
}): Promise<BaseCollectionInfo[]>;
|
|
113
|
+
createCollection(input: {
|
|
114
|
+
name: string;
|
|
115
|
+
description?: string;
|
|
116
|
+
mapping?: BaseMappingInput;
|
|
117
|
+
orgId?: string;
|
|
118
|
+
accountId?: string;
|
|
119
|
+
}): Promise<BaseCollectionInfo>;
|
|
120
|
+
getCollection(name: string): Promise<BaseCollectionInfo>;
|
|
121
|
+
updateCollection(name: string, patch: {
|
|
122
|
+
name?: string;
|
|
123
|
+
description?: string | null;
|
|
124
|
+
mapping?: BaseMappingInput;
|
|
125
|
+
}): Promise<BaseCollectionInfo>;
|
|
126
|
+
deleteCollection(name: string): Promise<{
|
|
127
|
+
ok: boolean;
|
|
128
|
+
id: string;
|
|
129
|
+
name: string;
|
|
130
|
+
}>;
|
|
131
|
+
collectionStats(name: string): Promise<unknown>;
|
|
132
|
+
createDocument<T = Record<string, unknown>>(collection: string, body: {
|
|
133
|
+
data?: Record<string, unknown>;
|
|
134
|
+
object?: T;
|
|
135
|
+
id?: string;
|
|
136
|
+
}): Promise<BaseDocument<T>>;
|
|
137
|
+
getDocument<T = Record<string, unknown>>(collection: string, id: string, query?: {
|
|
138
|
+
as?: 'data' | 'object';
|
|
139
|
+
}): Promise<BaseDocument<T>>;
|
|
140
|
+
setDocument<T = Record<string, unknown>>(collection: string, id: string, body: {
|
|
141
|
+
data?: Record<string, unknown>;
|
|
142
|
+
object?: T;
|
|
143
|
+
ifVersion?: number;
|
|
144
|
+
merge?: boolean;
|
|
145
|
+
}): Promise<BaseDocument<T>>;
|
|
146
|
+
updateDocument<T = Record<string, unknown>>(collection: string, id: string, body: {
|
|
147
|
+
data?: Record<string, unknown>;
|
|
148
|
+
object?: T;
|
|
149
|
+
unset?: string[];
|
|
150
|
+
ifVersion?: number;
|
|
151
|
+
}): Promise<BaseDocument<T>>;
|
|
152
|
+
deleteDocument(collection: string, id: string, opts?: {
|
|
153
|
+
ifVersion?: number;
|
|
154
|
+
}): Promise<{
|
|
155
|
+
ok: boolean;
|
|
156
|
+
id: string;
|
|
157
|
+
}>;
|
|
158
|
+
queryDocuments<T = Record<string, unknown>>(collection: string, query?: BaseQuery): Promise<BaseQueryResult<T>>;
|
|
159
|
+
vectorSearch<T = Record<string, unknown>>(collection: string, options: BaseVectorSearchOptions): Promise<BaseVectorSearchResult<T>>;
|
|
160
|
+
listDocuments<T = Record<string, unknown>>(collection: string, opts?: {
|
|
161
|
+
limit?: number;
|
|
162
|
+
offset?: number;
|
|
163
|
+
}): Promise<Array<BaseDocument<T>>>;
|
|
164
|
+
increment<T = Record<string, unknown>>(collection: string, id: string, body: {
|
|
165
|
+
field: string;
|
|
166
|
+
by?: number;
|
|
167
|
+
ifVersion?: number;
|
|
168
|
+
}): Promise<BaseDocument<T>>;
|
|
169
|
+
batch(collection: string, operations: Record<string, unknown>[]): Promise<{
|
|
170
|
+
results: any[];
|
|
171
|
+
ok: boolean;
|
|
172
|
+
}>;
|
|
173
|
+
changes<T = Record<string, unknown>>(collection: string, query: {
|
|
174
|
+
since: string;
|
|
175
|
+
limit?: number;
|
|
176
|
+
as?: 'data' | 'object';
|
|
177
|
+
}): Promise<{
|
|
178
|
+
changes: any[];
|
|
179
|
+
nextSince: string;
|
|
180
|
+
hasMore: boolean;
|
|
181
|
+
}>;
|
|
182
|
+
}
|
|
183
|
+
export interface BaseCollectionOptions<T> {
|
|
184
|
+
/** Optional factory turning a logical object into your model instance. */
|
|
185
|
+
model?: (obj: Record<string, unknown>) => T;
|
|
186
|
+
/** Server-side mapping (logical -> dot path), used for data responses. */
|
|
187
|
+
mapping?: BaseMappingInput;
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* A collection bound to a service, with optional model factory + mapping.
|
|
191
|
+
*
|
|
192
|
+
* Typed methods send logical `object` payloads; raw `data` writes are available
|
|
193
|
+
* through the `data` option. Reads use `as: 'object'` and run through the model
|
|
194
|
+
* factory, while endpoints that return raw `data` (list/increment/changes) are
|
|
195
|
+
* converted locally with the mapping.
|
|
196
|
+
*/
|
|
197
|
+
export declare class BaseCollection<T = Record<string, unknown>> {
|
|
198
|
+
private readonly service;
|
|
199
|
+
readonly name: string;
|
|
200
|
+
private readonly opts;
|
|
201
|
+
constructor(service: BaseService, name: string, opts?: BaseCollectionOptions<T>);
|
|
202
|
+
toObject(value: T): Record<string, unknown>;
|
|
203
|
+
fromObject(obj: Record<string, unknown> | null | undefined): T;
|
|
204
|
+
fromData(data: Record<string, unknown> | null | undefined): T;
|
|
205
|
+
private docResult;
|
|
206
|
+
create(value?: T, opts?: {
|
|
207
|
+
id?: string;
|
|
208
|
+
data?: Record<string, unknown>;
|
|
209
|
+
}): Promise<T>;
|
|
210
|
+
get(id: string): Promise<T>;
|
|
211
|
+
getDocument(id: string, as?: 'data' | 'object'): Promise<BaseDocument<any>>;
|
|
212
|
+
list(opts?: {
|
|
213
|
+
limit?: number;
|
|
214
|
+
offset?: number;
|
|
215
|
+
}): Promise<T[]>;
|
|
216
|
+
set(id: string, value?: T, opts?: {
|
|
217
|
+
data?: Record<string, unknown>;
|
|
218
|
+
ifVersion?: number;
|
|
219
|
+
merge?: boolean;
|
|
220
|
+
}): Promise<T>;
|
|
221
|
+
update(id: string, value?: T, opts?: {
|
|
222
|
+
data?: Record<string, unknown>;
|
|
223
|
+
unset?: string[];
|
|
224
|
+
ifVersion?: number;
|
|
225
|
+
}): Promise<T>;
|
|
226
|
+
delete(id: string, opts?: {
|
|
227
|
+
ifVersion?: number;
|
|
228
|
+
}): Promise<{
|
|
229
|
+
ok: boolean;
|
|
230
|
+
id: string;
|
|
231
|
+
}>;
|
|
232
|
+
increment(id: string, body: {
|
|
233
|
+
field: string;
|
|
234
|
+
by?: number;
|
|
235
|
+
ifVersion?: number;
|
|
236
|
+
}): Promise<T>;
|
|
237
|
+
query(query?: BaseQuery): Promise<BaseQueryResult<T>>;
|
|
238
|
+
vectorSearch(options: Omit<BaseVectorSearchOptions, 'as'>): Promise<BaseVectorSearchResult<T>>;
|
|
239
|
+
changes(query: {
|
|
240
|
+
since: string;
|
|
241
|
+
limit?: number;
|
|
242
|
+
}): Promise<{
|
|
243
|
+
changes: any[];
|
|
244
|
+
nextSince: string;
|
|
245
|
+
hasMore: boolean;
|
|
246
|
+
}>;
|
|
247
|
+
batch(operations: Record<string, unknown>[]): Promise<{
|
|
248
|
+
results: any[];
|
|
249
|
+
ok: boolean;
|
|
250
|
+
}>;
|
|
251
|
+
stats(): Promise<unknown>;
|
|
252
|
+
private writeInput;
|
|
253
|
+
}
|
package/dist/base.js
ADDED
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/*
|
|
3
|
+
* Copyright 2026 SynapseOne Contributors
|
|
4
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
5
|
+
* SynapseBase client: collections, documents, queries, batch writes, atomic
|
|
6
|
+
* counters, the change feed and typed object<->data mapping.
|
|
7
|
+
*
|
|
8
|
+
* The service stores raw JSON `data`; a collection may declare a mapping from
|
|
9
|
+
* logical field names to dot paths inside that data. Writes can send `object`
|
|
10
|
+
* (logical keys) and reads can ask `as: 'object'` — the service converts in
|
|
11
|
+
* both directions. `BaseCollection` is a typed wrapper for one collection.
|
|
12
|
+
*/
|
|
13
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
14
|
+
exports.BaseCollection = exports.BaseService = void 0;
|
|
15
|
+
exports.normalizeMapping = normalizeMapping;
|
|
16
|
+
exports.dataToObject = dataToObject;
|
|
17
|
+
exports.objectToData = objectToData;
|
|
18
|
+
const _UNSET = Symbol('unset');
|
|
19
|
+
// ---------------------------------------------------------------------------
|
|
20
|
+
// mapping helpers (client-side mirror of the server object<->data mapping)
|
|
21
|
+
// ---------------------------------------------------------------------------
|
|
22
|
+
function normalizeMapping(input) {
|
|
23
|
+
if (!input)
|
|
24
|
+
return {};
|
|
25
|
+
const raw = input.fields && typeof input.fields === 'object'
|
|
26
|
+
? input.fields
|
|
27
|
+
: input;
|
|
28
|
+
const out = {};
|
|
29
|
+
for (const [name, spec] of Object.entries(raw)) {
|
|
30
|
+
if (typeof spec === 'string')
|
|
31
|
+
out[name] = { path: spec };
|
|
32
|
+
else if (spec && typeof spec === 'object')
|
|
33
|
+
out[name] = { ...spec };
|
|
34
|
+
}
|
|
35
|
+
return out;
|
|
36
|
+
}
|
|
37
|
+
function getPath(data, path) {
|
|
38
|
+
let cur = data;
|
|
39
|
+
for (const key of String(path).split('.')) {
|
|
40
|
+
if (!cur || typeof cur !== 'object' || !(key in cur))
|
|
41
|
+
return _UNSET;
|
|
42
|
+
cur = cur[key];
|
|
43
|
+
}
|
|
44
|
+
return cur;
|
|
45
|
+
}
|
|
46
|
+
function setPath(target, path, value) {
|
|
47
|
+
const segments = String(path).split('.');
|
|
48
|
+
let cur = target;
|
|
49
|
+
for (const key of segments.slice(0, -1)) {
|
|
50
|
+
if (!cur[key] || typeof cur[key] !== 'object' || Array.isArray(cur[key]))
|
|
51
|
+
cur[key] = {};
|
|
52
|
+
cur = cur[key];
|
|
53
|
+
}
|
|
54
|
+
cur[segments[segments.length - 1]] = value;
|
|
55
|
+
}
|
|
56
|
+
/** Project stored `data` onto logical field names (empty mapping = copy). */
|
|
57
|
+
function dataToObject(data, mapping) {
|
|
58
|
+
const fields = normalizeMapping(mapping);
|
|
59
|
+
if (!Object.keys(fields).length)
|
|
60
|
+
return { ...(data || {}) };
|
|
61
|
+
const out = {};
|
|
62
|
+
for (const [name, spec] of Object.entries(fields)) {
|
|
63
|
+
const value = getPath(data || {}, spec.path);
|
|
64
|
+
if (value !== _UNSET)
|
|
65
|
+
out[name] = value;
|
|
66
|
+
}
|
|
67
|
+
return out;
|
|
68
|
+
}
|
|
69
|
+
/** Project a logical object onto stored `data` (empty mapping = copy). */
|
|
70
|
+
function objectToData(obj, mapping) {
|
|
71
|
+
const fields = normalizeMapping(mapping);
|
|
72
|
+
const out = {};
|
|
73
|
+
for (const [key, value] of Object.entries(obj || {})) {
|
|
74
|
+
setPath(out, fields[key] ? fields[key].path : key, value);
|
|
75
|
+
}
|
|
76
|
+
return out;
|
|
77
|
+
}
|
|
78
|
+
function writeBody(body) {
|
|
79
|
+
const hasData = body.data !== undefined;
|
|
80
|
+
const hasObject = body.object !== undefined;
|
|
81
|
+
if (hasData === hasObject)
|
|
82
|
+
throw new Error('provide exactly one of data or object');
|
|
83
|
+
return hasData ? { data: body.data } : { object: body.object };
|
|
84
|
+
}
|
|
85
|
+
function queryString(params) {
|
|
86
|
+
const p = new URLSearchParams();
|
|
87
|
+
for (const [k, v] of Object.entries(params)) {
|
|
88
|
+
if (v !== undefined && v !== null && String(v) !== '')
|
|
89
|
+
p.set(k, String(v));
|
|
90
|
+
}
|
|
91
|
+
const s = p.toString();
|
|
92
|
+
return s ? `?${s}` : '';
|
|
93
|
+
}
|
|
94
|
+
// ---------------------------------------------------------------------------
|
|
95
|
+
// service
|
|
96
|
+
// ---------------------------------------------------------------------------
|
|
97
|
+
class BaseService {
|
|
98
|
+
http;
|
|
99
|
+
constructor(http) {
|
|
100
|
+
this.http = http;
|
|
101
|
+
}
|
|
102
|
+
/** Bind a collection name (plus optional model/mapping) for typed use. */
|
|
103
|
+
collection(name, opts = {}) {
|
|
104
|
+
return new BaseCollection(this, name, opts);
|
|
105
|
+
}
|
|
106
|
+
// ---- collections ----
|
|
107
|
+
listCollections(query = {}) {
|
|
108
|
+
return this.http.req(`/v1/base/collections${queryString({ orgId: query.orgId, accountId: query.accountId })}`);
|
|
109
|
+
}
|
|
110
|
+
createCollection(input) {
|
|
111
|
+
return this.http.req('/v1/base/collections', { method: 'POST', body: JSON.stringify(input) });
|
|
112
|
+
}
|
|
113
|
+
getCollection(name) {
|
|
114
|
+
return this.http.req(`/v1/base/collections/${encodeURIComponent(name)}`);
|
|
115
|
+
}
|
|
116
|
+
updateCollection(name, patch) {
|
|
117
|
+
return this.http.req(`/v1/base/collections/${encodeURIComponent(name)}`, { method: 'PATCH', body: JSON.stringify(patch) });
|
|
118
|
+
}
|
|
119
|
+
deleteCollection(name) {
|
|
120
|
+
return this.http.req(`/v1/base/collections/${encodeURIComponent(name)}`, { method: 'DELETE' });
|
|
121
|
+
}
|
|
122
|
+
collectionStats(name) {
|
|
123
|
+
return this.http.req(`/v1/base/collections/${encodeURIComponent(name)}/stats`);
|
|
124
|
+
}
|
|
125
|
+
// ---- documents ----
|
|
126
|
+
createDocument(collection, body) {
|
|
127
|
+
return this.http.req(`/v1/base/collections/${encodeURIComponent(collection)}/documents`, {
|
|
128
|
+
method: 'POST',
|
|
129
|
+
body: JSON.stringify({ ...writeBody(body), ...(body.id !== undefined ? { id: body.id } : {}) }),
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
getDocument(collection, id, query = {}) {
|
|
133
|
+
return this.http.req(`/v1/base/collections/${encodeURIComponent(collection)}/documents/${encodeURIComponent(id)}${queryString({ as: query.as })}`);
|
|
134
|
+
}
|
|
135
|
+
setDocument(collection, id, body) {
|
|
136
|
+
return this.http.req(`/v1/base/collections/${encodeURIComponent(collection)}/documents/${encodeURIComponent(id)}`, {
|
|
137
|
+
method: 'PUT',
|
|
138
|
+
body: JSON.stringify({
|
|
139
|
+
...writeBody(body),
|
|
140
|
+
...(body.ifVersion !== undefined ? { ifVersion: body.ifVersion } : {}),
|
|
141
|
+
...(body.merge ? { merge: true } : {}),
|
|
142
|
+
}),
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
updateDocument(collection, id, body) {
|
|
146
|
+
if (body.data === undefined && body.object === undefined && !body.unset?.length) {
|
|
147
|
+
throw new Error('provide data/object and/or unset');
|
|
148
|
+
}
|
|
149
|
+
const payload = {};
|
|
150
|
+
if (body.data !== undefined || body.object !== undefined)
|
|
151
|
+
Object.assign(payload, writeBody(body));
|
|
152
|
+
if (body.unset?.length)
|
|
153
|
+
payload.unset = body.unset;
|
|
154
|
+
if (body.ifVersion !== undefined)
|
|
155
|
+
payload.ifVersion = body.ifVersion;
|
|
156
|
+
return this.http.req(`/v1/base/collections/${encodeURIComponent(collection)}/documents/${encodeURIComponent(id)}`, {
|
|
157
|
+
method: 'PATCH', body: JSON.stringify(payload),
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
deleteDocument(collection, id, opts = {}) {
|
|
161
|
+
return this.http.req(`/v1/base/collections/${encodeURIComponent(collection)}/documents/${encodeURIComponent(id)}${queryString({ ifVersion: opts.ifVersion })}`, { method: 'DELETE' });
|
|
162
|
+
}
|
|
163
|
+
// ---- query / batch / changes ----
|
|
164
|
+
queryDocuments(collection, query = {}) {
|
|
165
|
+
const body = { as: query.as ?? 'data' };
|
|
166
|
+
if (query.where !== undefined)
|
|
167
|
+
body.where = query.where;
|
|
168
|
+
if (query.orderBy !== undefined)
|
|
169
|
+
body.orderBy = query.orderBy;
|
|
170
|
+
if (query.limit !== undefined)
|
|
171
|
+
body.limit = query.limit;
|
|
172
|
+
if (query.offset !== undefined)
|
|
173
|
+
body.offset = query.offset;
|
|
174
|
+
if (query.cursor !== undefined)
|
|
175
|
+
body.cursor = query.cursor;
|
|
176
|
+
if (query.select !== undefined)
|
|
177
|
+
body.select = query.select;
|
|
178
|
+
return this.http.req(`/v1/base/collections/${encodeURIComponent(collection)}/query`, {
|
|
179
|
+
method: 'POST', body: JSON.stringify(body),
|
|
180
|
+
});
|
|
181
|
+
}
|
|
182
|
+
vectorSearch(collection, options) {
|
|
183
|
+
const body = {
|
|
184
|
+
vector: options.vector,
|
|
185
|
+
as: options.as ?? 'data',
|
|
186
|
+
};
|
|
187
|
+
if (options.limit !== undefined)
|
|
188
|
+
body.limit = options.limit;
|
|
189
|
+
if (options.k !== undefined)
|
|
190
|
+
body.k = options.k;
|
|
191
|
+
if (options.field !== undefined)
|
|
192
|
+
body.field = options.field;
|
|
193
|
+
if (options.metric !== undefined)
|
|
194
|
+
body.metric = options.metric;
|
|
195
|
+
if (options.where !== undefined)
|
|
196
|
+
body.where = options.where;
|
|
197
|
+
if (options.filter !== undefined)
|
|
198
|
+
body.filter = options.filter;
|
|
199
|
+
if (options.select !== undefined)
|
|
200
|
+
body.select = options.select;
|
|
201
|
+
return this.http.req(`/v1/base/collections/${encodeURIComponent(collection)}/vector-search`, {
|
|
202
|
+
method: 'POST',
|
|
203
|
+
body: JSON.stringify(body),
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
listDocuments(collection, opts = {}) {
|
|
207
|
+
return this.http.req(`/v1/base/collections/${encodeURIComponent(collection)}/documents${queryString({ limit: opts.limit, offset: opts.offset })}`);
|
|
208
|
+
}
|
|
209
|
+
increment(collection, id, body) {
|
|
210
|
+
return this.http.req(`/v1/base/collections/${encodeURIComponent(collection)}/documents/${encodeURIComponent(id)}/increment`, {
|
|
211
|
+
method: 'POST',
|
|
212
|
+
body: JSON.stringify({
|
|
213
|
+
field: body.field,
|
|
214
|
+
by: body.by ?? 1,
|
|
215
|
+
...(body.ifVersion !== undefined ? { ifVersion: body.ifVersion } : {}),
|
|
216
|
+
}),
|
|
217
|
+
});
|
|
218
|
+
}
|
|
219
|
+
batch(collection, operations) {
|
|
220
|
+
return this.http.req(`/v1/base/collections/${encodeURIComponent(collection)}/documents:batch`, { method: 'POST', body: JSON.stringify({ operations }) });
|
|
221
|
+
}
|
|
222
|
+
changes(collection, query) {
|
|
223
|
+
return this.http.req(`/v1/base/collections/${encodeURIComponent(collection)}/changes${queryString({
|
|
224
|
+
since: query.since, limit: query.limit, as: query.as,
|
|
225
|
+
})}`);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
exports.BaseService = BaseService;
|
|
229
|
+
/**
|
|
230
|
+
* A collection bound to a service, with optional model factory + mapping.
|
|
231
|
+
*
|
|
232
|
+
* Typed methods send logical `object` payloads; raw `data` writes are available
|
|
233
|
+
* through the `data` option. Reads use `as: 'object'` and run through the model
|
|
234
|
+
* factory, while endpoints that return raw `data` (list/increment/changes) are
|
|
235
|
+
* converted locally with the mapping.
|
|
236
|
+
*/
|
|
237
|
+
class BaseCollection {
|
|
238
|
+
service;
|
|
239
|
+
name;
|
|
240
|
+
opts;
|
|
241
|
+
constructor(service, name, opts = {}) {
|
|
242
|
+
this.service = service;
|
|
243
|
+
this.name = name;
|
|
244
|
+
this.opts = opts;
|
|
245
|
+
}
|
|
246
|
+
toObject(value) {
|
|
247
|
+
return value;
|
|
248
|
+
}
|
|
249
|
+
fromObject(obj) {
|
|
250
|
+
const value = obj ?? {};
|
|
251
|
+
return this.opts.model ? this.opts.model(value) : value;
|
|
252
|
+
}
|
|
253
|
+
fromData(data) {
|
|
254
|
+
return this.fromObject(dataToObject(data, this.opts.mapping));
|
|
255
|
+
}
|
|
256
|
+
docResult(doc) {
|
|
257
|
+
return doc.object !== undefined ? this.fromObject(doc.object) : this.fromData(doc.data);
|
|
258
|
+
}
|
|
259
|
+
create(value, opts = {}) {
|
|
260
|
+
const body = this.writeInput(value, opts.data, 'value');
|
|
261
|
+
return this.service
|
|
262
|
+
.createDocument(this.name, { ...body, id: opts.id })
|
|
263
|
+
.then((doc) => this.docResult(doc));
|
|
264
|
+
}
|
|
265
|
+
get(id) {
|
|
266
|
+
return this.service
|
|
267
|
+
.getDocument(this.name, id, { as: 'object' })
|
|
268
|
+
.then((doc) => this.fromObject(doc.object));
|
|
269
|
+
}
|
|
270
|
+
getDocument(id, as = 'data') {
|
|
271
|
+
return this.service.getDocument(this.name, id, { as });
|
|
272
|
+
}
|
|
273
|
+
list(opts = {}) {
|
|
274
|
+
return this.service
|
|
275
|
+
.listDocuments(this.name, opts)
|
|
276
|
+
.then((docs) => docs.map((doc) => this.fromData(doc.data)));
|
|
277
|
+
}
|
|
278
|
+
set(id, value, opts = {}) {
|
|
279
|
+
const body = this.writeInput(value, opts.data, 'value');
|
|
280
|
+
return this.service
|
|
281
|
+
.setDocument(this.name, id, { ...body, ifVersion: opts.ifVersion, merge: opts.merge })
|
|
282
|
+
.then((doc) => this.docResult(doc));
|
|
283
|
+
}
|
|
284
|
+
update(id, value, opts = {}) {
|
|
285
|
+
const body = {};
|
|
286
|
+
if (value !== undefined || opts.data !== undefined)
|
|
287
|
+
Object.assign(body, this.writeInput(value, opts.data, 'value'));
|
|
288
|
+
else if (!opts.unset?.length)
|
|
289
|
+
throw new Error('provide a value, data or unset');
|
|
290
|
+
return this.service
|
|
291
|
+
.updateDocument(this.name, id, { ...body, unset: opts.unset, ifVersion: opts.ifVersion })
|
|
292
|
+
.then((doc) => this.docResult(doc));
|
|
293
|
+
}
|
|
294
|
+
delete(id, opts = {}) {
|
|
295
|
+
return this.service.deleteDocument(this.name, id, opts);
|
|
296
|
+
}
|
|
297
|
+
increment(id, body) {
|
|
298
|
+
return this.service
|
|
299
|
+
.increment(this.name, id, body)
|
|
300
|
+
.then((doc) => this.fromData(doc.data));
|
|
301
|
+
}
|
|
302
|
+
query(query = {}) {
|
|
303
|
+
return this.service.queryDocuments(this.name, { ...query, as: 'object' }).then((result) => ({
|
|
304
|
+
...result,
|
|
305
|
+
items: result.items.map((item) => this.fromObject(item.object)),
|
|
306
|
+
}));
|
|
307
|
+
}
|
|
308
|
+
vectorSearch(options) {
|
|
309
|
+
return this.service
|
|
310
|
+
.vectorSearch(this.name, { ...options, as: 'object' })
|
|
311
|
+
.then((result) => ({
|
|
312
|
+
...result,
|
|
313
|
+
items: result.items.map((item) => ({
|
|
314
|
+
...item,
|
|
315
|
+
object: this.fromObject(item.object),
|
|
316
|
+
})),
|
|
317
|
+
}));
|
|
318
|
+
}
|
|
319
|
+
changes(query) {
|
|
320
|
+
return this.service.changes(this.name, { ...query, as: 'object' }).then((raw) => ({
|
|
321
|
+
...raw,
|
|
322
|
+
changes: raw.changes.map((ch) => ({ ...ch, document: this.fromObject(ch.object) })),
|
|
323
|
+
}));
|
|
324
|
+
}
|
|
325
|
+
batch(operations) {
|
|
326
|
+
return this.service.batch(this.name, operations);
|
|
327
|
+
}
|
|
328
|
+
stats() {
|
|
329
|
+
return this.service.collectionStats(this.name);
|
|
330
|
+
}
|
|
331
|
+
writeInput(value, data, name) {
|
|
332
|
+
if (value !== undefined && data !== undefined)
|
|
333
|
+
throw new Error(`provide exactly one of ${name} or data`);
|
|
334
|
+
if (value === undefined && data === undefined)
|
|
335
|
+
throw new Error(`provide exactly one of ${name} or data`);
|
|
336
|
+
return data !== undefined ? { data } : { object: value };
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
exports.BaseCollection = BaseCollection;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|