@devpad/api 2.0.1 → 2.0.2
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/chunk-5X36WMYQ.js +130 -0
- package/dist/chunk-FOO5XXY5.js +318 -0
- package/dist/chunk-WTGVONUB.js +166 -0
- package/dist/errors.d-C73AkrdX.d.ts +159 -0
- package/dist/index.d.ts +541 -13
- package/dist/index.js +1345 -6
- package/dist/media.d-R87HGuRp.d.ts +1047 -0
- package/dist/schema/blog.d.ts +5635 -0
- package/dist/schema/blog.js +348 -0
- package/dist/schema/index.d.ts +7 -0
- package/dist/schema/index.js +186 -0
- package/dist/schema/media.d.ts +1676 -0
- package/dist/schema/media.js +776 -0
- package/dist/schema.d-BceDyQED.d.ts +3187 -0
- package/dist/types.d-1hBObc_N.d.ts +684 -0
- package/dist/types.d-CoHRMrYJ.d.ts +539 -0
- package/dist/types.d-UV8B6hPN.d.ts +6146 -0
- package/package.json +17 -4
- package/dist/api-client.d.ts +0 -470
- package/dist/api-client.d.ts.map +0 -1
- package/dist/api-client.js +0 -530
- package/dist/error-handlers.d.ts +0 -55
- package/dist/error-handlers.d.ts.map +0 -1
- package/dist/error-handlers.js +0 -217
- package/dist/errors.d.ts +0 -19
- package/dist/errors.d.ts.map +0 -1
- package/dist/errors.js +0 -28
- package/dist/index.d.ts.map +0 -1
- package/dist/request.d.ts +0 -51
- package/dist/request.d.ts.map +0 -1
- package/dist/request.js +0 -197
- package/dist/result.d.ts +0 -10
- package/dist/result.d.ts.map +0 -1
- package/dist/result.js +0 -11
- package/dist/tools.d.ts +0 -84
- package/dist/tools.d.ts.map +0 -1
- package/dist/tools.js +0 -474
package/dist/index.js
CHANGED
|
@@ -1,6 +1,1345 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
1
|
+
import {
|
|
2
|
+
ArrayBufferedQueue,
|
|
3
|
+
save_config_request,
|
|
4
|
+
save_tags_request,
|
|
5
|
+
upsert_goal,
|
|
6
|
+
upsert_milestone,
|
|
7
|
+
upsert_project,
|
|
8
|
+
upsert_todo
|
|
9
|
+
} from "./chunk-WTGVONUB.js";
|
|
10
|
+
import "./chunk-5X36WMYQ.js";
|
|
11
|
+
import "./chunk-FOO5XXY5.js";
|
|
12
|
+
|
|
13
|
+
// src/errors.ts
|
|
14
|
+
var ApiError = class _ApiError extends Error {
|
|
15
|
+
constructor(message, options = {}) {
|
|
16
|
+
super(message);
|
|
17
|
+
this.name = "ApiError";
|
|
18
|
+
this.code = options.code ?? void 0;
|
|
19
|
+
this.statusCode = options.statusCode ?? void 0;
|
|
20
|
+
}
|
|
21
|
+
static fromResponse(response) {
|
|
22
|
+
return new _ApiError(`API request failed: ${response.statusText}`, {
|
|
23
|
+
statusCode: response.status
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
var AuthenticationError = class extends ApiError {
|
|
28
|
+
constructor(message = "Authentication failed") {
|
|
29
|
+
super(message, { code: "AUTHENTICATION_ERROR" });
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
var NetworkError = class extends ApiError {
|
|
33
|
+
constructor(message = "Network request failed") {
|
|
34
|
+
super(message, { code: "NETWORK_ERROR" });
|
|
35
|
+
}
|
|
36
|
+
};
|
|
37
|
+
var ValidationError = class extends ApiError {
|
|
38
|
+
constructor(message = "Validation failed") {
|
|
39
|
+
super(message, { code: "VALIDATION_ERROR" });
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
// src/error-handlers.ts
|
|
44
|
+
var HTTP_STATUS = {
|
|
45
|
+
OK: 200,
|
|
46
|
+
CREATED: 201,
|
|
47
|
+
NO_CONTENT: 204,
|
|
48
|
+
BAD_REQUEST: 400,
|
|
49
|
+
UNAUTHORIZED: 401,
|
|
50
|
+
FORBIDDEN: 403,
|
|
51
|
+
NOT_FOUND: 404,
|
|
52
|
+
INTERNAL_SERVER_ERROR: 500
|
|
53
|
+
};
|
|
54
|
+
function handleHttpResponse(response) {
|
|
55
|
+
switch (response.status) {
|
|
56
|
+
case HTTP_STATUS.UNAUTHORIZED:
|
|
57
|
+
throw new AuthenticationError("Invalid or expired API key");
|
|
58
|
+
case HTTP_STATUS.NOT_FOUND:
|
|
59
|
+
throw new ApiError("Resource not found", { statusCode: HTTP_STATUS.NOT_FOUND });
|
|
60
|
+
case HTTP_STATUS.BAD_REQUEST:
|
|
61
|
+
break;
|
|
62
|
+
default:
|
|
63
|
+
if (!response.ok) {
|
|
64
|
+
throw new ApiError(`Request failed: ${response.statusText}`, { statusCode: response.status });
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
async function handleResponseError(response) {
|
|
69
|
+
const errorText = await response.text();
|
|
70
|
+
const errorMessage = errorText || "Request failed";
|
|
71
|
+
let parsedError = null;
|
|
72
|
+
try {
|
|
73
|
+
parsedError = JSON.parse(errorText);
|
|
74
|
+
} catch {
|
|
75
|
+
}
|
|
76
|
+
if (response.status === HTTP_STATUS.BAD_REQUEST && parsedError?.error?.name === "ZodError") {
|
|
77
|
+
const zodErrorDetails = parsedError.error?.issues ? JSON.stringify(parsedError.error) : errorMessage;
|
|
78
|
+
throw new ValidationError(zodErrorDetails);
|
|
79
|
+
}
|
|
80
|
+
throw new ApiError(errorMessage, { statusCode: response.status });
|
|
81
|
+
}
|
|
82
|
+
function handleNetworkError(error) {
|
|
83
|
+
const message = error instanceof Error ? error.message : "Unknown network error";
|
|
84
|
+
throw new NetworkError(message);
|
|
85
|
+
}
|
|
86
|
+
function isApiError(error) {
|
|
87
|
+
return error instanceof ApiError;
|
|
88
|
+
}
|
|
89
|
+
function isAuthenticationError(error) {
|
|
90
|
+
return error instanceof AuthenticationError;
|
|
91
|
+
}
|
|
92
|
+
function isNetworkError(error) {
|
|
93
|
+
return error instanceof NetworkError;
|
|
94
|
+
}
|
|
95
|
+
function parseZodErrors(errorMessage) {
|
|
96
|
+
try {
|
|
97
|
+
let parsedError = null;
|
|
98
|
+
try {
|
|
99
|
+
parsedError = JSON.parse(errorMessage);
|
|
100
|
+
} catch {
|
|
101
|
+
const zodErrorMatch = errorMessage.match(/ZodError: (.+)/);
|
|
102
|
+
if (zodErrorMatch && zodErrorMatch[1]) {
|
|
103
|
+
try {
|
|
104
|
+
parsedError = JSON.parse(zodErrorMatch[1]);
|
|
105
|
+
} catch {
|
|
106
|
+
const issuesMatch = errorMessage.match(/issues:\s*(\[.*\])/s);
|
|
107
|
+
if (issuesMatch && issuesMatch[1]) {
|
|
108
|
+
try {
|
|
109
|
+
parsedError = { issues: JSON.parse(issuesMatch[1]) };
|
|
110
|
+
} catch {
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
if (parsedError?.issues && Array.isArray(parsedError.issues)) {
|
|
117
|
+
const friendlyMessages = parsedError.issues.map((issue) => {
|
|
118
|
+
const path = issue.path && issue.path.length > 0 ? issue.path.join(".") : "field";
|
|
119
|
+
const message = issue.message || "is invalid";
|
|
120
|
+
switch (issue.code) {
|
|
121
|
+
case "invalid_type":
|
|
122
|
+
return `${path} must be a ${issue.expected} (received ${issue.received})`;
|
|
123
|
+
case "too_small":
|
|
124
|
+
if (issue.type === "string") {
|
|
125
|
+
return `${path} must be at least ${issue.minimum} characters long`;
|
|
126
|
+
}
|
|
127
|
+
if (issue.type === "number") {
|
|
128
|
+
return `${path} must be at least ${issue.minimum}`;
|
|
129
|
+
}
|
|
130
|
+
return `${path} is too small`;
|
|
131
|
+
case "too_big":
|
|
132
|
+
if (issue.type === "string") {
|
|
133
|
+
return `${path} must be no more than ${issue.maximum} characters long`;
|
|
134
|
+
}
|
|
135
|
+
if (issue.type === "number") {
|
|
136
|
+
return `${path} must be no more than ${issue.maximum}`;
|
|
137
|
+
}
|
|
138
|
+
return `${path} is too large`;
|
|
139
|
+
case "invalid_string":
|
|
140
|
+
if (issue.validation === "email") {
|
|
141
|
+
return `${path} must be a valid email address`;
|
|
142
|
+
}
|
|
143
|
+
if (issue.validation === "url") {
|
|
144
|
+
return `${path} must be a valid URL`;
|
|
145
|
+
}
|
|
146
|
+
if (issue.validation === "uuid") {
|
|
147
|
+
return `${path} must be a valid UUID`;
|
|
148
|
+
}
|
|
149
|
+
return `${path} format is invalid`;
|
|
150
|
+
case "custom":
|
|
151
|
+
return `${path}: ${message}`;
|
|
152
|
+
default:
|
|
153
|
+
return `${path}: ${message}`;
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
if (friendlyMessages.length === 1) {
|
|
157
|
+
return friendlyMessages[0];
|
|
158
|
+
}
|
|
159
|
+
return `Validation failed:
|
|
160
|
+
\u2022 ${friendlyMessages.join("\n\u2022 ")}`;
|
|
161
|
+
}
|
|
162
|
+
} catch (e) {
|
|
163
|
+
console.debug("Failed to parse Zod error:", e);
|
|
164
|
+
}
|
|
165
|
+
return errorMessage;
|
|
166
|
+
}
|
|
167
|
+
function getUserFriendlyErrorMessage(error) {
|
|
168
|
+
if (isAuthenticationError(error)) {
|
|
169
|
+
return "Please check your API key and try again";
|
|
170
|
+
}
|
|
171
|
+
if (isNetworkError(error)) {
|
|
172
|
+
return "Network connection issue. Please try again";
|
|
173
|
+
}
|
|
174
|
+
if (isApiError(error)) {
|
|
175
|
+
if (error.statusCode === HTTP_STATUS.NOT_FOUND) {
|
|
176
|
+
return "The requested resource was not found";
|
|
177
|
+
}
|
|
178
|
+
if (error.statusCode === HTTP_STATUS.BAD_REQUEST) {
|
|
179
|
+
return "Invalid request. Please check your data";
|
|
180
|
+
}
|
|
181
|
+
if (error.code === "VALIDATION_ERROR" && error.message) {
|
|
182
|
+
return parseZodErrors(error.message);
|
|
183
|
+
}
|
|
184
|
+
return error.message || "An error occurred";
|
|
185
|
+
}
|
|
186
|
+
return "An unexpected error occurred";
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// src/request.ts
|
|
190
|
+
var ApiClient = class {
|
|
191
|
+
constructor(options) {
|
|
192
|
+
this.category = "api";
|
|
193
|
+
this.auth_mode = options.auth_mode ?? (options.api_key?.startsWith("jwt:") ? "session" : "key");
|
|
194
|
+
if (this.auth_mode !== "cookie") {
|
|
195
|
+
if (!options.api_key) throw new Error("API key is required");
|
|
196
|
+
if (options.api_key.length < 10) throw new Error("API key is too short");
|
|
197
|
+
}
|
|
198
|
+
this.base_url = options.base_url;
|
|
199
|
+
this.api_key = options.api_key ?? "";
|
|
200
|
+
this.category = options.category || "api";
|
|
201
|
+
this.credentials = options.credentials;
|
|
202
|
+
this.default_headers = options.default_headers ?? {};
|
|
203
|
+
this.custom_fetch = options.custom_fetch;
|
|
204
|
+
this.request_history = new ArrayBufferedQueue(options.max_history_size ?? 5);
|
|
205
|
+
this.debug = options.debug ?? false;
|
|
206
|
+
}
|
|
207
|
+
buildUrl(path, query) {
|
|
208
|
+
const url = new URL(`${this.base_url}${path}`);
|
|
209
|
+
if (query) {
|
|
210
|
+
Object.entries(query).forEach(([key, value]) => {
|
|
211
|
+
if (value) url.searchParams.append(key, value);
|
|
212
|
+
});
|
|
213
|
+
}
|
|
214
|
+
return url.toString();
|
|
215
|
+
}
|
|
216
|
+
generateRequestId() {
|
|
217
|
+
return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
|
|
218
|
+
}
|
|
219
|
+
async request(path, options = {}) {
|
|
220
|
+
const { method = "GET", headers = {}, body, query } = options;
|
|
221
|
+
const url = this.buildUrl(path, query);
|
|
222
|
+
const requestId = this.generateRequestId();
|
|
223
|
+
const startTime = Date.now();
|
|
224
|
+
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
225
|
+
if (this.debug) {
|
|
226
|
+
console.log(`[DEBUG][${this.category}] ${method} ${path} [${requestId}]`, { body, query });
|
|
227
|
+
}
|
|
228
|
+
const request_headers = {
|
|
229
|
+
"Content-Type": "application/json",
|
|
230
|
+
"X-Request-ID": requestId,
|
|
231
|
+
...this.default_headers,
|
|
232
|
+
...headers
|
|
233
|
+
};
|
|
234
|
+
if (this.auth_mode === "session") {
|
|
235
|
+
request_headers.Authorization = `Bearer jwt:${this.api_key.replace(/^jwt:/, "")}`;
|
|
236
|
+
} else if (this.auth_mode === "key") {
|
|
237
|
+
request_headers.Authorization = `Bearer ${this.api_key}`;
|
|
238
|
+
}
|
|
239
|
+
const historyEntry = {
|
|
240
|
+
timestamp,
|
|
241
|
+
method,
|
|
242
|
+
path,
|
|
243
|
+
options: { ...options, method },
|
|
244
|
+
url
|
|
245
|
+
};
|
|
246
|
+
try {
|
|
247
|
+
const fetchOptions = {
|
|
248
|
+
method,
|
|
249
|
+
headers: request_headers
|
|
250
|
+
};
|
|
251
|
+
if (body) {
|
|
252
|
+
fetchOptions.body = JSON.stringify(body);
|
|
253
|
+
}
|
|
254
|
+
if (this.credentials) {
|
|
255
|
+
fetchOptions.credentials = this.credentials;
|
|
256
|
+
} else if (this.auth_mode === "cookie") {
|
|
257
|
+
fetchOptions.credentials = "include";
|
|
258
|
+
}
|
|
259
|
+
const fetcher = this.custom_fetch ?? fetch;
|
|
260
|
+
const response = await fetcher(url, fetchOptions);
|
|
261
|
+
const duration = Date.now() - startTime;
|
|
262
|
+
historyEntry.status = response.status;
|
|
263
|
+
historyEntry.duration = duration;
|
|
264
|
+
if (!response.ok) {
|
|
265
|
+
if (this.debug) {
|
|
266
|
+
console.log(`[ERROR][${this.category}] ${method} ${path} [${requestId}] failed`, {
|
|
267
|
+
status: response.status,
|
|
268
|
+
duration: `${duration}ms`,
|
|
269
|
+
body,
|
|
270
|
+
query
|
|
271
|
+
});
|
|
272
|
+
}
|
|
273
|
+
try {
|
|
274
|
+
handleHttpResponse(response);
|
|
275
|
+
await handleResponseError(response);
|
|
276
|
+
} catch (error) {
|
|
277
|
+
const errorMessage = error instanceof Error ? error.message : "Request failed";
|
|
278
|
+
historyEntry.error = errorMessage;
|
|
279
|
+
this.request_history.add(historyEntry);
|
|
280
|
+
throw error;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
this.request_history.add(historyEntry);
|
|
284
|
+
let result;
|
|
285
|
+
if (response.status === HTTP_STATUS.NO_CONTENT) {
|
|
286
|
+
result = void 0;
|
|
287
|
+
} else {
|
|
288
|
+
const text = await response.text();
|
|
289
|
+
if (!text || text.trim() === "" || text.trim() === "null") {
|
|
290
|
+
result = void 0;
|
|
291
|
+
} else {
|
|
292
|
+
try {
|
|
293
|
+
result = JSON.parse(text);
|
|
294
|
+
} catch (parseError) {
|
|
295
|
+
result = text;
|
|
296
|
+
}
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
if (this.debug) {
|
|
300
|
+
console.log(`[INFO][${this.category}] ${method} ${path} [${requestId}] completed`, {
|
|
301
|
+
status: response.status,
|
|
302
|
+
duration: `${duration}ms`
|
|
303
|
+
});
|
|
304
|
+
}
|
|
305
|
+
return result;
|
|
306
|
+
} catch (error) {
|
|
307
|
+
const duration = Date.now() - startTime;
|
|
308
|
+
if (this.debug) {
|
|
309
|
+
console.log(`[ERROR][${this.category}] ${method} ${path} [${requestId}] failed`, {
|
|
310
|
+
url,
|
|
311
|
+
duration: `${duration}ms`,
|
|
312
|
+
error: error instanceof Error ? error.message : String(error),
|
|
313
|
+
body,
|
|
314
|
+
query
|
|
315
|
+
});
|
|
316
|
+
}
|
|
317
|
+
if (error instanceof ApiError || error instanceof AuthenticationError) {
|
|
318
|
+
throw error;
|
|
319
|
+
}
|
|
320
|
+
historyEntry.duration = duration;
|
|
321
|
+
try {
|
|
322
|
+
handleNetworkError(error);
|
|
323
|
+
} catch (networkError) {
|
|
324
|
+
const errorMessage = networkError instanceof Error ? networkError.message : "Unknown network error";
|
|
325
|
+
historyEntry.error = errorMessage;
|
|
326
|
+
this.request_history.add(historyEntry);
|
|
327
|
+
throw networkError;
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
get(path, options = {}) {
|
|
332
|
+
return this.request(path, { ...options, method: "GET" });
|
|
333
|
+
}
|
|
334
|
+
post(path, options = {}) {
|
|
335
|
+
return this.request(path, { ...options, method: "POST" });
|
|
336
|
+
}
|
|
337
|
+
patch(path, options = {}) {
|
|
338
|
+
return this.request(path, { ...options, method: "PATCH" });
|
|
339
|
+
}
|
|
340
|
+
put(path, options = {}) {
|
|
341
|
+
return this.request(path, { ...options, method: "PUT" });
|
|
342
|
+
}
|
|
343
|
+
delete(path, options = {}) {
|
|
344
|
+
return this.request(path, { ...options, method: "DELETE" });
|
|
345
|
+
}
|
|
346
|
+
history() {
|
|
347
|
+
return this.request_history;
|
|
348
|
+
}
|
|
349
|
+
url() {
|
|
350
|
+
return this.base_url;
|
|
351
|
+
}
|
|
352
|
+
headers() {
|
|
353
|
+
const headers = {
|
|
354
|
+
"Content-Type": "application/json"
|
|
355
|
+
};
|
|
356
|
+
if (this.auth_mode === "session") {
|
|
357
|
+
headers.Authorization = `Bearer jwt:${this.api_key.replace(/^jwt:/, "")}`;
|
|
358
|
+
} else if (this.auth_mode === "key") {
|
|
359
|
+
headers["X-API-KEY"] = this.api_key;
|
|
360
|
+
}
|
|
361
|
+
return headers;
|
|
362
|
+
}
|
|
363
|
+
};
|
|
364
|
+
|
|
365
|
+
// src/result.ts
|
|
366
|
+
import { err, ok } from "@f0rbit/corpus";
|
|
367
|
+
function wrap(fn) {
|
|
368
|
+
return fn().then((data) => ok(data)).catch(
|
|
369
|
+
(error) => err({
|
|
370
|
+
message: error.message || "Unknown error",
|
|
371
|
+
code: error.code,
|
|
372
|
+
status_code: error.statusCode || error.status_code
|
|
373
|
+
})
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
// src/api-client.ts
|
|
378
|
+
var ApiClient2 = class {
|
|
379
|
+
constructor(options) {
|
|
380
|
+
/**
|
|
381
|
+
* Auth namespace with Result-wrapped operations
|
|
382
|
+
*/
|
|
383
|
+
this.auth = {
|
|
384
|
+
session: () => wrap(() => this.clients.auth_root.get("/auth/session")),
|
|
385
|
+
keys: {
|
|
386
|
+
list: () => wrap(() => this.clients.auth.get("/keys")),
|
|
387
|
+
create: (name) => wrap(() => this.clients.auth.post("/keys", { body: name ? { name } : {} })),
|
|
388
|
+
revoke: (key_id) => wrap(() => this.clients.auth.delete(`/keys/${key_id}`)),
|
|
389
|
+
remove: (key_id) => wrap(() => this.clients.auth.delete(`/keys/${key_id}`))
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
/**
|
|
393
|
+
* Projects namespace with Result-wrapped operations
|
|
394
|
+
*/
|
|
395
|
+
this.projects = {
|
|
396
|
+
/**
|
|
397
|
+
* List projects with optional filtering
|
|
398
|
+
*/
|
|
399
|
+
list: (filters) => wrap(() => this.clients.projects.get(filters?.private === false ? "/projects/public" : "/projects")),
|
|
400
|
+
/**
|
|
401
|
+
* Get project map
|
|
402
|
+
*/
|
|
403
|
+
map: async (filters) => wrap(async () => {
|
|
404
|
+
const result = await this.projects.list(filters);
|
|
405
|
+
if (!result.ok) throw new Error(result.error.message);
|
|
406
|
+
return result.value.reduce(
|
|
407
|
+
(acc, project) => {
|
|
408
|
+
acc[project.id] = project;
|
|
409
|
+
return acc;
|
|
410
|
+
},
|
|
411
|
+
{}
|
|
412
|
+
);
|
|
413
|
+
}),
|
|
414
|
+
/**
|
|
415
|
+
* Get project by ID
|
|
416
|
+
*/
|
|
417
|
+
find: (id) => wrap(() => this.clients.projects.get("/projects", { query: { id } })),
|
|
418
|
+
/**
|
|
419
|
+
* Get project by name
|
|
420
|
+
*/
|
|
421
|
+
getByName: (name) => wrap(() => this.clients.projects.get("/projects", { query: { name } })),
|
|
422
|
+
/**
|
|
423
|
+
* Get project by ID (throws if not found)
|
|
424
|
+
*/
|
|
425
|
+
getById: (id) => wrap(() => this.clients.projects.get("/projects", { query: { id } })),
|
|
426
|
+
/**
|
|
427
|
+
* Create a new project
|
|
428
|
+
*/
|
|
429
|
+
create: (data) => wrap(() => this.clients.projects.patch("/projects", { body: data })),
|
|
430
|
+
/**
|
|
431
|
+
* Update an existing project
|
|
432
|
+
*/
|
|
433
|
+
update: async (idOrData, changes) => wrap(async () => {
|
|
434
|
+
if (typeof idOrData === "object" && idOrData.id) {
|
|
435
|
+
return this.clients.projects.patch("/projects", { body: idOrData });
|
|
436
|
+
}
|
|
437
|
+
const id = idOrData;
|
|
438
|
+
if (!changes) {
|
|
439
|
+
throw new Error("Changes parameter required for update");
|
|
440
|
+
}
|
|
441
|
+
const result = await this.projects.find(id);
|
|
442
|
+
if (!result.ok) throw new Error(result.error.message);
|
|
443
|
+
if (!result.value) throw new Error(`Project with id ${id} not found`);
|
|
444
|
+
const project = result.value;
|
|
445
|
+
const updateData = {
|
|
446
|
+
id: project.id,
|
|
447
|
+
project_id: project.project_id,
|
|
448
|
+
owner_id: project.owner_id,
|
|
449
|
+
name: project.name,
|
|
450
|
+
description: project.description,
|
|
451
|
+
specification: project.specification,
|
|
452
|
+
repo_url: project.repo_url,
|
|
453
|
+
repo_id: project.repo_id,
|
|
454
|
+
icon_url: project.icon_url,
|
|
455
|
+
status: project.status,
|
|
456
|
+
deleted: project.deleted,
|
|
457
|
+
link_url: project.link_url,
|
|
458
|
+
link_text: project.link_text,
|
|
459
|
+
visibility: project.visibility,
|
|
460
|
+
current_version: project.current_version,
|
|
461
|
+
...changes
|
|
462
|
+
};
|
|
463
|
+
return this.clients.projects.patch("/projects", { body: updateData });
|
|
464
|
+
}),
|
|
465
|
+
/**
|
|
466
|
+
* Project configuration operations
|
|
467
|
+
*/
|
|
468
|
+
config: {
|
|
469
|
+
/**
|
|
470
|
+
* Get project configuration
|
|
471
|
+
*/
|
|
472
|
+
load: (project_id) => wrap(() => this.clients.projects.get("/projects/config", { query: { project_id } })),
|
|
473
|
+
/**
|
|
474
|
+
* Save project configuration
|
|
475
|
+
*/
|
|
476
|
+
save: (request) => wrap(() => this.clients.projects.patch("/projects/save_config", { body: request }))
|
|
477
|
+
},
|
|
478
|
+
/**
|
|
479
|
+
* Scanning operations
|
|
480
|
+
*/
|
|
481
|
+
scan: {
|
|
482
|
+
/**
|
|
483
|
+
* Initiate a repository scan (returns stream)
|
|
484
|
+
*/
|
|
485
|
+
initiate: async (project_id) => {
|
|
486
|
+
const response = await fetch(`${this.clients.projects.url()}/projects/scan?project_id=${project_id}`, {
|
|
487
|
+
method: "POST",
|
|
488
|
+
headers: this.clients.projects.headers()
|
|
489
|
+
});
|
|
490
|
+
if (!response.body) {
|
|
491
|
+
throw new Error("No response body");
|
|
492
|
+
}
|
|
493
|
+
const stream = response.body.pipeThrough(new TextDecoderStream());
|
|
494
|
+
return stream;
|
|
495
|
+
},
|
|
496
|
+
/**
|
|
497
|
+
* Get pending scan updates for a project
|
|
498
|
+
*/
|
|
499
|
+
updates: (project_id) => wrap(() => this.clients.projects.get("/projects/updates", { query: { project_id } }).then((response) => response.updates)),
|
|
500
|
+
/**
|
|
501
|
+
* Process scan results
|
|
502
|
+
*/
|
|
503
|
+
update: (project_id, data) => wrap(() => this.clients.projects.post("/projects/scan_status", { query: { project_id }, body: data }))
|
|
504
|
+
},
|
|
505
|
+
/**
|
|
506
|
+
* Get project history
|
|
507
|
+
*/
|
|
508
|
+
history: (project_id) => wrap(() => this.clients.projects.get(`/projects/${project_id}/history`)),
|
|
509
|
+
/**
|
|
510
|
+
* Legacy methods (keeping for compatibility)
|
|
511
|
+
*/
|
|
512
|
+
upsert: (data) => wrap(() => this.clients.projects.patch("/projects", { body: data })),
|
|
513
|
+
/**
|
|
514
|
+
* Fetch project specification from GitHub
|
|
515
|
+
*/
|
|
516
|
+
specification: (project_id) => wrap(() => this.clients.projects.get("/projects/fetch_spec", { query: { project_id } })),
|
|
517
|
+
/**
|
|
518
|
+
* Delete project (soft delete)
|
|
519
|
+
*/
|
|
520
|
+
deleteProject: (project) => wrap(() => this.clients.projects.patch("/projects", { body: { ...project, deleted: true } }))
|
|
521
|
+
};
|
|
522
|
+
/**
|
|
523
|
+
* Milestones namespace with Result-wrapped operations
|
|
524
|
+
*/
|
|
525
|
+
this.milestones = {
|
|
526
|
+
/**
|
|
527
|
+
* List milestones for authenticated user
|
|
528
|
+
*/
|
|
529
|
+
list: () => wrap(() => this.clients.milestones.get("/milestones")),
|
|
530
|
+
/**
|
|
531
|
+
* Get milestones by project ID
|
|
532
|
+
*/
|
|
533
|
+
getByProject: (project_id) => wrap(() => this.clients.milestones.get(`/projects/${project_id}/milestones`)),
|
|
534
|
+
/**
|
|
535
|
+
* Get milestone by ID
|
|
536
|
+
*/
|
|
537
|
+
find: (id) => wrap(async () => {
|
|
538
|
+
try {
|
|
539
|
+
return await this.clients.milestones.get(`/milestones/${id}`);
|
|
540
|
+
} catch (error) {
|
|
541
|
+
return null;
|
|
542
|
+
}
|
|
543
|
+
}),
|
|
544
|
+
/**
|
|
545
|
+
* Create new milestone
|
|
546
|
+
*/
|
|
547
|
+
create: (data) => wrap(() => this.clients.milestones.post("/milestones", { body: data })),
|
|
548
|
+
/**
|
|
549
|
+
* Update milestone
|
|
550
|
+
*/
|
|
551
|
+
update: async (id, data) => wrap(async () => {
|
|
552
|
+
const result = await this.milestones.find(id);
|
|
553
|
+
if (!result.ok) throw new Error(result.error.message);
|
|
554
|
+
if (!result.value) throw new Error(`Milestone with id ${id} not found`);
|
|
555
|
+
const milestone = result.value;
|
|
556
|
+
const updateData = {
|
|
557
|
+
id: milestone.id,
|
|
558
|
+
project_id: milestone.project_id,
|
|
559
|
+
name: data.name ?? milestone.name,
|
|
560
|
+
description: data.description ?? milestone.description,
|
|
561
|
+
target_time: data.target_time ?? milestone.target_time,
|
|
562
|
+
target_version: data.target_version ?? milestone.target_version
|
|
563
|
+
};
|
|
564
|
+
return this.clients.milestones.patch(`/milestones/${id}`, { body: updateData });
|
|
565
|
+
}),
|
|
566
|
+
/**
|
|
567
|
+
* Delete milestone (soft delete)
|
|
568
|
+
*/
|
|
569
|
+
delete: (id) => wrap(() => this.clients.milestones.delete(`/milestones/${id}`)),
|
|
570
|
+
/**
|
|
571
|
+
* Get goals for a milestone
|
|
572
|
+
*/
|
|
573
|
+
goals: (id) => wrap(() => this.clients.milestones.get(`/milestones/${id}/goals`))
|
|
574
|
+
};
|
|
575
|
+
/**
|
|
576
|
+
* Goals namespace with Result-wrapped operations
|
|
577
|
+
*/
|
|
578
|
+
this.goals = {
|
|
579
|
+
/**
|
|
580
|
+
* List goals for authenticated user
|
|
581
|
+
*/
|
|
582
|
+
list: () => wrap(() => this.clients.goals.get("/goals")),
|
|
583
|
+
/**
|
|
584
|
+
* Get goal by ID
|
|
585
|
+
*/
|
|
586
|
+
find: (id) => wrap(() => this.clients.goals.get(`/goals/${id}`)),
|
|
587
|
+
/**
|
|
588
|
+
* Create new goal
|
|
589
|
+
*/
|
|
590
|
+
create: (data) => wrap(() => this.clients.goals.post("/goals", { body: data })),
|
|
591
|
+
/**
|
|
592
|
+
* Update goal
|
|
593
|
+
*/
|
|
594
|
+
update: async (id, data) => wrap(async () => {
|
|
595
|
+
const result = await this.goals.find(id);
|
|
596
|
+
if (!result.ok) throw new Error(result.error.message);
|
|
597
|
+
if (!result.value) throw new Error(`Goal with id ${id} not found`);
|
|
598
|
+
const goal = result.value;
|
|
599
|
+
const updateData = {
|
|
600
|
+
id: goal.id,
|
|
601
|
+
milestone_id: goal.milestone_id,
|
|
602
|
+
name: data.name ?? goal.name,
|
|
603
|
+
description: data.description ?? goal.description,
|
|
604
|
+
target_time: data.target_time ?? goal.target_time
|
|
605
|
+
};
|
|
606
|
+
return this.clients.goals.patch(`/goals/${id}`, { body: updateData });
|
|
607
|
+
}),
|
|
608
|
+
/**
|
|
609
|
+
* Delete goal (soft delete)
|
|
610
|
+
*/
|
|
611
|
+
delete: (id) => wrap(() => this.clients.goals.delete(`/goals/${id}`))
|
|
612
|
+
};
|
|
613
|
+
/**
|
|
614
|
+
* Tasks namespace with Result-wrapped operations
|
|
615
|
+
*/
|
|
616
|
+
this.tasks = {
|
|
617
|
+
/**
|
|
618
|
+
* List tasks with optional filtering
|
|
619
|
+
*/
|
|
620
|
+
list: (filters) => wrap(() => {
|
|
621
|
+
const query = {};
|
|
622
|
+
if (filters?.project_id) query.project = filters.project_id;
|
|
623
|
+
if (filters?.tag_id) query.tag = filters.tag_id;
|
|
624
|
+
return this.clients.tasks.get("/tasks", Object.keys(query).length > 0 ? { query } : {});
|
|
625
|
+
}),
|
|
626
|
+
/**
|
|
627
|
+
* Get task by ID
|
|
628
|
+
*/
|
|
629
|
+
find: (id) => wrap(() => this.clients.tasks.get("/tasks", { query: { id } })),
|
|
630
|
+
/**
|
|
631
|
+
* Get tasks by project ID
|
|
632
|
+
*/
|
|
633
|
+
getByProject: (project_id) => wrap(() => this.clients.tasks.get(`/tasks`, { query: { project: project_id } })),
|
|
634
|
+
/**
|
|
635
|
+
* Create a new task
|
|
636
|
+
*/
|
|
637
|
+
create: (data) => wrap(() => this.clients.tasks.patch("/tasks", { body: data })),
|
|
638
|
+
/**
|
|
639
|
+
* Update an existing task
|
|
640
|
+
*/
|
|
641
|
+
update: async (id, changes) => wrap(async () => {
|
|
642
|
+
const result = await this.tasks.find(id);
|
|
643
|
+
if (!result.ok) throw new Error(result.error.message);
|
|
644
|
+
if (!result.value) throw new Error(`Task with id ${id} not found`);
|
|
645
|
+
const task = result.value;
|
|
646
|
+
const updateData = {
|
|
647
|
+
id,
|
|
648
|
+
title: task.task.title,
|
|
649
|
+
summary: task.task.summary,
|
|
650
|
+
description: task.task.description,
|
|
651
|
+
progress: task.task.progress,
|
|
652
|
+
visibility: task.task.visibility,
|
|
653
|
+
start_time: task.task.start_time,
|
|
654
|
+
end_time: task.task.end_time,
|
|
655
|
+
priority: task.task.priority,
|
|
656
|
+
owner_id: task.task.owner_id,
|
|
657
|
+
project_id: task.task.project_id,
|
|
658
|
+
...changes
|
|
659
|
+
};
|
|
660
|
+
return this.clients.tasks.patch("/tasks", { body: updateData });
|
|
661
|
+
}),
|
|
662
|
+
/**
|
|
663
|
+
* Upsert task (create or update)
|
|
664
|
+
*/
|
|
665
|
+
upsert: (data) => wrap(() => this.clients.tasks.patch("/tasks", { body: data })),
|
|
666
|
+
/**
|
|
667
|
+
* Save tags for tasks
|
|
668
|
+
*/
|
|
669
|
+
saveTags: (data) => wrap(() => this.clients.tasks.patch("/tasks/save_tags", { body: data })),
|
|
670
|
+
/**
|
|
671
|
+
* Delete task (soft delete)
|
|
672
|
+
*/
|
|
673
|
+
deleteTask: (task) => wrap(() => this.clients.tasks.patch("/tasks", { body: { ...task.task, deleted: true } })),
|
|
674
|
+
/**
|
|
675
|
+
* Task history operations
|
|
676
|
+
*/
|
|
677
|
+
history: {
|
|
678
|
+
/**
|
|
679
|
+
* Get task history by task ID
|
|
680
|
+
*/
|
|
681
|
+
get: (task_id) => wrap(() => this.clients.tasks.get(`/tasks/history/${task_id}`))
|
|
682
|
+
}
|
|
683
|
+
};
|
|
684
|
+
/**
|
|
685
|
+
* Tags namespace with Result-wrapped operations
|
|
686
|
+
*/
|
|
687
|
+
this.tags = {
|
|
688
|
+
/**
|
|
689
|
+
* List tags for authenticated user
|
|
690
|
+
*/
|
|
691
|
+
list: () => wrap(() => this.clients.tags.get("/tags"))
|
|
692
|
+
};
|
|
693
|
+
/**
|
|
694
|
+
* GitHub namespace with Result-wrapped operations
|
|
695
|
+
*/
|
|
696
|
+
this.github = {
|
|
697
|
+
/**
|
|
698
|
+
* List repositories for authenticated user
|
|
699
|
+
*/
|
|
700
|
+
repos: () => wrap(() => this.clients.github.get("/repos")),
|
|
701
|
+
/**
|
|
702
|
+
* List branches for a GitHub repository
|
|
703
|
+
*/
|
|
704
|
+
branches: (owner, repo) => wrap(() => this.clients.github.get(`/repos/${owner}/${repo}/branches`))
|
|
705
|
+
};
|
|
706
|
+
this.blog = {
|
|
707
|
+
posts: {
|
|
708
|
+
list: (params) => wrap(() => {
|
|
709
|
+
const query = {};
|
|
710
|
+
if (params?.category) query.category = params.category;
|
|
711
|
+
if (params?.tag) query.tag = params.tag;
|
|
712
|
+
if (params?.project) query.project = params.project;
|
|
713
|
+
if (params?.status) query.status = params.status;
|
|
714
|
+
if (params?.archived !== void 0) query.archived = String(params.archived);
|
|
715
|
+
if (params?.limit) query.limit = String(params.limit);
|
|
716
|
+
if (params?.offset !== void 0) query.offset = String(params.offset);
|
|
717
|
+
if (params?.sort) query.sort = params.sort;
|
|
718
|
+
return this.clients.blog.get("/blog/posts", Object.keys(query).length ? { query } : {});
|
|
719
|
+
}),
|
|
720
|
+
getBySlug: (slug) => wrap(() => this.clients.blog.get(`/blog/posts/${slug}`)),
|
|
721
|
+
create: (data) => wrap(() => this.clients.blog.post("/blog/posts", { body: data })),
|
|
722
|
+
update: (uuid, data) => wrap(() => this.clients.blog.put(`/blog/posts/${uuid}`, { body: data })),
|
|
723
|
+
delete: (uuid) => wrap(() => this.clients.blog.delete(`/blog/posts/${uuid}`)),
|
|
724
|
+
versions: (uuid) => wrap(() => this.clients.blog.get(`/blog/posts/${uuid}/versions`)),
|
|
725
|
+
version: (uuid, hash) => wrap(() => this.clients.blog.get(`/blog/posts/${uuid}/version/${hash}`)),
|
|
726
|
+
restore: (uuid, hash) => wrap(() => this.clients.blog.post(`/blog/posts/${uuid}/restore/${hash}`))
|
|
727
|
+
},
|
|
728
|
+
tags: {
|
|
729
|
+
list: () => wrap(() => this.clients.blog.get("/blog/tags")),
|
|
730
|
+
getForPost: (uuid) => wrap(() => this.clients.blog.get(`/blog/tags/posts/${uuid}/tags`)),
|
|
731
|
+
setForPost: (uuid, tags) => wrap(() => this.clients.blog.put(`/blog/tags/posts/${uuid}/tags`, { body: { tags } })),
|
|
732
|
+
addToPost: (uuid, tags) => wrap(() => this.clients.blog.post(`/blog/tags/posts/${uuid}/tags`, { body: { tags } })),
|
|
733
|
+
removeFromPost: (uuid, tag) => wrap(() => this.clients.blog.delete(`/blog/tags/posts/${uuid}/tags/${tag}`))
|
|
734
|
+
},
|
|
735
|
+
categories: {
|
|
736
|
+
tree: () => wrap(() => this.clients.blog.get("/blog/categories")),
|
|
737
|
+
create: (data) => wrap(() => this.clients.blog.post("/blog/categories", { body: data })),
|
|
738
|
+
update: (name, data) => wrap(() => this.clients.blog.put(`/blog/categories/${name}`, { body: data })),
|
|
739
|
+
delete: (name) => wrap(() => this.clients.blog.delete(`/blog/categories/${name}`))
|
|
740
|
+
},
|
|
741
|
+
tokens: {
|
|
742
|
+
list: () => wrap(() => this.clients.blog.get("/blog/tokens")),
|
|
743
|
+
create: (data) => wrap(() => this.clients.blog.post("/blog/tokens", { body: data })),
|
|
744
|
+
update: (id, data) => wrap(() => this.clients.blog.put(`/blog/tokens/${id}`, { body: data })),
|
|
745
|
+
delete: (id) => wrap(() => this.clients.blog.delete(`/blog/tokens/${id}`))
|
|
746
|
+
}
|
|
747
|
+
};
|
|
748
|
+
this.media = {
|
|
749
|
+
profiles: {
|
|
750
|
+
list: () => wrap(async () => {
|
|
751
|
+
const res = await this.clients.media.get("/profiles");
|
|
752
|
+
return res.profiles;
|
|
753
|
+
}),
|
|
754
|
+
create: (data) => wrap(() => this.clients.media.post("/profiles", { body: data })),
|
|
755
|
+
get: (id) => wrap(() => this.clients.media.get(`/profiles/${id}`)),
|
|
756
|
+
update: (id, data) => wrap(() => this.clients.media.patch(`/profiles/${id}`, { body: data })),
|
|
757
|
+
delete: (id) => wrap(() => this.clients.media.delete(`/profiles/${id}`)),
|
|
758
|
+
filters: {
|
|
759
|
+
list: (profile_id) => wrap(async () => {
|
|
760
|
+
const res = await this.clients.media.get(`/profiles/${profile_id}/filters`);
|
|
761
|
+
return res.filters;
|
|
762
|
+
}),
|
|
763
|
+
add: (profile_id, data) => wrap(() => this.clients.media.post(`/profiles/${profile_id}/filters`, { body: data })),
|
|
764
|
+
remove: (profile_id, filter_id) => wrap(() => this.clients.media.delete(`/profiles/${profile_id}/filters/${filter_id}`))
|
|
765
|
+
},
|
|
766
|
+
timeline: (slug, params) => wrap(() => {
|
|
767
|
+
const query = {};
|
|
768
|
+
if (params?.limit) query.limit = String(params.limit);
|
|
769
|
+
if (params?.before) query.before = params.before;
|
|
770
|
+
return this.clients.media.get(`/profiles/${slug}/timeline`, Object.keys(query).length ? { query } : {});
|
|
771
|
+
})
|
|
772
|
+
},
|
|
773
|
+
connections: {
|
|
774
|
+
list: (profile_id, options) => wrap(async () => {
|
|
775
|
+
const query = { profile_id };
|
|
776
|
+
if (options?.include_settings) query.include_settings = "true";
|
|
777
|
+
const res = await this.clients.media.get("/connections", { query });
|
|
778
|
+
return res.accounts;
|
|
779
|
+
}),
|
|
780
|
+
create: (data) => wrap(() => this.clients.media.post("/connections", { body: data })),
|
|
781
|
+
delete: (account_id) => wrap(() => this.clients.media.delete(`/connections/${account_id}`)),
|
|
782
|
+
refresh: (account_id) => wrap(() => this.clients.media.post(`/connections/${account_id}/refresh`)),
|
|
783
|
+
refreshAll: () => wrap(() => this.clients.media.post("/connections/refresh-all")),
|
|
784
|
+
updateStatus: (account_id, is_active) => wrap(() => this.clients.media.patch(`/connections/${account_id}`, { body: { is_active } })),
|
|
785
|
+
settings: {
|
|
786
|
+
get: (account_id) => wrap(() => this.clients.media.get(`/connections/${account_id}/settings`)),
|
|
787
|
+
update: (account_id, settings) => wrap(() => this.clients.media.put(`/connections/${account_id}/settings`, { body: { settings } }))
|
|
788
|
+
},
|
|
789
|
+
repos: (account_id) => wrap(async () => {
|
|
790
|
+
const res = await this.clients.media.get(`/connections/${account_id}/repos`);
|
|
791
|
+
return res.repos;
|
|
792
|
+
}),
|
|
793
|
+
subreddits: (account_id) => wrap(async () => {
|
|
794
|
+
const res = await this.clients.media.get(`/connections/${account_id}/subreddits`);
|
|
795
|
+
return res.subreddits;
|
|
796
|
+
})
|
|
797
|
+
},
|
|
798
|
+
credentials: {
|
|
799
|
+
check: (platform, profile_id) => wrap(() => this.clients.media.get(`/credentials/${platform}`, { query: { profile_id } })),
|
|
800
|
+
save: (platform, data) => wrap(() => this.clients.media.post(`/credentials/${platform}`, { body: data })),
|
|
801
|
+
delete: (platform, profile_id) => wrap(() => this.clients.media.delete(`/credentials/${platform}`, { query: { profile_id } }))
|
|
802
|
+
},
|
|
803
|
+
timeline: {
|
|
804
|
+
get: (user_id, params) => wrap(() => {
|
|
805
|
+
const query = {};
|
|
806
|
+
if (params?.from) query.from = params.from;
|
|
807
|
+
if (params?.to) query.to = params.to;
|
|
808
|
+
return this.clients.media.get(`/timeline/${user_id}`, Object.keys(query).length ? { query } : {});
|
|
809
|
+
}),
|
|
810
|
+
getRaw: (user_id, platform, account_id) => wrap(() => this.clients.media.get(`/timeline/${user_id}/raw/${platform}`, { query: { account_id } }))
|
|
811
|
+
}
|
|
812
|
+
};
|
|
813
|
+
/**
|
|
814
|
+
* User namespace with Result-wrapped operations
|
|
815
|
+
*/
|
|
816
|
+
this.user = {
|
|
817
|
+
/**
|
|
818
|
+
* Get user activity history
|
|
819
|
+
*/
|
|
820
|
+
history: () => wrap(() => this.clients.auth.get("/user/history")),
|
|
821
|
+
/**
|
|
822
|
+
* Update user preferences
|
|
823
|
+
*/
|
|
824
|
+
preferences: (data) => wrap(() => this.clients.auth.patch("/user/preferences", { body: data }))
|
|
825
|
+
};
|
|
826
|
+
const base_url = options.base_url || "http://localhost:4321/api/v1";
|
|
827
|
+
this._api_key = options.api_key ?? "";
|
|
828
|
+
this._auth_mode = options.auth_mode ?? (options.api_key?.startsWith("jwt:") ? "session" : options.api_key ? "key" : "cookie");
|
|
829
|
+
const clientOptions = {
|
|
830
|
+
base_url,
|
|
831
|
+
api_key: options.api_key,
|
|
832
|
+
max_history_size: options.max_history_size,
|
|
833
|
+
auth_mode: this._auth_mode,
|
|
834
|
+
credentials: options.credentials,
|
|
835
|
+
default_headers: options.default_headers,
|
|
836
|
+
custom_fetch: options.custom_fetch
|
|
837
|
+
};
|
|
838
|
+
const auth_base_url = base_url.replace(/\/v1\/?$/, "");
|
|
839
|
+
this.clients = {
|
|
840
|
+
auth: new ApiClient({ ...clientOptions, category: "auth" }),
|
|
841
|
+
auth_root: new ApiClient({ ...clientOptions, base_url: auth_base_url, category: "auth" }),
|
|
842
|
+
projects: new ApiClient({ ...clientOptions, category: "projects" }),
|
|
843
|
+
tasks: new ApiClient({ ...clientOptions, category: "tasks" }),
|
|
844
|
+
milestones: new ApiClient({ ...clientOptions, category: "milestones" }),
|
|
845
|
+
goals: new ApiClient({ ...clientOptions, category: "goals" }),
|
|
846
|
+
github: new ApiClient({ ...clientOptions, category: "github" }),
|
|
847
|
+
tags: new ApiClient({ ...clientOptions, category: "tags" }),
|
|
848
|
+
blog: new ApiClient({ ...clientOptions, category: "blog" }),
|
|
849
|
+
media: new ApiClient({ ...clientOptions, category: "media" })
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
/**
|
|
853
|
+
* Get request history for debugging
|
|
854
|
+
*/
|
|
855
|
+
history() {
|
|
856
|
+
return this.clients.projects.history();
|
|
857
|
+
}
|
|
858
|
+
/**
|
|
859
|
+
* Get the API key
|
|
860
|
+
*/
|
|
861
|
+
getApiKey() {
|
|
862
|
+
return this._api_key;
|
|
863
|
+
}
|
|
864
|
+
/**
|
|
865
|
+
* Get the authentication mode
|
|
866
|
+
*/
|
|
867
|
+
getAuthMode() {
|
|
868
|
+
return this._auth_mode;
|
|
869
|
+
}
|
|
870
|
+
};
|
|
871
|
+
|
|
872
|
+
// src/tools.ts
|
|
873
|
+
import { z } from "zod";
|
|
874
|
+
function unwrap(result) {
|
|
875
|
+
if (!result.ok) throw new Error(result.error?.message ?? "Unknown error");
|
|
876
|
+
return result.value;
|
|
877
|
+
}
|
|
878
|
+
var project_filters = z.object({
|
|
879
|
+
private: z.boolean().optional().describe("Include private projects (default: true)")
|
|
880
|
+
});
|
|
881
|
+
var project_by_id_or_name = z.object({
|
|
882
|
+
id: z.string().optional().describe("Project ID"),
|
|
883
|
+
name: z.string().optional().describe("Project name")
|
|
884
|
+
}).refine((data) => data.id || data.name, {
|
|
885
|
+
message: "Either 'id' or 'name' must be provided"
|
|
886
|
+
});
|
|
887
|
+
var task_filters = z.object({
|
|
888
|
+
project_id: z.string().optional().describe("Filter by project ID"),
|
|
889
|
+
tag_id: z.string().optional().describe("Filter by tag ID")
|
|
890
|
+
});
|
|
891
|
+
var task_by_id = z.object({
|
|
892
|
+
id: z.string().describe("Task ID")
|
|
893
|
+
});
|
|
894
|
+
var milestone_filters = z.object({
|
|
895
|
+
project_id: z.string().optional().describe("Filter by project ID")
|
|
896
|
+
});
|
|
897
|
+
var milestone_by_id = z.object({
|
|
898
|
+
id: z.string().describe("Milestone ID")
|
|
899
|
+
});
|
|
900
|
+
var goal_by_id = z.object({
|
|
901
|
+
id: z.string().describe("Goal ID")
|
|
902
|
+
});
|
|
903
|
+
var github_branches = z.object({
|
|
904
|
+
owner: z.string().describe("Repository owner"),
|
|
905
|
+
repo: z.string().describe("Repository name")
|
|
906
|
+
});
|
|
907
|
+
var tools = {
|
|
908
|
+
// Projects
|
|
909
|
+
devpad_projects_list: {
|
|
910
|
+
name: "devpad_projects_list",
|
|
911
|
+
description: "List all projects (or only public ones)",
|
|
912
|
+
inputSchema: project_filters,
|
|
913
|
+
execute: async (client, input) => unwrap(await client.projects.list(input))
|
|
914
|
+
},
|
|
915
|
+
devpad_projects_get: {
|
|
916
|
+
name: "devpad_projects_get",
|
|
917
|
+
description: "Get project by ID or name",
|
|
918
|
+
inputSchema: project_by_id_or_name,
|
|
919
|
+
execute: async (client, input) => unwrap(input.id ? await client.projects.getById(input.id) : await client.projects.getByName(input.name))
|
|
920
|
+
},
|
|
921
|
+
devpad_projects_upsert: {
|
|
922
|
+
name: "devpad_projects_upsert",
|
|
923
|
+
description: "Create or update a project (set deleted=true to delete)",
|
|
924
|
+
inputSchema: upsert_project,
|
|
925
|
+
execute: async (client, input) => unwrap(await client.projects.upsert(input))
|
|
926
|
+
},
|
|
927
|
+
devpad_projects_config_save: {
|
|
928
|
+
name: "devpad_projects_config_save",
|
|
929
|
+
description: "Save project configuration",
|
|
930
|
+
inputSchema: save_config_request,
|
|
931
|
+
execute: async (client, input) => {
|
|
932
|
+
unwrap(await client.projects.config.save(input));
|
|
933
|
+
return { success: true };
|
|
934
|
+
}
|
|
935
|
+
},
|
|
936
|
+
// Tasks
|
|
937
|
+
devpad_tasks_list: {
|
|
938
|
+
name: "devpad_tasks_list",
|
|
939
|
+
description: "List tasks, optionally filtered by project or tag",
|
|
940
|
+
inputSchema: task_filters,
|
|
941
|
+
execute: async (client, input) => unwrap(await client.tasks.list(input))
|
|
942
|
+
},
|
|
943
|
+
devpad_tasks_get: {
|
|
944
|
+
name: "devpad_tasks_get",
|
|
945
|
+
description: "Get task by ID",
|
|
946
|
+
inputSchema: task_by_id,
|
|
947
|
+
execute: async (client, input) => unwrap(await client.tasks.find(input.id))
|
|
948
|
+
},
|
|
949
|
+
devpad_tasks_upsert: {
|
|
950
|
+
name: "devpad_tasks_upsert",
|
|
951
|
+
description: "Create or update a task (set deleted=true to delete)",
|
|
952
|
+
inputSchema: upsert_todo,
|
|
953
|
+
execute: async (client, input) => unwrap(await client.tasks.upsert(input))
|
|
954
|
+
},
|
|
955
|
+
devpad_tasks_save_tags: {
|
|
956
|
+
name: "devpad_tasks_save_tags",
|
|
957
|
+
description: "Save tags for tasks",
|
|
958
|
+
inputSchema: save_tags_request,
|
|
959
|
+
execute: async (client, input) => {
|
|
960
|
+
unwrap(await client.tasks.saveTags(input));
|
|
961
|
+
return { success: true };
|
|
962
|
+
}
|
|
963
|
+
},
|
|
964
|
+
// Milestones
|
|
965
|
+
devpad_milestones_list: {
|
|
966
|
+
name: "devpad_milestones_list",
|
|
967
|
+
description: "List milestones for authenticated user or by project",
|
|
968
|
+
inputSchema: milestone_filters,
|
|
969
|
+
execute: async (client, input) => unwrap(input.project_id ? await client.milestones.getByProject(input.project_id) : await client.milestones.list())
|
|
970
|
+
},
|
|
971
|
+
devpad_milestones_get: {
|
|
972
|
+
name: "devpad_milestones_get",
|
|
973
|
+
description: "Get milestone by ID",
|
|
974
|
+
inputSchema: milestone_by_id,
|
|
975
|
+
execute: async (client, input) => unwrap(await client.milestones.find(input.id))
|
|
976
|
+
},
|
|
977
|
+
devpad_milestones_upsert: {
|
|
978
|
+
name: "devpad_milestones_upsert",
|
|
979
|
+
description: "Create or update a milestone",
|
|
980
|
+
inputSchema: upsert_milestone,
|
|
981
|
+
execute: async (client, input) => unwrap(
|
|
982
|
+
input.id ? await client.milestones.update(input.id, {
|
|
983
|
+
name: input.name,
|
|
984
|
+
description: input.description,
|
|
985
|
+
target_time: input.target_time,
|
|
986
|
+
target_version: input.target_version
|
|
987
|
+
}) : await client.milestones.create({
|
|
988
|
+
project_id: input.project_id,
|
|
989
|
+
name: input.name,
|
|
990
|
+
description: input.description,
|
|
991
|
+
target_time: input.target_time,
|
|
992
|
+
target_version: input.target_version
|
|
993
|
+
})
|
|
994
|
+
)
|
|
995
|
+
},
|
|
996
|
+
// Goals
|
|
997
|
+
devpad_goals_list: {
|
|
998
|
+
name: "devpad_goals_list",
|
|
999
|
+
description: "List goals for authenticated user",
|
|
1000
|
+
inputSchema: z.object({}),
|
|
1001
|
+
execute: async (client) => unwrap(await client.goals.list())
|
|
1002
|
+
},
|
|
1003
|
+
devpad_goals_get: {
|
|
1004
|
+
name: "devpad_goals_get",
|
|
1005
|
+
description: "Get goal by ID",
|
|
1006
|
+
inputSchema: goal_by_id,
|
|
1007
|
+
execute: async (client, input) => unwrap(await client.goals.find(input.id))
|
|
1008
|
+
},
|
|
1009
|
+
devpad_goals_upsert: {
|
|
1010
|
+
name: "devpad_goals_upsert",
|
|
1011
|
+
description: "Create or update a goal",
|
|
1012
|
+
inputSchema: upsert_goal,
|
|
1013
|
+
execute: async (client, input) => unwrap(
|
|
1014
|
+
input.id ? await client.goals.update(input.id, {
|
|
1015
|
+
name: input.name,
|
|
1016
|
+
description: input.description,
|
|
1017
|
+
target_time: input.target_time
|
|
1018
|
+
}) : await client.goals.create({
|
|
1019
|
+
milestone_id: input.milestone_id,
|
|
1020
|
+
name: input.name,
|
|
1021
|
+
description: input.description,
|
|
1022
|
+
target_time: input.target_time
|
|
1023
|
+
})
|
|
1024
|
+
)
|
|
1025
|
+
},
|
|
1026
|
+
// Tags
|
|
1027
|
+
devpad_tags_list: {
|
|
1028
|
+
name: "devpad_tags_list",
|
|
1029
|
+
description: "List tags for authenticated user",
|
|
1030
|
+
inputSchema: z.object({}),
|
|
1031
|
+
execute: async (client) => unwrap(await client.tags.list())
|
|
1032
|
+
},
|
|
1033
|
+
// GitHub integration
|
|
1034
|
+
devpad_github_repos: {
|
|
1035
|
+
name: "devpad_github_repos",
|
|
1036
|
+
description: "List GitHub repositories for authenticated user",
|
|
1037
|
+
inputSchema: z.object({}),
|
|
1038
|
+
execute: async (client) => unwrap(await client.github.repos())
|
|
1039
|
+
},
|
|
1040
|
+
devpad_github_branches: {
|
|
1041
|
+
name: "devpad_github_branches",
|
|
1042
|
+
description: "List branches for a GitHub repository",
|
|
1043
|
+
inputSchema: github_branches,
|
|
1044
|
+
execute: async (client, input) => unwrap(await client.github.branches(input.owner, input.repo))
|
|
1045
|
+
},
|
|
1046
|
+
// Additional project operations
|
|
1047
|
+
devpad_projects_delete: {
|
|
1048
|
+
name: "devpad_projects_delete",
|
|
1049
|
+
description: "Delete a project",
|
|
1050
|
+
inputSchema: z.object({
|
|
1051
|
+
id: z.string().describe("Project ID")
|
|
1052
|
+
}),
|
|
1053
|
+
execute: async (client, input) => {
|
|
1054
|
+
const project = unwrap(await client.projects.find(input.id));
|
|
1055
|
+
if (!project) throw new Error(`Project ${input.id} not found`);
|
|
1056
|
+
unwrap(await client.projects.deleteProject(project));
|
|
1057
|
+
return { success: true };
|
|
1058
|
+
}
|
|
1059
|
+
},
|
|
1060
|
+
devpad_projects_history: {
|
|
1061
|
+
name: "devpad_projects_history",
|
|
1062
|
+
description: "Get project history",
|
|
1063
|
+
inputSchema: z.object({
|
|
1064
|
+
project_id: z.string().describe("Project ID")
|
|
1065
|
+
}),
|
|
1066
|
+
execute: async (client, input) => unwrap(await client.projects.history(input.project_id))
|
|
1067
|
+
},
|
|
1068
|
+
devpad_projects_specification: {
|
|
1069
|
+
name: "devpad_projects_specification",
|
|
1070
|
+
description: "Fetch project specification from GitHub",
|
|
1071
|
+
inputSchema: z.object({
|
|
1072
|
+
project_id: z.string().describe("Project ID")
|
|
1073
|
+
}),
|
|
1074
|
+
execute: async (client, input) => unwrap(await client.projects.specification(input.project_id))
|
|
1075
|
+
},
|
|
1076
|
+
devpad_projects_config_load: {
|
|
1077
|
+
name: "devpad_projects_config_load",
|
|
1078
|
+
description: "Load project configuration",
|
|
1079
|
+
inputSchema: z.object({
|
|
1080
|
+
project_id: z.string().describe("Project ID")
|
|
1081
|
+
}),
|
|
1082
|
+
execute: async (client, input) => unwrap(await client.projects.config.load(input.project_id))
|
|
1083
|
+
},
|
|
1084
|
+
// Additional milestone operations
|
|
1085
|
+
devpad_milestones_delete: {
|
|
1086
|
+
name: "devpad_milestones_delete",
|
|
1087
|
+
description: "Delete a milestone",
|
|
1088
|
+
inputSchema: z.object({
|
|
1089
|
+
id: z.string().describe("Milestone ID")
|
|
1090
|
+
}),
|
|
1091
|
+
execute: async (client, input) => unwrap(await client.milestones.delete(input.id))
|
|
1092
|
+
},
|
|
1093
|
+
devpad_milestones_goals: {
|
|
1094
|
+
name: "devpad_milestones_goals",
|
|
1095
|
+
description: "Get goals for a milestone",
|
|
1096
|
+
inputSchema: z.object({
|
|
1097
|
+
id: z.string().describe("Milestone ID")
|
|
1098
|
+
}),
|
|
1099
|
+
execute: async (client, input) => unwrap(await client.milestones.goals(input.id))
|
|
1100
|
+
},
|
|
1101
|
+
// Additional goal operations
|
|
1102
|
+
devpad_goals_delete: {
|
|
1103
|
+
name: "devpad_goals_delete",
|
|
1104
|
+
description: "Delete a goal",
|
|
1105
|
+
inputSchema: z.object({
|
|
1106
|
+
id: z.string().describe("Goal ID")
|
|
1107
|
+
}),
|
|
1108
|
+
execute: async (client, input) => unwrap(await client.goals.delete(input.id))
|
|
1109
|
+
},
|
|
1110
|
+
// Additional task operations
|
|
1111
|
+
devpad_tasks_delete: {
|
|
1112
|
+
name: "devpad_tasks_delete",
|
|
1113
|
+
description: "Delete a task",
|
|
1114
|
+
inputSchema: z.object({
|
|
1115
|
+
id: z.string().describe("Task ID")
|
|
1116
|
+
}),
|
|
1117
|
+
execute: async (client, input) => {
|
|
1118
|
+
const task = unwrap(await client.tasks.find(input.id));
|
|
1119
|
+
if (!task) throw new Error(`Task ${input.id} not found`);
|
|
1120
|
+
unwrap(await client.tasks.deleteTask(task));
|
|
1121
|
+
return { success: true };
|
|
1122
|
+
}
|
|
1123
|
+
},
|
|
1124
|
+
devpad_tasks_history: {
|
|
1125
|
+
name: "devpad_tasks_history",
|
|
1126
|
+
description: "Get task history",
|
|
1127
|
+
inputSchema: z.object({
|
|
1128
|
+
task_id: z.string().describe("Task ID")
|
|
1129
|
+
}),
|
|
1130
|
+
execute: async (client, input) => unwrap(await client.tasks.history.get(input.task_id))
|
|
1131
|
+
},
|
|
1132
|
+
// User operations
|
|
1133
|
+
devpad_user_history: {
|
|
1134
|
+
name: "devpad_user_history",
|
|
1135
|
+
description: "Get user activity history",
|
|
1136
|
+
inputSchema: z.object({}),
|
|
1137
|
+
execute: async (client) => unwrap(await client.user.history())
|
|
1138
|
+
},
|
|
1139
|
+
devpad_user_preferences: {
|
|
1140
|
+
name: "devpad_user_preferences",
|
|
1141
|
+
description: "Update user preferences",
|
|
1142
|
+
inputSchema: z.object({
|
|
1143
|
+
id: z.string().describe("User ID"),
|
|
1144
|
+
task_view: z.enum(["list", "grid"]).describe("Task view preference")
|
|
1145
|
+
}),
|
|
1146
|
+
execute: async (client, input) => unwrap(await client.user.preferences(input))
|
|
1147
|
+
},
|
|
1148
|
+
devpad_blog_posts_list: {
|
|
1149
|
+
name: "devpad_blog_posts_list",
|
|
1150
|
+
description: "List blog posts with optional filters",
|
|
1151
|
+
inputSchema: z.object({
|
|
1152
|
+
category: z.string().optional().describe("Filter by category"),
|
|
1153
|
+
tag: z.string().optional().describe("Filter by tag"),
|
|
1154
|
+
project: z.string().optional().describe("Filter by project ID"),
|
|
1155
|
+
status: z.enum(["draft", "published"]).optional().describe("Filter by status"),
|
|
1156
|
+
archived: z.boolean().optional().describe("Filter by archived state"),
|
|
1157
|
+
limit: z.number().optional().describe("Max posts to return"),
|
|
1158
|
+
offset: z.number().optional().describe("Offset for pagination"),
|
|
1159
|
+
sort: z.string().optional().describe("Sort order")
|
|
1160
|
+
}),
|
|
1161
|
+
execute: async (client, input) => unwrap(await client.blog.posts.list(input))
|
|
1162
|
+
},
|
|
1163
|
+
devpad_blog_posts_get: {
|
|
1164
|
+
name: "devpad_blog_posts_get",
|
|
1165
|
+
description: "Get a blog post by slug",
|
|
1166
|
+
inputSchema: z.object({
|
|
1167
|
+
slug: z.string().describe("Post slug")
|
|
1168
|
+
}),
|
|
1169
|
+
execute: async (client, input) => unwrap(await client.blog.posts.getBySlug(input.slug))
|
|
1170
|
+
},
|
|
1171
|
+
devpad_blog_posts_create: {
|
|
1172
|
+
name: "devpad_blog_posts_create",
|
|
1173
|
+
description: "Create a new blog post",
|
|
1174
|
+
inputSchema: z.object({
|
|
1175
|
+
title: z.string().describe("Post title"),
|
|
1176
|
+
content: z.string().describe("Post content"),
|
|
1177
|
+
format: z.enum(["markdown", "html"]).describe("Content format"),
|
|
1178
|
+
slug: z.string().optional().describe("Custom slug"),
|
|
1179
|
+
category: z.string().optional().describe("Category name"),
|
|
1180
|
+
tags: z.array(z.string()).optional().describe("Tag names"),
|
|
1181
|
+
description: z.string().optional().describe("Post description"),
|
|
1182
|
+
publish_at: z.string().optional().describe("Scheduled publish date (ISO string)"),
|
|
1183
|
+
project_ids: z.array(z.string()).optional().describe("Associated project IDs"),
|
|
1184
|
+
archived: z.boolean().optional().describe("Whether post is archived")
|
|
1185
|
+
}),
|
|
1186
|
+
execute: async (client, input) => unwrap(await client.blog.posts.create(input))
|
|
1187
|
+
},
|
|
1188
|
+
devpad_blog_posts_update: {
|
|
1189
|
+
name: "devpad_blog_posts_update",
|
|
1190
|
+
description: "Update a blog post by UUID",
|
|
1191
|
+
inputSchema: z.object({
|
|
1192
|
+
uuid: z.string().describe("Post UUID"),
|
|
1193
|
+
title: z.string().optional().describe("Post title"),
|
|
1194
|
+
content: z.string().optional().describe("Post content"),
|
|
1195
|
+
format: z.enum(["markdown", "html"]).optional().describe("Content format"),
|
|
1196
|
+
slug: z.string().optional().describe("Custom slug"),
|
|
1197
|
+
category: z.string().optional().describe("Category name"),
|
|
1198
|
+
tags: z.array(z.string()).optional().describe("Tag names"),
|
|
1199
|
+
description: z.string().optional().describe("Post description"),
|
|
1200
|
+
publish_at: z.string().optional().describe("Scheduled publish date (ISO string)"),
|
|
1201
|
+
project_ids: z.array(z.string()).optional().describe("Associated project IDs"),
|
|
1202
|
+
archived: z.boolean().optional().describe("Whether post is archived")
|
|
1203
|
+
}),
|
|
1204
|
+
execute: async (client, input) => {
|
|
1205
|
+
const { uuid, ...data } = input;
|
|
1206
|
+
return unwrap(await client.blog.posts.update(uuid, data));
|
|
1207
|
+
}
|
|
1208
|
+
},
|
|
1209
|
+
devpad_blog_posts_delete: {
|
|
1210
|
+
name: "devpad_blog_posts_delete",
|
|
1211
|
+
description: "Delete a blog post by UUID",
|
|
1212
|
+
inputSchema: z.object({
|
|
1213
|
+
uuid: z.string().describe("Post UUID")
|
|
1214
|
+
}),
|
|
1215
|
+
execute: async (client, input) => unwrap(await client.blog.posts.delete(input.uuid))
|
|
1216
|
+
},
|
|
1217
|
+
devpad_blog_tags_list: {
|
|
1218
|
+
name: "devpad_blog_tags_list",
|
|
1219
|
+
description: "List all blog tags with post counts",
|
|
1220
|
+
inputSchema: z.object({}),
|
|
1221
|
+
execute: async (client) => unwrap(await client.blog.tags.list())
|
|
1222
|
+
},
|
|
1223
|
+
devpad_blog_categories_tree: {
|
|
1224
|
+
name: "devpad_blog_categories_tree",
|
|
1225
|
+
description: "Get the blog category tree",
|
|
1226
|
+
inputSchema: z.object({}),
|
|
1227
|
+
execute: async (client) => unwrap(await client.blog.categories.tree())
|
|
1228
|
+
},
|
|
1229
|
+
devpad_blog_categories_create: {
|
|
1230
|
+
name: "devpad_blog_categories_create",
|
|
1231
|
+
description: "Create a blog category",
|
|
1232
|
+
inputSchema: z.object({
|
|
1233
|
+
name: z.string().describe("Category name"),
|
|
1234
|
+
parent: z.string().optional().describe("Parent category name")
|
|
1235
|
+
}),
|
|
1236
|
+
execute: async (client, input) => unwrap(await client.blog.categories.create(input))
|
|
1237
|
+
},
|
|
1238
|
+
devpad_blog_tokens_list: {
|
|
1239
|
+
name: "devpad_blog_tokens_list",
|
|
1240
|
+
description: "List blog access tokens",
|
|
1241
|
+
inputSchema: z.object({}),
|
|
1242
|
+
execute: async (client) => unwrap(await client.blog.tokens.list())
|
|
1243
|
+
},
|
|
1244
|
+
devpad_blog_tokens_create: {
|
|
1245
|
+
name: "devpad_blog_tokens_create",
|
|
1246
|
+
description: "Create a blog access token",
|
|
1247
|
+
inputSchema: z.object({
|
|
1248
|
+
name: z.string().describe("Token name"),
|
|
1249
|
+
note: z.string().optional().describe("Optional note")
|
|
1250
|
+
}),
|
|
1251
|
+
execute: async (client, input) => unwrap(await client.blog.tokens.create(input))
|
|
1252
|
+
},
|
|
1253
|
+
devpad_media_profiles_list: {
|
|
1254
|
+
name: "devpad_media_profiles_list",
|
|
1255
|
+
description: "List media profiles",
|
|
1256
|
+
inputSchema: z.object({}),
|
|
1257
|
+
execute: async (client) => unwrap(await client.media.profiles.list())
|
|
1258
|
+
},
|
|
1259
|
+
devpad_media_profiles_create: {
|
|
1260
|
+
name: "devpad_media_profiles_create",
|
|
1261
|
+
description: "Create a media profile",
|
|
1262
|
+
inputSchema: z.object({
|
|
1263
|
+
name: z.string().describe("Profile name"),
|
|
1264
|
+
slug: z.string().describe("Profile slug")
|
|
1265
|
+
}),
|
|
1266
|
+
execute: async (client, input) => unwrap(await client.media.profiles.create(input))
|
|
1267
|
+
},
|
|
1268
|
+
devpad_media_profiles_get: {
|
|
1269
|
+
name: "devpad_media_profiles_get",
|
|
1270
|
+
description: "Get a media profile by ID",
|
|
1271
|
+
inputSchema: z.object({
|
|
1272
|
+
id: z.string().describe("Profile ID")
|
|
1273
|
+
}),
|
|
1274
|
+
execute: async (client, input) => unwrap(await client.media.profiles.get(input.id))
|
|
1275
|
+
},
|
|
1276
|
+
devpad_media_profiles_update: {
|
|
1277
|
+
name: "devpad_media_profiles_update",
|
|
1278
|
+
description: "Update a media profile by ID",
|
|
1279
|
+
inputSchema: z.object({
|
|
1280
|
+
id: z.string().describe("Profile ID"),
|
|
1281
|
+
name: z.string().optional().describe("Profile name"),
|
|
1282
|
+
slug: z.string().optional().describe("Profile slug")
|
|
1283
|
+
}),
|
|
1284
|
+
execute: async (client, input) => {
|
|
1285
|
+
const { id, ...data } = input;
|
|
1286
|
+
return unwrap(await client.media.profiles.update(id, data));
|
|
1287
|
+
}
|
|
1288
|
+
},
|
|
1289
|
+
devpad_media_profiles_delete: {
|
|
1290
|
+
name: "devpad_media_profiles_delete",
|
|
1291
|
+
description: "Delete a media profile by ID",
|
|
1292
|
+
inputSchema: z.object({
|
|
1293
|
+
id: z.string().describe("Profile ID")
|
|
1294
|
+
}),
|
|
1295
|
+
execute: async (client, input) => unwrap(await client.media.profiles.delete(input.id))
|
|
1296
|
+
},
|
|
1297
|
+
devpad_media_connections_list: {
|
|
1298
|
+
name: "devpad_media_connections_list",
|
|
1299
|
+
description: "List connections for a media profile",
|
|
1300
|
+
inputSchema: z.object({
|
|
1301
|
+
profile_id: z.string().describe("Profile ID")
|
|
1302
|
+
}),
|
|
1303
|
+
execute: async (client, input) => unwrap(await client.media.connections.list(input.profile_id))
|
|
1304
|
+
},
|
|
1305
|
+
devpad_media_connections_refresh: {
|
|
1306
|
+
name: "devpad_media_connections_refresh",
|
|
1307
|
+
description: "Refresh a media connection",
|
|
1308
|
+
inputSchema: z.object({
|
|
1309
|
+
account_id: z.string().describe("Account/connection ID")
|
|
1310
|
+
}),
|
|
1311
|
+
execute: async (client, input) => unwrap(await client.media.connections.refresh(input.account_id))
|
|
1312
|
+
},
|
|
1313
|
+
devpad_media_timeline_get: {
|
|
1314
|
+
name: "devpad_media_timeline_get",
|
|
1315
|
+
description: "Get media timeline for a user",
|
|
1316
|
+
inputSchema: z.object({
|
|
1317
|
+
user_id: z.string().describe("User ID"),
|
|
1318
|
+
from: z.string().optional().describe("Start date (ISO string)"),
|
|
1319
|
+
to: z.string().optional().describe("End date (ISO string)")
|
|
1320
|
+
}),
|
|
1321
|
+
execute: async (client, input) => {
|
|
1322
|
+
const { user_id, ...params } = input;
|
|
1323
|
+
return unwrap(await client.media.timeline.get(user_id, params));
|
|
1324
|
+
}
|
|
1325
|
+
}
|
|
1326
|
+
};
|
|
1327
|
+
var toolNames = Object.keys(tools);
|
|
1328
|
+
function getTool(name) {
|
|
1329
|
+
return tools[name];
|
|
1330
|
+
}
|
|
1331
|
+
|
|
1332
|
+
// src/index.ts
|
|
1333
|
+
var src_default = ApiClient2;
|
|
1334
|
+
export {
|
|
1335
|
+
ApiClient2 as ApiClient,
|
|
1336
|
+
src_default as default,
|
|
1337
|
+
err,
|
|
1338
|
+
getTool,
|
|
1339
|
+
getUserFriendlyErrorMessage,
|
|
1340
|
+
ok,
|
|
1341
|
+
parseZodErrors,
|
|
1342
|
+
toolNames,
|
|
1343
|
+
tools,
|
|
1344
|
+
wrap
|
|
1345
|
+
};
|