@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.
@@ -0,0 +1,322 @@
1
+ import { H as HttpClientConfig } from '../http-client-Wr9lXo9_.js';
2
+
3
+ /**
4
+ * Type definitions for Stack0 CDN API
5
+ */
6
+ type AssetStatus = "pending" | "processing" | "ready" | "failed" | "deleted";
7
+ type AssetType = "image" | "video" | "audio" | "document" | "other";
8
+ interface Asset {
9
+ id: string;
10
+ filename: string;
11
+ originalFilename: string;
12
+ mimeType: string;
13
+ size: number;
14
+ type: AssetType;
15
+ s3Key: string;
16
+ cdnUrl: string;
17
+ width: number | null;
18
+ height: number | null;
19
+ duration: number | null;
20
+ status: AssetStatus;
21
+ folder: string | null;
22
+ tags: string[] | null;
23
+ metadata: Record<string, unknown> | null;
24
+ alt: string | null;
25
+ createdAt: Date;
26
+ updatedAt: Date | null;
27
+ }
28
+ interface UploadUrlRequest {
29
+ projectSlug: string;
30
+ filename: string;
31
+ mimeType: string;
32
+ size: number;
33
+ folder?: string;
34
+ metadata?: Record<string, unknown>;
35
+ }
36
+ interface UploadUrlResponse {
37
+ uploadUrl: string;
38
+ assetId: string;
39
+ cdnUrl: string;
40
+ expiresAt: Date;
41
+ }
42
+ interface ConfirmUploadRequest {
43
+ assetId: string;
44
+ }
45
+ interface ConfirmUploadResponse {
46
+ asset: Asset;
47
+ }
48
+ interface GetAssetRequest {
49
+ id: string;
50
+ }
51
+ interface UpdateAssetRequest {
52
+ id: string;
53
+ filename?: string;
54
+ folder?: string;
55
+ tags?: string[];
56
+ alt?: string;
57
+ metadata?: Record<string, unknown>;
58
+ }
59
+ interface DeleteAssetRequest {
60
+ id: string;
61
+ }
62
+ interface DeleteAssetsRequest {
63
+ ids: string[];
64
+ }
65
+ interface DeleteAssetsResponse {
66
+ success: boolean;
67
+ deletedCount: number;
68
+ }
69
+ interface ListAssetsRequest {
70
+ projectSlug: string;
71
+ folder?: string | null;
72
+ type?: AssetType;
73
+ status?: AssetStatus;
74
+ search?: string;
75
+ tags?: string[];
76
+ sortBy?: "createdAt" | "filename" | "size" | "type";
77
+ sortOrder?: "asc" | "desc";
78
+ limit?: number;
79
+ offset?: number;
80
+ }
81
+ interface ListAssetsResponse {
82
+ assets: Asset[];
83
+ total: number;
84
+ hasMore: boolean;
85
+ }
86
+ interface MoveAssetsRequest {
87
+ assetIds: string[];
88
+ folder: string | null;
89
+ }
90
+ interface MoveAssetsResponse {
91
+ success: boolean;
92
+ movedCount: number;
93
+ }
94
+ interface TransformOptions {
95
+ width?: number;
96
+ height?: number;
97
+ fit?: "cover" | "contain" | "fill" | "inside" | "outside";
98
+ format?: "webp" | "jpeg" | "png" | "avif";
99
+ quality?: number;
100
+ }
101
+ interface GetTransformUrlRequest {
102
+ assetId: string;
103
+ options: TransformOptions;
104
+ }
105
+ interface GetTransformUrlResponse {
106
+ url: string;
107
+ originalUrl: string;
108
+ width?: number;
109
+ height?: number;
110
+ format?: string;
111
+ }
112
+ interface FolderTreeNode {
113
+ id: string;
114
+ name: string;
115
+ path: string;
116
+ assetCount: number;
117
+ children: FolderTreeNode[];
118
+ }
119
+ interface GetFolderTreeRequest {
120
+ projectSlug: string;
121
+ maxDepth?: number;
122
+ }
123
+ interface CreateFolderRequest {
124
+ projectSlug: string;
125
+ name: string;
126
+ parentId?: string;
127
+ }
128
+ interface Folder {
129
+ id: string;
130
+ name: string;
131
+ path: string;
132
+ parentId: string | null;
133
+ assetCount: number;
134
+ totalSize: number;
135
+ createdAt: Date;
136
+ updatedAt: Date | null;
137
+ }
138
+
139
+ /**
140
+ * Stack0 CDN Client
141
+ * Upload, manage, and transform assets
142
+ */
143
+
144
+ declare class CDN {
145
+ private http;
146
+ constructor(config: HttpClientConfig);
147
+ /**
148
+ * Generate a presigned URL for uploading a file
149
+ *
150
+ * @example
151
+ * ```typescript
152
+ * const { uploadUrl, assetId } = await cdn.getUploadUrl({
153
+ * projectSlug: 'my-project',
154
+ * filename: 'image.jpg',
155
+ * mimeType: 'image/jpeg',
156
+ * size: 1024 * 1024,
157
+ * });
158
+ *
159
+ * // Upload file to the presigned URL
160
+ * await fetch(uploadUrl, {
161
+ * method: 'PUT',
162
+ * body: file,
163
+ * headers: { 'Content-Type': 'image/jpeg' },
164
+ * });
165
+ *
166
+ * // Confirm the upload
167
+ * const asset = await cdn.confirmUpload(assetId);
168
+ * ```
169
+ */
170
+ getUploadUrl(request: UploadUrlRequest): Promise<UploadUrlResponse>;
171
+ /**
172
+ * Confirm that an upload has completed
173
+ */
174
+ confirmUpload(assetId: string): Promise<Asset>;
175
+ /**
176
+ * Upload a file directly (handles presigned URL flow automatically)
177
+ *
178
+ * @example
179
+ * ```typescript
180
+ * const asset = await cdn.upload({
181
+ * projectSlug: 'my-project',
182
+ * file: fileBuffer,
183
+ * filename: 'image.jpg',
184
+ * mimeType: 'image/jpeg',
185
+ * });
186
+ * ```
187
+ */
188
+ upload(options: {
189
+ projectSlug: string;
190
+ file: Blob | Buffer | ArrayBuffer;
191
+ filename: string;
192
+ mimeType: string;
193
+ folder?: string;
194
+ metadata?: Record<string, unknown>;
195
+ }): Promise<Asset>;
196
+ /**
197
+ * Get an asset by ID
198
+ *
199
+ * @example
200
+ * ```typescript
201
+ * const asset = await cdn.get('asset-id');
202
+ * console.log(asset.cdnUrl);
203
+ * ```
204
+ */
205
+ get(id: string): Promise<Asset>;
206
+ /**
207
+ * Update asset metadata
208
+ *
209
+ * @example
210
+ * ```typescript
211
+ * const asset = await cdn.update({
212
+ * id: 'asset-id',
213
+ * alt: 'A beautiful sunset',
214
+ * tags: ['nature', 'sunset'],
215
+ * });
216
+ * ```
217
+ */
218
+ update(request: UpdateAssetRequest): Promise<Asset>;
219
+ /**
220
+ * Delete an asset
221
+ *
222
+ * @example
223
+ * ```typescript
224
+ * await cdn.delete('asset-id');
225
+ * ```
226
+ */
227
+ delete(id: string): Promise<{
228
+ success: boolean;
229
+ }>;
230
+ /**
231
+ * Delete multiple assets
232
+ *
233
+ * @example
234
+ * ```typescript
235
+ * const result = await cdn.deleteMany(['asset-1', 'asset-2']);
236
+ * console.log(`Deleted ${result.deletedCount} assets`);
237
+ * ```
238
+ */
239
+ deleteMany(ids: string[]): Promise<DeleteAssetsResponse>;
240
+ /**
241
+ * List assets with filters and pagination
242
+ *
243
+ * @example
244
+ * ```typescript
245
+ * const { assets, total, hasMore } = await cdn.list({
246
+ * projectSlug: 'my-project',
247
+ * type: 'image',
248
+ * limit: 20,
249
+ * });
250
+ * ```
251
+ */
252
+ list(request: ListAssetsRequest): Promise<ListAssetsResponse>;
253
+ /**
254
+ * Move assets to a different folder
255
+ *
256
+ * @example
257
+ * ```typescript
258
+ * await cdn.move({
259
+ * assetIds: ['asset-1', 'asset-2'],
260
+ * folder: '/images/archive',
261
+ * });
262
+ * ```
263
+ */
264
+ move(request: MoveAssetsRequest): Promise<MoveAssetsResponse>;
265
+ /**
266
+ * Get a transformed image URL
267
+ *
268
+ * @example
269
+ * ```typescript
270
+ * const { url } = await cdn.getTransformUrl({
271
+ * assetId: 'asset-id',
272
+ * options: {
273
+ * width: 800,
274
+ * height: 600,
275
+ * fit: 'cover',
276
+ * format: 'webp',
277
+ * quality: 80,
278
+ * },
279
+ * });
280
+ * ```
281
+ */
282
+ getTransformUrl(request: GetTransformUrlRequest): Promise<GetTransformUrlResponse>;
283
+ /**
284
+ * Get folder tree for navigation
285
+ *
286
+ * @example
287
+ * ```typescript
288
+ * const tree = await cdn.getFolderTree({
289
+ * projectSlug: 'my-project',
290
+ * maxDepth: 3,
291
+ * });
292
+ * ```
293
+ */
294
+ getFolderTree(request: GetFolderTreeRequest): Promise<FolderTreeNode[]>;
295
+ /**
296
+ * Create a new folder
297
+ *
298
+ * @example
299
+ * ```typescript
300
+ * const folder = await cdn.createFolder({
301
+ * projectSlug: 'my-project',
302
+ * name: 'images',
303
+ * });
304
+ * ```
305
+ */
306
+ createFolder(request: CreateFolderRequest): Promise<Folder>;
307
+ /**
308
+ * Delete a folder
309
+ *
310
+ * @example
311
+ * ```typescript
312
+ * await cdn.deleteFolder('folder-id');
313
+ * ```
314
+ */
315
+ deleteFolder(id: string, deleteContents?: boolean): Promise<{
316
+ success: boolean;
317
+ }>;
318
+ private convertAssetDates;
319
+ private convertFolderDates;
320
+ }
321
+
322
+ export { type Asset, type AssetStatus, type AssetType, CDN, type ConfirmUploadRequest, type ConfirmUploadResponse, type CreateFolderRequest, type DeleteAssetRequest, type DeleteAssetsRequest, type DeleteAssetsResponse, type Folder, type FolderTreeNode, type GetAssetRequest, type GetFolderTreeRequest, type GetTransformUrlRequest, type GetTransformUrlResponse, type ListAssetsRequest, type ListAssetsResponse, type MoveAssetsRequest, type MoveAssetsResponse, type TransformOptions, type UpdateAssetRequest, type UploadUrlRequest, type UploadUrlResponse };
@@ -0,0 +1,347 @@
1
+ 'use strict';
2
+
3
+ // src/lib/http-client.ts
4
+ var HttpClient = class {
5
+ apiKey;
6
+ baseUrl;
7
+ constructor(config) {
8
+ this.apiKey = config.apiKey;
9
+ this.baseUrl = config.baseUrl || "https://api.stack0.com/v1";
10
+ }
11
+ getHeaders() {
12
+ return {
13
+ "Content-Type": "application/json",
14
+ Authorization: `Bearer ${this.apiKey}`
15
+ };
16
+ }
17
+ async request(method, path, body) {
18
+ const url = `${this.baseUrl}${path}`;
19
+ try {
20
+ const response = await fetch(url, {
21
+ method,
22
+ headers: this.getHeaders(),
23
+ body: body ? JSON.stringify(body) : void 0
24
+ });
25
+ if (!response.ok) {
26
+ await this.handleErrorResponse(response);
27
+ }
28
+ const data = await response.json();
29
+ return data;
30
+ } catch (error) {
31
+ if (error instanceof Error && "statusCode" in error) {
32
+ throw error;
33
+ }
34
+ throw this.createError("Network error", error);
35
+ }
36
+ }
37
+ async handleErrorResponse(response) {
38
+ let errorBody;
39
+ try {
40
+ errorBody = await response.json();
41
+ } catch {
42
+ errorBody = { message: response.statusText };
43
+ }
44
+ const error = new Error(errorBody?.message || `HTTP ${response.status}`);
45
+ error.statusCode = response.status;
46
+ error.code = errorBody?.code ?? "";
47
+ error.response = errorBody;
48
+ throw error;
49
+ }
50
+ createError(message, cause) {
51
+ const error = new Error(message);
52
+ error.cause = cause;
53
+ return error;
54
+ }
55
+ async get(path) {
56
+ return this.request("GET", path);
57
+ }
58
+ async post(path, body) {
59
+ return this.request("POST", path, body);
60
+ }
61
+ async put(path, body) {
62
+ return this.request("PUT", path, body);
63
+ }
64
+ async delete(path) {
65
+ return this.request("DELETE", path);
66
+ }
67
+ };
68
+
69
+ // src/cdn/client.ts
70
+ var CDN = class {
71
+ http;
72
+ constructor(config) {
73
+ this.http = new HttpClient(config);
74
+ }
75
+ /**
76
+ * Generate a presigned URL for uploading a file
77
+ *
78
+ * @example
79
+ * ```typescript
80
+ * const { uploadUrl, assetId } = await cdn.getUploadUrl({
81
+ * projectSlug: 'my-project',
82
+ * filename: 'image.jpg',
83
+ * mimeType: 'image/jpeg',
84
+ * size: 1024 * 1024,
85
+ * });
86
+ *
87
+ * // Upload file to the presigned URL
88
+ * await fetch(uploadUrl, {
89
+ * method: 'PUT',
90
+ * body: file,
91
+ * headers: { 'Content-Type': 'image/jpeg' },
92
+ * });
93
+ *
94
+ * // Confirm the upload
95
+ * const asset = await cdn.confirmUpload(assetId);
96
+ * ```
97
+ */
98
+ async getUploadUrl(request) {
99
+ const response = await this.http.post("/cdn/assets/upload-url", request);
100
+ if (typeof response.expiresAt === "string") {
101
+ response.expiresAt = new Date(response.expiresAt);
102
+ }
103
+ return response;
104
+ }
105
+ /**
106
+ * Confirm that an upload has completed
107
+ */
108
+ async confirmUpload(assetId) {
109
+ const response = await this.http.post("/cdn/assets/confirm", { assetId });
110
+ return this.convertAssetDates(response.asset);
111
+ }
112
+ /**
113
+ * Upload a file directly (handles presigned URL flow automatically)
114
+ *
115
+ * @example
116
+ * ```typescript
117
+ * const asset = await cdn.upload({
118
+ * projectSlug: 'my-project',
119
+ * file: fileBuffer,
120
+ * filename: 'image.jpg',
121
+ * mimeType: 'image/jpeg',
122
+ * });
123
+ * ```
124
+ */
125
+ async upload(options) {
126
+ const { projectSlug, file, filename, mimeType, folder, metadata } = options;
127
+ let size;
128
+ if (file instanceof Blob) {
129
+ size = file.size;
130
+ } else if (file instanceof ArrayBuffer) {
131
+ size = file.byteLength;
132
+ } else {
133
+ size = file.length;
134
+ }
135
+ const { uploadUrl, assetId } = await this.getUploadUrl({
136
+ projectSlug,
137
+ filename,
138
+ mimeType,
139
+ size,
140
+ folder,
141
+ metadata
142
+ });
143
+ const uploadResponse = await fetch(uploadUrl, {
144
+ method: "PUT",
145
+ body: file,
146
+ headers: {
147
+ "Content-Type": mimeType
148
+ }
149
+ });
150
+ if (!uploadResponse.ok) {
151
+ throw new Error(`Upload failed: ${uploadResponse.statusText}`);
152
+ }
153
+ return this.confirmUpload(assetId);
154
+ }
155
+ /**
156
+ * Get an asset by ID
157
+ *
158
+ * @example
159
+ * ```typescript
160
+ * const asset = await cdn.get('asset-id');
161
+ * console.log(asset.cdnUrl);
162
+ * ```
163
+ */
164
+ async get(id) {
165
+ const response = await this.http.get(`/cdn/assets/${id}`);
166
+ return this.convertAssetDates(response);
167
+ }
168
+ /**
169
+ * Update asset metadata
170
+ *
171
+ * @example
172
+ * ```typescript
173
+ * const asset = await cdn.update({
174
+ * id: 'asset-id',
175
+ * alt: 'A beautiful sunset',
176
+ * tags: ['nature', 'sunset'],
177
+ * });
178
+ * ```
179
+ */
180
+ async update(request) {
181
+ const { id, ...data } = request;
182
+ const response = await this.http.put(`/cdn/assets/${id}`, data);
183
+ return this.convertAssetDates(response);
184
+ }
185
+ /**
186
+ * Delete an asset
187
+ *
188
+ * @example
189
+ * ```typescript
190
+ * await cdn.delete('asset-id');
191
+ * ```
192
+ */
193
+ async delete(id) {
194
+ return this.http.delete(`/cdn/assets/${id}`);
195
+ }
196
+ /**
197
+ * Delete multiple assets
198
+ *
199
+ * @example
200
+ * ```typescript
201
+ * const result = await cdn.deleteMany(['asset-1', 'asset-2']);
202
+ * console.log(`Deleted ${result.deletedCount} assets`);
203
+ * ```
204
+ */
205
+ async deleteMany(ids) {
206
+ return this.http.post("/cdn/assets/delete-many", { ids });
207
+ }
208
+ /**
209
+ * List assets with filters and pagination
210
+ *
211
+ * @example
212
+ * ```typescript
213
+ * const { assets, total, hasMore } = await cdn.list({
214
+ * projectSlug: 'my-project',
215
+ * type: 'image',
216
+ * limit: 20,
217
+ * });
218
+ * ```
219
+ */
220
+ async list(request) {
221
+ const params = new URLSearchParams();
222
+ params.set("projectSlug", request.projectSlug);
223
+ if (request.folder !== void 0) params.set("folder", request.folder ?? "");
224
+ if (request.type) params.set("type", request.type);
225
+ if (request.status) params.set("status", request.status);
226
+ if (request.search) params.set("search", request.search);
227
+ if (request.tags) params.set("tags", request.tags.join(","));
228
+ if (request.sortBy) params.set("sortBy", request.sortBy);
229
+ if (request.sortOrder) params.set("sortOrder", request.sortOrder);
230
+ if (request.limit) params.set("limit", request.limit.toString());
231
+ if (request.offset) params.set("offset", request.offset.toString());
232
+ const response = await this.http.get(`/cdn/assets?${params.toString()}`);
233
+ return {
234
+ ...response,
235
+ assets: response.assets.map((asset) => this.convertAssetDates(asset))
236
+ };
237
+ }
238
+ /**
239
+ * Move assets to a different folder
240
+ *
241
+ * @example
242
+ * ```typescript
243
+ * await cdn.move({
244
+ * assetIds: ['asset-1', 'asset-2'],
245
+ * folder: '/images/archive',
246
+ * });
247
+ * ```
248
+ */
249
+ async move(request) {
250
+ return this.http.post("/cdn/assets/move", request);
251
+ }
252
+ /**
253
+ * Get a transformed image URL
254
+ *
255
+ * @example
256
+ * ```typescript
257
+ * const { url } = await cdn.getTransformUrl({
258
+ * assetId: 'asset-id',
259
+ * options: {
260
+ * width: 800,
261
+ * height: 600,
262
+ * fit: 'cover',
263
+ * format: 'webp',
264
+ * quality: 80,
265
+ * },
266
+ * });
267
+ * ```
268
+ */
269
+ async getTransformUrl(request) {
270
+ const params = new URLSearchParams();
271
+ params.set("assetId", request.assetId);
272
+ const { options } = request;
273
+ if (options.width) params.set("width", options.width.toString());
274
+ if (options.height) params.set("height", options.height.toString());
275
+ if (options.fit) params.set("fit", options.fit);
276
+ if (options.format) params.set("format", options.format);
277
+ if (options.quality) params.set("quality", options.quality.toString());
278
+ return this.http.get(`/cdn/assets/transform?${params.toString()}`);
279
+ }
280
+ /**
281
+ * Get folder tree for navigation
282
+ *
283
+ * @example
284
+ * ```typescript
285
+ * const tree = await cdn.getFolderTree({
286
+ * projectSlug: 'my-project',
287
+ * maxDepth: 3,
288
+ * });
289
+ * ```
290
+ */
291
+ async getFolderTree(request) {
292
+ const params = new URLSearchParams();
293
+ params.set("projectSlug", request.projectSlug);
294
+ if (request.maxDepth) params.set("maxDepth", request.maxDepth.toString());
295
+ return this.http.get(`/cdn/folders/tree?${params.toString()}`);
296
+ }
297
+ /**
298
+ * Create a new folder
299
+ *
300
+ * @example
301
+ * ```typescript
302
+ * const folder = await cdn.createFolder({
303
+ * projectSlug: 'my-project',
304
+ * name: 'images',
305
+ * });
306
+ * ```
307
+ */
308
+ async createFolder(request) {
309
+ const response = await this.http.post("/cdn/folders", request);
310
+ return this.convertFolderDates(response);
311
+ }
312
+ /**
313
+ * Delete a folder
314
+ *
315
+ * @example
316
+ * ```typescript
317
+ * await cdn.deleteFolder('folder-id');
318
+ * ```
319
+ */
320
+ async deleteFolder(id, deleteContents = false) {
321
+ const params = new URLSearchParams();
322
+ if (deleteContents) params.set("deleteContents", "true");
323
+ return this.http.delete(`/cdn/folders/${id}?${params.toString()}`);
324
+ }
325
+ convertAssetDates(asset) {
326
+ if (typeof asset.createdAt === "string") {
327
+ asset.createdAt = new Date(asset.createdAt);
328
+ }
329
+ if (asset.updatedAt && typeof asset.updatedAt === "string") {
330
+ asset.updatedAt = new Date(asset.updatedAt);
331
+ }
332
+ return asset;
333
+ }
334
+ convertFolderDates(folder) {
335
+ if (typeof folder.createdAt === "string") {
336
+ folder.createdAt = new Date(folder.createdAt);
337
+ }
338
+ if (folder.updatedAt && typeof folder.updatedAt === "string") {
339
+ folder.updatedAt = new Date(folder.updatedAt);
340
+ }
341
+ return folder;
342
+ }
343
+ };
344
+
345
+ exports.CDN = CDN;
346
+ //# sourceMappingURL=index.js.map
347
+ //# sourceMappingURL=index.js.map