@synapseone/sdk 0.7.1 → 0.8.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/dist/iam.d.ts CHANGED
@@ -112,6 +112,13 @@ export declare class IamService {
112
112
  createUser(orgId: string, email: string, displayName?: string): Promise<unknown>;
113
113
  createAccount(orgId: string, slug: string, displayName: string): Promise<unknown>;
114
114
  userPolicies(userId: string): Promise<unknown>;
115
+ createScimToken(input?: {
116
+ description?: string;
117
+ scopes?: string[];
118
+ ttlSeconds?: number;
119
+ }): Promise<unknown>;
120
+ listScimTokens(): Promise<unknown>;
121
+ revokeScimToken(id: string): Promise<unknown>;
115
122
  createRole(accountId: string, slug: string, description?: string): Promise<unknown>;
116
123
  listRoles(accountId: string): Promise<unknown>;
117
124
  deleteRole(roleId: string): Promise<unknown>;
package/dist/iam.js CHANGED
@@ -110,6 +110,12 @@ class IamService {
110
110
  return this.http.req(`/v1/orgs/${encodeURIComponent(orgId)}/accounts`, { method: 'POST', body: JSON.stringify({ slug, displayName }) });
111
111
  }
112
112
  userPolicies(userId) { return this.http.req(`/v1/users/${encodeURIComponent(userId)}/policies`); }
113
+ // ---- SCIM provisioning (#48) ----
114
+ createScimToken(input = {}) {
115
+ return this.http.req('/v1/scim/tokens', { method: 'POST', body: JSON.stringify(input) });
116
+ }
117
+ listScimTokens() { return this.http.req('/v1/scim/tokens'); }
118
+ revokeScimToken(id) { return this.http.req(`/v1/scim/tokens/${encodeURIComponent(id)}`, { method: 'DELETE' }); }
113
119
  // ---- roles / policies ----
114
120
  createRole(accountId, slug, description = '') {
115
121
  return this.http.req(`/v1/accounts/${encodeURIComponent(accountId)}/roles`, { method: 'POST', body: JSON.stringify({ slug, description }) });
package/dist/index.d.ts CHANGED
@@ -10,6 +10,8 @@ import { InferenceService } from './inference';
10
10
  import { AiService } from './ai';
11
11
  import { HealthService } from './health';
12
12
  import { StorageService } from './storage';
13
+ import { SearchService } from './search';
14
+ import { OcsService } from './ocs';
13
15
  import { NotificationsService } from './notifications';
14
16
  export * from './_http';
15
17
  export * from './iam';
@@ -23,6 +25,8 @@ export * from './stream';
23
25
  export * from './inference';
24
26
  export * from './health';
25
27
  export * from './storage';
28
+ export * from './search';
29
+ export * from './ocs';
26
30
  export * from './notifications';
27
31
  /** Legacy flat LDS signatures (the namespaced service drops the `lds` prefix). */
28
32
  export interface LdsLegacyMethods {
@@ -56,6 +60,10 @@ export declare class SynapseOneClient {
56
60
  readonly stream: StreamService;
57
61
  readonly inference: InferenceService;
58
62
  readonly storage: StorageService;
63
+ /** Tenant-scoped search over Base documents (#46). */
64
+ readonly search: SearchService;
65
+ /** SynapseOCS bucket/object API; `storage` remains the default-bucket alias. */
66
+ readonly ocs: OcsService;
59
67
  readonly notifications: NotificationsService;
60
68
  readonly health: HealthService;
61
69
  readonly readiness: HealthService;
package/dist/index.js CHANGED
@@ -50,6 +50,8 @@ const inference_1 = require("./inference");
50
50
  const ai_1 = require("./ai");
51
51
  const health_1 = require("./health");
52
52
  const storage_1 = require("./storage");
53
+ const search_1 = require("./search");
54
+ const ocs_1 = require("./ocs");
53
55
  const notifications_1 = require("./notifications");
54
56
  __exportStar(require("./_http"), exports);
55
57
  __exportStar(require("./iam"), exports);
@@ -63,6 +65,8 @@ __exportStar(require("./stream"), exports);
63
65
  __exportStar(require("./inference"), exports);
64
66
  __exportStar(require("./health"), exports);
65
67
  __exportStar(require("./storage"), exports);
68
+ __exportStar(require("./search"), exports);
69
+ __exportStar(require("./ocs"), exports);
66
70
  __exportStar(require("./notifications"), exports);
67
71
  class SynapseOneClient {
68
72
  http;
@@ -76,6 +80,10 @@ class SynapseOneClient {
76
80
  stream;
77
81
  inference;
78
82
  storage;
83
+ /** Tenant-scoped search over Base documents (#46). */
84
+ search;
85
+ /** SynapseOCS bucket/object API; `storage` remains the default-bucket alias. */
86
+ ocs;
79
87
  notifications;
80
88
  health;
81
89
  readiness;
@@ -91,6 +99,8 @@ class SynapseOneClient {
91
99
  this.stream = new stream_1.StreamService(this.http);
92
100
  this.inference = new inference_1.InferenceService(this.http);
93
101
  this.storage = new storage_1.StorageService(this.http);
102
+ this.search = new search_1.SearchService(this.http);
103
+ this.ocs = new ocs_1.OcsService(this.http);
94
104
  this.notifications = new notifications_1.NotificationsService(this.http);
95
105
  this.health = new health_1.HealthService(this.http);
96
106
  // Alias: `client.readiness.ready()` reads naturally; same instance.
package/dist/ocs.d.ts ADDED
@@ -0,0 +1,119 @@
1
+ import { HttpClient, RequestOptions } from './_http';
2
+ export interface OcsBucket {
3
+ name: string;
4
+ createdAt: string;
5
+ updatedAt?: string;
6
+ owner?: string;
7
+ quotaBytes?: number;
8
+ objects?: number;
9
+ bytes?: number;
10
+ }
11
+ export interface OcsObject {
12
+ key: string;
13
+ bucket: string;
14
+ size: number;
15
+ contentType: string;
16
+ etag: string;
17
+ checksumSha256?: string;
18
+ createdAt: string;
19
+ updatedAt: string;
20
+ }
21
+ export interface OcsList {
22
+ bucket: string;
23
+ prefix: string;
24
+ delimiter?: string;
25
+ objects: OcsObject[];
26
+ commonPrefixes: string[];
27
+ nextCursor: string | null;
28
+ }
29
+ export interface PutOcsOptions extends RequestOptions {
30
+ contentType?: string;
31
+ checksumSha256?: string;
32
+ }
33
+ export interface GetOcsOptions extends RequestOptions {
34
+ range?: string;
35
+ ifNoneMatch?: string;
36
+ ifMatch?: string;
37
+ }
38
+ export declare class OcsService {
39
+ private readonly http;
40
+ constructor(http: HttpClient);
41
+ createBucket(name: string, opts?: {
42
+ quotaBytes?: number;
43
+ }): Promise<{
44
+ bucket: OcsBucket;
45
+ }>;
46
+ listBuckets(opts?: {
47
+ withStats?: boolean;
48
+ }): Promise<{
49
+ buckets: OcsBucket[];
50
+ total: number;
51
+ }>;
52
+ getBucket(name: string): Promise<{
53
+ bucket: OcsBucket;
54
+ }>;
55
+ headBucket(name: string, opts?: RequestOptions): Promise<Record<string, string> | null>;
56
+ bucketStats(name: string): Promise<{
57
+ bucket: string;
58
+ objects: number;
59
+ bytes: number;
60
+ quotaBytes: number;
61
+ }>;
62
+ deleteBucket(name: string, opts?: {
63
+ force?: boolean;
64
+ }): Promise<{
65
+ ok: boolean;
66
+ bucket: string;
67
+ deletedObjects: number;
68
+ }>;
69
+ putObject(bucket: string, key: string, body: Uint8Array | ArrayBuffer | string, opts?: PutOcsOptions): Promise<OcsObject>;
70
+ getObject(bucket: string, key: string, opts?: GetOcsOptions): Promise<Uint8Array>;
71
+ headObject(bucket: string, key: string, opts?: RequestOptions): Promise<OcsObject | null>;
72
+ deleteObject(bucket: string, key: string): Promise<{
73
+ ok: boolean;
74
+ bucket: string;
75
+ key: string;
76
+ }>;
77
+ listObjects(bucket: string, opts?: {
78
+ prefix?: string;
79
+ delimiter?: string;
80
+ limit?: number;
81
+ cursor?: string;
82
+ }): Promise<OcsList>;
83
+ copyObject(bucket: string, input: {
84
+ sourceKey: string;
85
+ destinationKey: string;
86
+ sourceBucket?: string;
87
+ contentType?: string;
88
+ }): Promise<{
89
+ object: OcsObject;
90
+ }>;
91
+ presign(bucket: string, key: string, opts?: {
92
+ method?: 'GET' | 'PUT' | 'DELETE' | 'HEAD';
93
+ expiresIn?: number;
94
+ }): Promise<{
95
+ url: string;
96
+ bucket: string;
97
+ key: string;
98
+ method: string;
99
+ expiresIn: number;
100
+ }>;
101
+ createMultipart(bucket: string, key: string, contentType?: string): Promise<{
102
+ uploadId: string;
103
+ bucket: string;
104
+ key: string;
105
+ contentType: string;
106
+ }>;
107
+ uploadPart(bucket: string, uploadId: string, key: string, partNumber: number, body: Uint8Array | string): Promise<{
108
+ partNumber: number;
109
+ etag: string;
110
+ size: number;
111
+ }>;
112
+ completeMultipart(bucket: string, uploadId: string, key: string, parts: Array<{
113
+ partNumber: number;
114
+ etag: string;
115
+ }>): Promise<{
116
+ object: OcsObject;
117
+ }>;
118
+ abortMultipart(bucket: string, uploadId: string, key: string): Promise<unknown>;
119
+ }
package/dist/ocs.js ADDED
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+ // SPDX-License-Identifier: Apache-2.0
3
+ // SPDX-FileCopyrightText: 2026 VKU.VIC
4
+ /*
5
+ * Copyright 2026 SynapseOne Contributors
6
+ * Licensed under the Apache License, Version 2.0 (the "License");
7
+ * SynapseOCS client: buckets, objects, copy, range/conditional reads,
8
+ * delimited listing, presigned URLs and multipart uploads.
9
+ */
10
+ Object.defineProperty(exports, "__esModule", { value: true });
11
+ exports.OcsService = void 0;
12
+ const P = '/v1/ocs';
13
+ class OcsService {
14
+ http;
15
+ constructor(http) {
16
+ this.http = http;
17
+ }
18
+ createBucket(name, opts = {}) {
19
+ return this.http.req(`${P}/buckets`, {
20
+ method: 'POST',
21
+ body: JSON.stringify({ name, ...(opts.quotaBytes ? { quotaBytes: opts.quotaBytes } : {}) }),
22
+ });
23
+ }
24
+ listBuckets(opts = {}) {
25
+ return this.http.req(`${P}/buckets${opts.withStats ? '?withStats=1' : ''}`);
26
+ }
27
+ getBucket(name) {
28
+ return this.http.req(`${P}/buckets/${encodeURIComponent(name)}`);
29
+ }
30
+ async headBucket(name, opts = {}) {
31
+ try {
32
+ return await this.http.head(`${P}/buckets/${encodeURIComponent(name)}`, opts);
33
+ }
34
+ catch (error) {
35
+ if (error?.status === 404)
36
+ return null;
37
+ throw error;
38
+ }
39
+ }
40
+ bucketStats(name) {
41
+ return this.http.req(`${P}/buckets/${encodeURIComponent(name)}/stats`);
42
+ }
43
+ deleteBucket(name, opts = {}) {
44
+ return this.http.req(`${P}/buckets/${encodeURIComponent(name)}${opts.force ? '?force=true' : ''}`, { method: 'DELETE' });
45
+ }
46
+ async putObject(bucket, key, body, opts = {}) {
47
+ const bytes = typeof body === 'string' ? new TextEncoder().encode(body) : body instanceof Uint8Array ? body : new Uint8Array(body);
48
+ const result = await this.http.upload(`${P}/buckets/${encodeURIComponent(bucket)}/objects/${encodeKey(key)}`, bytes, {
49
+ ...opts,
50
+ contentType: opts.contentType || 'application/octet-stream',
51
+ headers: { ...(opts.checksumSha256 ? { 'x-object-checksum-sha256': opts.checksumSha256 } : {}), ...(opts.headers || {}) },
52
+ });
53
+ return result.object;
54
+ }
55
+ getObject(bucket, key, opts = {}) {
56
+ const headers = { ...(opts.headers || {}) };
57
+ if (opts.range)
58
+ headers.Range = opts.range;
59
+ if (opts.ifNoneMatch)
60
+ headers['If-None-Match'] = opts.ifNoneMatch;
61
+ if (opts.ifMatch)
62
+ headers['If-Match'] = opts.ifMatch;
63
+ return this.http.reqBinary(`${P}/buckets/${encodeURIComponent(bucket)}/objects/${encodeKey(key)}`, undefined, { ...opts, headers });
64
+ }
65
+ async headObject(bucket, key, opts = {}) {
66
+ try {
67
+ const headers = await this.http.head(`${P}/buckets/${encodeURIComponent(bucket)}/objects/${encodeKey(key)}`, opts);
68
+ return {
69
+ key: headers['x-object-key'] || key,
70
+ bucket: headers['x-ocs-bucket'] || bucket,
71
+ size: Number(headers['content-length'] || 0),
72
+ contentType: headers['content-type'] || 'application/octet-stream',
73
+ etag: (headers.etag || '').replace(/"/g, ''),
74
+ checksumSha256: headers['x-object-checksum-sha256'],
75
+ createdAt: headers['x-object-created-at'] || '',
76
+ updatedAt: headers['x-object-updated-at'] || '',
77
+ };
78
+ }
79
+ catch (error) {
80
+ if (error?.status === 404)
81
+ return null;
82
+ throw error;
83
+ }
84
+ }
85
+ deleteObject(bucket, key) {
86
+ return this.http.req(`${P}/buckets/${encodeURIComponent(bucket)}/objects/${encodeKey(key)}`, { method: 'DELETE' });
87
+ }
88
+ listObjects(bucket, opts = {}) {
89
+ const query = new URLSearchParams();
90
+ if (opts.prefix)
91
+ query.set('prefix', opts.prefix);
92
+ if (opts.delimiter)
93
+ query.set('delimiter', opts.delimiter);
94
+ if (opts.limit)
95
+ query.set('limit', String(opts.limit));
96
+ if (opts.cursor)
97
+ query.set('cursor', opts.cursor);
98
+ const suffix = query.toString();
99
+ return this.http.req(`${P}/buckets/${encodeURIComponent(bucket)}/objects${suffix ? `?${suffix}` : ''}`);
100
+ }
101
+ copyObject(bucket, input) {
102
+ return this.http.req(`${P}/buckets/${encodeURIComponent(bucket)}/objects/copy`, {
103
+ method: 'POST',
104
+ body: JSON.stringify(input),
105
+ });
106
+ }
107
+ presign(bucket, key, opts = {}) {
108
+ return this.http.req(`${P}/buckets/${encodeURIComponent(bucket)}/presign`, { method: 'POST', body: JSON.stringify({ key, method: opts.method || 'GET', expiresIn: opts.expiresIn ?? 900 }) });
109
+ }
110
+ createMultipart(bucket, key, contentType = 'application/octet-stream') {
111
+ return this.http.req(`${P}/buckets/${encodeURIComponent(bucket)}/uploads`, { method: 'POST', body: JSON.stringify({ key, contentType }) });
112
+ }
113
+ uploadPart(bucket, uploadId, key, partNumber, body) {
114
+ const bytes = typeof body === 'string' ? new TextEncoder().encode(body) : body;
115
+ return this.http.upload(`${P}/buckets/${encodeURIComponent(bucket)}/uploads/${encodeURIComponent(uploadId)}/parts/${partNumber}?key=${encodeURIComponent(key)}`, bytes, { method: 'PUT', contentType: 'application/octet-stream' });
116
+ }
117
+ completeMultipart(bucket, uploadId, key, parts) {
118
+ return this.http.req(`${P}/buckets/${encodeURIComponent(bucket)}/uploads/${encodeURIComponent(uploadId)}/complete`, { method: 'POST', body: JSON.stringify({ key, parts }) });
119
+ }
120
+ abortMultipart(bucket, uploadId, key) {
121
+ return this.http.req(`${P}/buckets/${encodeURIComponent(bucket)}/uploads/${encodeURIComponent(uploadId)}?key=${encodeURIComponent(key)}`, { method: 'DELETE' });
122
+ }
123
+ }
124
+ exports.OcsService = OcsService;
125
+ function encodeKey(key) {
126
+ return String(key || '')
127
+ .split('/')
128
+ .map((segment) => encodeURIComponent(segment))
129
+ .join('/');
130
+ }
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ // SPDX-License-Identifier: Apache-2.0
7
+ // SPDX-FileCopyrightText: 2026 VKU.VIC
8
+ /* SynapseOCS JS SDK contract tests: buckets, objects, copy, list, multipart. */
9
+ const node_test_1 = require("node:test");
10
+ const strict_1 = __importDefault(require("node:assert/strict"));
11
+ const node_http_1 = __importDefault(require("node:http"));
12
+ const index_1 = require("./index");
13
+ let server;
14
+ let base = '';
15
+ const calls = [];
16
+ (0, node_test_1.before)(() => new Promise((resolve) => {
17
+ server = node_http_1.default.createServer((req, res) => {
18
+ const url = new URL(req.url || '/', 'http://x');
19
+ const chunks = [];
20
+ req.on('data', (chunk) => chunks.push(chunk));
21
+ req.on('end', () => {
22
+ const body = Buffer.concat(chunks).toString('utf8');
23
+ calls.push({ method: req.method || 'GET', path: url.pathname + url.search, body });
24
+ res.setHeader('content-type', 'application/json');
25
+ if (url.pathname === '/v1/ocs/buckets' && req.method === 'GET') {
26
+ res.end(JSON.stringify({ buckets: [{ name: 'media', createdAt: 't' }], total: 1 }));
27
+ return;
28
+ }
29
+ if (url.pathname === '/v1/ocs/buckets' && req.method === 'POST') {
30
+ res.statusCode = 201;
31
+ res.end(JSON.stringify({ bucket: { name: 'media', createdAt: 't' } }));
32
+ return;
33
+ }
34
+ if (url.pathname.endsWith('/stats')) {
35
+ res.end(JSON.stringify({ bucket: 'media', objects: 1, bytes: 5, quotaBytes: 100 }));
36
+ return;
37
+ }
38
+ if (url.pathname.endsWith('/objects') && req.method === 'GET') {
39
+ res.end(JSON.stringify({ bucket: 'media', prefix: '', objects: [{ key: 'a.txt', bucket: 'media', size: 5, contentType: 'text/plain', etag: 'e', createdAt: 't', updatedAt: 't' }], commonPrefixes: [], nextCursor: null }));
40
+ return;
41
+ }
42
+ if (url.pathname.endsWith('/copy')) {
43
+ res.statusCode = 201;
44
+ res.end(JSON.stringify({ object: { key: 'b.txt', bucket: 'media', size: 5, contentType: 'text/plain', etag: 'e', createdAt: 't', updatedAt: 't' } }));
45
+ return;
46
+ }
47
+ if (url.pathname.endsWith('/presign')) {
48
+ res.end(JSON.stringify({ url: 'https://ocs.example/x', bucket: 'media', key: 'a.txt', method: 'GET', expiresIn: 60 }));
49
+ return;
50
+ }
51
+ if (url.pathname.endsWith('/uploads')) {
52
+ res.statusCode = 201;
53
+ res.end(JSON.stringify({ uploadId: 'u1', bucket: 'media', key: 'a.txt', contentType: 'text/plain' }));
54
+ return;
55
+ }
56
+ if (url.pathname.includes('/parts/')) {
57
+ res.end(JSON.stringify({ partNumber: 1, etag: 'p1', size: 3 }));
58
+ return;
59
+ }
60
+ if (url.pathname.endsWith('/complete')) {
61
+ res.statusCode = 201;
62
+ res.end(JSON.stringify({ object: { key: 'a.txt', bucket: 'media', size: 3, contentType: 'text/plain', etag: 'e', createdAt: 't', updatedAt: 't' } }));
63
+ return;
64
+ }
65
+ if (req.method === 'PUT') {
66
+ res.statusCode = 201;
67
+ res.end(JSON.stringify({ object: { key: 'a.txt', bucket: 'media', size: 5, contentType: 'text/plain', etag: 'e', createdAt: 't', updatedAt: 't' } }));
68
+ return;
69
+ }
70
+ if (req.method === 'HEAD') {
71
+ res.setHeader('content-length', '5');
72
+ res.setHeader('content-type', 'text/plain');
73
+ res.setHeader('etag', '"e"');
74
+ res.setHeader('x-object-key', 'a.txt');
75
+ res.setHeader('x-ocs-bucket', 'media');
76
+ res.end();
77
+ return;
78
+ }
79
+ if (req.method === 'DELETE') {
80
+ res.end(JSON.stringify({ ok: true, bucket: 'media', key: 'a.txt' }));
81
+ return;
82
+ }
83
+ if (req.method === 'GET') {
84
+ res.setHeader('content-type', 'text/plain');
85
+ res.end('hello');
86
+ return;
87
+ }
88
+ res.statusCode = 404;
89
+ res.end('{}');
90
+ });
91
+ }).listen(0, '127.0.0.1', () => {
92
+ const address = server.address();
93
+ base = `http://127.0.0.1:${typeof address === 'object' && address ? address.port : 0}`;
94
+ resolve();
95
+ });
96
+ }));
97
+ (0, node_test_1.after)(() => new Promise((resolve) => server.close(() => resolve())));
98
+ (0, node_test_1.describe)('SynapseOCS SDK', () => {
99
+ (0, node_test_1.it)('manages buckets and stats', async () => {
100
+ const client = new index_1.SynapseOneClient({ baseUrl: base });
101
+ const created = await client.ocs.createBucket('media', { quotaBytes: 100 });
102
+ strict_1.default.equal(created.bucket.name, 'media');
103
+ const list = await client.ocs.listBuckets({ withStats: true });
104
+ strict_1.default.equal(list.total, 1);
105
+ const stats = await client.ocs.bucketStats('media');
106
+ strict_1.default.equal(stats.objects, 1);
107
+ const head = await client.ocs.headBucket('media');
108
+ strict_1.default.equal(head?.['x-ocs-bucket'], 'media');
109
+ await client.ocs.deleteBucket('media', { force: true });
110
+ strict_1.default.ok(calls.some((call) => call.path.includes('force=true')));
111
+ });
112
+ (0, node_test_1.it)('puts, gets, heads, lists, copies and deletes objects', async () => {
113
+ const client = new index_1.SynapseOneClient({ baseUrl: base });
114
+ const object = await client.ocs.putObject('media', 'a.txt', 'hello', { contentType: 'text/plain' });
115
+ strict_1.default.equal(object.key, 'a.txt');
116
+ const body = await client.ocs.getObject('media', 'a.txt', { range: 'bytes=0-1' });
117
+ strict_1.default.equal(Buffer.from(body).toString(), 'hello');
118
+ const head = await client.ocs.headObject('media', 'a.txt');
119
+ strict_1.default.equal(head?.etag, 'e');
120
+ const list = await client.ocs.listObjects('media', { prefix: 'a' });
121
+ strict_1.default.equal(list.objects[0].key, 'a.txt');
122
+ const copy = await client.ocs.copyObject('media', { sourceKey: 'a.txt', destinationKey: 'b.txt' });
123
+ strict_1.default.equal(copy.object.key, 'b.txt');
124
+ await client.ocs.deleteObject('media', 'a.txt');
125
+ });
126
+ (0, node_test_1.it)('presigns and runs multipart uploads', async () => {
127
+ const client = new index_1.SynapseOneClient({ baseUrl: base });
128
+ const presigned = await client.ocs.presign('media', 'a.txt', { expiresIn: 60 });
129
+ strict_1.default.equal(presigned.method, 'GET');
130
+ const upload = await client.ocs.createMultipart('media', 'a.txt', 'text/plain');
131
+ strict_1.default.equal(upload.uploadId, 'u1');
132
+ const part = await client.ocs.uploadPart('media', 'u1', 'a.txt', 1, new Uint8Array([1, 2, 3]));
133
+ strict_1.default.equal(part.etag, 'p1');
134
+ const done = await client.ocs.completeMultipart('media', 'u1', 'a.txt', [{ partNumber: 1, etag: 'p1' }]);
135
+ strict_1.default.equal(done.object.size, 3);
136
+ });
137
+ });
@@ -0,0 +1,20 @@
1
+ import { HttpClient } from './_http';
2
+ export interface SearchQuery {
3
+ query: string;
4
+ mode?: 'fulltext' | 'semantic' | 'hybrid';
5
+ collection?: string;
6
+ collections?: string[];
7
+ filters?: Record<string, string>;
8
+ limit?: number;
9
+ cursor?: string | null;
10
+ }
11
+ export declare class SearchService {
12
+ private readonly http;
13
+ constructor(http: HttpClient);
14
+ query(input: SearchQuery): Promise<unknown>;
15
+ fulltext(query: string, opts?: Omit<SearchQuery, 'query' | 'mode'>): Promise<unknown>;
16
+ semantic(query: string, opts?: Omit<SearchQuery, 'query' | 'mode'>): Promise<unknown>;
17
+ hybrid(query: string, opts?: Omit<SearchQuery, 'query' | 'mode'>): Promise<unknown>;
18
+ reindex(collections?: string[]): Promise<unknown>;
19
+ status(): Promise<unknown>;
20
+ }
package/dist/search.js ADDED
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SearchService = void 0;
4
+ class SearchService {
5
+ http;
6
+ constructor(http) {
7
+ this.http = http;
8
+ }
9
+ query(input) {
10
+ return this.http.req('/v1/search', { method: 'POST', body: JSON.stringify(input) });
11
+ }
12
+ fulltext(query, opts = {}) {
13
+ return this.query({ query, ...opts, mode: 'fulltext' });
14
+ }
15
+ semantic(query, opts = {}) {
16
+ return this.query({ query, ...opts, mode: 'semantic' });
17
+ }
18
+ hybrid(query, opts = {}) {
19
+ return this.query({ query, ...opts, mode: 'hybrid' });
20
+ }
21
+ reindex(collections) {
22
+ return this.http.req('/v1/search/reindex', {
23
+ method: 'POST', body: JSON.stringify(collections ? { collections } : {}),
24
+ });
25
+ }
26
+ status() { return this.http.req('/v1/search/status'); }
27
+ }
28
+ exports.SearchService = SearchService;
@@ -50,6 +50,36 @@ export declare class WorkflowService {
50
50
  getCredential(id: string): Promise<CredentialMetadata>;
51
51
  rotateCredential(id: string, secret: string): Promise<CredentialMetadata>;
52
52
  deleteCredential(id: string): Promise<unknown>;
53
+ /** Create a standalone human task (workflow nodes create theirs on pause). */
54
+ createHumanTask(input: {
55
+ title: string;
56
+ description?: string;
57
+ assignee?: string;
58
+ candidateRoles?: string[];
59
+ deadline?: string;
60
+ decisionSchema?: Record<string, unknown>;
61
+ payload?: Record<string, unknown>;
62
+ workflowId?: string;
63
+ executionId?: string;
64
+ node?: string;
65
+ }): Promise<unknown>;
66
+ listHumanTasks(query?: Record<string, string | number | boolean | undefined>): Promise<unknown>;
67
+ getHumanTask(id: string): Promise<unknown>;
68
+ claimHumanTask(id: string): Promise<unknown>;
69
+ completeHumanTask(id: string, decision?: Record<string, unknown>, note?: string): Promise<unknown>;
70
+ rejectHumanTask(id: string, note: string, decision?: Record<string, unknown>): Promise<unknown>;
71
+ expireHumanTask(id: string, force?: boolean): Promise<unknown>;
72
+ createSecret(name: string, value: string, opts?: {
73
+ description?: string;
74
+ scope?: string;
75
+ accountId?: string;
76
+ }): Promise<unknown>;
77
+ listSecrets(): Promise<unknown>;
78
+ getSecret(name: string): Promise<unknown>;
79
+ readSecret(name: string, version?: number): Promise<unknown>;
80
+ rotateSecret(name: string, value: string, graceSeconds?: number): Promise<unknown>;
81
+ revokeSecret(name: string, version?: number): Promise<unknown>;
82
+ deleteSecret(name: string): Promise<unknown>;
53
83
  /**
54
84
  * Fire a public inbound webhook through the gateway: `ANY /webhook/:path`.
55
85
  * No auth is required; per-workflow auth/rate-limit/idempotency still apply.
package/dist/workflow.js CHANGED
@@ -106,6 +106,63 @@ class WorkflowService {
106
106
  deleteCredential(id) {
107
107
  return this.http.req(`/v1/credentials/${encodeURIComponent(id)}`, { method: 'DELETE' });
108
108
  }
109
+ // ---- durable human tasks (#44) ----
110
+ /** Create a standalone human task (workflow nodes create theirs on pause). */
111
+ createHumanTask(input) {
112
+ return this.http.req('/v1/human-tasks', { method: 'POST', body: JSON.stringify(input) });
113
+ }
114
+ listHumanTasks(query = {}) {
115
+ const allowed = ['status', 'executionId', 'workflowId', 'assignee', 'limit', 'offset'];
116
+ const params = new URLSearchParams();
117
+ for (const k of allowed) {
118
+ const v = query[k];
119
+ if (v !== undefined && v !== null && String(v) !== '')
120
+ params.set(k, String(v));
121
+ }
122
+ const s = params.toString();
123
+ return this.http.req(`/v1/human-tasks${s ? `?${s}` : ''}`);
124
+ }
125
+ getHumanTask(id) { return this.http.req(`/v1/human-tasks/${encodeURIComponent(id)}`); }
126
+ claimHumanTask(id) { return this.http.req(`/v1/human-tasks/${encodeURIComponent(id)}/claim`, { method: 'POST', body: '{}' }); }
127
+ completeHumanTask(id, decision = {}, note) {
128
+ return this.http.req(`/v1/human-tasks/${encodeURIComponent(id)}/complete`, {
129
+ method: 'POST', body: JSON.stringify({ decision, ...(note ? { note } : {}) }),
130
+ });
131
+ }
132
+ rejectHumanTask(id, note, decision = {}) {
133
+ return this.http.req(`/v1/human-tasks/${encodeURIComponent(id)}/reject`, {
134
+ method: 'POST', body: JSON.stringify({ note, decision }),
135
+ });
136
+ }
137
+ expireHumanTask(id, force = false) {
138
+ return this.http.req(`/v1/human-tasks/${encodeURIComponent(id)}/expire`, {
139
+ method: 'POST', body: JSON.stringify({ force }),
140
+ });
141
+ }
142
+ // ---- tenant secret vault (#47) ----
143
+ createSecret(name, value, opts = {}) {
144
+ return this.http.req('/v1/secrets', { method: 'POST', body: JSON.stringify({ name, value, ...opts }) });
145
+ }
146
+ listSecrets() { return this.http.req('/v1/secrets'); }
147
+ getSecret(name) { return this.http.req(`/v1/secrets/${encodeURIComponent(name)}`); }
148
+ readSecret(name, version) {
149
+ return this.http.req(`/v1/secrets/${encodeURIComponent(name)}/read`, {
150
+ method: 'POST', body: JSON.stringify(version ? { version } : {}),
151
+ });
152
+ }
153
+ rotateSecret(name, value, graceSeconds = 86400) {
154
+ return this.http.req(`/v1/secrets/${encodeURIComponent(name)}/rotate`, {
155
+ method: 'POST', body: JSON.stringify({ value, graceSeconds }),
156
+ });
157
+ }
158
+ revokeSecret(name, version) {
159
+ return this.http.req(`/v1/secrets/${encodeURIComponent(name)}/revoke`, {
160
+ method: 'POST', body: JSON.stringify(version ? { version } : {}),
161
+ });
162
+ }
163
+ deleteSecret(name) {
164
+ return this.http.req(`/v1/secrets/${encodeURIComponent(name)}`, { method: 'DELETE' });
165
+ }
109
166
  // ---- public inbound webhooks ----
110
167
  /**
111
168
  * Fire a public inbound webhook through the gateway: `ANY /webhook/:path`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@synapseone/sdk",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "license": "Apache-2.0",
5
5
  "description": "synapseone SDK for JavaScript/TypeScript",
6
6
  "homepage": "https://synapseone.space",