@stack0/sdk 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +388 -0
- package/dist/cdn/index.d.mts +322 -0
- package/dist/cdn/index.d.ts +322 -0
- package/dist/cdn/index.js +347 -0
- package/dist/cdn/index.js.map +1 -0
- package/dist/cdn/index.mjs +345 -0
- package/dist/cdn/index.mjs.map +1 -0
- package/dist/http-client-Wr9lXo9_.d.mts +10 -0
- package/dist/http-client-Wr9lXo9_.d.ts +10 -0
- package/dist/index.d.mts +49 -0
- package/dist/index.d.ts +49 -0
- package/dist/index.js +421 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +414 -0
- package/dist/index.mjs.map +1 -0
- package/dist/mail/index.d.mts +101 -0
- package/dist/mail/index.d.ts +101 -0
- package/dist/mail/index.js +125 -0
- package/dist/mail/index.js.map +1 -0
- package/dist/mail/index.mjs +123 -0
- package/dist/mail/index.mjs.map +1 -0
- package/package.json +58 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,414 @@
|
|
|
1
|
+
// src/lib/http-client.ts
|
|
2
|
+
var HttpClient = class {
|
|
3
|
+
apiKey;
|
|
4
|
+
baseUrl;
|
|
5
|
+
constructor(config) {
|
|
6
|
+
this.apiKey = config.apiKey;
|
|
7
|
+
this.baseUrl = config.baseUrl || "https://api.stack0.com/v1";
|
|
8
|
+
}
|
|
9
|
+
getHeaders() {
|
|
10
|
+
return {
|
|
11
|
+
"Content-Type": "application/json",
|
|
12
|
+
Authorization: `Bearer ${this.apiKey}`
|
|
13
|
+
};
|
|
14
|
+
}
|
|
15
|
+
async request(method, path, body) {
|
|
16
|
+
const url = `${this.baseUrl}${path}`;
|
|
17
|
+
try {
|
|
18
|
+
const response = await fetch(url, {
|
|
19
|
+
method,
|
|
20
|
+
headers: this.getHeaders(),
|
|
21
|
+
body: body ? JSON.stringify(body) : void 0
|
|
22
|
+
});
|
|
23
|
+
if (!response.ok) {
|
|
24
|
+
await this.handleErrorResponse(response);
|
|
25
|
+
}
|
|
26
|
+
const data = await response.json();
|
|
27
|
+
return data;
|
|
28
|
+
} catch (error) {
|
|
29
|
+
if (error instanceof Error && "statusCode" in error) {
|
|
30
|
+
throw error;
|
|
31
|
+
}
|
|
32
|
+
throw this.createError("Network error", error);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
async handleErrorResponse(response) {
|
|
36
|
+
let errorBody;
|
|
37
|
+
try {
|
|
38
|
+
errorBody = await response.json();
|
|
39
|
+
} catch {
|
|
40
|
+
errorBody = { message: response.statusText };
|
|
41
|
+
}
|
|
42
|
+
const error = new Error(errorBody?.message || `HTTP ${response.status}`);
|
|
43
|
+
error.statusCode = response.status;
|
|
44
|
+
error.code = errorBody?.code ?? "";
|
|
45
|
+
error.response = errorBody;
|
|
46
|
+
throw error;
|
|
47
|
+
}
|
|
48
|
+
createError(message, cause) {
|
|
49
|
+
const error = new Error(message);
|
|
50
|
+
error.cause = cause;
|
|
51
|
+
return error;
|
|
52
|
+
}
|
|
53
|
+
async get(path) {
|
|
54
|
+
return this.request("GET", path);
|
|
55
|
+
}
|
|
56
|
+
async post(path, body) {
|
|
57
|
+
return this.request("POST", path, body);
|
|
58
|
+
}
|
|
59
|
+
async put(path, body) {
|
|
60
|
+
return this.request("PUT", path, body);
|
|
61
|
+
}
|
|
62
|
+
async delete(path) {
|
|
63
|
+
return this.request("DELETE", path);
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// src/mail/client.ts
|
|
68
|
+
var Mail = class {
|
|
69
|
+
http;
|
|
70
|
+
constructor(config) {
|
|
71
|
+
this.http = new HttpClient(config);
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Send an email
|
|
75
|
+
*
|
|
76
|
+
* @example
|
|
77
|
+
* ```typescript
|
|
78
|
+
* const result = await mail.send({
|
|
79
|
+
* from: 'noreply@example.com',
|
|
80
|
+
* to: 'user@example.com',
|
|
81
|
+
* subject: 'Hello World',
|
|
82
|
+
* html: '<p>Welcome!</p>',
|
|
83
|
+
* });
|
|
84
|
+
* ```
|
|
85
|
+
*/
|
|
86
|
+
async send(request) {
|
|
87
|
+
const response = await this.http.post("/mail/send", request);
|
|
88
|
+
if (typeof response.createdAt === "string") {
|
|
89
|
+
response.createdAt = new Date(response.createdAt);
|
|
90
|
+
}
|
|
91
|
+
return response;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Get email details by ID
|
|
95
|
+
*
|
|
96
|
+
* @example
|
|
97
|
+
* ```typescript
|
|
98
|
+
* const email = await mail.get('email-id');
|
|
99
|
+
* console.log(email.status); // 'delivered'
|
|
100
|
+
* ```
|
|
101
|
+
*/
|
|
102
|
+
async get(id) {
|
|
103
|
+
const response = await this.http.get(`/mail/${id}`);
|
|
104
|
+
const dateFields = [
|
|
105
|
+
"createdAt",
|
|
106
|
+
"sentAt",
|
|
107
|
+
"deliveredAt",
|
|
108
|
+
"openedAt",
|
|
109
|
+
"clickedAt",
|
|
110
|
+
"bouncedAt"
|
|
111
|
+
];
|
|
112
|
+
for (const field of dateFields) {
|
|
113
|
+
if (response[field] && typeof response[field] === "string") {
|
|
114
|
+
response[field] = new Date(response[field]);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
return response;
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// src/cdn/client.ts
|
|
122
|
+
var CDN = class {
|
|
123
|
+
http;
|
|
124
|
+
constructor(config) {
|
|
125
|
+
this.http = new HttpClient(config);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Generate a presigned URL for uploading a file
|
|
129
|
+
*
|
|
130
|
+
* @example
|
|
131
|
+
* ```typescript
|
|
132
|
+
* const { uploadUrl, assetId } = await cdn.getUploadUrl({
|
|
133
|
+
* projectSlug: 'my-project',
|
|
134
|
+
* filename: 'image.jpg',
|
|
135
|
+
* mimeType: 'image/jpeg',
|
|
136
|
+
* size: 1024 * 1024,
|
|
137
|
+
* });
|
|
138
|
+
*
|
|
139
|
+
* // Upload file to the presigned URL
|
|
140
|
+
* await fetch(uploadUrl, {
|
|
141
|
+
* method: 'PUT',
|
|
142
|
+
* body: file,
|
|
143
|
+
* headers: { 'Content-Type': 'image/jpeg' },
|
|
144
|
+
* });
|
|
145
|
+
*
|
|
146
|
+
* // Confirm the upload
|
|
147
|
+
* const asset = await cdn.confirmUpload(assetId);
|
|
148
|
+
* ```
|
|
149
|
+
*/
|
|
150
|
+
async getUploadUrl(request) {
|
|
151
|
+
const response = await this.http.post("/cdn/assets/upload-url", request);
|
|
152
|
+
if (typeof response.expiresAt === "string") {
|
|
153
|
+
response.expiresAt = new Date(response.expiresAt);
|
|
154
|
+
}
|
|
155
|
+
return response;
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* Confirm that an upload has completed
|
|
159
|
+
*/
|
|
160
|
+
async confirmUpload(assetId) {
|
|
161
|
+
const response = await this.http.post("/cdn/assets/confirm", { assetId });
|
|
162
|
+
return this.convertAssetDates(response.asset);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Upload a file directly (handles presigned URL flow automatically)
|
|
166
|
+
*
|
|
167
|
+
* @example
|
|
168
|
+
* ```typescript
|
|
169
|
+
* const asset = await cdn.upload({
|
|
170
|
+
* projectSlug: 'my-project',
|
|
171
|
+
* file: fileBuffer,
|
|
172
|
+
* filename: 'image.jpg',
|
|
173
|
+
* mimeType: 'image/jpeg',
|
|
174
|
+
* });
|
|
175
|
+
* ```
|
|
176
|
+
*/
|
|
177
|
+
async upload(options) {
|
|
178
|
+
const { projectSlug, file, filename, mimeType, folder, metadata } = options;
|
|
179
|
+
let size;
|
|
180
|
+
if (file instanceof Blob) {
|
|
181
|
+
size = file.size;
|
|
182
|
+
} else if (file instanceof ArrayBuffer) {
|
|
183
|
+
size = file.byteLength;
|
|
184
|
+
} else {
|
|
185
|
+
size = file.length;
|
|
186
|
+
}
|
|
187
|
+
const { uploadUrl, assetId } = await this.getUploadUrl({
|
|
188
|
+
projectSlug,
|
|
189
|
+
filename,
|
|
190
|
+
mimeType,
|
|
191
|
+
size,
|
|
192
|
+
folder,
|
|
193
|
+
metadata
|
|
194
|
+
});
|
|
195
|
+
const uploadResponse = await fetch(uploadUrl, {
|
|
196
|
+
method: "PUT",
|
|
197
|
+
body: file,
|
|
198
|
+
headers: {
|
|
199
|
+
"Content-Type": mimeType
|
|
200
|
+
}
|
|
201
|
+
});
|
|
202
|
+
if (!uploadResponse.ok) {
|
|
203
|
+
throw new Error(`Upload failed: ${uploadResponse.statusText}`);
|
|
204
|
+
}
|
|
205
|
+
return this.confirmUpload(assetId);
|
|
206
|
+
}
|
|
207
|
+
/**
|
|
208
|
+
* Get an asset by ID
|
|
209
|
+
*
|
|
210
|
+
* @example
|
|
211
|
+
* ```typescript
|
|
212
|
+
* const asset = await cdn.get('asset-id');
|
|
213
|
+
* console.log(asset.cdnUrl);
|
|
214
|
+
* ```
|
|
215
|
+
*/
|
|
216
|
+
async get(id) {
|
|
217
|
+
const response = await this.http.get(`/cdn/assets/${id}`);
|
|
218
|
+
return this.convertAssetDates(response);
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Update asset metadata
|
|
222
|
+
*
|
|
223
|
+
* @example
|
|
224
|
+
* ```typescript
|
|
225
|
+
* const asset = await cdn.update({
|
|
226
|
+
* id: 'asset-id',
|
|
227
|
+
* alt: 'A beautiful sunset',
|
|
228
|
+
* tags: ['nature', 'sunset'],
|
|
229
|
+
* });
|
|
230
|
+
* ```
|
|
231
|
+
*/
|
|
232
|
+
async update(request) {
|
|
233
|
+
const { id, ...data } = request;
|
|
234
|
+
const response = await this.http.put(`/cdn/assets/${id}`, data);
|
|
235
|
+
return this.convertAssetDates(response);
|
|
236
|
+
}
|
|
237
|
+
/**
|
|
238
|
+
* Delete an asset
|
|
239
|
+
*
|
|
240
|
+
* @example
|
|
241
|
+
* ```typescript
|
|
242
|
+
* await cdn.delete('asset-id');
|
|
243
|
+
* ```
|
|
244
|
+
*/
|
|
245
|
+
async delete(id) {
|
|
246
|
+
return this.http.delete(`/cdn/assets/${id}`);
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Delete multiple assets
|
|
250
|
+
*
|
|
251
|
+
* @example
|
|
252
|
+
* ```typescript
|
|
253
|
+
* const result = await cdn.deleteMany(['asset-1', 'asset-2']);
|
|
254
|
+
* console.log(`Deleted ${result.deletedCount} assets`);
|
|
255
|
+
* ```
|
|
256
|
+
*/
|
|
257
|
+
async deleteMany(ids) {
|
|
258
|
+
return this.http.post("/cdn/assets/delete-many", { ids });
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* List assets with filters and pagination
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* ```typescript
|
|
265
|
+
* const { assets, total, hasMore } = await cdn.list({
|
|
266
|
+
* projectSlug: 'my-project',
|
|
267
|
+
* type: 'image',
|
|
268
|
+
* limit: 20,
|
|
269
|
+
* });
|
|
270
|
+
* ```
|
|
271
|
+
*/
|
|
272
|
+
async list(request) {
|
|
273
|
+
const params = new URLSearchParams();
|
|
274
|
+
params.set("projectSlug", request.projectSlug);
|
|
275
|
+
if (request.folder !== void 0) params.set("folder", request.folder ?? "");
|
|
276
|
+
if (request.type) params.set("type", request.type);
|
|
277
|
+
if (request.status) params.set("status", request.status);
|
|
278
|
+
if (request.search) params.set("search", request.search);
|
|
279
|
+
if (request.tags) params.set("tags", request.tags.join(","));
|
|
280
|
+
if (request.sortBy) params.set("sortBy", request.sortBy);
|
|
281
|
+
if (request.sortOrder) params.set("sortOrder", request.sortOrder);
|
|
282
|
+
if (request.limit) params.set("limit", request.limit.toString());
|
|
283
|
+
if (request.offset) params.set("offset", request.offset.toString());
|
|
284
|
+
const response = await this.http.get(`/cdn/assets?${params.toString()}`);
|
|
285
|
+
return {
|
|
286
|
+
...response,
|
|
287
|
+
assets: response.assets.map((asset) => this.convertAssetDates(asset))
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
/**
|
|
291
|
+
* Move assets to a different folder
|
|
292
|
+
*
|
|
293
|
+
* @example
|
|
294
|
+
* ```typescript
|
|
295
|
+
* await cdn.move({
|
|
296
|
+
* assetIds: ['asset-1', 'asset-2'],
|
|
297
|
+
* folder: '/images/archive',
|
|
298
|
+
* });
|
|
299
|
+
* ```
|
|
300
|
+
*/
|
|
301
|
+
async move(request) {
|
|
302
|
+
return this.http.post("/cdn/assets/move", request);
|
|
303
|
+
}
|
|
304
|
+
/**
|
|
305
|
+
* Get a transformed image URL
|
|
306
|
+
*
|
|
307
|
+
* @example
|
|
308
|
+
* ```typescript
|
|
309
|
+
* const { url } = await cdn.getTransformUrl({
|
|
310
|
+
* assetId: 'asset-id',
|
|
311
|
+
* options: {
|
|
312
|
+
* width: 800,
|
|
313
|
+
* height: 600,
|
|
314
|
+
* fit: 'cover',
|
|
315
|
+
* format: 'webp',
|
|
316
|
+
* quality: 80,
|
|
317
|
+
* },
|
|
318
|
+
* });
|
|
319
|
+
* ```
|
|
320
|
+
*/
|
|
321
|
+
async getTransformUrl(request) {
|
|
322
|
+
const params = new URLSearchParams();
|
|
323
|
+
params.set("assetId", request.assetId);
|
|
324
|
+
const { options } = request;
|
|
325
|
+
if (options.width) params.set("width", options.width.toString());
|
|
326
|
+
if (options.height) params.set("height", options.height.toString());
|
|
327
|
+
if (options.fit) params.set("fit", options.fit);
|
|
328
|
+
if (options.format) params.set("format", options.format);
|
|
329
|
+
if (options.quality) params.set("quality", options.quality.toString());
|
|
330
|
+
return this.http.get(`/cdn/assets/transform?${params.toString()}`);
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* Get folder tree for navigation
|
|
334
|
+
*
|
|
335
|
+
* @example
|
|
336
|
+
* ```typescript
|
|
337
|
+
* const tree = await cdn.getFolderTree({
|
|
338
|
+
* projectSlug: 'my-project',
|
|
339
|
+
* maxDepth: 3,
|
|
340
|
+
* });
|
|
341
|
+
* ```
|
|
342
|
+
*/
|
|
343
|
+
async getFolderTree(request) {
|
|
344
|
+
const params = new URLSearchParams();
|
|
345
|
+
params.set("projectSlug", request.projectSlug);
|
|
346
|
+
if (request.maxDepth) params.set("maxDepth", request.maxDepth.toString());
|
|
347
|
+
return this.http.get(`/cdn/folders/tree?${params.toString()}`);
|
|
348
|
+
}
|
|
349
|
+
/**
|
|
350
|
+
* Create a new folder
|
|
351
|
+
*
|
|
352
|
+
* @example
|
|
353
|
+
* ```typescript
|
|
354
|
+
* const folder = await cdn.createFolder({
|
|
355
|
+
* projectSlug: 'my-project',
|
|
356
|
+
* name: 'images',
|
|
357
|
+
* });
|
|
358
|
+
* ```
|
|
359
|
+
*/
|
|
360
|
+
async createFolder(request) {
|
|
361
|
+
const response = await this.http.post("/cdn/folders", request);
|
|
362
|
+
return this.convertFolderDates(response);
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Delete a folder
|
|
366
|
+
*
|
|
367
|
+
* @example
|
|
368
|
+
* ```typescript
|
|
369
|
+
* await cdn.deleteFolder('folder-id');
|
|
370
|
+
* ```
|
|
371
|
+
*/
|
|
372
|
+
async deleteFolder(id, deleteContents = false) {
|
|
373
|
+
const params = new URLSearchParams();
|
|
374
|
+
if (deleteContents) params.set("deleteContents", "true");
|
|
375
|
+
return this.http.delete(`/cdn/folders/${id}?${params.toString()}`);
|
|
376
|
+
}
|
|
377
|
+
convertAssetDates(asset) {
|
|
378
|
+
if (typeof asset.createdAt === "string") {
|
|
379
|
+
asset.createdAt = new Date(asset.createdAt);
|
|
380
|
+
}
|
|
381
|
+
if (asset.updatedAt && typeof asset.updatedAt === "string") {
|
|
382
|
+
asset.updatedAt = new Date(asset.updatedAt);
|
|
383
|
+
}
|
|
384
|
+
return asset;
|
|
385
|
+
}
|
|
386
|
+
convertFolderDates(folder) {
|
|
387
|
+
if (typeof folder.createdAt === "string") {
|
|
388
|
+
folder.createdAt = new Date(folder.createdAt);
|
|
389
|
+
}
|
|
390
|
+
if (folder.updatedAt && typeof folder.updatedAt === "string") {
|
|
391
|
+
folder.updatedAt = new Date(folder.updatedAt);
|
|
392
|
+
}
|
|
393
|
+
return folder;
|
|
394
|
+
}
|
|
395
|
+
};
|
|
396
|
+
|
|
397
|
+
// src/index.ts
|
|
398
|
+
var Stack0 = class {
|
|
399
|
+
mail;
|
|
400
|
+
cdn;
|
|
401
|
+
constructor(config) {
|
|
402
|
+
const clientConfig = {
|
|
403
|
+
apiKey: config.apiKey,
|
|
404
|
+
baseUrl: config.baseUrl
|
|
405
|
+
};
|
|
406
|
+
this.mail = new Mail(clientConfig);
|
|
407
|
+
this.cdn = new CDN(clientConfig);
|
|
408
|
+
}
|
|
409
|
+
};
|
|
410
|
+
var src_default = Stack0;
|
|
411
|
+
|
|
412
|
+
export { CDN, Mail, Stack0, src_default as default };
|
|
413
|
+
//# sourceMappingURL=index.mjs.map
|
|
414
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/lib/http-client.ts","../src/mail/client.ts","../src/cdn/client.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * HTTP client for Stack0 API\n * Handles authentication, request/response formatting, and error handling\n */\n\nexport interface HttpClientConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\nexport class HttpClient {\n private apiKey: string;\n private baseUrl: string;\n\n constructor(config: HttpClientConfig) {\n this.apiKey = config.apiKey;\n this.baseUrl = config.baseUrl || \"https://api.stack0.com/v1\";\n }\n\n private getHeaders(): Record<string, string> {\n return {\n \"Content-Type\": \"application/json\",\n Authorization: `Bearer ${this.apiKey}`,\n };\n }\n\n async request<T>(method: string, path: string, body?: unknown): Promise<T> {\n const url = `${this.baseUrl}${path}`;\n\n try {\n const response = await fetch(url, {\n method,\n headers: this.getHeaders(),\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!response.ok) {\n await this.handleErrorResponse(response);\n }\n\n const data = await response.json();\n return data as T;\n } catch (error) {\n if (error instanceof Error && \"statusCode\" in error) {\n throw error; // Re-throw our custom errors\n }\n throw this.createError(\"Network error\", error);\n }\n }\n\n private async handleErrorResponse(response: Response): Promise<never> {\n let errorBody: { message: string } | undefined;\n try {\n errorBody = (await response.json()) as { message: string };\n } catch {\n errorBody = { message: response.statusText };\n }\n\n const error = new Error(errorBody?.message || `HTTP ${response.status}`) as Error & {\n statusCode: number;\n code: string;\n response: unknown;\n };\n error.statusCode = response.status;\n error.code = (errorBody as unknown as { code: string } | undefined)?.code ?? \"\";\n error.response = errorBody;\n throw error;\n }\n\n private createError(message: string, cause?: unknown): Error {\n const error = new Error(message) as Error & { cause: unknown };\n error.cause = cause;\n return error;\n }\n\n async get<T>(path: string): Promise<T> {\n return this.request<T>(\"GET\", path);\n }\n\n async post<T>(path: string, body: unknown): Promise<T> {\n return this.request<T>(\"POST\", path, body);\n }\n\n async put<T>(path: string, body: unknown): Promise<T> {\n return this.request<T>(\"PUT\", path, body);\n }\n\n async delete<T>(path: string): Promise<T> {\n return this.request<T>(\"DELETE\", path);\n }\n}\n","/**\n * Stack0 Mail Client\n * API compatible with Resend for easy migration\n */\n\nimport { HttpClient, type HttpClientConfig } from \"../lib/http-client\";\nimport type { SendEmailRequest, SendEmailResponse, GetEmailResponse } from \"./types\";\n\nexport class Mail {\n private http: HttpClient;\n\n constructor(config: HttpClientConfig) {\n this.http = new HttpClient(config);\n }\n\n /**\n * Send an email\n *\n * @example\n * ```typescript\n * const result = await mail.send({\n * from: 'noreply@example.com',\n * to: 'user@example.com',\n * subject: 'Hello World',\n * html: '<p>Welcome!</p>',\n * });\n * ```\n */\n async send(request: SendEmailRequest): Promise<SendEmailResponse> {\n const response = await this.http.post<SendEmailResponse>(\"/mail/send\", request);\n\n // Convert date strings to Date objects if needed\n if (typeof response.createdAt === \"string\") {\n response.createdAt = new Date(response.createdAt);\n }\n\n return response;\n }\n\n /**\n * Get email details by ID\n *\n * @example\n * ```typescript\n * const email = await mail.get('email-id');\n * console.log(email.status); // 'delivered'\n * ```\n */\n async get(id: string): Promise<GetEmailResponse> {\n const response = await this.http.get<GetEmailResponse>(`/mail/${id}`);\n\n // Convert date strings to Date objects\n const dateFields = [\n \"createdAt\",\n \"sentAt\",\n \"deliveredAt\",\n \"openedAt\",\n \"clickedAt\",\n \"bouncedAt\",\n ] as const;\n\n for (const field of dateFields) {\n if (response[field] && typeof response[field] === \"string\") {\n (response[field] as any) = new Date(response[field] as string);\n }\n }\n\n return response;\n }\n}\n","/**\n * Stack0 CDN Client\n * Upload, manage, and transform assets\n */\n\nimport { HttpClient, type HttpClientConfig } from \"../lib/http-client\";\nimport type {\n Asset,\n UploadUrlRequest,\n UploadUrlResponse,\n ConfirmUploadResponse,\n UpdateAssetRequest,\n DeleteAssetsResponse,\n ListAssetsRequest,\n ListAssetsResponse,\n MoveAssetsRequest,\n MoveAssetsResponse,\n GetTransformUrlRequest,\n GetTransformUrlResponse,\n GetFolderTreeRequest,\n FolderTreeNode,\n CreateFolderRequest,\n Folder,\n} from \"./types\";\n\nexport class CDN {\n private http: HttpClient;\n\n constructor(config: HttpClientConfig) {\n this.http = new HttpClient(config);\n }\n\n /**\n * Generate a presigned URL for uploading a file\n *\n * @example\n * ```typescript\n * const { uploadUrl, assetId } = await cdn.getUploadUrl({\n * projectSlug: 'my-project',\n * filename: 'image.jpg',\n * mimeType: 'image/jpeg',\n * size: 1024 * 1024,\n * });\n *\n * // Upload file to the presigned URL\n * await fetch(uploadUrl, {\n * method: 'PUT',\n * body: file,\n * headers: { 'Content-Type': 'image/jpeg' },\n * });\n *\n * // Confirm the upload\n * const asset = await cdn.confirmUpload(assetId);\n * ```\n */\n async getUploadUrl(request: UploadUrlRequest): Promise<UploadUrlResponse> {\n const response = await this.http.post<UploadUrlResponse>(\"/cdn/assets/upload-url\", request);\n\n if (typeof response.expiresAt === \"string\") {\n response.expiresAt = new Date(response.expiresAt);\n }\n\n return response;\n }\n\n /**\n * Confirm that an upload has completed\n */\n async confirmUpload(assetId: string): Promise<Asset> {\n const response = await this.http.post<ConfirmUploadResponse>(\"/cdn/assets/confirm\", { assetId });\n return this.convertAssetDates(response.asset);\n }\n\n /**\n * Upload a file directly (handles presigned URL flow automatically)\n *\n * @example\n * ```typescript\n * const asset = await cdn.upload({\n * projectSlug: 'my-project',\n * file: fileBuffer,\n * filename: 'image.jpg',\n * mimeType: 'image/jpeg',\n * });\n * ```\n */\n async upload(options: {\n projectSlug: string;\n file: Blob | Buffer | ArrayBuffer;\n filename: string;\n mimeType: string;\n folder?: string;\n metadata?: Record<string, unknown>;\n }): Promise<Asset> {\n const { projectSlug, file, filename, mimeType, folder, metadata } = options;\n\n // Get file size\n let size: number;\n if (file instanceof Blob) {\n size = file.size;\n } else if (file instanceof ArrayBuffer) {\n size = file.byteLength;\n } else {\n // Buffer\n size = (file as Buffer).length;\n }\n\n // Get presigned URL\n const { uploadUrl, assetId } = await this.getUploadUrl({\n projectSlug,\n filename,\n mimeType,\n size,\n folder,\n metadata,\n });\n\n // Upload file\n const uploadResponse = await fetch(uploadUrl, {\n method: \"PUT\",\n body: file,\n headers: {\n \"Content-Type\": mimeType,\n },\n });\n\n if (!uploadResponse.ok) {\n throw new Error(`Upload failed: ${uploadResponse.statusText}`);\n }\n\n // Confirm upload\n return this.confirmUpload(assetId);\n }\n\n /**\n * Get an asset by ID\n *\n * @example\n * ```typescript\n * const asset = await cdn.get('asset-id');\n * console.log(asset.cdnUrl);\n * ```\n */\n async get(id: string): Promise<Asset> {\n const response = await this.http.get<Asset>(`/cdn/assets/${id}`);\n return this.convertAssetDates(response);\n }\n\n /**\n * Update asset metadata\n *\n * @example\n * ```typescript\n * const asset = await cdn.update({\n * id: 'asset-id',\n * alt: 'A beautiful sunset',\n * tags: ['nature', 'sunset'],\n * });\n * ```\n */\n async update(request: UpdateAssetRequest): Promise<Asset> {\n const { id, ...data } = request;\n const response = await this.http.put<Asset>(`/cdn/assets/${id}`, data);\n return this.convertAssetDates(response);\n }\n\n /**\n * Delete an asset\n *\n * @example\n * ```typescript\n * await cdn.delete('asset-id');\n * ```\n */\n async delete(id: string): Promise<{ success: boolean }> {\n return this.http.delete<{ success: boolean }>(`/cdn/assets/${id}`);\n }\n\n /**\n * Delete multiple assets\n *\n * @example\n * ```typescript\n * const result = await cdn.deleteMany(['asset-1', 'asset-2']);\n * console.log(`Deleted ${result.deletedCount} assets`);\n * ```\n */\n async deleteMany(ids: string[]): Promise<DeleteAssetsResponse> {\n return this.http.post<DeleteAssetsResponse>(\"/cdn/assets/delete-many\", { ids });\n }\n\n /**\n * List assets with filters and pagination\n *\n * @example\n * ```typescript\n * const { assets, total, hasMore } = await cdn.list({\n * projectSlug: 'my-project',\n * type: 'image',\n * limit: 20,\n * });\n * ```\n */\n async list(request: ListAssetsRequest): Promise<ListAssetsResponse> {\n const params = new URLSearchParams();\n\n params.set(\"projectSlug\", request.projectSlug);\n if (request.folder !== undefined) params.set(\"folder\", request.folder ?? \"\");\n if (request.type) params.set(\"type\", request.type);\n if (request.status) params.set(\"status\", request.status);\n if (request.search) params.set(\"search\", request.search);\n if (request.tags) params.set(\"tags\", request.tags.join(\",\"));\n if (request.sortBy) params.set(\"sortBy\", request.sortBy);\n if (request.sortOrder) params.set(\"sortOrder\", request.sortOrder);\n if (request.limit) params.set(\"limit\", request.limit.toString());\n if (request.offset) params.set(\"offset\", request.offset.toString());\n\n const response = await this.http.get<ListAssetsResponse>(`/cdn/assets?${params.toString()}`);\n\n return {\n ...response,\n assets: response.assets.map((asset) => this.convertAssetDates(asset)),\n };\n }\n\n /**\n * Move assets to a different folder\n *\n * @example\n * ```typescript\n * await cdn.move({\n * assetIds: ['asset-1', 'asset-2'],\n * folder: '/images/archive',\n * });\n * ```\n */\n async move(request: MoveAssetsRequest): Promise<MoveAssetsResponse> {\n return this.http.post<MoveAssetsResponse>(\"/cdn/assets/move\", request);\n }\n\n /**\n * Get a transformed image URL\n *\n * @example\n * ```typescript\n * const { url } = await cdn.getTransformUrl({\n * assetId: 'asset-id',\n * options: {\n * width: 800,\n * height: 600,\n * fit: 'cover',\n * format: 'webp',\n * quality: 80,\n * },\n * });\n * ```\n */\n async getTransformUrl(request: GetTransformUrlRequest): Promise<GetTransformUrlResponse> {\n const params = new URLSearchParams();\n params.set(\"assetId\", request.assetId);\n\n const { options } = request;\n if (options.width) params.set(\"width\", options.width.toString());\n if (options.height) params.set(\"height\", options.height.toString());\n if (options.fit) params.set(\"fit\", options.fit);\n if (options.format) params.set(\"format\", options.format);\n if (options.quality) params.set(\"quality\", options.quality.toString());\n\n return this.http.get<GetTransformUrlResponse>(`/cdn/assets/transform?${params.toString()}`);\n }\n\n /**\n * Get folder tree for navigation\n *\n * @example\n * ```typescript\n * const tree = await cdn.getFolderTree({\n * projectSlug: 'my-project',\n * maxDepth: 3,\n * });\n * ```\n */\n async getFolderTree(request: GetFolderTreeRequest): Promise<FolderTreeNode[]> {\n const params = new URLSearchParams();\n params.set(\"projectSlug\", request.projectSlug);\n if (request.maxDepth) params.set(\"maxDepth\", request.maxDepth.toString());\n\n return this.http.get<FolderTreeNode[]>(`/cdn/folders/tree?${params.toString()}`);\n }\n\n /**\n * Create a new folder\n *\n * @example\n * ```typescript\n * const folder = await cdn.createFolder({\n * projectSlug: 'my-project',\n * name: 'images',\n * });\n * ```\n */\n async createFolder(request: CreateFolderRequest): Promise<Folder> {\n const response = await this.http.post<Folder>(\"/cdn/folders\", request);\n return this.convertFolderDates(response);\n }\n\n /**\n * Delete a folder\n *\n * @example\n * ```typescript\n * await cdn.deleteFolder('folder-id');\n * ```\n */\n async deleteFolder(id: string, deleteContents = false): Promise<{ success: boolean }> {\n const params = new URLSearchParams();\n if (deleteContents) params.set(\"deleteContents\", \"true\");\n\n return this.http.delete<{ success: boolean }>(`/cdn/folders/${id}?${params.toString()}`);\n }\n\n private convertAssetDates(asset: Asset): Asset {\n if (typeof asset.createdAt === \"string\") {\n asset.createdAt = new Date(asset.createdAt);\n }\n if (asset.updatedAt && typeof asset.updatedAt === \"string\") {\n asset.updatedAt = new Date(asset.updatedAt);\n }\n return asset;\n }\n\n private convertFolderDates(folder: Folder): Folder {\n if (typeof folder.createdAt === \"string\") {\n folder.createdAt = new Date(folder.createdAt);\n }\n if (folder.updatedAt && typeof folder.updatedAt === \"string\") {\n folder.updatedAt = new Date(folder.updatedAt);\n }\n return folder;\n }\n}\n","/**\n * Stack0 SDK\n * Official SDK for Stack0 services\n *\n * @example\n * ```typescript\n * import { Stack0 } from '@stack0/sdk';\n *\n * const stack0 = new Stack0({ apiKey: 'stack0_...' });\n *\n * // Send an email\n * await stack0.mail.send({\n * from: 'noreply@example.com',\n * to: 'user@example.com',\n * subject: 'Hello',\n * html: '<p>World</p>',\n * });\n *\n * // Upload a file to CDN\n * const asset = await stack0.cdn.upload({\n * projectSlug: 'my-project',\n * file: fileBuffer,\n * filename: 'image.jpg',\n * mimeType: 'image/jpeg',\n * });\n * ```\n */\n\nimport { Mail } from \"./mail/client\";\nimport { CDN } from \"./cdn/client\";\nimport type { HttpClientConfig } from \"./lib/http-client\";\n\nexport interface Stack0Config extends HttpClientConfig {\n apiKey: string;\n baseUrl?: string;\n}\n\n/**\n * Main Stack0 SDK class\n * Provides access to all Stack0 services\n */\nexport class Stack0 {\n public mail: Mail;\n public cdn: CDN;\n\n constructor(config: Stack0Config) {\n const clientConfig = {\n apiKey: config.apiKey,\n baseUrl: config.baseUrl,\n };\n\n // Initialize clients\n this.mail = new Mail(clientConfig);\n this.cdn = new CDN(clientConfig);\n }\n}\n\n// Export sub-modules\nexport * from \"./mail\";\nexport * from \"./cdn\";\n\n// Default export\nexport default Stack0;\n"]}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { H as HttpClientConfig } from '../http-client-Wr9lXo9_.mjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Type definitions for Stack0 Mail API
|
|
5
|
+
* Compatible with Resend API for easy migration
|
|
6
|
+
*/
|
|
7
|
+
interface EmailAddress {
|
|
8
|
+
email: string;
|
|
9
|
+
name?: string;
|
|
10
|
+
}
|
|
11
|
+
type EmailRecipient = string | EmailAddress;
|
|
12
|
+
interface Attachment {
|
|
13
|
+
filename: string;
|
|
14
|
+
content: string;
|
|
15
|
+
contentType?: string;
|
|
16
|
+
path?: string;
|
|
17
|
+
}
|
|
18
|
+
interface SendEmailRequest {
|
|
19
|
+
from: EmailRecipient;
|
|
20
|
+
to: EmailRecipient | EmailRecipient[];
|
|
21
|
+
cc?: EmailRecipient | EmailRecipient[];
|
|
22
|
+
bcc?: EmailRecipient | EmailRecipient[];
|
|
23
|
+
replyTo?: EmailRecipient;
|
|
24
|
+
subject: string;
|
|
25
|
+
html?: string;
|
|
26
|
+
text?: string;
|
|
27
|
+
templateId?: string;
|
|
28
|
+
templateVariables?: Record<string, unknown>;
|
|
29
|
+
tags?: string[];
|
|
30
|
+
metadata?: Record<string, unknown>;
|
|
31
|
+
attachments?: Attachment[];
|
|
32
|
+
headers?: Record<string, string>;
|
|
33
|
+
scheduledAt?: Date;
|
|
34
|
+
}
|
|
35
|
+
interface SendEmailResponse {
|
|
36
|
+
id: string;
|
|
37
|
+
from: string;
|
|
38
|
+
to: string;
|
|
39
|
+
subject: string;
|
|
40
|
+
status: string;
|
|
41
|
+
createdAt: Date;
|
|
42
|
+
}
|
|
43
|
+
interface GetEmailResponse {
|
|
44
|
+
id: string;
|
|
45
|
+
from: string;
|
|
46
|
+
to: string;
|
|
47
|
+
subject: string;
|
|
48
|
+
status: "pending" | "sent" | "delivered" | "bounced" | "failed" | "deferred";
|
|
49
|
+
html: string | null;
|
|
50
|
+
text: string | null;
|
|
51
|
+
tags: string[] | null;
|
|
52
|
+
metadata: Record<string, unknown> | null;
|
|
53
|
+
createdAt: Date;
|
|
54
|
+
sentAt: Date | null;
|
|
55
|
+
deliveredAt: Date | null;
|
|
56
|
+
openedAt: Date | null;
|
|
57
|
+
clickedAt: Date | null;
|
|
58
|
+
bouncedAt: Date | null;
|
|
59
|
+
providerMessageId: string | null;
|
|
60
|
+
}
|
|
61
|
+
interface Stack0Error extends Error {
|
|
62
|
+
statusCode?: number;
|
|
63
|
+
code?: string;
|
|
64
|
+
response?: any;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Stack0 Mail Client
|
|
69
|
+
* API compatible with Resend for easy migration
|
|
70
|
+
*/
|
|
71
|
+
|
|
72
|
+
declare class Mail {
|
|
73
|
+
private http;
|
|
74
|
+
constructor(config: HttpClientConfig);
|
|
75
|
+
/**
|
|
76
|
+
* Send an email
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* const result = await mail.send({
|
|
81
|
+
* from: 'noreply@example.com',
|
|
82
|
+
* to: 'user@example.com',
|
|
83
|
+
* subject: 'Hello World',
|
|
84
|
+
* html: '<p>Welcome!</p>',
|
|
85
|
+
* });
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
send(request: SendEmailRequest): Promise<SendEmailResponse>;
|
|
89
|
+
/**
|
|
90
|
+
* Get email details by ID
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* const email = await mail.get('email-id');
|
|
95
|
+
* console.log(email.status); // 'delivered'
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
get(id: string): Promise<GetEmailResponse>;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export { type Attachment, type EmailAddress, type EmailRecipient, type GetEmailResponse, Mail, type SendEmailRequest, type SendEmailResponse, type Stack0Error };
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import { H as HttpClientConfig } from '../http-client-Wr9lXo9_.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Type definitions for Stack0 Mail API
|
|
5
|
+
* Compatible with Resend API for easy migration
|
|
6
|
+
*/
|
|
7
|
+
interface EmailAddress {
|
|
8
|
+
email: string;
|
|
9
|
+
name?: string;
|
|
10
|
+
}
|
|
11
|
+
type EmailRecipient = string | EmailAddress;
|
|
12
|
+
interface Attachment {
|
|
13
|
+
filename: string;
|
|
14
|
+
content: string;
|
|
15
|
+
contentType?: string;
|
|
16
|
+
path?: string;
|
|
17
|
+
}
|
|
18
|
+
interface SendEmailRequest {
|
|
19
|
+
from: EmailRecipient;
|
|
20
|
+
to: EmailRecipient | EmailRecipient[];
|
|
21
|
+
cc?: EmailRecipient | EmailRecipient[];
|
|
22
|
+
bcc?: EmailRecipient | EmailRecipient[];
|
|
23
|
+
replyTo?: EmailRecipient;
|
|
24
|
+
subject: string;
|
|
25
|
+
html?: string;
|
|
26
|
+
text?: string;
|
|
27
|
+
templateId?: string;
|
|
28
|
+
templateVariables?: Record<string, unknown>;
|
|
29
|
+
tags?: string[];
|
|
30
|
+
metadata?: Record<string, unknown>;
|
|
31
|
+
attachments?: Attachment[];
|
|
32
|
+
headers?: Record<string, string>;
|
|
33
|
+
scheduledAt?: Date;
|
|
34
|
+
}
|
|
35
|
+
interface SendEmailResponse {
|
|
36
|
+
id: string;
|
|
37
|
+
from: string;
|
|
38
|
+
to: string;
|
|
39
|
+
subject: string;
|
|
40
|
+
status: string;
|
|
41
|
+
createdAt: Date;
|
|
42
|
+
}
|
|
43
|
+
interface GetEmailResponse {
|
|
44
|
+
id: string;
|
|
45
|
+
from: string;
|
|
46
|
+
to: string;
|
|
47
|
+
subject: string;
|
|
48
|
+
status: "pending" | "sent" | "delivered" | "bounced" | "failed" | "deferred";
|
|
49
|
+
html: string | null;
|
|
50
|
+
text: string | null;
|
|
51
|
+
tags: string[] | null;
|
|
52
|
+
metadata: Record<string, unknown> | null;
|
|
53
|
+
createdAt: Date;
|
|
54
|
+
sentAt: Date | null;
|
|
55
|
+
deliveredAt: Date | null;
|
|
56
|
+
openedAt: Date | null;
|
|
57
|
+
clickedAt: Date | null;
|
|
58
|
+
bouncedAt: Date | null;
|
|
59
|
+
providerMessageId: string | null;
|
|
60
|
+
}
|
|
61
|
+
interface Stack0Error extends Error {
|
|
62
|
+
statusCode?: number;
|
|
63
|
+
code?: string;
|
|
64
|
+
response?: any;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Stack0 Mail Client
|
|
69
|
+
* API compatible with Resend for easy migration
|
|
70
|
+
*/
|
|
71
|
+
|
|
72
|
+
declare class Mail {
|
|
73
|
+
private http;
|
|
74
|
+
constructor(config: HttpClientConfig);
|
|
75
|
+
/**
|
|
76
|
+
* Send an email
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* ```typescript
|
|
80
|
+
* const result = await mail.send({
|
|
81
|
+
* from: 'noreply@example.com',
|
|
82
|
+
* to: 'user@example.com',
|
|
83
|
+
* subject: 'Hello World',
|
|
84
|
+
* html: '<p>Welcome!</p>',
|
|
85
|
+
* });
|
|
86
|
+
* ```
|
|
87
|
+
*/
|
|
88
|
+
send(request: SendEmailRequest): Promise<SendEmailResponse>;
|
|
89
|
+
/**
|
|
90
|
+
* Get email details by ID
|
|
91
|
+
*
|
|
92
|
+
* @example
|
|
93
|
+
* ```typescript
|
|
94
|
+
* const email = await mail.get('email-id');
|
|
95
|
+
* console.log(email.status); // 'delivered'
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
get(id: string): Promise<GetEmailResponse>;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export { type Attachment, type EmailAddress, type EmailRecipient, type GetEmailResponse, Mail, type SendEmailRequest, type SendEmailResponse, type Stack0Error };
|