memorysync-sdk 1.0.2 → 1.1.1
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/README.md +50 -0
- package/dist/index.d.mts +414 -28
- package/dist/index.d.ts +414 -28
- package/dist/index.js +452 -20
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +450 -21
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -21,6 +21,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
23
|
AuthError: () => AuthError,
|
|
24
|
+
ControlPlaneClient: () => ControlPlaneClient,
|
|
24
25
|
MemorySyncClient: () => MemorySyncClient,
|
|
25
26
|
MemorySyncError: () => MemorySyncError,
|
|
26
27
|
NotFoundError: () => NotFoundError,
|
|
@@ -29,47 +30,477 @@ __export(index_exports, {
|
|
|
29
30
|
ValidationError: () => ValidationError
|
|
30
31
|
});
|
|
31
32
|
module.exports = __toCommonJS(index_exports);
|
|
33
|
+
|
|
34
|
+
// src/errors.ts
|
|
32
35
|
var MemorySyncError = class extends Error {
|
|
33
|
-
constructor(message,
|
|
36
|
+
constructor(message, options = {}) {
|
|
34
37
|
super(message);
|
|
35
38
|
this.name = "MemorySyncError";
|
|
36
|
-
this.statusCode =
|
|
37
|
-
this.response =
|
|
38
|
-
this.requestId =
|
|
39
|
+
this.statusCode = options.statusCode;
|
|
40
|
+
this.response = options.response;
|
|
41
|
+
this.requestId = options.requestId;
|
|
39
42
|
}
|
|
40
43
|
};
|
|
41
44
|
var AuthError = class extends MemorySyncError {
|
|
42
|
-
constructor(message,
|
|
43
|
-
super(message,
|
|
45
|
+
constructor(message, options) {
|
|
46
|
+
super(message, options);
|
|
44
47
|
this.name = "AuthError";
|
|
45
48
|
}
|
|
46
49
|
};
|
|
47
50
|
var ValidationError = class extends MemorySyncError {
|
|
48
|
-
constructor(message,
|
|
49
|
-
super(message,
|
|
51
|
+
constructor(message, options) {
|
|
52
|
+
super(message, options);
|
|
50
53
|
this.name = "ValidationError";
|
|
51
54
|
}
|
|
52
55
|
};
|
|
53
56
|
var NotFoundError = class extends MemorySyncError {
|
|
54
|
-
constructor(message,
|
|
55
|
-
super(message,
|
|
57
|
+
constructor(message, options) {
|
|
58
|
+
super(message, options);
|
|
56
59
|
this.name = "NotFoundError";
|
|
57
60
|
}
|
|
58
61
|
};
|
|
59
62
|
var RateLimitError = class extends MemorySyncError {
|
|
60
|
-
constructor(message, retryAfterSeconds,
|
|
61
|
-
super(message,
|
|
63
|
+
constructor(message, retryAfterSeconds, options) {
|
|
64
|
+
super(message, options);
|
|
62
65
|
this.name = "RateLimitError";
|
|
63
66
|
this.retryAfterSeconds = retryAfterSeconds;
|
|
64
67
|
}
|
|
65
68
|
};
|
|
66
69
|
var ServerError = class extends MemorySyncError {
|
|
67
|
-
constructor(message,
|
|
68
|
-
super(message,
|
|
70
|
+
constructor(message, options) {
|
|
71
|
+
super(message, options);
|
|
69
72
|
this.name = "ServerError";
|
|
70
73
|
}
|
|
71
74
|
};
|
|
72
|
-
|
|
75
|
+
|
|
76
|
+
// src/control-plane.ts
|
|
77
|
+
var SDK_VERSION = "1.1.1";
|
|
78
|
+
function safeJson(text) {
|
|
79
|
+
try {
|
|
80
|
+
return JSON.parse(text);
|
|
81
|
+
} catch {
|
|
82
|
+
return text;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function extractDetail(body) {
|
|
86
|
+
if (!body || typeof body !== "object") return void 0;
|
|
87
|
+
const value = body;
|
|
88
|
+
if (typeof value.detail === "string") return value.detail;
|
|
89
|
+
if (value.error && typeof value.error === "object") {
|
|
90
|
+
const error = value.error;
|
|
91
|
+
if (typeof error.message === "string") return error.message;
|
|
92
|
+
}
|
|
93
|
+
if (Array.isArray(value.detail) && value.detail.length > 0) {
|
|
94
|
+
const first = value.detail[0];
|
|
95
|
+
if (first && typeof first === "object" && typeof first.msg === "string") {
|
|
96
|
+
return first.msg;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return void 0;
|
|
100
|
+
}
|
|
101
|
+
function extractBodyRetryAfter(body) {
|
|
102
|
+
if (!body || typeof body !== "object") return 0;
|
|
103
|
+
const value = body;
|
|
104
|
+
if (typeof value.retry_after === "number") return value.retry_after;
|
|
105
|
+
if (value.error && typeof value.error === "object") {
|
|
106
|
+
const retryAfter = value.error.retry_after;
|
|
107
|
+
if (typeof retryAfter === "number") return retryAfter;
|
|
108
|
+
}
|
|
109
|
+
return 0;
|
|
110
|
+
}
|
|
111
|
+
function parseRetryAfter(value) {
|
|
112
|
+
if (!value) return void 0;
|
|
113
|
+
const seconds = Number(value);
|
|
114
|
+
if (Number.isFinite(seconds) && seconds >= 0) return seconds;
|
|
115
|
+
const date = Date.parse(value);
|
|
116
|
+
if (Number.isNaN(date)) return void 0;
|
|
117
|
+
return Math.max(0, Math.ceil((date - Date.now()) / 1e3));
|
|
118
|
+
}
|
|
119
|
+
function snakeToCamel(key) {
|
|
120
|
+
return key.replace(/_([a-z0-9])/g, (_, character) => character.toUpperCase());
|
|
121
|
+
}
|
|
122
|
+
var OPAQUE_RESPONSE_KEYS = /* @__PURE__ */ new Set(["payload", "metadata", "geo", "configuration"]);
|
|
123
|
+
function normalizeResponse(value) {
|
|
124
|
+
if (Array.isArray(value)) return value.map(normalizeResponse);
|
|
125
|
+
if (!value || typeof value !== "object") return value;
|
|
126
|
+
const normalized = {};
|
|
127
|
+
for (const [key, item] of Object.entries(value)) {
|
|
128
|
+
const camelKey = snakeToCamel(key);
|
|
129
|
+
normalized[camelKey] = OPAQUE_RESPONSE_KEYS.has(camelKey) ? item : normalizeResponse(item);
|
|
130
|
+
}
|
|
131
|
+
return normalized;
|
|
132
|
+
}
|
|
133
|
+
function queryString(values) {
|
|
134
|
+
const params = new URLSearchParams();
|
|
135
|
+
for (const [key, value] of Object.entries(values)) {
|
|
136
|
+
if (value !== void 0 && value !== null) params.set(key, String(value));
|
|
137
|
+
}
|
|
138
|
+
const encoded = params.toString();
|
|
139
|
+
return encoded ? `?${encoded}` : "";
|
|
140
|
+
}
|
|
141
|
+
function positiveId(value, name) {
|
|
142
|
+
if (!Number.isInteger(value) || value <= 0) {
|
|
143
|
+
throw new ValidationError(`${name} must be a positive integer`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
function nonEmpty(value, name) {
|
|
147
|
+
if (typeof value !== "string" || !value.trim()) throw new ValidationError(`${name} must not be empty`);
|
|
148
|
+
}
|
|
149
|
+
function boundedInteger(value, name, minimum, maximum) {
|
|
150
|
+
if (!Number.isInteger(value) || value < minimum || value > maximum) {
|
|
151
|
+
throw new ValidationError(`${name} must be an integer between ${minimum} and ${maximum}`);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
function nonNegativeInteger(value, name) {
|
|
155
|
+
if (!Number.isInteger(value) || value < 0) {
|
|
156
|
+
throw new ValidationError(`${name} must be a non-negative integer`);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
function nonEmptyStrings(values, name) {
|
|
160
|
+
if (!Array.isArray(values) || values.length === 0 || values.some((value) => typeof value !== "string" || !value.trim())) {
|
|
161
|
+
throw new ValidationError(`${name} must contain at least one non-empty string`);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
function webhookRetryConfig(config) {
|
|
165
|
+
const wire = {};
|
|
166
|
+
if (config.enabled !== void 0) wire.enabled = config.enabled;
|
|
167
|
+
if (config.maxRetries !== void 0) wire.max_retries = config.maxRetries;
|
|
168
|
+
if (config.initialDelaySeconds !== void 0) wire.initial_delay_seconds = config.initialDelaySeconds;
|
|
169
|
+
if (config.maxDelaySeconds !== void 0) wire.max_delay_seconds = config.maxDelaySeconds;
|
|
170
|
+
if (config.backoffMultiplier !== void 0) wire.backoff_multiplier = config.backoffMultiplier;
|
|
171
|
+
if (config.retryStatusCodes !== void 0) wire.retry_status_codes = config.retryStatusCodes;
|
|
172
|
+
return wire;
|
|
173
|
+
}
|
|
174
|
+
function webhookSignatureConfig(config) {
|
|
175
|
+
const wire = {};
|
|
176
|
+
if (config.algorithm !== void 0) wire.algorithm = config.algorithm;
|
|
177
|
+
if (config.headerName !== void 0) wire.header_name = config.headerName;
|
|
178
|
+
if (config.timestampHeader !== void 0) wire.timestamp_header = config.timestampHeader;
|
|
179
|
+
if (config.toleranceSeconds !== void 0) wire.tolerance_seconds = config.toleranceSeconds;
|
|
180
|
+
return wire;
|
|
181
|
+
}
|
|
182
|
+
function validateWebhook(name, url, events) {
|
|
183
|
+
nonEmpty(name, "name");
|
|
184
|
+
if (name.length > 128) throw new ValidationError("name may contain at most 128 characters");
|
|
185
|
+
nonEmptyStrings(events, "events");
|
|
186
|
+
validateWebhookUrl(url);
|
|
187
|
+
}
|
|
188
|
+
function validateWebhookUrl(url) {
|
|
189
|
+
nonEmpty(url, "url");
|
|
190
|
+
let parsed;
|
|
191
|
+
try {
|
|
192
|
+
parsed = new URL(url);
|
|
193
|
+
} catch {
|
|
194
|
+
throw new ValidationError("url must be a valid HTTP or HTTPS URL");
|
|
195
|
+
}
|
|
196
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
197
|
+
throw new ValidationError("url must be a valid HTTP or HTTPS URL");
|
|
198
|
+
}
|
|
199
|
+
if (parsed.username || parsed.password) throw new ValidationError("url must not contain credentials");
|
|
200
|
+
}
|
|
201
|
+
var ControlPlaneClient = class {
|
|
202
|
+
constructor(config) {
|
|
203
|
+
if (!config.baseUrl?.trim()) throw new ValidationError("baseUrl is required");
|
|
204
|
+
let parsed;
|
|
205
|
+
try {
|
|
206
|
+
parsed = new URL(config.baseUrl);
|
|
207
|
+
} catch {
|
|
208
|
+
throw new ValidationError("baseUrl must be an absolute HTTP or HTTPS URL");
|
|
209
|
+
}
|
|
210
|
+
if (parsed.protocol !== "http:" && parsed.protocol !== "https:") {
|
|
211
|
+
throw new ValidationError("baseUrl must be an absolute HTTP or HTTPS URL");
|
|
212
|
+
}
|
|
213
|
+
if (config.accessToken !== void 0 && !config.accessToken.trim()) {
|
|
214
|
+
throw new ValidationError("accessToken must not be empty when provided");
|
|
215
|
+
}
|
|
216
|
+
if (config.projectId !== void 0 && !config.projectId.trim()) {
|
|
217
|
+
throw new ValidationError("projectId must not be empty when provided");
|
|
218
|
+
}
|
|
219
|
+
if (config.timeoutMs !== void 0 && (!Number.isFinite(config.timeoutMs) || config.timeoutMs <= 0)) {
|
|
220
|
+
throw new ValidationError("timeoutMs must be greater than zero");
|
|
221
|
+
}
|
|
222
|
+
this.baseUrl = config.baseUrl.replace(/\/+$/, "");
|
|
223
|
+
this.accessToken = config.accessToken?.trim();
|
|
224
|
+
this.projectId = config.projectId?.trim();
|
|
225
|
+
this.timeoutMs = config.timeoutMs ?? 3e4;
|
|
226
|
+
const implementation = config.fetch ?? (typeof fetch !== "undefined" ? fetch : void 0);
|
|
227
|
+
if (!implementation) {
|
|
228
|
+
throw new Error("No fetch implementation available. Pass `fetch` in config or use Node 18+.");
|
|
229
|
+
}
|
|
230
|
+
this.fetchImpl = implementation;
|
|
231
|
+
}
|
|
232
|
+
async request(method, path, options = {}) {
|
|
233
|
+
const requiresAuth = options.auth !== false;
|
|
234
|
+
if (requiresAuth && !this.accessToken) {
|
|
235
|
+
throw new AuthError("accessToken is required for this operation");
|
|
236
|
+
}
|
|
237
|
+
if (options.projectId !== void 0 && !options.projectId.trim()) {
|
|
238
|
+
throw new ValidationError("projectId override must not be empty");
|
|
239
|
+
}
|
|
240
|
+
const headers = {
|
|
241
|
+
Accept: "application/json",
|
|
242
|
+
"User-Agent": `memorysync-sdk-js/${SDK_VERSION}`
|
|
243
|
+
};
|
|
244
|
+
if (requiresAuth) headers.Authorization = `Bearer ${this.accessToken}`;
|
|
245
|
+
const selectedProject = options.projectId?.trim() ?? this.projectId;
|
|
246
|
+
if (selectedProject) headers["X-Project-ID"] = selectedProject;
|
|
247
|
+
if (options.body !== void 0) headers["Content-Type"] = "application/json";
|
|
248
|
+
const controller = new AbortController();
|
|
249
|
+
const timer = setTimeout(() => controller.abort(), this.timeoutMs);
|
|
250
|
+
try {
|
|
251
|
+
const response = await this.fetchImpl(`${this.baseUrl}${path}`, {
|
|
252
|
+
method,
|
|
253
|
+
headers,
|
|
254
|
+
body: options.body === void 0 ? void 0 : JSON.stringify(options.body),
|
|
255
|
+
signal: controller.signal
|
|
256
|
+
});
|
|
257
|
+
const requestId = response.headers.get("X-Request-ID") ?? void 0;
|
|
258
|
+
if (response.status === 204) return void 0;
|
|
259
|
+
const text = await response.text();
|
|
260
|
+
const parsedBody = text ? safeJson(text) : null;
|
|
261
|
+
if (!response.ok) {
|
|
262
|
+
this.throwForStatus(response.status, parsedBody, requestId, response.headers.get("Retry-After"));
|
|
263
|
+
}
|
|
264
|
+
return normalizeResponse(parsedBody);
|
|
265
|
+
} catch (error) {
|
|
266
|
+
if (error instanceof MemorySyncError) throw error;
|
|
267
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
268
|
+
throw new MemorySyncError(`Request timed out after ${this.timeoutMs}ms`);
|
|
269
|
+
}
|
|
270
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
271
|
+
throw new MemorySyncError(`Network error: ${message}`);
|
|
272
|
+
} finally {
|
|
273
|
+
clearTimeout(timer);
|
|
274
|
+
}
|
|
275
|
+
}
|
|
276
|
+
throwForStatus(status, body, requestId, retryAfterHeader) {
|
|
277
|
+
const detail = extractDetail(body);
|
|
278
|
+
const options = { statusCode: status, response: body, requestId };
|
|
279
|
+
if (status === 401) throw new AuthError(detail || "Unauthenticated", options);
|
|
280
|
+
if (status === 403) throw new AuthError(detail || "Forbidden", options);
|
|
281
|
+
if (status === 404) throw new NotFoundError(detail || "Not found", options);
|
|
282
|
+
if (status === 400 || status === 409 || status === 422) {
|
|
283
|
+
throw new ValidationError(detail || "Validation error", options);
|
|
284
|
+
}
|
|
285
|
+
if (status === 429) {
|
|
286
|
+
const retryAfter = parseRetryAfter(retryAfterHeader) ?? extractBodyRetryAfter(body);
|
|
287
|
+
throw new RateLimitError(detail || "Rate limited", retryAfter, options);
|
|
288
|
+
}
|
|
289
|
+
if (status >= 500) throw new ServerError(detail || `Server error (${status})`, options);
|
|
290
|
+
throw new MemorySyncError(detail || `Unexpected status ${status}`, options);
|
|
291
|
+
}
|
|
292
|
+
async bulkRevokeApiKeys(request, options = {}) {
|
|
293
|
+
if (!Array.isArray(request.keyIds) || request.keyIds.length < 1 || request.keyIds.length > 100) {
|
|
294
|
+
throw new ValidationError("keyIds must contain between 1 and 100 entries");
|
|
295
|
+
}
|
|
296
|
+
request.keyIds.forEach((id) => positiveId(id, "keyIds entry"));
|
|
297
|
+
return this.request("POST", "/org/api-keys/bulk-revoke", {
|
|
298
|
+
...options,
|
|
299
|
+
body: { key_ids: request.keyIds }
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
async testApiKey(keyId, options = {}) {
|
|
303
|
+
positiveId(keyId, "keyId");
|
|
304
|
+
return this.request("POST", `/org/api-keys/${keyId}/test`, options);
|
|
305
|
+
}
|
|
306
|
+
async login(request, options = {}) {
|
|
307
|
+
nonEmpty(request.email, "email");
|
|
308
|
+
nonEmpty(request.password, "password");
|
|
309
|
+
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(request.email)) {
|
|
310
|
+
throw new ValidationError("email must be a valid email address");
|
|
311
|
+
}
|
|
312
|
+
return this.request("POST", "/auth/login", {
|
|
313
|
+
...options,
|
|
314
|
+
auth: false,
|
|
315
|
+
body: { email: request.email, password: request.password }
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
async getCurrentPlan(options = {}) {
|
|
319
|
+
return this.request("GET", "/org/billing/current-plan", options);
|
|
320
|
+
}
|
|
321
|
+
async listTeamMembers(options = {}) {
|
|
322
|
+
return this.request("GET", "/admin/team/members", options);
|
|
323
|
+
}
|
|
324
|
+
async suspendTeamMember(memberId, options = {}) {
|
|
325
|
+
positiveId(memberId, "memberId");
|
|
326
|
+
return this.request("PATCH", `/admin/team/members/${memberId}`, {
|
|
327
|
+
...options,
|
|
328
|
+
body: { status: "suspended" }
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
async removeTeamMember(memberId, options = {}) {
|
|
332
|
+
positiveId(memberId, "memberId");
|
|
333
|
+
return this.request("DELETE", `/admin/team/members/${memberId}`, options);
|
|
334
|
+
}
|
|
335
|
+
async listSessions(options = {}) {
|
|
336
|
+
return this.request("GET", "/auth/sessions", options);
|
|
337
|
+
}
|
|
338
|
+
async revokeSession(sessionId, options = {}) {
|
|
339
|
+
positiveId(sessionId, "sessionId");
|
|
340
|
+
return this.request("POST", `/auth/sessions/${sessionId}/revoke`, options);
|
|
341
|
+
}
|
|
342
|
+
async listAuditEvents(query = {}, options = {}) {
|
|
343
|
+
if (query.limit !== void 0) boundedInteger(query.limit, "limit", 1, 200);
|
|
344
|
+
if (query.cursor !== void 0) nonNegativeInteger(query.cursor, "cursor");
|
|
345
|
+
if (query.skip !== void 0) nonNegativeInteger(query.skip, "skip");
|
|
346
|
+
if (query.sortDirection !== void 0 && query.sortDirection !== "asc" && query.sortDirection !== "desc") {
|
|
347
|
+
throw new ValidationError("sortDirection must be 'asc' or 'desc'");
|
|
348
|
+
}
|
|
349
|
+
const path = "/admin/audit-logs" + queryString({
|
|
350
|
+
limit: query.limit,
|
|
351
|
+
cursor: query.cursor,
|
|
352
|
+
skip: query.skip,
|
|
353
|
+
sort: query.sortDirection,
|
|
354
|
+
tenant_id: query.tenantId,
|
|
355
|
+
actor: query.actor,
|
|
356
|
+
actor_email: query.actorEmail,
|
|
357
|
+
ip: query.ip,
|
|
358
|
+
action: query.action,
|
|
359
|
+
resource_type: query.resourceType,
|
|
360
|
+
resource_id: query.resourceId,
|
|
361
|
+
severity: query.severity,
|
|
362
|
+
category: query.category,
|
|
363
|
+
start: query.start,
|
|
364
|
+
end: query.end,
|
|
365
|
+
success: query.success,
|
|
366
|
+
source: query.source,
|
|
367
|
+
ingest_method: query.ingestMethod,
|
|
368
|
+
search: query.search,
|
|
369
|
+
include_stats: query.includeStats
|
|
370
|
+
});
|
|
371
|
+
const raw = await this.request("GET", path, options);
|
|
372
|
+
return {
|
|
373
|
+
events: raw.logs ?? [],
|
|
374
|
+
nextCursor: raw.nextCursor ?? null,
|
|
375
|
+
stats: raw.stats ?? null,
|
|
376
|
+
sort: raw.sort ?? query.sortDirection ?? "desc"
|
|
377
|
+
};
|
|
378
|
+
}
|
|
379
|
+
async listIntegrations(query = {}, options = {}) {
|
|
380
|
+
if (query.category !== void 0) nonEmpty(query.category, "category");
|
|
381
|
+
const path = "/api/v1/integrations/catalog" + queryString({ category: query.category });
|
|
382
|
+
return this.request("GET", path, options);
|
|
383
|
+
}
|
|
384
|
+
async createOrganization(request, options = {}) {
|
|
385
|
+
nonEmpty(request.name, "name");
|
|
386
|
+
if (request.domain !== void 0) nonEmpty(request.domain, "domain");
|
|
387
|
+
const body = { name: request.name };
|
|
388
|
+
if (request.domain !== void 0) body.domain = request.domain;
|
|
389
|
+
return this.request("POST", "/organizations", { ...options, body });
|
|
390
|
+
}
|
|
391
|
+
async listOrganizations(options = {}) {
|
|
392
|
+
return this.request("GET", "/organizations", options);
|
|
393
|
+
}
|
|
394
|
+
async listOrganizationMembers(options = {}) {
|
|
395
|
+
return this.listTeamMembers(options);
|
|
396
|
+
}
|
|
397
|
+
async getOrganizationSettings(query = {}, options = {}) {
|
|
398
|
+
if (query.tenantId !== void 0) nonEmpty(query.tenantId, "tenantId");
|
|
399
|
+
const path = "/admin/tenant-settings" + queryString({ tenant_id: query.tenantId });
|
|
400
|
+
return this.request("GET", path, options);
|
|
401
|
+
}
|
|
402
|
+
async listProjects(options = {}) {
|
|
403
|
+
return this.request("GET", "/org/projects", options);
|
|
404
|
+
}
|
|
405
|
+
async createWebhook(request, options = {}) {
|
|
406
|
+
validateWebhook(request.name, request.url, request.events);
|
|
407
|
+
if (request.description !== void 0 && request.description.length > 500) {
|
|
408
|
+
throw new ValidationError("description may contain at most 500 characters");
|
|
409
|
+
}
|
|
410
|
+
if (request.projectId !== void 0) nonEmpty(request.projectId, "projectId");
|
|
411
|
+
if (options.projectId !== void 0) nonEmpty(options.projectId, "projectId override");
|
|
412
|
+
if (request.projectId && options.projectId && request.projectId.trim() !== options.projectId.trim()) {
|
|
413
|
+
throw new ValidationError("request projectId and options projectId must match");
|
|
414
|
+
}
|
|
415
|
+
const body = { name: request.name, url: request.url, events: request.events };
|
|
416
|
+
if (request.description !== void 0) body.description = request.description;
|
|
417
|
+
if (request.retryConfig !== void 0) body.retry_config = webhookRetryConfig(request.retryConfig);
|
|
418
|
+
if (request.signatureConfig !== void 0) body.signature_config = webhookSignatureConfig(request.signatureConfig);
|
|
419
|
+
if (request.projectId !== void 0) body.project_id = request.projectId;
|
|
420
|
+
return this.request("POST", "/org/webhooks", {
|
|
421
|
+
...options,
|
|
422
|
+
projectId: options.projectId ?? request.projectId,
|
|
423
|
+
body
|
|
424
|
+
});
|
|
425
|
+
}
|
|
426
|
+
async listWebhooks(options = {}) {
|
|
427
|
+
return this.request("GET", "/org/webhooks", options);
|
|
428
|
+
}
|
|
429
|
+
async updateWebhook(endpointId, request, options = {}) {
|
|
430
|
+
positiveId(endpointId, "endpointId");
|
|
431
|
+
const body = {};
|
|
432
|
+
if (request.name !== void 0) {
|
|
433
|
+
nonEmpty(request.name, "name");
|
|
434
|
+
if (request.name.length > 128) throw new ValidationError("name may contain at most 128 characters");
|
|
435
|
+
body.name = request.name;
|
|
436
|
+
}
|
|
437
|
+
if (request.url !== void 0) {
|
|
438
|
+
validateWebhookUrl(request.url);
|
|
439
|
+
body.url = request.url;
|
|
440
|
+
}
|
|
441
|
+
if (request.description !== void 0) {
|
|
442
|
+
if (request.description.length > 500) {
|
|
443
|
+
throw new ValidationError("description may contain at most 500 characters");
|
|
444
|
+
}
|
|
445
|
+
body.description = request.description;
|
|
446
|
+
}
|
|
447
|
+
if (request.events !== void 0) {
|
|
448
|
+
nonEmptyStrings(request.events, "events");
|
|
449
|
+
body.events = request.events;
|
|
450
|
+
}
|
|
451
|
+
if (request.retryConfig !== void 0) body.retry_config = webhookRetryConfig(request.retryConfig);
|
|
452
|
+
if (request.signatureConfig !== void 0) body.signature_config = webhookSignatureConfig(request.signatureConfig);
|
|
453
|
+
if (Object.keys(body).length === 0) {
|
|
454
|
+
throw new ValidationError("updateWebhook requires at least one editable field");
|
|
455
|
+
}
|
|
456
|
+
return this.request("PATCH", `/org/webhooks/${endpointId}`, { ...options, body });
|
|
457
|
+
}
|
|
458
|
+
async deleteWebhook(endpointId, options = {}) {
|
|
459
|
+
positiveId(endpointId, "endpointId");
|
|
460
|
+
return this.request("DELETE", `/org/webhooks/${endpointId}`, options);
|
|
461
|
+
}
|
|
462
|
+
async testWebhook(endpointId, request = {}, options = {}) {
|
|
463
|
+
positiveId(endpointId, "endpointId");
|
|
464
|
+
const body = {};
|
|
465
|
+
if (request.eventType !== void 0) {
|
|
466
|
+
nonEmpty(request.eventType, "eventType");
|
|
467
|
+
body.event_type = request.eventType;
|
|
468
|
+
}
|
|
469
|
+
return this.request("POST", `/org/webhooks/${endpointId}/test`, { ...options, body });
|
|
470
|
+
}
|
|
471
|
+
async replayWebhookDeliveries(endpointId, request = {}, options = {}) {
|
|
472
|
+
positiveId(endpointId, "endpointId");
|
|
473
|
+
if (request.sinceMinutes !== void 0 && (!Number.isInteger(request.sinceMinutes) || request.sinceMinutes < 1 || request.sinceMinutes > 10080)) {
|
|
474
|
+
throw new ValidationError("sinceMinutes must be an integer between 1 and 10080");
|
|
475
|
+
}
|
|
476
|
+
if (request.limit !== void 0 && (!Number.isInteger(request.limit) || request.limit < 1 || request.limit > 1e3)) {
|
|
477
|
+
throw new ValidationError("limit must be an integer between 1 and 1000");
|
|
478
|
+
}
|
|
479
|
+
if (request.statuses !== void 0) nonEmptyStrings(request.statuses, "statuses");
|
|
480
|
+
const body = {};
|
|
481
|
+
if (request.sinceMinutes !== void 0) body.since_minutes = request.sinceMinutes;
|
|
482
|
+
if (request.statuses !== void 0) body.statuses = request.statuses;
|
|
483
|
+
if (request.limit !== void 0) body.limit = request.limit;
|
|
484
|
+
return this.request("POST", `/org/webhooks/${endpointId}/replay`, { ...options, body });
|
|
485
|
+
}
|
|
486
|
+
async listWebhookDeliveries(endpointId, query = {}, options = {}) {
|
|
487
|
+
positiveId(endpointId, "endpointId");
|
|
488
|
+
if (query.page !== void 0) positiveId(query.page, "page");
|
|
489
|
+
if (query.pageSize !== void 0 && (!Number.isInteger(query.pageSize) || query.pageSize < 1 || query.pageSize > 100)) {
|
|
490
|
+
throw new ValidationError("pageSize must be an integer between 1 and 100");
|
|
491
|
+
}
|
|
492
|
+
if (query.status !== void 0) nonEmpty(query.status, "status");
|
|
493
|
+
const path = `/org/webhooks/${endpointId}/deliveries` + queryString({
|
|
494
|
+
page: query.page,
|
|
495
|
+
page_size: query.pageSize,
|
|
496
|
+
status_filter: query.status
|
|
497
|
+
});
|
|
498
|
+
return this.request("GET", path, options);
|
|
499
|
+
}
|
|
500
|
+
};
|
|
501
|
+
|
|
502
|
+
// src/index.ts
|
|
503
|
+
var SDK_VERSION2 = "1.1.0";
|
|
73
504
|
function camelToSnakeKey(key) {
|
|
74
505
|
return key.replace(/([A-Z])/g, "_$1").toLowerCase();
|
|
75
506
|
}
|
|
@@ -98,14 +529,14 @@ function snakeToCamelMemory(m) {
|
|
|
98
529
|
score: m.score ?? null
|
|
99
530
|
};
|
|
100
531
|
}
|
|
101
|
-
function
|
|
532
|
+
function safeJson2(text) {
|
|
102
533
|
try {
|
|
103
534
|
return JSON.parse(text);
|
|
104
535
|
} catch {
|
|
105
536
|
return text;
|
|
106
537
|
}
|
|
107
538
|
}
|
|
108
|
-
function
|
|
539
|
+
function extractDetail2(body) {
|
|
109
540
|
if (!body || typeof body !== "object") return void 0;
|
|
110
541
|
const b = body;
|
|
111
542
|
if (typeof b.detail === "string") return b.detail;
|
|
@@ -149,7 +580,7 @@ var MemorySyncClient = class {
|
|
|
149
580
|
"X-API-Key": this.apiKey,
|
|
150
581
|
"Content-Type": "application/json",
|
|
151
582
|
"Accept": "application/json",
|
|
152
|
-
"User-Agent": `memorysync-sdk-js/${
|
|
583
|
+
"User-Agent": `memorysync-sdk-js/${SDK_VERSION2}`,
|
|
153
584
|
...extra
|
|
154
585
|
};
|
|
155
586
|
if (this.projectId) h["X-Project-ID"] = this.projectId;
|
|
@@ -173,7 +604,7 @@ var MemorySyncClient = class {
|
|
|
173
604
|
const requestId = res.headers.get("X-Request-ID") ?? void 0;
|
|
174
605
|
if (res.status === 204) return void 0;
|
|
175
606
|
const text = await res.text();
|
|
176
|
-
const parsed = text ?
|
|
607
|
+
const parsed = text ? safeJson2(text) : null;
|
|
177
608
|
if (!res.ok) this.throwForStatus(res.status, parsed, requestId);
|
|
178
609
|
return parsed;
|
|
179
610
|
} catch (e) {
|
|
@@ -187,7 +618,7 @@ var MemorySyncClient = class {
|
|
|
187
618
|
}
|
|
188
619
|
}
|
|
189
620
|
throwForStatus(status, body, requestId) {
|
|
190
|
-
const detail =
|
|
621
|
+
const detail = extractDetail2(body);
|
|
191
622
|
const opts = { statusCode: status, response: body, requestId };
|
|
192
623
|
if (status === 401) throw new AuthError(detail || "Unauthenticated", opts);
|
|
193
624
|
if (status === 403) throw new AuthError(detail || "Forbidden", opts);
|
|
@@ -363,6 +794,7 @@ var MemorySyncClient = class {
|
|
|
363
794
|
// Annotate the CommonJS export names for ESM import in node:
|
|
364
795
|
0 && (module.exports = {
|
|
365
796
|
AuthError,
|
|
797
|
+
ControlPlaneClient,
|
|
366
798
|
MemorySyncClient,
|
|
367
799
|
MemorySyncError,
|
|
368
800
|
NotFoundError,
|