teak-sdk 0.0.0-stage → 1.0.79
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 +21 -0
- package/README.md +26 -2
- package/dist/sdk.js +998 -0
- package/dist/types/client/authDiscovery.d.ts +18 -0
- package/dist/types/client/sdk.d.ts +193 -0
- package/dist/types/devUrls.d.ts +15 -0
- package/dist/types/shared/boundedResponse.d.ts +2 -0
- package/dist/types/shared/constants.d.ts +81 -0
- package/dist/types/shared/fileFormats.d.ts +65 -0
- package/dist/types/shared/markdown.d.ts +17 -0
- package/dist/types/shared/workosResources.d.ts +4 -0
- package/package.json +35 -4
package/dist/sdk.js
ADDED
|
@@ -0,0 +1,998 @@
|
|
|
1
|
+
// ../convex/devUrls.ts
|
|
2
|
+
var isLocalDevelopmentHostname = (hostname) => {
|
|
3
|
+
const normalizedHostname = hostname.trim().toLowerCase();
|
|
4
|
+
return normalizedHostname === "localhost" || normalizedHostname === "127.0.0.1" || normalizedHostname.endsWith(".localhost");
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
// ../convex/shared/boundedResponse.ts
|
|
8
|
+
class ResponseSizeLimitError extends Error {
|
|
9
|
+
}
|
|
10
|
+
var consumeResponseWithinLimit = async (response, maxBytes, consume) => {
|
|
11
|
+
if (!(Number.isFinite(maxBytes) && maxBytes >= 0)) {
|
|
12
|
+
throw new RangeError("maxBytes must be a non-negative finite number");
|
|
13
|
+
}
|
|
14
|
+
if (!response.body) {
|
|
15
|
+
return consume(response);
|
|
16
|
+
}
|
|
17
|
+
let bytesRead = 0;
|
|
18
|
+
const boundedBody = response.body.pipeThrough(new TransformStream({
|
|
19
|
+
transform(chunk, controller) {
|
|
20
|
+
bytesRead += chunk.byteLength;
|
|
21
|
+
if (bytesRead > maxBytes) {
|
|
22
|
+
throw new ResponseSizeLimitError;
|
|
23
|
+
}
|
|
24
|
+
controller.enqueue(chunk);
|
|
25
|
+
}
|
|
26
|
+
}));
|
|
27
|
+
try {
|
|
28
|
+
return await consume(new Response(boundedBody, {
|
|
29
|
+
headers: response.headers
|
|
30
|
+
}));
|
|
31
|
+
} catch (error) {
|
|
32
|
+
if (error instanceof ResponseSizeLimitError) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
throw error;
|
|
36
|
+
}
|
|
37
|
+
};
|
|
38
|
+
var readResponseTextWithinLimit = (response, maxBytes) => consumeResponseWithinLimit(response, maxBytes, (boundedResponse) => boundedResponse.text());
|
|
39
|
+
|
|
40
|
+
// ../convex/shared/workosResources.ts
|
|
41
|
+
var WORKOS_RESOURCES = {
|
|
42
|
+
api: "https://teakvault.com/api",
|
|
43
|
+
mcp: "https://teakvault.com/mcp"
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
// ../convex/client/authDiscovery.ts
|
|
47
|
+
var OAUTH_SURFACES = [
|
|
48
|
+
"cli",
|
|
49
|
+
"raycast",
|
|
50
|
+
"chrome",
|
|
51
|
+
"firefox",
|
|
52
|
+
"safari"
|
|
53
|
+
];
|
|
54
|
+
var caches = new WeakMap;
|
|
55
|
+
var object = (value) => {
|
|
56
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
57
|
+
throw new Error("Invalid OAuth discovery document");
|
|
58
|
+
}
|
|
59
|
+
return value;
|
|
60
|
+
};
|
|
61
|
+
var loopback = (hostname) => isLocalDevelopmentHostname(hostname) || hostname === "[::1]";
|
|
62
|
+
var privateHost = (hostname) => {
|
|
63
|
+
const octets = hostname.split(".").map(Number);
|
|
64
|
+
return hostname.endsWith(".localhost") || hostname.endsWith(".local") || hostname.startsWith("[") || octets.length === 4 && octets.every((n) => Number.isInteger(n) && n >= 0 && n <= 255) && (octets[0] === 0 || octets[0] === 10 || octets[0] === 100 && octets[1] >= 64 && octets[1] <= 127 || octets[0] === 127 || octets[0] === 169 && octets[1] === 254 || octets[0] === 172 && octets[1] >= 16 && octets[1] <= 31 || octets[0] === 192 && octets[1] === 168);
|
|
65
|
+
};
|
|
66
|
+
var validateOAuthUrl = (raw, local = false) => {
|
|
67
|
+
if (typeof raw !== "string") {
|
|
68
|
+
throw new Error("Missing OAuth discovery URL");
|
|
69
|
+
}
|
|
70
|
+
const url = new URL(raw);
|
|
71
|
+
if (url.username || url.password || url.hash || url.protocol !== "https:" && !(local && url.protocol === "http:" && loopback(url.hostname)) || !local && loopback(url.hostname) || privateHost(url.hostname) && !(local && loopback(url.hostname))) {
|
|
72
|
+
throw new Error("Unsafe OAuth discovery URL");
|
|
73
|
+
}
|
|
74
|
+
return url;
|
|
75
|
+
};
|
|
76
|
+
function discoverAuthServer(siteUrl, options = {}) {
|
|
77
|
+
const site = validateOAuthUrl(siteUrl, true);
|
|
78
|
+
const siteIsLocal = loopback(site.hostname);
|
|
79
|
+
const permittedLocalIssuer = options.localIssuer === undefined ? undefined : validateOAuthUrl(options.localIssuer, true);
|
|
80
|
+
if (permittedLocalIssuer && !loopback(permittedLocalIssuer.hostname)) {
|
|
81
|
+
throw new Error("Development issuer must use loopback");
|
|
82
|
+
}
|
|
83
|
+
const local = siteIsLocal || permittedLocalIssuer !== undefined;
|
|
84
|
+
const validateUrl = (raw) => {
|
|
85
|
+
const url = validateOAuthUrl(raw, local);
|
|
86
|
+
if (loopback(url.hostname) && !siteIsLocal && url.origin !== permittedLocalIssuer?.origin) {
|
|
87
|
+
throw new Error("Unapproved loopback OAuth server");
|
|
88
|
+
}
|
|
89
|
+
return url;
|
|
90
|
+
};
|
|
91
|
+
const cacheKey = `${site.origin}|${permittedLocalIssuer?.href ?? ""}`;
|
|
92
|
+
const fetchImpl = options.fetch ?? fetch;
|
|
93
|
+
let cache = caches.get(fetchImpl);
|
|
94
|
+
if (!cache) {
|
|
95
|
+
cache = new Map;
|
|
96
|
+
caches.set(fetchImpl, cache);
|
|
97
|
+
}
|
|
98
|
+
const previous = cache.get(cacheKey);
|
|
99
|
+
if (!options.forceRefresh && previous && previous.expiresAt > Date.now()) {
|
|
100
|
+
return previous.pending;
|
|
101
|
+
}
|
|
102
|
+
if (cache.size >= 16 && !cache.has(cacheKey)) {
|
|
103
|
+
const oldest = cache.keys().next().value;
|
|
104
|
+
if (oldest !== undefined) {
|
|
105
|
+
cache.delete(oldest);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
const controller = new AbortController;
|
|
109
|
+
const timeout = setTimeout(() => controller.abort(), options.timeoutMs ?? 1e4);
|
|
110
|
+
const read = async (url) => {
|
|
111
|
+
const response = await fetchImpl(url, {
|
|
112
|
+
method: "GET",
|
|
113
|
+
credentials: "omit",
|
|
114
|
+
redirect: "error",
|
|
115
|
+
headers: { Accept: "application/json" },
|
|
116
|
+
signal: controller.signal
|
|
117
|
+
});
|
|
118
|
+
if (!response.ok) {
|
|
119
|
+
throw new Error("OAuth discovery request failed");
|
|
120
|
+
}
|
|
121
|
+
const text = await readResponseTextWithinLimit(response, 64 * 1024);
|
|
122
|
+
if (text === null) {
|
|
123
|
+
throw new Error("OAuth discovery document is too large");
|
|
124
|
+
}
|
|
125
|
+
return object(JSON.parse(text));
|
|
126
|
+
};
|
|
127
|
+
const pending = (async () => {
|
|
128
|
+
const [resource, clientDocument] = await Promise.all([
|
|
129
|
+
read(`${site.origin}/.well-known/oauth-protected-resource/mcp`),
|
|
130
|
+
read(`${site.origin}/.well-known/teak-oauth-clients.json`)
|
|
131
|
+
]);
|
|
132
|
+
const servers = resource.authorization_servers;
|
|
133
|
+
if (!Array.isArray(servers) || servers.length !== 1) {
|
|
134
|
+
throw new Error("Expected one OAuth authorization server");
|
|
135
|
+
}
|
|
136
|
+
const issuer = validateUrl(servers[0]);
|
|
137
|
+
if (issuer.search || clientDocument.issuer !== servers[0]) {
|
|
138
|
+
throw new Error("OAuth provider configuration changed; retry discovery");
|
|
139
|
+
}
|
|
140
|
+
const metadataUrl = new URL(issuer.origin);
|
|
141
|
+
metadataUrl.pathname = `/.well-known/oauth-authorization-server${issuer.pathname.replace(/\/$/, "")}`;
|
|
142
|
+
const metadata = await read(metadataUrl.href);
|
|
143
|
+
if (metadata.issuer !== servers[0]) {
|
|
144
|
+
throw new Error("OAuth issuer mismatch");
|
|
145
|
+
}
|
|
146
|
+
if (clientDocument.primary !== "betterauth" && clientDocument.primary !== "workos") {
|
|
147
|
+
throw new Error("Unknown OAuth provider");
|
|
148
|
+
}
|
|
149
|
+
if (!(Array.isArray(metadata.code_challenge_methods_supported) && metadata.code_challenge_methods_supported.includes("S256"))) {
|
|
150
|
+
throw new Error("OAuth server does not support S256 PKCE");
|
|
151
|
+
}
|
|
152
|
+
const clients = object(clientDocument.clients);
|
|
153
|
+
for (const surface of OAUTH_SURFACES) {
|
|
154
|
+
if (typeof clients[surface] !== "string" || !clients[surface].trim()) {
|
|
155
|
+
throw new Error("Missing OAuth client registration");
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
const expectedResource = clientDocument.primary === "workos" ? WORKOS_RESOURCES.mcp : `${site.origin}/mcp`;
|
|
159
|
+
if (resource.resource !== expectedResource) {
|
|
160
|
+
throw new Error("OAuth resource mismatch");
|
|
161
|
+
}
|
|
162
|
+
return Object.freeze({
|
|
163
|
+
primary: clientDocument.primary,
|
|
164
|
+
issuer: servers[0],
|
|
165
|
+
authorizationEndpoint: validateUrl(metadata.authorization_endpoint).href,
|
|
166
|
+
tokenEndpoint: validateUrl(metadata.token_endpoint).href,
|
|
167
|
+
...metadata.revocation_endpoint === undefined ? {} : {
|
|
168
|
+
revocationEndpoint: validateUrl(metadata.revocation_endpoint).href
|
|
169
|
+
},
|
|
170
|
+
resource: resource.resource,
|
|
171
|
+
clients: Object.freeze(Object.fromEntries(OAUTH_SURFACES.map((surface) => [surface, clients[surface]])))
|
|
172
|
+
});
|
|
173
|
+
})().finally(() => {
|
|
174
|
+
controller.abort();
|
|
175
|
+
clearTimeout(timeout);
|
|
176
|
+
});
|
|
177
|
+
const entry = { expiresAt: Date.now() + 60000, pending };
|
|
178
|
+
cache.set(cacheKey, entry);
|
|
179
|
+
pending.catch(() => {
|
|
180
|
+
if (cache.get(cacheKey) === entry) {
|
|
181
|
+
cache.delete(cacheKey);
|
|
182
|
+
}
|
|
183
|
+
});
|
|
184
|
+
return pending;
|
|
185
|
+
}
|
|
186
|
+
// ../convex/shared/markdown.ts
|
|
187
|
+
var MARKDOWN_CONTENT_MAX_BYTES = 512 * 1024;
|
|
188
|
+
|
|
189
|
+
// ../convex/shared/fileFormats.ts
|
|
190
|
+
var MAX_FILE_SIZE = 100 * 1024 * 1024;
|
|
191
|
+
var GENERIC_MIME_TYPES = new Set([
|
|
192
|
+
"",
|
|
193
|
+
"application/binary",
|
|
194
|
+
"application/octet-stream",
|
|
195
|
+
"binary/octet-stream"
|
|
196
|
+
]);
|
|
197
|
+
var defineFormat = (definition) => ({
|
|
198
|
+
...definition,
|
|
199
|
+
mimeType: definition.mimeType ?? definition.mimeTypes[0] ?? ""
|
|
200
|
+
});
|
|
201
|
+
var FILE_FORMATS = [
|
|
202
|
+
defineFormat({
|
|
203
|
+
id: "design-tokens",
|
|
204
|
+
suffixes: ["tokens.json"],
|
|
205
|
+
cardType: "document",
|
|
206
|
+
extension: "tokens.json",
|
|
207
|
+
kind: "tokens",
|
|
208
|
+
language: "json",
|
|
209
|
+
mimeTypes: ["application/json", "text/json", "text/plain"],
|
|
210
|
+
preview: "source"
|
|
211
|
+
}),
|
|
212
|
+
defineFormat({
|
|
213
|
+
id: "tailwind-config",
|
|
214
|
+
fileNames: ["tailwind.config.js"],
|
|
215
|
+
suffixes: [],
|
|
216
|
+
cardType: "document",
|
|
217
|
+
extension: "tailwind.config.js",
|
|
218
|
+
kind: "source",
|
|
219
|
+
language: "javascript",
|
|
220
|
+
mimeTypes: [
|
|
221
|
+
"application/javascript",
|
|
222
|
+
"text/javascript",
|
|
223
|
+
"application/x-javascript",
|
|
224
|
+
"text/plain"
|
|
225
|
+
],
|
|
226
|
+
preview: "source"
|
|
227
|
+
}),
|
|
228
|
+
defineFormat({
|
|
229
|
+
id: "css-variables",
|
|
230
|
+
fileNames: ["theme.css", "variables.css"],
|
|
231
|
+
suffixes: [],
|
|
232
|
+
cardType: "document",
|
|
233
|
+
extension: "css",
|
|
234
|
+
kind: "tokens",
|
|
235
|
+
language: "css",
|
|
236
|
+
mimeTypes: ["text/css", "text/plain"],
|
|
237
|
+
preview: "source"
|
|
238
|
+
}),
|
|
239
|
+
defineFormat({
|
|
240
|
+
id: "json",
|
|
241
|
+
suffixes: ["json"],
|
|
242
|
+
cardType: "document",
|
|
243
|
+
extension: "json",
|
|
244
|
+
kind: "source",
|
|
245
|
+
language: "json",
|
|
246
|
+
mimeTypes: ["application/json", "text/json", "application/ld+json"],
|
|
247
|
+
preview: "source"
|
|
248
|
+
}),
|
|
249
|
+
defineFormat({
|
|
250
|
+
id: "tsx",
|
|
251
|
+
suffixes: ["tsx"],
|
|
252
|
+
cardType: "document",
|
|
253
|
+
extension: "tsx",
|
|
254
|
+
kind: "source",
|
|
255
|
+
language: "tsx",
|
|
256
|
+
mimeTypes: [
|
|
257
|
+
"text/tsx",
|
|
258
|
+
"text/typescript",
|
|
259
|
+
"application/typescript",
|
|
260
|
+
"text/plain"
|
|
261
|
+
],
|
|
262
|
+
preview: "source"
|
|
263
|
+
}),
|
|
264
|
+
defineFormat({
|
|
265
|
+
id: "jsx",
|
|
266
|
+
suffixes: ["jsx"],
|
|
267
|
+
cardType: "document",
|
|
268
|
+
extension: "jsx",
|
|
269
|
+
kind: "source",
|
|
270
|
+
language: "jsx",
|
|
271
|
+
mimeTypes: [
|
|
272
|
+
"text/jsx",
|
|
273
|
+
"text/javascript",
|
|
274
|
+
"application/javascript",
|
|
275
|
+
"text/plain"
|
|
276
|
+
],
|
|
277
|
+
preview: "source"
|
|
278
|
+
}),
|
|
279
|
+
defineFormat({
|
|
280
|
+
id: "vue",
|
|
281
|
+
suffixes: ["vue"],
|
|
282
|
+
cardType: "document",
|
|
283
|
+
extension: "vue",
|
|
284
|
+
kind: "source",
|
|
285
|
+
language: "markup",
|
|
286
|
+
mimeTypes: ["text/x-vue", "application/x-vue", "text/plain"],
|
|
287
|
+
preview: "source"
|
|
288
|
+
}),
|
|
289
|
+
defineFormat({
|
|
290
|
+
id: "svelte",
|
|
291
|
+
suffixes: ["svelte"],
|
|
292
|
+
cardType: "document",
|
|
293
|
+
extension: "svelte",
|
|
294
|
+
kind: "source",
|
|
295
|
+
language: "markup",
|
|
296
|
+
mimeTypes: ["text/x-svelte", "application/x-svelte", "text/plain"],
|
|
297
|
+
preview: "source"
|
|
298
|
+
}),
|
|
299
|
+
defineFormat({
|
|
300
|
+
id: "html",
|
|
301
|
+
suffixes: ["html", "htm"],
|
|
302
|
+
cardType: "document",
|
|
303
|
+
extension: "html",
|
|
304
|
+
kind: "source",
|
|
305
|
+
language: "markup",
|
|
306
|
+
mimeTypes: ["text/html", "application/xhtml+xml", "text/plain"],
|
|
307
|
+
preview: "source"
|
|
308
|
+
}),
|
|
309
|
+
defineFormat({
|
|
310
|
+
id: "css",
|
|
311
|
+
suffixes: ["css"],
|
|
312
|
+
cardType: "document",
|
|
313
|
+
extension: "css",
|
|
314
|
+
kind: "source",
|
|
315
|
+
language: "css",
|
|
316
|
+
mimeTypes: ["text/css", "text/plain"],
|
|
317
|
+
preview: "source"
|
|
318
|
+
}),
|
|
319
|
+
defineFormat({
|
|
320
|
+
id: "markdown",
|
|
321
|
+
suffixes: ["md", "markdown"],
|
|
322
|
+
cardType: "text",
|
|
323
|
+
extension: "md",
|
|
324
|
+
kind: "markdown",
|
|
325
|
+
language: "markdown",
|
|
326
|
+
mimeTypes: ["text/markdown", "text/x-markdown", "text/plain"],
|
|
327
|
+
preview: "markdown"
|
|
328
|
+
}),
|
|
329
|
+
defineFormat({
|
|
330
|
+
id: "mdx",
|
|
331
|
+
suffixes: ["mdx"],
|
|
332
|
+
cardType: "document",
|
|
333
|
+
extension: "mdx",
|
|
334
|
+
kind: "markdown",
|
|
335
|
+
language: "mdx",
|
|
336
|
+
mimeTypes: ["text/mdx", "text/x-mdx", "text/markdown", "text/plain"],
|
|
337
|
+
preview: "markdown"
|
|
338
|
+
}),
|
|
339
|
+
defineFormat({
|
|
340
|
+
id: "text",
|
|
341
|
+
suffixes: ["txt"],
|
|
342
|
+
cardType: "document",
|
|
343
|
+
extension: "txt",
|
|
344
|
+
kind: "text",
|
|
345
|
+
language: "text",
|
|
346
|
+
mimeTypes: ["text/plain"],
|
|
347
|
+
preview: "source"
|
|
348
|
+
}),
|
|
349
|
+
defineFormat({
|
|
350
|
+
id: "rtf",
|
|
351
|
+
suffixes: ["rtf"],
|
|
352
|
+
cardType: "document",
|
|
353
|
+
extension: "rtf",
|
|
354
|
+
kind: "text",
|
|
355
|
+
language: "text",
|
|
356
|
+
mimeTypes: ["application/rtf", "text/rtf"],
|
|
357
|
+
preview: "source"
|
|
358
|
+
}),
|
|
359
|
+
defineFormat({
|
|
360
|
+
id: "pdf",
|
|
361
|
+
suffixes: ["pdf"],
|
|
362
|
+
cardType: "document",
|
|
363
|
+
extension: "pdf",
|
|
364
|
+
kind: "pdf",
|
|
365
|
+
mimeTypes: ["application/pdf"],
|
|
366
|
+
preview: "pdf"
|
|
367
|
+
}),
|
|
368
|
+
defineFormat({
|
|
369
|
+
id: "word",
|
|
370
|
+
suffixes: ["docx"],
|
|
371
|
+
cardType: "document",
|
|
372
|
+
extension: "docx",
|
|
373
|
+
kind: "office",
|
|
374
|
+
mimeTypes: [
|
|
375
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document"
|
|
376
|
+
],
|
|
377
|
+
preview: "office"
|
|
378
|
+
}),
|
|
379
|
+
defineFormat({
|
|
380
|
+
id: "word-legacy",
|
|
381
|
+
suffixes: ["doc"],
|
|
382
|
+
cardType: "document",
|
|
383
|
+
extension: "doc",
|
|
384
|
+
kind: "office",
|
|
385
|
+
mimeTypes: ["application/msword"],
|
|
386
|
+
preview: "facts"
|
|
387
|
+
}),
|
|
388
|
+
defineFormat({
|
|
389
|
+
id: "powerpoint",
|
|
390
|
+
suffixes: ["pptx"],
|
|
391
|
+
cardType: "document",
|
|
392
|
+
extension: "pptx",
|
|
393
|
+
kind: "office",
|
|
394
|
+
mimeTypes: [
|
|
395
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation"
|
|
396
|
+
],
|
|
397
|
+
preview: "office"
|
|
398
|
+
}),
|
|
399
|
+
defineFormat({
|
|
400
|
+
id: "powerpoint-legacy",
|
|
401
|
+
suffixes: ["ppt"],
|
|
402
|
+
cardType: "document",
|
|
403
|
+
extension: "ppt",
|
|
404
|
+
kind: "office",
|
|
405
|
+
mimeTypes: ["application/vnd.ms-powerpoint"],
|
|
406
|
+
preview: "facts"
|
|
407
|
+
}),
|
|
408
|
+
defineFormat({
|
|
409
|
+
id: "excel",
|
|
410
|
+
suffixes: ["xlsx"],
|
|
411
|
+
cardType: "document",
|
|
412
|
+
extension: "xlsx",
|
|
413
|
+
kind: "office",
|
|
414
|
+
mimeTypes: [
|
|
415
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"
|
|
416
|
+
],
|
|
417
|
+
preview: "office"
|
|
418
|
+
}),
|
|
419
|
+
defineFormat({
|
|
420
|
+
id: "excel-legacy",
|
|
421
|
+
suffixes: ["xls"],
|
|
422
|
+
cardType: "document",
|
|
423
|
+
extension: "xls",
|
|
424
|
+
kind: "office",
|
|
425
|
+
mimeTypes: ["application/vnd.ms-excel"],
|
|
426
|
+
preview: "facts"
|
|
427
|
+
}),
|
|
428
|
+
defineFormat({
|
|
429
|
+
id: "csv",
|
|
430
|
+
suffixes: ["csv"],
|
|
431
|
+
cardType: "document",
|
|
432
|
+
extension: "csv",
|
|
433
|
+
kind: "text",
|
|
434
|
+
language: "csv",
|
|
435
|
+
mimeTypes: [
|
|
436
|
+
"text/csv",
|
|
437
|
+
"application/csv",
|
|
438
|
+
"text/plain",
|
|
439
|
+
"application/vnd.ms-excel"
|
|
440
|
+
],
|
|
441
|
+
preview: "source"
|
|
442
|
+
}),
|
|
443
|
+
defineFormat({
|
|
444
|
+
id: "zip",
|
|
445
|
+
suffixes: ["zip"],
|
|
446
|
+
cardType: "document",
|
|
447
|
+
extension: "zip",
|
|
448
|
+
kind: "archive",
|
|
449
|
+
mimeTypes: ["application/zip", "application/x-zip-compressed"],
|
|
450
|
+
preview: "archive"
|
|
451
|
+
}),
|
|
452
|
+
defineFormat({
|
|
453
|
+
id: "figma",
|
|
454
|
+
suffixes: ["fig"],
|
|
455
|
+
cardType: "document",
|
|
456
|
+
extension: "fig",
|
|
457
|
+
kind: "design",
|
|
458
|
+
mimeTypes: ["application/x-figma", "application/figma"],
|
|
459
|
+
mimeType: "application/octet-stream",
|
|
460
|
+
preview: "facts"
|
|
461
|
+
}),
|
|
462
|
+
defineFormat({
|
|
463
|
+
id: "pages",
|
|
464
|
+
suffixes: ["pages"],
|
|
465
|
+
cardType: "document",
|
|
466
|
+
extension: "pages",
|
|
467
|
+
kind: "office",
|
|
468
|
+
mimeTypes: ["application/vnd.apple.pages"],
|
|
469
|
+
preview: "facts"
|
|
470
|
+
}),
|
|
471
|
+
defineFormat({
|
|
472
|
+
id: "numbers",
|
|
473
|
+
suffixes: ["numbers"],
|
|
474
|
+
cardType: "document",
|
|
475
|
+
extension: "numbers",
|
|
476
|
+
kind: "office",
|
|
477
|
+
mimeTypes: ["application/vnd.apple.numbers"],
|
|
478
|
+
preview: "facts"
|
|
479
|
+
}),
|
|
480
|
+
defineFormat({
|
|
481
|
+
id: "gif",
|
|
482
|
+
suffixes: ["gif"],
|
|
483
|
+
cardType: "video",
|
|
484
|
+
extension: "gif",
|
|
485
|
+
kind: "motion",
|
|
486
|
+
mimeTypes: ["image/gif"],
|
|
487
|
+
preview: "motion"
|
|
488
|
+
}),
|
|
489
|
+
defineFormat({
|
|
490
|
+
id: "webm",
|
|
491
|
+
suffixes: ["webm"],
|
|
492
|
+
cardType: "video",
|
|
493
|
+
extension: "webm",
|
|
494
|
+
kind: "motion",
|
|
495
|
+
mimeTypes: ["video/webm"],
|
|
496
|
+
preview: "motion"
|
|
497
|
+
}),
|
|
498
|
+
defineFormat({
|
|
499
|
+
id: "webm-audio",
|
|
500
|
+
suffixes: ["webm"],
|
|
501
|
+
cardType: "audio",
|
|
502
|
+
extension: "webm",
|
|
503
|
+
kind: "audio",
|
|
504
|
+
mimeTypes: ["audio/webm"],
|
|
505
|
+
preview: "audio"
|
|
506
|
+
}),
|
|
507
|
+
defineFormat({
|
|
508
|
+
id: "mp4",
|
|
509
|
+
suffixes: ["mp4"],
|
|
510
|
+
cardType: "video",
|
|
511
|
+
extension: "mp4",
|
|
512
|
+
kind: "motion",
|
|
513
|
+
mimeTypes: ["video/mp4", "application/mp4"],
|
|
514
|
+
preview: "motion"
|
|
515
|
+
}),
|
|
516
|
+
defineFormat({
|
|
517
|
+
id: "quicktime",
|
|
518
|
+
suffixes: ["mov", "m4v"],
|
|
519
|
+
cardType: "video",
|
|
520
|
+
extension: "mov",
|
|
521
|
+
kind: "motion",
|
|
522
|
+
mimeTypes: ["video/quicktime", "video/x-m4v"],
|
|
523
|
+
preview: "motion"
|
|
524
|
+
}),
|
|
525
|
+
defineFormat({
|
|
526
|
+
id: "video",
|
|
527
|
+
suffixes: ["mkv", "avi", "mpeg", "mpg", "wmv"],
|
|
528
|
+
cardType: "video",
|
|
529
|
+
extension: "video",
|
|
530
|
+
kind: "motion",
|
|
531
|
+
mimeTypes: [
|
|
532
|
+
"video/x-matroska",
|
|
533
|
+
"video/x-msvideo",
|
|
534
|
+
"video/mpeg",
|
|
535
|
+
"video/x-ms-wmv"
|
|
536
|
+
],
|
|
537
|
+
preview: "motion"
|
|
538
|
+
}),
|
|
539
|
+
defineFormat({
|
|
540
|
+
id: "png",
|
|
541
|
+
suffixes: ["png"],
|
|
542
|
+
cardType: "image",
|
|
543
|
+
extension: "png",
|
|
544
|
+
kind: "image",
|
|
545
|
+
mimeTypes: ["image/png"],
|
|
546
|
+
preview: "image"
|
|
547
|
+
}),
|
|
548
|
+
defineFormat({
|
|
549
|
+
id: "jpeg",
|
|
550
|
+
suffixes: ["jpg", "jpeg"],
|
|
551
|
+
cardType: "image",
|
|
552
|
+
extension: "jpg",
|
|
553
|
+
kind: "image",
|
|
554
|
+
mimeTypes: ["image/jpeg", "image/jpg", "image/pjpeg"],
|
|
555
|
+
preview: "image"
|
|
556
|
+
}),
|
|
557
|
+
defineFormat({
|
|
558
|
+
id: "webp",
|
|
559
|
+
suffixes: ["webp"],
|
|
560
|
+
cardType: "image",
|
|
561
|
+
extension: "webp",
|
|
562
|
+
kind: "image",
|
|
563
|
+
mimeTypes: ["image/webp"],
|
|
564
|
+
preview: "image"
|
|
565
|
+
}),
|
|
566
|
+
defineFormat({
|
|
567
|
+
id: "avif",
|
|
568
|
+
suffixes: ["avif"],
|
|
569
|
+
cardType: "image",
|
|
570
|
+
extension: "avif",
|
|
571
|
+
kind: "image",
|
|
572
|
+
mimeTypes: ["image/avif"],
|
|
573
|
+
preview: "image"
|
|
574
|
+
}),
|
|
575
|
+
defineFormat({
|
|
576
|
+
id: "svg",
|
|
577
|
+
suffixes: ["svg"],
|
|
578
|
+
cardType: "image",
|
|
579
|
+
extension: "svg",
|
|
580
|
+
kind: "image",
|
|
581
|
+
language: "markup",
|
|
582
|
+
mimeTypes: ["image/svg+xml", "application/xml", "text/xml"],
|
|
583
|
+
preview: "image"
|
|
584
|
+
}),
|
|
585
|
+
defineFormat({
|
|
586
|
+
id: "heic",
|
|
587
|
+
suffixes: ["heic", "heif"],
|
|
588
|
+
cardType: "image",
|
|
589
|
+
extension: "heic",
|
|
590
|
+
kind: "image",
|
|
591
|
+
mimeTypes: ["image/heic", "image/heif", "image/heic-sequence"],
|
|
592
|
+
preview: "image"
|
|
593
|
+
}),
|
|
594
|
+
defineFormat({
|
|
595
|
+
id: "bitmap",
|
|
596
|
+
suffixes: ["bmp", "tif", "tiff"],
|
|
597
|
+
cardType: "image",
|
|
598
|
+
extension: "image",
|
|
599
|
+
kind: "image",
|
|
600
|
+
mimeTypes: ["image/bmp", "image/tiff"],
|
|
601
|
+
preview: "image"
|
|
602
|
+
}),
|
|
603
|
+
defineFormat({
|
|
604
|
+
id: "mpeg-audio",
|
|
605
|
+
suffixes: ["mp3"],
|
|
606
|
+
cardType: "audio",
|
|
607
|
+
extension: "mp3",
|
|
608
|
+
kind: "audio",
|
|
609
|
+
mimeTypes: ["audio/mpeg", "audio/mp3"],
|
|
610
|
+
preview: "audio"
|
|
611
|
+
}),
|
|
612
|
+
defineFormat({
|
|
613
|
+
id: "wave-audio",
|
|
614
|
+
suffixes: ["wav"],
|
|
615
|
+
cardType: "audio",
|
|
616
|
+
extension: "wav",
|
|
617
|
+
kind: "audio",
|
|
618
|
+
mimeTypes: ["audio/wav", "audio/x-wav"],
|
|
619
|
+
preview: "audio"
|
|
620
|
+
}),
|
|
621
|
+
defineFormat({
|
|
622
|
+
id: "mp4-audio",
|
|
623
|
+
suffixes: ["m4a", "mp4"],
|
|
624
|
+
cardType: "audio",
|
|
625
|
+
extension: "m4a",
|
|
626
|
+
kind: "audio",
|
|
627
|
+
mimeTypes: ["audio/mp4", "audio/x-m4a"],
|
|
628
|
+
preview: "audio"
|
|
629
|
+
}),
|
|
630
|
+
defineFormat({
|
|
631
|
+
id: "aac-audio",
|
|
632
|
+
suffixes: ["aac"],
|
|
633
|
+
cardType: "audio",
|
|
634
|
+
extension: "aac",
|
|
635
|
+
kind: "audio",
|
|
636
|
+
mimeTypes: ["audio/aac"],
|
|
637
|
+
preview: "audio"
|
|
638
|
+
}),
|
|
639
|
+
defineFormat({
|
|
640
|
+
id: "other-audio",
|
|
641
|
+
suffixes: ["flac", "ogg", "oga", "opus"],
|
|
642
|
+
cardType: "audio",
|
|
643
|
+
extension: "audio",
|
|
644
|
+
kind: "audio",
|
|
645
|
+
mimeTypes: ["audio/flac", "audio/ogg", "audio/opus"],
|
|
646
|
+
preview: "audio"
|
|
647
|
+
})
|
|
648
|
+
];
|
|
649
|
+
// ../convex/shared/constants.ts
|
|
650
|
+
var cardTypes = [
|
|
651
|
+
"text",
|
|
652
|
+
"link",
|
|
653
|
+
"image",
|
|
654
|
+
"video",
|
|
655
|
+
"audio",
|
|
656
|
+
"document",
|
|
657
|
+
"palette",
|
|
658
|
+
"quote"
|
|
659
|
+
];
|
|
660
|
+
var MULTIPART_UPLOAD_THRESHOLD = 8 * 1024 * 1024;
|
|
661
|
+
var CARD_TYPES = [...cardTypes];
|
|
662
|
+
var CARD_TYPE_REGISTRY = {
|
|
663
|
+
text: {
|
|
664
|
+
label: "Text",
|
|
665
|
+
icon: "FileText",
|
|
666
|
+
searchLabel: "Text"
|
|
667
|
+
},
|
|
668
|
+
link: {
|
|
669
|
+
label: "Link",
|
|
670
|
+
icon: "Link",
|
|
671
|
+
searchLabel: "Links"
|
|
672
|
+
},
|
|
673
|
+
image: {
|
|
674
|
+
label: "Image",
|
|
675
|
+
icon: "Image",
|
|
676
|
+
searchLabel: "Images"
|
|
677
|
+
},
|
|
678
|
+
video: {
|
|
679
|
+
label: "Video",
|
|
680
|
+
icon: "Video",
|
|
681
|
+
searchLabel: "Videos"
|
|
682
|
+
},
|
|
683
|
+
audio: {
|
|
684
|
+
label: "Audio",
|
|
685
|
+
icon: "Volume2",
|
|
686
|
+
searchLabel: "Audio"
|
|
687
|
+
},
|
|
688
|
+
document: {
|
|
689
|
+
label: "Document",
|
|
690
|
+
icon: "File",
|
|
691
|
+
searchLabel: "Documents"
|
|
692
|
+
},
|
|
693
|
+
palette: {
|
|
694
|
+
label: "Palette",
|
|
695
|
+
icon: "Palette",
|
|
696
|
+
searchLabel: "Palettes"
|
|
697
|
+
},
|
|
698
|
+
quote: {
|
|
699
|
+
label: "Quote",
|
|
700
|
+
icon: "Quote",
|
|
701
|
+
searchLabel: "Quotes"
|
|
702
|
+
}
|
|
703
|
+
};
|
|
704
|
+
var RESERVED_KEYWORDS = [
|
|
705
|
+
...cardTypes.map((cardType) => ({
|
|
706
|
+
value: cardType,
|
|
707
|
+
label: CARD_TYPE_REGISTRY[cardType].searchLabel
|
|
708
|
+
})),
|
|
709
|
+
{ value: "favorites", label: "Favorites" },
|
|
710
|
+
{ value: "trash", label: "Trash" }
|
|
711
|
+
];
|
|
712
|
+
|
|
713
|
+
// ../convex/client/sdk.ts
|
|
714
|
+
var CARD_TYPES2 = cardTypes;
|
|
715
|
+
var CARD_SORTS = ["newest", "oldest"];
|
|
716
|
+
var ERROR_CODES = [
|
|
717
|
+
"AUTH_REQUIRED",
|
|
718
|
+
"BAD_REQUEST",
|
|
719
|
+
"CONFIG_ERROR",
|
|
720
|
+
"CONFLICT",
|
|
721
|
+
"CONTENT_TOO_LARGE",
|
|
722
|
+
"INTERNAL_ERROR",
|
|
723
|
+
"INVALID_API_KEY",
|
|
724
|
+
"INVALID_INPUT",
|
|
725
|
+
"INVALID_UTF8",
|
|
726
|
+
"METHOD_NOT_ALLOWED",
|
|
727
|
+
"NETWORK_ERROR",
|
|
728
|
+
"NOT_FOUND",
|
|
729
|
+
"PARSE_ERROR",
|
|
730
|
+
"RATE_LIMITED",
|
|
731
|
+
"REQUEST_FAILED",
|
|
732
|
+
"TIMEOUT",
|
|
733
|
+
"UNAUTHORIZED"
|
|
734
|
+
];
|
|
735
|
+
|
|
736
|
+
class TeakApiError extends Error {
|
|
737
|
+
code;
|
|
738
|
+
requestId;
|
|
739
|
+
retryAt;
|
|
740
|
+
status;
|
|
741
|
+
constructor(code, message, init) {
|
|
742
|
+
super(message || defaultErrorMessage(code));
|
|
743
|
+
this.name = "TeakApiError";
|
|
744
|
+
this.code = code;
|
|
745
|
+
this.requestId = init?.requestId;
|
|
746
|
+
this.retryAt = init?.retryAt;
|
|
747
|
+
this.status = init?.status;
|
|
748
|
+
}
|
|
749
|
+
}
|
|
750
|
+
var staticTokenProvider = (token) => ({
|
|
751
|
+
getAccessToken: () => token
|
|
752
|
+
});
|
|
753
|
+
var defaultErrorMessage = (code) => {
|
|
754
|
+
switch (code) {
|
|
755
|
+
case "AUTH_REQUIRED":
|
|
756
|
+
case "INVALID_API_KEY":
|
|
757
|
+
case "UNAUTHORIZED":
|
|
758
|
+
return "Authentication is required. Run `teak login` or set TEAK_API_KEY.";
|
|
759
|
+
case "RATE_LIMITED":
|
|
760
|
+
return "Too many requests. Wait a moment and try again.";
|
|
761
|
+
case "NETWORK_ERROR":
|
|
762
|
+
return "Unable to reach Teak.";
|
|
763
|
+
case "TIMEOUT":
|
|
764
|
+
return "The Teak request timed out.";
|
|
765
|
+
case "NOT_FOUND":
|
|
766
|
+
return "Teak could not find that resource.";
|
|
767
|
+
default:
|
|
768
|
+
return "The Teak request failed.";
|
|
769
|
+
}
|
|
770
|
+
};
|
|
771
|
+
var isObject = (value) => Boolean(value && typeof value === "object" && !Array.isArray(value));
|
|
772
|
+
var isStringArray = (value) => Array.isArray(value) && value.every((entry) => typeof entry === "string");
|
|
773
|
+
var codeFrom = (value, fallback) => typeof value === "string" && ERROR_CODES.includes(value) ? value : fallback;
|
|
774
|
+
var normalizeLimit = (limit) => {
|
|
775
|
+
if (!Number.isFinite(limit)) {
|
|
776
|
+
return 50;
|
|
777
|
+
}
|
|
778
|
+
return Math.max(1, Math.min(Math.trunc(limit ?? 50), 100));
|
|
779
|
+
};
|
|
780
|
+
var byteLengthForBody = (bytes) => {
|
|
781
|
+
if (bytes instanceof ArrayBuffer) {
|
|
782
|
+
return bytes.byteLength;
|
|
783
|
+
}
|
|
784
|
+
if (ArrayBuffer.isView(bytes)) {
|
|
785
|
+
return bytes.byteLength;
|
|
786
|
+
}
|
|
787
|
+
if (typeof Blob !== "undefined" && bytes instanceof Blob) {
|
|
788
|
+
return bytes.size;
|
|
789
|
+
}
|
|
790
|
+
if (typeof bytes === "string") {
|
|
791
|
+
return new TextEncoder().encode(bytes).byteLength;
|
|
792
|
+
}
|
|
793
|
+
return null;
|
|
794
|
+
};
|
|
795
|
+
var buildCardsSearchParams = (input) => {
|
|
796
|
+
const search = new URLSearchParams;
|
|
797
|
+
if (input.query?.trim()) {
|
|
798
|
+
search.set("q", input.query.trim());
|
|
799
|
+
}
|
|
800
|
+
let types = [];
|
|
801
|
+
if (Array.isArray(input.type)) {
|
|
802
|
+
types = input.type;
|
|
803
|
+
} else if (typeof input.type === "string") {
|
|
804
|
+
types = [input.type];
|
|
805
|
+
}
|
|
806
|
+
for (const type of types) {
|
|
807
|
+
if (type.trim()) {
|
|
808
|
+
search.append("type", type.trim());
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
if (input.tag?.trim()) {
|
|
812
|
+
search.set("tag", input.tag.trim());
|
|
813
|
+
}
|
|
814
|
+
if (input.cursor?.trim()) {
|
|
815
|
+
search.set("cursor", input.cursor.trim());
|
|
816
|
+
}
|
|
817
|
+
if (input.include?.trim()) {
|
|
818
|
+
search.set("include", input.include.trim());
|
|
819
|
+
}
|
|
820
|
+
if (input.favorited) {
|
|
821
|
+
search.set("favorited", "true");
|
|
822
|
+
}
|
|
823
|
+
if (input.sort === "oldest") {
|
|
824
|
+
search.set("sort", "oldest");
|
|
825
|
+
}
|
|
826
|
+
if (typeof input.createdAfter === "number") {
|
|
827
|
+
search.set("createdAfter", String(input.createdAfter));
|
|
828
|
+
}
|
|
829
|
+
if (typeof input.createdBefore === "number") {
|
|
830
|
+
search.set("createdBefore", String(input.createdBefore));
|
|
831
|
+
}
|
|
832
|
+
search.set("limit", String(normalizeLimit(input.limit)));
|
|
833
|
+
return search.toString();
|
|
834
|
+
};
|
|
835
|
+
var parseJson = async (response) => {
|
|
836
|
+
if (response.status === 204) {
|
|
837
|
+
return null;
|
|
838
|
+
}
|
|
839
|
+
const text = await response.text();
|
|
840
|
+
if (!text.trim()) {
|
|
841
|
+
return null;
|
|
842
|
+
}
|
|
843
|
+
try {
|
|
844
|
+
return JSON.parse(text);
|
|
845
|
+
} catch {
|
|
846
|
+
throw new TeakApiError("PARSE_ERROR", "Teak returned malformed JSON.", {
|
|
847
|
+
status: response.status
|
|
848
|
+
});
|
|
849
|
+
}
|
|
850
|
+
};
|
|
851
|
+
var asCard = (value) => {
|
|
852
|
+
if (!isObject(value) || typeof value.id !== "string" || typeof value.content !== "string") {
|
|
853
|
+
throw new TeakApiError("PARSE_ERROR", "Teak returned an unexpected card payload.");
|
|
854
|
+
}
|
|
855
|
+
return value;
|
|
856
|
+
};
|
|
857
|
+
var asPage = (value) => {
|
|
858
|
+
if (!(isObject(value) && Array.isArray(value.items) && isObject(value.pageInfo))) {
|
|
859
|
+
throw new TeakApiError("PARSE_ERROR");
|
|
860
|
+
}
|
|
861
|
+
return value;
|
|
862
|
+
};
|
|
863
|
+
var asTags = (value) => {
|
|
864
|
+
if (!(isObject(value) && Array.isArray(value.items))) {
|
|
865
|
+
throw new TeakApiError("PARSE_ERROR");
|
|
866
|
+
}
|
|
867
|
+
return {
|
|
868
|
+
items: value.items.filter(isObject).map((tag) => ({
|
|
869
|
+
count: Number(tag.count) || 0,
|
|
870
|
+
name: String(tag.name || "")
|
|
871
|
+
}))
|
|
872
|
+
};
|
|
873
|
+
};
|
|
874
|
+
var asCreate = (value) => {
|
|
875
|
+
if (!isObject(value) || typeof value.cardId !== "string" || value.status !== "created") {
|
|
876
|
+
throw new TeakApiError("PARSE_ERROR");
|
|
877
|
+
}
|
|
878
|
+
return value;
|
|
879
|
+
};
|
|
880
|
+
var asUpload = (value) => {
|
|
881
|
+
if (!isObject(value) || typeof value.uploadUrl !== "string" || typeof value.fileKey !== "string" || value.method !== "PUT" || typeof value.maxFileSize !== "number" || typeof value.expiresIn !== "number") {
|
|
882
|
+
throw new TeakApiError("PARSE_ERROR");
|
|
883
|
+
}
|
|
884
|
+
return value;
|
|
885
|
+
};
|
|
886
|
+
var withoutTrailingSlashes = (value) => {
|
|
887
|
+
let end = value.length;
|
|
888
|
+
while (end > 0 && value.charCodeAt(end - 1) === 47) {
|
|
889
|
+
end -= 1;
|
|
890
|
+
}
|
|
891
|
+
return value.slice(0, end);
|
|
892
|
+
};
|
|
893
|
+
var createTeakClient = (options) => {
|
|
894
|
+
const baseUrl = withoutTrailingSlashes(options.baseUrl || "https://teakvault.com/api");
|
|
895
|
+
const fetchImpl = options.fetch ?? fetch;
|
|
896
|
+
const timeoutMs = options.timeoutMs ?? 1e4;
|
|
897
|
+
const request = async (path, init, parser, retry = true, accessToken) => {
|
|
898
|
+
const token = accessToken ?? await options.tokenProvider.getAccessToken();
|
|
899
|
+
if (!token) {
|
|
900
|
+
throw new TeakApiError("AUTH_REQUIRED");
|
|
901
|
+
}
|
|
902
|
+
const controller = new AbortController;
|
|
903
|
+
const timeout = setTimeout(() => controller.abort(), timeoutMs);
|
|
904
|
+
const headers = new Headers(init.headers);
|
|
905
|
+
headers.set("Authorization", `Bearer ${token}`);
|
|
906
|
+
headers.set("User-Agent", options.userAgent || "teak-cli");
|
|
907
|
+
if (init.body && !headers.has("Content-Type")) {
|
|
908
|
+
headers.set("Content-Type", "application/json");
|
|
909
|
+
}
|
|
910
|
+
let response;
|
|
911
|
+
try {
|
|
912
|
+
response = await fetchImpl(`${baseUrl}${path}`, {
|
|
913
|
+
...init,
|
|
914
|
+
headers,
|
|
915
|
+
signal: controller.signal
|
|
916
|
+
});
|
|
917
|
+
} catch (error) {
|
|
918
|
+
throw new TeakApiError(error instanceof DOMException && error.name === "AbortError" ? "TIMEOUT" : "NETWORK_ERROR");
|
|
919
|
+
} finally {
|
|
920
|
+
clearTimeout(timeout);
|
|
921
|
+
}
|
|
922
|
+
if (response.status === 401 && retry && options.tokenProvider.onUnauthorized) {
|
|
923
|
+
const next = await options.tokenProvider.onUnauthorized(token);
|
|
924
|
+
if (next) {
|
|
925
|
+
return request(path, init, parser, false, next);
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
const payload = await parseJson(response);
|
|
929
|
+
if (!response.ok) {
|
|
930
|
+
const object = isObject(payload) ? payload : {};
|
|
931
|
+
throw new TeakApiError(codeFrom(object.code, response.status === 404 ? "NOT_FOUND" : "REQUEST_FAILED"), String(object.error || response.statusText), {
|
|
932
|
+
requestId: typeof object.requestId === "string" ? object.requestId : undefined,
|
|
933
|
+
retryAt: typeof object.retryAt === "number" ? object.retryAt : undefined,
|
|
934
|
+
status: response.status
|
|
935
|
+
});
|
|
936
|
+
}
|
|
937
|
+
return parser(payload);
|
|
938
|
+
};
|
|
939
|
+
const qs = (params) => buildCardsSearchParams(params);
|
|
940
|
+
return {
|
|
941
|
+
cards: {
|
|
942
|
+
bulk: (operation, items) => request("/v1/cards/bulk", { body: JSON.stringify({ items, operation }), method: "POST" }, (v) => v),
|
|
943
|
+
changes: (input) => {
|
|
944
|
+
const search = new URLSearchParams(qs(input));
|
|
945
|
+
search.set("since", String(input.since));
|
|
946
|
+
return request(`/v1/cards/changes?${search.toString()}`, { method: "GET" }, (v) => v);
|
|
947
|
+
},
|
|
948
|
+
create: (input) => request("/v1/cards", { body: JSON.stringify(input), method: "POST" }, asCreate),
|
|
949
|
+
delete: (id) => request(`/v1/cards/${encodeURIComponent(id)}`, { method: "DELETE" }, () => null),
|
|
950
|
+
favorites: (input = {}) => request(`/v1/cards?${qs({ ...input, favorited: true, include: "content,metadata" })}`, { method: "GET" }, asPage),
|
|
951
|
+
get: (id) => request(`/v1/cards/${encodeURIComponent(id)}`, { method: "GET" }, asCard),
|
|
952
|
+
list: (input = {}) => request(`/v1/cards?${qs(input)}`, { method: "GET" }, asPage),
|
|
953
|
+
search: (input = {}) => request(`/v1/cards?${qs({ ...input, include: "content,metadata" })}`, { method: "GET" }, asPage),
|
|
954
|
+
setFavorite: (id, isFavorited) => request(`/v1/cards/${encodeURIComponent(id)}/favorite`, { body: JSON.stringify({ isFavorited }), method: "PATCH" }, asCard),
|
|
955
|
+
update: (id, input) => request(`/v1/cards/${encodeURIComponent(id)}`, { body: JSON.stringify(input), method: "PATCH" }, asCard)
|
|
956
|
+
},
|
|
957
|
+
tags: {
|
|
958
|
+
list: () => request("/v1/tags", { method: "GET" }, asTags)
|
|
959
|
+
},
|
|
960
|
+
uploads: {
|
|
961
|
+
create: (input) => request("/v1/uploads", { body: JSON.stringify(input), method: "POST" }, asUpload),
|
|
962
|
+
putFile: async (uploadUrl, bytes, mimeType) => {
|
|
963
|
+
const headers = new Headers({ "Content-Type": mimeType });
|
|
964
|
+
const byteLength = byteLengthForBody(bytes);
|
|
965
|
+
if (byteLength !== null) {
|
|
966
|
+
headers.set("Content-Length", String(byteLength));
|
|
967
|
+
}
|
|
968
|
+
const response = await fetchImpl(uploadUrl, {
|
|
969
|
+
body: bytes,
|
|
970
|
+
headers,
|
|
971
|
+
method: "PUT"
|
|
972
|
+
});
|
|
973
|
+
if (!response.ok) {
|
|
974
|
+
throw new TeakApiError("REQUEST_FAILED", `Upload failed with status ${response.status}`, { status: response.status });
|
|
975
|
+
}
|
|
976
|
+
return { fileEtag: response.headers.get("etag") ?? undefined };
|
|
977
|
+
}
|
|
978
|
+
}
|
|
979
|
+
};
|
|
980
|
+
};
|
|
981
|
+
var parseTags = (value) => value === undefined ? undefined : Array.from(new Set(value.split(",").map((tag) => tag.trim()).filter(Boolean)));
|
|
982
|
+
var isCardType = (value) => CARD_TYPES2.includes(value);
|
|
983
|
+
var isStringList = isStringArray;
|
|
984
|
+
export {
|
|
985
|
+
CARD_SORTS,
|
|
986
|
+
CARD_TYPES2 as CARD_TYPES,
|
|
987
|
+
ERROR_CODES,
|
|
988
|
+
TeakApiError,
|
|
989
|
+
buildCardsSearchParams,
|
|
990
|
+
createTeakClient,
|
|
991
|
+
discoverAuthServer,
|
|
992
|
+
isCardType,
|
|
993
|
+
isStringList,
|
|
994
|
+
normalizeLimit,
|
|
995
|
+
parseTags,
|
|
996
|
+
staticTokenProvider,
|
|
997
|
+
validateOAuthUrl
|
|
998
|
+
};
|