@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/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 };