@wowsql/sdk 3.6.0 → 3.8.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 +1293 -699
- package/dist/auth.d.ts +114 -0
- package/dist/auth.js +246 -1
- package/dist/errors.d.ts +9 -0
- package/dist/errors.js +22 -1
- package/dist/index.d.ts +135 -0
- package/dist/index.js +259 -0
- package/dist/schema.d.ts +165 -13
- package/dist/schema.js +208 -79
- package/dist/storage.d.ts +138 -322
- package/dist/storage.js +181 -270
- package/package.json +1 -1
package/dist/storage.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
/**
|
|
3
|
-
* WowSQL Storage SDK -
|
|
3
|
+
* WowSQL Storage SDK - PostgreSQL-native file storage
|
|
4
4
|
*
|
|
5
|
-
*
|
|
5
|
+
* Files are stored as BYTEA inside each project's `storage` schema.
|
|
6
|
+
* No external S3 dependency — everything lives in PostgreSQL.
|
|
7
|
+
*
|
|
8
|
+
* @version 3.0.0
|
|
6
9
|
* @license MIT
|
|
7
10
|
*/
|
|
8
11
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
@@ -44,359 +47,267 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
44
47
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
45
48
|
exports.WowSQLStorage = exports.StorageLimitExceededError = exports.StorageError = void 0;
|
|
46
49
|
const axios_1 = __importDefault(require("axios"));
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
this.
|
|
53
|
-
this.
|
|
50
|
+
const errors_1 = require("./errors");
|
|
51
|
+
Object.defineProperty(exports, "StorageError", { enumerable: true, get: function () { return errors_1.StorageError; } });
|
|
52
|
+
Object.defineProperty(exports, "StorageLimitExceededError", { enumerable: true, get: function () { return errors_1.StorageLimitExceededError; } });
|
|
53
|
+
class StorageFileImpl {
|
|
54
|
+
constructor(data) {
|
|
55
|
+
this.id = data.id;
|
|
56
|
+
this.bucket_id = data.bucket_id;
|
|
57
|
+
this.name = data.name;
|
|
58
|
+
this.path = data.path;
|
|
59
|
+
this.mime_type = data.mime_type ?? null;
|
|
60
|
+
this.size = data.size ?? 0;
|
|
61
|
+
this.metadata = data.metadata ?? {};
|
|
62
|
+
this.created_at = data.created_at ?? '';
|
|
63
|
+
this.public_url = data.public_url;
|
|
54
64
|
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
this.name = 'StorageLimitExceededError';
|
|
65
|
+
get sizeMb() {
|
|
66
|
+
return this.size / (1024 * 1024);
|
|
67
|
+
}
|
|
68
|
+
get sizeGb() {
|
|
69
|
+
return this.size / (1024 * 1024 * 1024);
|
|
61
70
|
}
|
|
62
71
|
}
|
|
63
|
-
exports.StorageLimitExceededError = StorageLimitExceededError;
|
|
64
72
|
// ==================== Storage Client ====================
|
|
65
73
|
/**
|
|
66
|
-
* WowSQL Storage Client -
|
|
74
|
+
* WowSQL Storage Client — PostgreSQL-native file storage.
|
|
67
75
|
*
|
|
68
|
-
*
|
|
69
|
-
*
|
|
70
|
-
* - Real-time quota checking
|
|
71
|
-
* - File upload/download/delete operations
|
|
72
|
-
* - Presigned URL generation
|
|
73
|
-
* - Storage provisioning and management
|
|
76
|
+
* All files are stored directly in the project's PostgreSQL database
|
|
77
|
+
* inside the `storage` schema (buckets + objects as BYTEA).
|
|
74
78
|
*
|
|
75
79
|
* @example
|
|
76
80
|
* ```typescript
|
|
77
81
|
* const storage = new WowSQLStorage({
|
|
78
|
-
*
|
|
79
|
-
* apiKey: '
|
|
82
|
+
* projectUrl: 'myproject',
|
|
83
|
+
* apiKey: 'wowsql_anon_...'
|
|
80
84
|
* });
|
|
81
85
|
*
|
|
82
|
-
* //
|
|
83
|
-
* const
|
|
84
|
-
* console.log(`Available: ${quota.storage_available_gb.toFixed(2)} GB`);
|
|
86
|
+
* // Create a bucket
|
|
87
|
+
* const bucket = await storage.createBucket('avatars', { public: true });
|
|
85
88
|
*
|
|
86
|
-
* // Upload file
|
|
87
|
-
* const
|
|
88
|
-
* const result = await storage.
|
|
89
|
-
* folder: 'documents'
|
|
90
|
-
* });
|
|
89
|
+
* // Upload a file
|
|
90
|
+
* const file = document.querySelector('input[type="file"]').files[0];
|
|
91
|
+
* const result = await storage.upload('avatars', file, 'users/profile.jpg');
|
|
91
92
|
*
|
|
92
93
|
* // List files
|
|
93
|
-
* const files = await storage.listFiles({ prefix: '
|
|
94
|
+
* const files = await storage.listFiles('avatars', { prefix: 'users/' });
|
|
95
|
+
*
|
|
96
|
+
* // Get public URL
|
|
97
|
+
* const url = storage.getPublicUrl('avatars', 'users/profile.jpg');
|
|
94
98
|
* ```
|
|
95
99
|
*/
|
|
96
100
|
class WowSQLStorage {
|
|
97
101
|
constructor(config) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
+
const protocol = config.secure !== false ? 'https' : 'http';
|
|
103
|
+
if (config.baseUrl) {
|
|
104
|
+
this.baseUrl = config.baseUrl.replace(/\/+$/, '');
|
|
105
|
+
}
|
|
106
|
+
else if (config.projectUrl.startsWith('http://') || config.projectUrl.startsWith('https://')) {
|
|
107
|
+
this.baseUrl = config.projectUrl.replace(/\/+$/, '');
|
|
108
|
+
}
|
|
109
|
+
else {
|
|
110
|
+
const domain = config.baseDomain || 'wowsql.com';
|
|
111
|
+
if (config.projectUrl.includes(`.${domain}`) || config.projectUrl.endsWith(domain)) {
|
|
112
|
+
this.baseUrl = `${protocol}://${config.projectUrl}`;
|
|
113
|
+
}
|
|
114
|
+
else {
|
|
115
|
+
this.baseUrl = `${protocol}://${config.projectUrl}.${domain}`;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
this.projectSlug = config.projectSlug || config.projectUrl.split('.')[0].replace(/^https?:\/\//, '');
|
|
102
119
|
this.client = axios_1.default.create({
|
|
103
|
-
baseURL: baseUrl
|
|
120
|
+
baseURL: `${this.baseUrl}/api/v1/storage`,
|
|
104
121
|
headers: {
|
|
105
122
|
'Authorization': `Bearer ${config.apiKey}`,
|
|
106
123
|
},
|
|
107
|
-
timeout: config.timeout || 60000,
|
|
124
|
+
timeout: config.timeout || 60000,
|
|
108
125
|
});
|
|
109
|
-
// Add error interceptor
|
|
110
126
|
this.client.interceptors.response.use((response) => response, (error) => {
|
|
111
127
|
if (error.response) {
|
|
112
128
|
const errorData = error.response.data;
|
|
113
129
|
const errorMessage = errorData?.detail || errorData?.message || error.message;
|
|
114
|
-
// Check for storage limit exceeded
|
|
115
130
|
if (error.response.status === 413) {
|
|
116
|
-
throw new StorageLimitExceededError(errorMessage,
|
|
131
|
+
throw new errors_1.StorageLimitExceededError(errorMessage, 413, errorData);
|
|
117
132
|
}
|
|
118
|
-
throw new StorageError(errorMessage, error.response.status, errorData);
|
|
133
|
+
throw new errors_1.StorageError(errorMessage, error.response.status, errorData);
|
|
119
134
|
}
|
|
120
|
-
throw new StorageError(error.message);
|
|
135
|
+
throw new errors_1.StorageError(error.message);
|
|
121
136
|
});
|
|
122
137
|
}
|
|
138
|
+
// ==================== Bucket Operations ====================
|
|
123
139
|
/**
|
|
124
|
-
*
|
|
140
|
+
* Create a new storage bucket.
|
|
125
141
|
*
|
|
126
|
-
* @param
|
|
127
|
-
* @
|
|
128
|
-
*
|
|
129
|
-
* @example
|
|
130
|
-
* ```typescript
|
|
131
|
-
* const quota = await storage.getQuota();
|
|
132
|
-
* console.log(`Used: ${quota.storage_used_gb} GB`);
|
|
133
|
-
* console.log(`Available: ${quota.storage_available_gb} GB`);
|
|
134
|
-
* console.log(`Usage: ${quota.usage_percentage}%`);
|
|
135
|
-
* ```
|
|
142
|
+
* @param name - Bucket name (unique per project)
|
|
143
|
+
* @param options - Bucket configuration
|
|
136
144
|
*/
|
|
137
|
-
async
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
145
|
+
async createBucket(name, options) {
|
|
146
|
+
const response = await this.client.post(`/projects/${this.projectSlug}/buckets`, {
|
|
147
|
+
name,
|
|
148
|
+
public: options?.public ?? false,
|
|
149
|
+
file_size_limit: options?.fileSizeLimit ?? null,
|
|
150
|
+
allowed_mime_types: options?.allowedMimeTypes ?? null,
|
|
151
|
+
});
|
|
143
152
|
return response.data;
|
|
144
153
|
}
|
|
145
154
|
/**
|
|
146
|
-
*
|
|
147
|
-
*
|
|
148
|
-
* @param fileSizeBytes - Size of file to upload in bytes
|
|
149
|
-
* @returns Object with allowed status and message
|
|
150
|
-
*
|
|
151
|
-
* @example
|
|
152
|
-
* ```typescript
|
|
153
|
-
* const fileSize = 1024 * 1024 * 500; // 500 MB
|
|
154
|
-
* const check = await storage.checkUploadAllowed(fileSize);
|
|
155
|
-
* if (!check.allowed) {
|
|
156
|
-
* console.error(check.message);
|
|
157
|
-
* }
|
|
158
|
-
* ```
|
|
155
|
+
* List all buckets in the project.
|
|
159
156
|
*/
|
|
160
|
-
async
|
|
161
|
-
const
|
|
162
|
-
|
|
163
|
-
if (fileSizeGB > quota.storage_available_gb) {
|
|
164
|
-
return {
|
|
165
|
-
allowed: false,
|
|
166
|
-
message: `Storage limit exceeded! File size: ${fileSizeGB.toFixed(4)} GB, ` +
|
|
167
|
-
`Available: ${quota.storage_available_gb.toFixed(4)} GB. ` +
|
|
168
|
-
`Upgrade your plan to get more storage.`
|
|
169
|
-
};
|
|
170
|
-
}
|
|
171
|
-
return {
|
|
172
|
-
allowed: true,
|
|
173
|
-
message: `Upload allowed. ${quota.storage_available_gb.toFixed(4)} GB available.`
|
|
174
|
-
};
|
|
157
|
+
async listBuckets() {
|
|
158
|
+
const response = await this.client.get(`/projects/${this.projectSlug}/buckets`);
|
|
159
|
+
return response.data;
|
|
175
160
|
}
|
|
176
161
|
/**
|
|
177
|
-
*
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
*
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
162
|
+
* Get a specific bucket by name.
|
|
163
|
+
*/
|
|
164
|
+
async getBucket(name) {
|
|
165
|
+
const response = await this.client.get(`/projects/${this.projectSlug}/buckets/${name}`);
|
|
166
|
+
return response.data;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Update bucket settings.
|
|
170
|
+
*/
|
|
171
|
+
async updateBucket(name, updates) {
|
|
172
|
+
const body = {};
|
|
173
|
+
if (updates.name !== undefined)
|
|
174
|
+
body.name = updates.name;
|
|
175
|
+
if (updates.public !== undefined)
|
|
176
|
+
body.public = updates.public;
|
|
177
|
+
if (updates.fileSizeLimit !== undefined)
|
|
178
|
+
body.file_size_limit = updates.fileSizeLimit;
|
|
179
|
+
if (updates.allowedMimeTypes !== undefined)
|
|
180
|
+
body.allowed_mime_types = updates.allowedMimeTypes;
|
|
181
|
+
const response = await this.client.patch(`/projects/${this.projectSlug}/buckets/${name}`, body);
|
|
182
|
+
return response.data;
|
|
183
|
+
}
|
|
184
|
+
/**
|
|
185
|
+
* Delete a bucket and all its files.
|
|
186
|
+
*/
|
|
187
|
+
async deleteBucket(name) {
|
|
188
|
+
const response = await this.client.delete(`/projects/${this.projectSlug}/buckets/${name}`);
|
|
189
|
+
return response.data;
|
|
190
|
+
}
|
|
191
|
+
// ==================== File Operations ====================
|
|
192
|
+
/**
|
|
193
|
+
* Upload a file to a bucket.
|
|
195
194
|
*
|
|
196
|
-
*
|
|
197
|
-
*
|
|
198
|
-
*
|
|
199
|
-
*
|
|
200
|
-
* Buffer.from(arrayBuffer),
|
|
201
|
-
* file.name,
|
|
202
|
-
* { folder: 'uploads' }
|
|
203
|
-
* );
|
|
204
|
-
* ```
|
|
195
|
+
* @param bucketName - Target bucket
|
|
196
|
+
* @param fileData - File data (File, Blob, or Buffer)
|
|
197
|
+
* @param path - Optional path within the bucket (e.g., 'users/avatar.png')
|
|
198
|
+
* @param fileName - Optional file name override
|
|
205
199
|
*/
|
|
206
|
-
async
|
|
207
|
-
// Get file size
|
|
208
|
-
const fileSize = fileData instanceof Buffer ? fileData.length : fileData.size;
|
|
209
|
-
// Check quota if enabled
|
|
210
|
-
const shouldCheck = options?.checkQuota !== undefined ? options.checkQuota : this.autoCheckQuota;
|
|
211
|
-
if (shouldCheck) {
|
|
212
|
-
const check = await this.checkUploadAllowed(fileSize);
|
|
213
|
-
if (!check.allowed) {
|
|
214
|
-
throw new StorageLimitExceededError(check.message, 413);
|
|
215
|
-
}
|
|
216
|
-
}
|
|
217
|
-
// Prepare form data
|
|
200
|
+
async upload(bucketName, fileData, path, fileName) {
|
|
218
201
|
const formData = new FormData();
|
|
219
202
|
const blob = fileData instanceof Buffer ? new Blob([fileData]) : fileData;
|
|
220
|
-
|
|
221
|
-
|
|
203
|
+
const name = fileName || fileData.name || path || 'file';
|
|
204
|
+
formData.append('file', blob, name);
|
|
222
205
|
const params = new URLSearchParams();
|
|
223
|
-
if (
|
|
224
|
-
|
|
206
|
+
if (path) {
|
|
207
|
+
const folder = path.includes('/') ? path.substring(0, path.lastIndexOf('/')) : '';
|
|
208
|
+
if (folder)
|
|
209
|
+
params.append('folder', folder);
|
|
225
210
|
}
|
|
226
|
-
const url = `/
|
|
227
|
-
// Upload
|
|
211
|
+
const url = `/projects/${this.projectSlug}/buckets/${bucketName}/files${params.toString() ? '?' + params.toString() : ''}`;
|
|
228
212
|
const response = await this.client.post(url, formData, {
|
|
229
|
-
headers: {
|
|
230
|
-
'Content-Type': 'multipart/form-data',
|
|
231
|
-
},
|
|
213
|
+
headers: { 'Content-Type': 'multipart/form-data' },
|
|
232
214
|
});
|
|
233
|
-
|
|
234
|
-
this.quotaCache = undefined;
|
|
235
|
-
return response.data;
|
|
215
|
+
return new StorageFileImpl(response.data);
|
|
236
216
|
}
|
|
237
217
|
/**
|
|
238
|
-
* Upload a file
|
|
239
|
-
*
|
|
240
|
-
* @param filePath - Path to local file
|
|
241
|
-
* @param fileName - Optional file name in bucket (defaults to filename)
|
|
242
|
-
* @param options - Upload options
|
|
243
|
-
* @returns Upload result
|
|
218
|
+
* Upload a file (compatibility alias for upload).
|
|
244
219
|
*
|
|
245
|
-
* @
|
|
246
|
-
*
|
|
247
|
-
*
|
|
248
|
-
*
|
|
249
|
-
* 'report.pdf',
|
|
250
|
-
* { folder: 'reports' }
|
|
251
|
-
* );
|
|
252
|
-
* ```
|
|
220
|
+
* @param bucketName - Target bucket
|
|
221
|
+
* @param fileData - File data (File, Blob, or Buffer)
|
|
222
|
+
* @param path - Optional path within the bucket
|
|
223
|
+
* @param fileName - Optional file name override
|
|
253
224
|
*/
|
|
254
|
-
async
|
|
255
|
-
|
|
256
|
-
throw new Error(`File not found: ${filePath}`);
|
|
257
|
-
}
|
|
258
|
-
const fileBuffer = fs.readFileSync(filePath);
|
|
259
|
-
const name = fileName || filePath.split('/').pop() || 'file';
|
|
260
|
-
return this.uploadFile(fileBuffer, name, options);
|
|
225
|
+
async uploadFile(bucketName, fileData, path, fileName) {
|
|
226
|
+
return this.upload(bucketName, fileData, path, fileName);
|
|
261
227
|
}
|
|
262
228
|
/**
|
|
263
|
-
*
|
|
229
|
+
* Upload a file from a local file path (Node.js only).
|
|
264
230
|
*
|
|
265
|
-
* @param
|
|
266
|
-
* @
|
|
231
|
+
* @param filePath - Local file path to upload
|
|
232
|
+
* @param bucketName - Target bucket (defaults to 'default')
|
|
233
|
+
* @param path - Optional path within the bucket
|
|
234
|
+
*/
|
|
235
|
+
async uploadFromPath(filePath, bucketName = 'default', path) {
|
|
236
|
+
const fs = await Promise.resolve().then(() => __importStar(require('fs')));
|
|
237
|
+
const nodePath = await Promise.resolve().then(() => __importStar(require('path')));
|
|
238
|
+
const data = fs.readFileSync(filePath);
|
|
239
|
+
const fileName = nodePath.basename(filePath);
|
|
240
|
+
return this.upload(bucketName, Buffer.from(data), path || fileName, fileName);
|
|
241
|
+
}
|
|
242
|
+
/**
|
|
243
|
+
* List files in a bucket.
|
|
267
244
|
*
|
|
268
|
-
* @
|
|
269
|
-
*
|
|
270
|
-
* const files = await storage.listFiles({ prefix: 'documents/' });
|
|
271
|
-
* for (const file of files) {
|
|
272
|
-
* console.log(`${file.key}: ${(file.size / 1024 / 1024).toFixed(2)} MB`);
|
|
273
|
-
* }
|
|
274
|
-
* ```
|
|
245
|
+
* @param bucketName - Bucket to list
|
|
246
|
+
* @param options - Filter and pagination options
|
|
275
247
|
*/
|
|
276
|
-
async listFiles(options) {
|
|
248
|
+
async listFiles(bucketName, options) {
|
|
277
249
|
const params = {};
|
|
278
250
|
if (options?.prefix)
|
|
279
251
|
params.prefix = options.prefix;
|
|
280
|
-
if (options?.
|
|
281
|
-
params.
|
|
282
|
-
|
|
283
|
-
|
|
252
|
+
if (options?.limit)
|
|
253
|
+
params.limit = options.limit;
|
|
254
|
+
if (options?.offset)
|
|
255
|
+
params.offset = options.offset;
|
|
256
|
+
const response = await this.client.get(`/projects/${this.projectSlug}/buckets/${bucketName}/files`, { params });
|
|
257
|
+
return response.data.map((f) => new StorageFileImpl(f));
|
|
284
258
|
}
|
|
285
259
|
/**
|
|
286
|
-
*
|
|
287
|
-
*
|
|
288
|
-
* @param fileKey - Path to file in bucket
|
|
289
|
-
* @returns Deletion result
|
|
260
|
+
* Download a file. Returns binary data as ArrayBuffer.
|
|
290
261
|
*
|
|
291
|
-
* @
|
|
292
|
-
*
|
|
293
|
-
* const result = await storage.deleteFile('documents/old-file.pdf');
|
|
294
|
-
* console.log(result.message);
|
|
295
|
-
* ```
|
|
262
|
+
* @param bucketName - Bucket name
|
|
263
|
+
* @param filePath - Path to file within the bucket
|
|
296
264
|
*/
|
|
297
|
-
async
|
|
298
|
-
const response = await this.client.
|
|
299
|
-
// Clear quota cache after delete
|
|
300
|
-
this.quotaCache = undefined;
|
|
265
|
+
async download(bucketName, filePath) {
|
|
266
|
+
const response = await this.client.get(`/projects/${this.projectSlug}/files/${bucketName}/${filePath}`, { responseType: 'arraybuffer' });
|
|
301
267
|
return response.data;
|
|
302
268
|
}
|
|
303
269
|
/**
|
|
304
|
-
*
|
|
270
|
+
* Download a file and save to a local path (Node.js only).
|
|
305
271
|
*
|
|
306
|
-
* @param
|
|
307
|
-
* @param
|
|
308
|
-
* @
|
|
309
|
-
*
|
|
310
|
-
* @example
|
|
311
|
-
* ```typescript
|
|
312
|
-
* const urlData = await storage.getFileUrl('photo.jpg', 7200);
|
|
313
|
-
* console.log(urlData.file_url); // Use this for downloads
|
|
314
|
-
* ```
|
|
272
|
+
* @param bucketName - Bucket name
|
|
273
|
+
* @param filePath - Path to file within the bucket
|
|
274
|
+
* @param localPath - Local file path to save to
|
|
315
275
|
*/
|
|
316
|
-
async
|
|
317
|
-
const
|
|
318
|
-
|
|
276
|
+
async downloadToFile(bucketName, filePath, localPath) {
|
|
277
|
+
const data = await this.download(bucketName, filePath);
|
|
278
|
+
const fs = await Promise.resolve().then(() => __importStar(require('fs')));
|
|
279
|
+
fs.writeFileSync(localPath, Buffer.from(data));
|
|
319
280
|
}
|
|
320
281
|
/**
|
|
321
|
-
*
|
|
322
|
-
*
|
|
323
|
-
* @param fileKey - Path to file in bucket
|
|
324
|
-
* @param options - Presigned URL options
|
|
325
|
-
* @returns Presigned URL string
|
|
326
|
-
*
|
|
327
|
-
* @example
|
|
328
|
-
* ```typescript
|
|
329
|
-
* // Download URL
|
|
330
|
-
* const downloadUrl = await storage.getPresignedUrl('file.pdf');
|
|
282
|
+
* Delete a file from a bucket.
|
|
331
283
|
*
|
|
332
|
-
*
|
|
333
|
-
*
|
|
334
|
-
* operation: 'put_object',
|
|
335
|
-
* expiresIn: 1800
|
|
336
|
-
* });
|
|
337
|
-
* ```
|
|
284
|
+
* @param bucketName - Bucket name
|
|
285
|
+
* @param filePath - Path to file within the bucket
|
|
338
286
|
*/
|
|
339
|
-
async
|
|
340
|
-
const response = await this.client.
|
|
341
|
-
|
|
342
|
-
expires_in: options?.expiresIn || 3600,
|
|
343
|
-
operation: options?.operation || 'get_object',
|
|
344
|
-
});
|
|
345
|
-
return response.data.url;
|
|
287
|
+
async deleteFile(bucketName, filePath) {
|
|
288
|
+
const response = await this.client.delete(`/projects/${this.projectSlug}/files/${bucketName}/${filePath}`);
|
|
289
|
+
return response.data;
|
|
346
290
|
}
|
|
291
|
+
// ==================== Utilities ====================
|
|
347
292
|
/**
|
|
348
|
-
* Get
|
|
349
|
-
*
|
|
350
|
-
* @returns Storage information
|
|
351
|
-
*
|
|
352
|
-
* @example
|
|
353
|
-
* ```typescript
|
|
354
|
-
* const info = await storage.getStorageInfo();
|
|
355
|
-
* console.log(`Bucket: ${info.bucket_name}`);
|
|
356
|
-
* console.log(`Region: ${info.region}`);
|
|
357
|
-
* console.log(`Objects: ${info.total_objects}`);
|
|
358
|
-
* console.log(`Size: ${info.total_size_gb.toFixed(2)} GB`);
|
|
359
|
-
* ```
|
|
293
|
+
* Get the public URL for a file in a public bucket.
|
|
294
|
+
* This URL works without authentication.
|
|
360
295
|
*/
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
return response.data;
|
|
296
|
+
getPublicUrl(bucketName, filePath) {
|
|
297
|
+
return `${this.baseUrl}/storage/v1/object/public/${bucketName}/${filePath}`;
|
|
364
298
|
}
|
|
365
299
|
/**
|
|
366
|
-
*
|
|
367
|
-
*
|
|
368
|
-
* **IMPORTANT**: Save the credentials returned! They're only shown once.
|
|
369
|
-
*
|
|
370
|
-
* @param region - AWS region (default: 'us-east-1')
|
|
371
|
-
* @returns Provisioning result with credentials
|
|
372
|
-
*
|
|
373
|
-
* @example
|
|
374
|
-
* ```typescript
|
|
375
|
-
* const result = await storage.provisionStorage('us-west-2');
|
|
376
|
-
* console.log(`Bucket: ${result.bucket_name}`);
|
|
377
|
-
* console.log(`Access Key: ${result.credentials.access_key_id}`);
|
|
378
|
-
* // SAVE THESE CREDENTIALS SECURELY!
|
|
379
|
-
* ```
|
|
300
|
+
* Get storage statistics for the project.
|
|
380
301
|
*/
|
|
381
|
-
async
|
|
382
|
-
const response = await this.client.
|
|
302
|
+
async getStats() {
|
|
303
|
+
const response = await this.client.get(`/projects/${this.projectSlug}/stats`);
|
|
383
304
|
return response.data;
|
|
384
305
|
}
|
|
385
306
|
/**
|
|
386
|
-
* Get
|
|
387
|
-
*
|
|
388
|
-
* @returns Array of available regions
|
|
389
|
-
*
|
|
390
|
-
* @example
|
|
391
|
-
* ```typescript
|
|
392
|
-
* const regions = await storage.getAvailableRegions();
|
|
393
|
-
* for (const region of regions) {
|
|
394
|
-
* console.log(`${region.name}: $${region.storage_price_gb}/GB/month`);
|
|
395
|
-
* }
|
|
396
|
-
* ```
|
|
307
|
+
* Get storage quota for the project.
|
|
397
308
|
*/
|
|
398
|
-
async
|
|
399
|
-
const response = await this.client.get(
|
|
309
|
+
async getQuota() {
|
|
310
|
+
const response = await this.client.get(`/projects/${this.projectSlug}/quota`);
|
|
400
311
|
return response.data;
|
|
401
312
|
}
|
|
402
313
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@wowsql/sdk",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.8.0",
|
|
4
4
|
"description": "Official TypeScript/JavaScript SDK for WowSQL - MySQL Backend-as-a-Service with S3 Storage, type-safe queries and fluent API",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|