@mymehq/sdk 3.5.0 → 3.7.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/index.d.ts +155 -7
- package/dist/index.js +89 -18
- package/package.json +2 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { MergeStrategy, ConflictSnapshot, MergePolicy,
|
|
1
|
+
import { MergeStrategy, ConflictSnapshot, MergePolicy, ItemState, Item, CreateItemInput, PaginatedResult, ItemWithMetadata, Version, Edge, Metadata, SearchResult, CreateEdgeInput, EdgeTypeSchema, TypeSchema, CreateKeyInput, ApiKey, UpdateKeyInput, CreateWebhookInput, Webhook, UpdateWebhookInput, WebhookDelivery, TenantConfig } from '@mymehq/shared';
|
|
2
2
|
export { ApiKey, ConflictSnapshot, CreateItemInput, CreateKeyInput, Item, ItemState, MergePolicy, MergeStrategy, Metadata, PaginatedResult, SearchResult, TypeSchema, UpdateKeyInput, Version } from '@mymehq/shared';
|
|
3
3
|
|
|
4
4
|
/**
|
|
@@ -163,6 +163,126 @@ interface SearchFilters {
|
|
|
163
163
|
interface MetadataInput {
|
|
164
164
|
tags?: string[];
|
|
165
165
|
}
|
|
166
|
+
/** One item to create or upsert in a `POST /items/bulk` call. Shape is
|
|
167
|
+
* `CreateItemInput` plus compact outbound-only inline `edges`. */
|
|
168
|
+
interface BulkItemInput {
|
|
169
|
+
id?: string;
|
|
170
|
+
type: string;
|
|
171
|
+
properties?: Record<string, unknown>;
|
|
172
|
+
state?: ItemState;
|
|
173
|
+
library?: boolean;
|
|
174
|
+
timestamp?: string;
|
|
175
|
+
/** Ignored on the wire — server stamps `source` from the credential.
|
|
176
|
+
* Kept on the input shape for round-trip parity with /export output. */
|
|
177
|
+
source?: string;
|
|
178
|
+
source_id?: string;
|
|
179
|
+
origin?: "user" | "ai" | "worker";
|
|
180
|
+
device?: string;
|
|
181
|
+
tags?: string[];
|
|
182
|
+
/** Outbound edges to reconcile in the same transaction as the item
|
|
183
|
+
* write. Replace-all semantics per edge_type. Absent = untouched. */
|
|
184
|
+
edges?: Record<string, string[]>;
|
|
185
|
+
}
|
|
186
|
+
type BulkMode = "upsert" | "create_only";
|
|
187
|
+
interface BulkInput {
|
|
188
|
+
items: BulkItemInput[];
|
|
189
|
+
/** Default: `"upsert"`. */
|
|
190
|
+
mode?: BulkMode;
|
|
191
|
+
/** Default: `true`. When false, errors are collected per item and the
|
|
192
|
+
* batch continues past failures. */
|
|
193
|
+
atomic?: boolean;
|
|
194
|
+
/** Default: `false`. Per-item events are suppressed on bulk writes
|
|
195
|
+
* unless the caller opts in. */
|
|
196
|
+
emit_events?: boolean;
|
|
197
|
+
}
|
|
198
|
+
type BulkOutcome = "created" | "updated" | "skipped" | "errored";
|
|
199
|
+
interface BulkResultEntry {
|
|
200
|
+
index: number;
|
|
201
|
+
outcome: BulkOutcome;
|
|
202
|
+
id?: string;
|
|
203
|
+
reason?: string;
|
|
204
|
+
error?: {
|
|
205
|
+
code: string;
|
|
206
|
+
message: string;
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
interface BulkResult {
|
|
210
|
+
counts: {
|
|
211
|
+
created: number;
|
|
212
|
+
updated: number;
|
|
213
|
+
skipped: number;
|
|
214
|
+
errored: number;
|
|
215
|
+
};
|
|
216
|
+
results: BulkResultEntry[];
|
|
217
|
+
/** Present only on archive-restore paths. */
|
|
218
|
+
blobs_imported?: number;
|
|
219
|
+
}
|
|
220
|
+
/** Filter shape for `POST /items/bulk_action`. Mirrors the `GET /items`
|
|
221
|
+
* query grammar — every field is AND-composed, `filter` accepts the
|
|
222
|
+
* full filter-SQL DSL. */
|
|
223
|
+
interface BulkActionFilter {
|
|
224
|
+
type?: string;
|
|
225
|
+
state?: ItemState;
|
|
226
|
+
source?: string;
|
|
227
|
+
library?: boolean;
|
|
228
|
+
tags?: string[];
|
|
229
|
+
since?: string;
|
|
230
|
+
until?: string;
|
|
231
|
+
/** Same grammar as `GET /items?filter=`. `edge[type]=id` shorthand
|
|
232
|
+
* becomes `edge[type] eq "id"` here. */
|
|
233
|
+
filter?: string;
|
|
234
|
+
}
|
|
235
|
+
/** Shared knobs every bulk action accepts. */
|
|
236
|
+
interface BulkActionBase {
|
|
237
|
+
filter?: BulkActionFilter;
|
|
238
|
+
dry_run?: boolean;
|
|
239
|
+
max_items?: number;
|
|
240
|
+
emit_events?: boolean;
|
|
241
|
+
}
|
|
242
|
+
/** Discriminated union over the six bulk actions. The compiler pins the
|
|
243
|
+
* per-case parameters at the call site — no runtime string fiddling. */
|
|
244
|
+
type BulkActionInput = (BulkActionBase & {
|
|
245
|
+
action: "transition";
|
|
246
|
+
state: "active" | "archived" | "trashed";
|
|
247
|
+
}) | (BulkActionBase & {
|
|
248
|
+
action: "purge";
|
|
249
|
+
/** Required literal. The server returns `400 bulk_confirmation_required`
|
|
250
|
+
* without it; the SDK throws the same shape before sending. */
|
|
251
|
+
confirm: "PURGE";
|
|
252
|
+
}) | (BulkActionBase & {
|
|
253
|
+
action: "update_tags";
|
|
254
|
+
add?: string[];
|
|
255
|
+
remove?: string[];
|
|
256
|
+
}) | (BulkActionBase & {
|
|
257
|
+
action: "update_library";
|
|
258
|
+
library: boolean;
|
|
259
|
+
}) | (BulkActionBase & {
|
|
260
|
+
action: "update_properties";
|
|
261
|
+
patch: Record<string, unknown>;
|
|
262
|
+
}) | (BulkActionBase & {
|
|
263
|
+
action: "update_timestamp";
|
|
264
|
+
timestamp: string;
|
|
265
|
+
});
|
|
266
|
+
interface BulkActionErrorEntry {
|
|
267
|
+
id: string;
|
|
268
|
+
code: string;
|
|
269
|
+
message: string;
|
|
270
|
+
}
|
|
271
|
+
interface BulkActionResult {
|
|
272
|
+
action: string;
|
|
273
|
+
matched: number;
|
|
274
|
+
succeeded: number;
|
|
275
|
+
errored: number;
|
|
276
|
+
dry_run: boolean;
|
|
277
|
+
/** Present when matched / succeeded is small enough to be useful
|
|
278
|
+
* (dry-run always, otherwise when succeeded ≤ 100). */
|
|
279
|
+
ids?: string[];
|
|
280
|
+
errors?: BulkActionErrorEntry[];
|
|
281
|
+
/** Unique blob hashes referenced by items in a `purge` action. Not a
|
|
282
|
+
* strict orphan count — callers that need that should wait for blob
|
|
283
|
+
* GC to land. Omitted for non-purge actions. */
|
|
284
|
+
blob_hashes_referenced?: number;
|
|
285
|
+
}
|
|
166
286
|
declare class MymeClient {
|
|
167
287
|
private readonly transport;
|
|
168
288
|
private readonly defaultConflictStrategy;
|
|
@@ -196,6 +316,25 @@ declare class MymeClient {
|
|
|
196
316
|
transition: (id: string, state: string) => Promise<Item>;
|
|
197
317
|
versions: (id: string) => Promise<Version[]>;
|
|
198
318
|
stats: () => Promise<Record<string, number>>;
|
|
319
|
+
/**
|
|
320
|
+
* Create or upsert many items in one call (admin-only). Replaces the
|
|
321
|
+
* historical `/import` endpoint. Up to 5000 items per call.
|
|
322
|
+
*
|
|
323
|
+
* Modes: `"upsert"` (default) updates matching `(source, source_id)`
|
|
324
|
+
* rows in place; `"create_only"` surfaces matches as `skipped`.
|
|
325
|
+
* `atomic: true` (default) rolls back the whole batch on any failure.
|
|
326
|
+
*/
|
|
327
|
+
bulk: (input: BulkInput) => Promise<BulkResult>;
|
|
328
|
+
/**
|
|
329
|
+
* Apply one action to every item matching a filter. Six actions
|
|
330
|
+
* discriminated on `action`. Purge is admin-only and requires
|
|
331
|
+
* `confirm: "PURGE"` — the SDK throws a `bulk_confirmation_required`
|
|
332
|
+
* `MymeError` client-side if you forget, matching the server's 400.
|
|
333
|
+
*
|
|
334
|
+
* Non-admin callers see their match set narrowed to writable types
|
|
335
|
+
* for every action except `purge`, which hard-403s.
|
|
336
|
+
*/
|
|
337
|
+
bulkAction: (input: BulkActionInput) => Promise<BulkActionResult>;
|
|
199
338
|
/** Outbound edges from this item. Shortcut for edges.listFromSource. */
|
|
200
339
|
edges: (itemId: string, filters?: {
|
|
201
340
|
edge_type?: string | string[];
|
|
@@ -348,19 +487,28 @@ declare class MymeError extends Error {
|
|
|
348
487
|
readonly code: string;
|
|
349
488
|
readonly status: number;
|
|
350
489
|
readonly details?: Record<string, unknown>;
|
|
351
|
-
constructor(code: string, message: string, status: number, details?: Record<string, unknown
|
|
490
|
+
constructor(code: string, message: string, status: number, details?: Record<string, unknown>, cause?: unknown);
|
|
352
491
|
}
|
|
492
|
+
/**
|
|
493
|
+
* Status-coded subclasses preserve the server-supplied `code` so callers
|
|
494
|
+
* can branch on specific codes (`bulk_cap_exceeded`, `edge_not_found`,
|
|
495
|
+
* `reset_disabled`, …) while still matching `instanceof NotFoundError`
|
|
496
|
+
* etc. for generic handling. The status family (4xx bucket) is
|
|
497
|
+
* communicated by the class; the specific code is communicated by the
|
|
498
|
+
* `code` field. When the server omits a code, the canonical value for
|
|
499
|
+
* the status family is used as a fallback.
|
|
500
|
+
*/
|
|
353
501
|
declare class NotFoundError extends MymeError {
|
|
354
|
-
constructor(message: string, details?: Record<string, unknown
|
|
502
|
+
constructor(message: string, details?: Record<string, unknown>, code?: string);
|
|
355
503
|
}
|
|
356
504
|
declare class ValidationError extends MymeError {
|
|
357
|
-
constructor(message: string, details?: Record<string, unknown
|
|
505
|
+
constructor(message: string, details?: Record<string, unknown>, code?: string);
|
|
358
506
|
}
|
|
359
507
|
declare class UnauthorizedError extends MymeError {
|
|
360
|
-
constructor(message: string, details?: Record<string, unknown
|
|
508
|
+
constructor(message: string, details?: Record<string, unknown>, code?: string);
|
|
361
509
|
}
|
|
362
510
|
declare class ForbiddenError extends MymeError {
|
|
363
|
-
constructor(message: string, details?: Record<string, unknown
|
|
511
|
+
constructor(message: string, details?: Record<string, unknown>, code?: string);
|
|
364
512
|
}
|
|
365
513
|
declare class ConflictError extends MymeError {
|
|
366
514
|
readonly current: ConflictSnapshot;
|
|
@@ -422,4 +570,4 @@ interface VerifyWebhookSignatureInput {
|
|
|
422
570
|
*/
|
|
423
571
|
declare function verifyWebhookSignature(input: VerifyWebhookSignatureInput): WebhookVerifyResult;
|
|
424
572
|
|
|
425
|
-
export { type ClientConfig, type ConflictAutoMergeListener, type ConflictAutoMergedEvent, type ConflictData, ConflictError, type ConflictResolver, type ConflictStrategy, ForbiddenError, type ItemWithExtensions, type ListFilters, type MetadataInput, MymeClient, MymeError, NotFoundError, type SearchFilters, UnauthorizedError, type UpdateOptions, ValidationError, type VerifyWebhookSignatureInput, type WebhookVerifyReason, type WebhookVerifyResult, verifyWebhookSignature };
|
|
573
|
+
export { type BulkActionErrorEntry, type BulkActionFilter, type BulkActionInput, type BulkActionResult, type BulkInput, type BulkItemInput, type BulkMode, type BulkOutcome, type BulkResult, type BulkResultEntry, type ClientConfig, type ConflictAutoMergeListener, type ConflictAutoMergedEvent, type ConflictData, ConflictError, type ConflictResolver, type ConflictStrategy, ForbiddenError, type ItemWithExtensions, type ListFilters, type MetadataInput, MymeClient, MymeError, NotFoundError, type SearchFilters, UnauthorizedError, type UpdateOptions, ValidationError, type VerifyWebhookSignatureInput, type WebhookVerifyReason, type WebhookVerifyResult, verifyWebhookSignature };
|
package/dist/index.js
CHANGED
|
@@ -3,8 +3,8 @@ var MymeError = class extends Error {
|
|
|
3
3
|
code;
|
|
4
4
|
status;
|
|
5
5
|
details;
|
|
6
|
-
constructor(code, message, status, details) {
|
|
7
|
-
super(message);
|
|
6
|
+
constructor(code, message, status, details, cause) {
|
|
7
|
+
super(message, cause !== void 0 ? { cause } : void 0);
|
|
8
8
|
this.name = "MymeError";
|
|
9
9
|
this.code = code;
|
|
10
10
|
this.status = status;
|
|
@@ -12,26 +12,26 @@ var MymeError = class extends Error {
|
|
|
12
12
|
}
|
|
13
13
|
};
|
|
14
14
|
var NotFoundError = class extends MymeError {
|
|
15
|
-
constructor(message, details) {
|
|
16
|
-
super("not_found", message, 404, details);
|
|
15
|
+
constructor(message, details, code) {
|
|
16
|
+
super(code ?? "not_found", message, 404, details);
|
|
17
17
|
this.name = "NotFoundError";
|
|
18
18
|
}
|
|
19
19
|
};
|
|
20
20
|
var ValidationError = class extends MymeError {
|
|
21
|
-
constructor(message, details) {
|
|
22
|
-
super("validation_error", message, 400, details);
|
|
21
|
+
constructor(message, details, code) {
|
|
22
|
+
super(code ?? "validation_error", message, 400, details);
|
|
23
23
|
this.name = "ValidationError";
|
|
24
24
|
}
|
|
25
25
|
};
|
|
26
26
|
var UnauthorizedError = class extends MymeError {
|
|
27
|
-
constructor(message, details) {
|
|
28
|
-
super("unauthorized", message, 401, details);
|
|
27
|
+
constructor(message, details, code) {
|
|
28
|
+
super(code ?? "unauthorized", message, 401, details);
|
|
29
29
|
this.name = "UnauthorizedError";
|
|
30
30
|
}
|
|
31
31
|
};
|
|
32
32
|
var ForbiddenError = class extends MymeError {
|
|
33
|
-
constructor(message, details) {
|
|
34
|
-
super("forbidden", message, 403, details);
|
|
33
|
+
constructor(message, details, code) {
|
|
34
|
+
super(code ?? "forbidden", message, 403, details);
|
|
35
35
|
this.name = "ForbiddenError";
|
|
36
36
|
}
|
|
37
37
|
};
|
|
@@ -68,7 +68,7 @@ var HttpTransport = class {
|
|
|
68
68
|
if (response.status === 204) {
|
|
69
69
|
return void 0;
|
|
70
70
|
}
|
|
71
|
-
const body = await
|
|
71
|
+
const body = await this.parseJson(response);
|
|
72
72
|
if (!response.ok) {
|
|
73
73
|
this.throwForError(response.status, body);
|
|
74
74
|
}
|
|
@@ -81,7 +81,7 @@ var HttpTransport = class {
|
|
|
81
81
|
*/
|
|
82
82
|
async requestWithConflict(method, path, options) {
|
|
83
83
|
const response = await this.rawRequest(method, path, options);
|
|
84
|
-
const body = await
|
|
84
|
+
const body = await this.parseJson(response);
|
|
85
85
|
if (response.status === 409) {
|
|
86
86
|
return body;
|
|
87
87
|
}
|
|
@@ -109,10 +109,42 @@ var HttpTransport = class {
|
|
|
109
109
|
}
|
|
110
110
|
try {
|
|
111
111
|
return await this.fetch(url, init);
|
|
112
|
+
} catch (err) {
|
|
113
|
+
if (err instanceof DOMException && err.name === "AbortError") {
|
|
114
|
+
throw new MymeError(
|
|
115
|
+
"timeout",
|
|
116
|
+
`Request to ${path} timed out after ${String(this.timeoutMs)}ms`,
|
|
117
|
+
0,
|
|
118
|
+
{ path, timeoutMs: this.timeoutMs },
|
|
119
|
+
err
|
|
120
|
+
);
|
|
121
|
+
}
|
|
122
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
123
|
+
throw new MymeError(
|
|
124
|
+
"network_error",
|
|
125
|
+
`Network request to ${path} failed: ${reason}`,
|
|
126
|
+
0,
|
|
127
|
+
{ path },
|
|
128
|
+
err
|
|
129
|
+
);
|
|
112
130
|
} finally {
|
|
113
131
|
clearTimeout(timeout);
|
|
114
132
|
}
|
|
115
133
|
}
|
|
134
|
+
async parseJson(response) {
|
|
135
|
+
try {
|
|
136
|
+
return await response.json();
|
|
137
|
+
} catch (err) {
|
|
138
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
139
|
+
throw new MymeError(
|
|
140
|
+
"parse_error",
|
|
141
|
+
`Failed to parse response body as JSON (HTTP ${String(response.status)}): ${reason}`,
|
|
142
|
+
0,
|
|
143
|
+
{ httpStatus: response.status },
|
|
144
|
+
err
|
|
145
|
+
);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
116
148
|
buildUrl(path, query) {
|
|
117
149
|
const url = `${this.baseUrl}${path}`;
|
|
118
150
|
if (!query) return url;
|
|
@@ -135,18 +167,18 @@ var HttpTransport = class {
|
|
|
135
167
|
const errObj = parsed?.error;
|
|
136
168
|
const message = errObj?.message ?? `HTTP ${String(status)}`;
|
|
137
169
|
const details = errObj?.details;
|
|
138
|
-
const
|
|
170
|
+
const serverCode = errObj?.code;
|
|
139
171
|
switch (status) {
|
|
140
172
|
case 400:
|
|
141
|
-
throw new ValidationError(message, details);
|
|
173
|
+
throw new ValidationError(message, details, serverCode);
|
|
142
174
|
case 401:
|
|
143
|
-
throw new UnauthorizedError(message, details);
|
|
175
|
+
throw new UnauthorizedError(message, details, serverCode);
|
|
144
176
|
case 403:
|
|
145
|
-
throw new ForbiddenError(message, details);
|
|
177
|
+
throw new ForbiddenError(message, details, serverCode);
|
|
146
178
|
case 404:
|
|
147
|
-
throw new NotFoundError(message, details);
|
|
179
|
+
throw new NotFoundError(message, details, serverCode);
|
|
148
180
|
default:
|
|
149
|
-
throw new MymeError(
|
|
181
|
+
throw new MymeError(serverCode ?? "unknown", message, status, details);
|
|
150
182
|
}
|
|
151
183
|
}
|
|
152
184
|
};
|
|
@@ -412,6 +444,45 @@ var MymeClient = class {
|
|
|
412
444
|
"/items/stats"
|
|
413
445
|
);
|
|
414
446
|
},
|
|
447
|
+
/**
|
|
448
|
+
* Create or upsert many items in one call (admin-only). Replaces the
|
|
449
|
+
* historical `/import` endpoint. Up to 5000 items per call.
|
|
450
|
+
*
|
|
451
|
+
* Modes: `"upsert"` (default) updates matching `(source, source_id)`
|
|
452
|
+
* rows in place; `"create_only"` surfaces matches as `skipped`.
|
|
453
|
+
* `atomic: true` (default) rolls back the whole batch on any failure.
|
|
454
|
+
*/
|
|
455
|
+
bulk: async (input) => {
|
|
456
|
+
return this.transport.request("POST", "/items/bulk", {
|
|
457
|
+
body: input
|
|
458
|
+
});
|
|
459
|
+
},
|
|
460
|
+
/**
|
|
461
|
+
* Apply one action to every item matching a filter. Six actions
|
|
462
|
+
* discriminated on `action`. Purge is admin-only and requires
|
|
463
|
+
* `confirm: "PURGE"` — the SDK throws a `bulk_confirmation_required`
|
|
464
|
+
* `MymeError` client-side if you forget, matching the server's 400.
|
|
465
|
+
*
|
|
466
|
+
* Non-admin callers see their match set narrowed to writable types
|
|
467
|
+
* for every action except `purge`, which hard-403s.
|
|
468
|
+
*/
|
|
469
|
+
bulkAction: async (input) => {
|
|
470
|
+
if (input.action === "purge") {
|
|
471
|
+
const confirm = input.confirm;
|
|
472
|
+
if (confirm !== "PURGE") {
|
|
473
|
+
throw new MymeError(
|
|
474
|
+
"bulk_confirmation_required",
|
|
475
|
+
"bulkAction({ action: 'purge' }) requires confirm: 'PURGE'",
|
|
476
|
+
400
|
|
477
|
+
);
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
return this.transport.request(
|
|
481
|
+
"POST",
|
|
482
|
+
"/items/bulk_action",
|
|
483
|
+
{ body: input }
|
|
484
|
+
);
|
|
485
|
+
},
|
|
415
486
|
/** Outbound edges from this item. Shortcut for edges.listFromSource. */
|
|
416
487
|
edges: (itemId, filters) => this.edges.listFromSource(itemId, filters),
|
|
417
488
|
/** Inbound edges targeting this item. Shortcut for edges.listToTarget. */
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mymehq/sdk",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.7.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"dist"
|
|
17
17
|
],
|
|
18
18
|
"dependencies": {
|
|
19
|
-
"@mymehq/shared": "3.
|
|
19
|
+
"@mymehq/shared": "3.5.0"
|
|
20
20
|
},
|
|
21
21
|
"devDependencies": {
|
|
22
22
|
"@types/node": "^22.0.0",
|