tinbase 0.1.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/LICENSE +21 -0
- package/README.md +185 -0
- package/assets/logo.svg +18 -0
- package/dist/auth/handler.d.ts +43 -0
- package/dist/auth/handler.js +291 -0
- package/dist/auth/handler.js.map +1 -0
- package/dist/auth/password.d.ts +3 -0
- package/dist/auth/password.js +40 -0
- package/dist/auth/password.js.map +1 -0
- package/dist/cli.d.ts +2 -0
- package/dist/cli.js +181 -0
- package/dist/cli.js.map +1 -0
- package/dist/db/bootstrap.d.ts +6 -0
- package/dist/db/bootstrap.js +213 -0
- package/dist/db/bootstrap.js.map +1 -0
- package/dist/db/database.d.ts +83 -0
- package/dist/db/database.js +270 -0
- package/dist/db/database.js.map +1 -0
- package/dist/db/engine.d.ts +30 -0
- package/dist/db/engine.js +28 -0
- package/dist/db/engine.js.map +1 -0
- package/dist/db/pglite-engine.d.ts +3 -0
- package/dist/db/pglite-engine.js +39 -0
- package/dist/db/pglite-engine.js.map +1 -0
- package/dist/index.d.ts +23 -0
- package/dist/index.js +145 -0
- package/dist/index.js.map +1 -0
- package/dist/jwt.d.ts +20 -0
- package/dist/jwt.js +72 -0
- package/dist/jwt.js.map +1 -0
- package/dist/node/bun-server.d.ts +8 -0
- package/dist/node/bun-server.js +41 -0
- package/dist/node/bun-server.js.map +1 -0
- package/dist/node/fs-driver.d.ts +11 -0
- package/dist/node/fs-driver.js +39 -0
- package/dist/node/fs-driver.js.map +1 -0
- package/dist/node/index.d.ts +7 -0
- package/dist/node/index.js +8 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/native/engine.d.ts +13 -0
- package/dist/node/native/engine.js +186 -0
- package/dist/node/native/engine.js.map +1 -0
- package/dist/node/native/wire.d.ts +38 -0
- package/dist/node/native/wire.js +345 -0
- package/dist/node/native/wire.js.map +1 -0
- package/dist/node/project.d.ts +6 -0
- package/dist/node/project.js +29 -0
- package/dist/node/project.js.map +1 -0
- package/dist/node/server-shared.d.ts +6 -0
- package/dist/node/server-shared.js +2 -0
- package/dist/node/server-shared.js.map +1 -0
- package/dist/node/server.d.ts +14 -0
- package/dist/node/server.js +83 -0
- package/dist/node/server.js.map +1 -0
- package/dist/node/ws.d.ts +8 -0
- package/dist/node/ws.js +165 -0
- package/dist/node/ws.js.map +1 -0
- package/dist/realtime/engine.d.ts +53 -0
- package/dist/realtime/engine.js +437 -0
- package/dist/realtime/engine.js.map +1 -0
- package/dist/rest/build.d.ts +53 -0
- package/dist/rest/build.js +505 -0
- package/dist/rest/build.js.map +1 -0
- package/dist/rest/errors.d.ts +2 -0
- package/dist/rest/errors.js +48 -0
- package/dist/rest/errors.js.map +1 -0
- package/dist/rest/handler.d.ts +11 -0
- package/dist/rest/handler.js +332 -0
- package/dist/rest/handler.js.map +1 -0
- package/dist/rest/parse.d.ts +69 -0
- package/dist/rest/parse.js +261 -0
- package/dist/rest/parse.js.map +1 -0
- package/dist/storage/driver.d.ts +9 -0
- package/dist/storage/driver.js +18 -0
- package/dist/storage/driver.js.map +1 -0
- package/dist/storage/handler.d.ts +49 -0
- package/dist/storage/handler.js +534 -0
- package/dist/storage/handler.js.map +1 -0
- package/dist/types.d.ts +51 -0
- package/dist/types.js +11 -0
- package/dist/types.js.map +1 -0
- package/package.json +59 -0
|
@@ -0,0 +1,534 @@
|
|
|
1
|
+
import { signJwt, verifyJwt } from '../jwt.js';
|
|
2
|
+
function storageError(status, error, message) {
|
|
3
|
+
return json(status, { statusCode: String(status), error, message });
|
|
4
|
+
}
|
|
5
|
+
function json(status, body) {
|
|
6
|
+
return new Response(JSON.stringify(body), {
|
|
7
|
+
status,
|
|
8
|
+
headers: { 'content-type': 'application/json; charset=utf-8' },
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
function iso(v) {
|
|
12
|
+
if (v === null || v === undefined)
|
|
13
|
+
return null;
|
|
14
|
+
return v instanceof Date ? v.toISOString() : new Date(v).toISOString();
|
|
15
|
+
}
|
|
16
|
+
const SERVICE_CTX = { role: 'service_role', claims: { role: 'service_role' } };
|
|
17
|
+
export class StorageHandler {
|
|
18
|
+
db;
|
|
19
|
+
driver;
|
|
20
|
+
config;
|
|
21
|
+
constructor(db, driver, config) {
|
|
22
|
+
this.db = db;
|
|
23
|
+
this.driver = driver;
|
|
24
|
+
this.config = config;
|
|
25
|
+
}
|
|
26
|
+
async handle(req, ctx, url) {
|
|
27
|
+
const rest = url.pathname.replace(/^\/storage\/v1\/?/, '').replace(/\/+$/, '');
|
|
28
|
+
const method = req.method.toUpperCase();
|
|
29
|
+
try {
|
|
30
|
+
// ── buckets ──
|
|
31
|
+
if (rest === 'bucket' && method === 'POST')
|
|
32
|
+
return await this.createBucket(req, ctx);
|
|
33
|
+
if (rest === 'bucket' && method === 'GET')
|
|
34
|
+
return await this.listBuckets();
|
|
35
|
+
const bucketMatch = rest.match(/^bucket\/([^/]+)$/);
|
|
36
|
+
if (bucketMatch && method === 'GET')
|
|
37
|
+
return await this.getBucket(dec(bucketMatch[1]));
|
|
38
|
+
if (bucketMatch && method === 'PUT')
|
|
39
|
+
return await this.updateBucket(req, ctx, dec(bucketMatch[1]));
|
|
40
|
+
if (bucketMatch && method === 'DELETE')
|
|
41
|
+
return await this.deleteBucket(ctx, dec(bucketMatch[1]));
|
|
42
|
+
const emptyMatch = rest.match(/^bucket\/([^/]+)\/empty$/);
|
|
43
|
+
if (emptyMatch && method === 'POST')
|
|
44
|
+
return await this.emptyBucket(ctx, dec(emptyMatch[1]));
|
|
45
|
+
// ── objects ──
|
|
46
|
+
const parts = rest.split('/').map(dec);
|
|
47
|
+
if (parts[0] !== 'object')
|
|
48
|
+
return storageError(404, 'not_found', `unknown storage endpoint: ${rest}`);
|
|
49
|
+
if (parts[1] === 'move' && method === 'POST')
|
|
50
|
+
return await this.moveOrCopy(req, ctx, 'move');
|
|
51
|
+
if (parts[1] === 'copy' && method === 'POST')
|
|
52
|
+
return await this.moveOrCopy(req, ctx, 'copy');
|
|
53
|
+
if (parts[1] === 'list' && parts.length === 3 && method === 'POST') {
|
|
54
|
+
return await this.listObjects(req, ctx, parts[2]);
|
|
55
|
+
}
|
|
56
|
+
if (parts[1] === 'public' && parts.length >= 4 && (method === 'GET' || method === 'HEAD')) {
|
|
57
|
+
return await this.downloadPublic(parts[2], parts.slice(3).join('/'), method === 'HEAD');
|
|
58
|
+
}
|
|
59
|
+
if (parts[1] === 'authenticated' && parts.length >= 4 && (method === 'GET' || method === 'HEAD')) {
|
|
60
|
+
return await this.download(ctx, parts[2], parts.slice(3).join('/'), method === 'HEAD');
|
|
61
|
+
}
|
|
62
|
+
if (parts[1] === 'sign' && parts.length === 3 && method === 'POST') {
|
|
63
|
+
return await this.signUrls(req, ctx, parts[2]);
|
|
64
|
+
}
|
|
65
|
+
if (parts[1] === 'sign' && parts.length >= 4 && method === 'POST') {
|
|
66
|
+
return await this.signUrl(req, ctx, parts[2], parts.slice(3).join('/'));
|
|
67
|
+
}
|
|
68
|
+
if (parts[1] === 'sign' && parts.length >= 4 && method === 'GET') {
|
|
69
|
+
return await this.redeemSignedUrl(url, parts[2], parts.slice(3).join('/'));
|
|
70
|
+
}
|
|
71
|
+
if (parts[1] === 'upload' && parts[2] === 'sign' && parts.length >= 5) {
|
|
72
|
+
const bucket = parts[3];
|
|
73
|
+
const key = parts.slice(4).join('/');
|
|
74
|
+
if (method === 'POST')
|
|
75
|
+
return await this.signUploadUrl(ctx, bucket, key);
|
|
76
|
+
if (method === 'PUT')
|
|
77
|
+
return await this.redeemSignedUpload(req, url, bucket, key);
|
|
78
|
+
}
|
|
79
|
+
if (parts[1] === 'info' && parts.length >= 4 && method === 'GET') {
|
|
80
|
+
return await this.objectInfo(ctx, parts[2], parts.slice(3).join('/'));
|
|
81
|
+
}
|
|
82
|
+
// plain /object/:bucket[/:path...]
|
|
83
|
+
const bucket = parts[1];
|
|
84
|
+
const key = parts.slice(2).join('/');
|
|
85
|
+
if (key === '' && method === 'DELETE')
|
|
86
|
+
return await this.removeObjects(req, ctx, bucket);
|
|
87
|
+
if (key !== '') {
|
|
88
|
+
if (method === 'POST' || method === 'PUT')
|
|
89
|
+
return await this.upload(req, ctx, bucket, key);
|
|
90
|
+
if (method === 'GET' || method === 'HEAD')
|
|
91
|
+
return await this.download(ctx, bucket, key, method === 'HEAD');
|
|
92
|
+
if (method === 'DELETE')
|
|
93
|
+
return await this.removeOne(ctx, bucket, key);
|
|
94
|
+
}
|
|
95
|
+
return storageError(404, 'not_found', `unknown storage endpoint: ${rest}`);
|
|
96
|
+
}
|
|
97
|
+
catch (e) {
|
|
98
|
+
const pg = e;
|
|
99
|
+
if (pg.code === '42501') {
|
|
100
|
+
return storageError(403, 'Unauthorized', pg.message ?? 'new row violates row-level security policy');
|
|
101
|
+
}
|
|
102
|
+
const msg = e instanceof Error ? e.message : String(e);
|
|
103
|
+
return storageError(500, 'internal', msg);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
// ── buckets ─────────────────────────────────────────────────────────────
|
|
107
|
+
requireService(ctx) {
|
|
108
|
+
if (ctx.role !== 'service_role') {
|
|
109
|
+
return storageError(403, 'Unauthorized', 'Bucket management requires the service_role key');
|
|
110
|
+
}
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
async createBucket(req, ctx) {
|
|
114
|
+
const denied = this.requireService(ctx);
|
|
115
|
+
if (denied)
|
|
116
|
+
return denied;
|
|
117
|
+
const body = (await req.json().catch(() => ({})));
|
|
118
|
+
const id = body.id ?? body.name;
|
|
119
|
+
if (!id)
|
|
120
|
+
return storageError(400, 'invalid_request', 'bucket id is required');
|
|
121
|
+
const existing = await this.db.query(`select id from storage.buckets where id = $1`, [id]);
|
|
122
|
+
if (existing.rows.length > 0) {
|
|
123
|
+
return storageError(409, 'Duplicate', 'The resource already exists');
|
|
124
|
+
}
|
|
125
|
+
await this.db.query(`insert into storage.buckets (id, name, public, file_size_limit, allowed_mime_types)
|
|
126
|
+
values ($1, $2, $3, $4, $5)`, [id, body.name ?? id, body.public ?? false, parseSizeLimit(body.file_size_limit), body.allowed_mime_types ?? null]);
|
|
127
|
+
return json(200, { name: id });
|
|
128
|
+
}
|
|
129
|
+
async listBuckets() {
|
|
130
|
+
const res = await this.db.query(`select * from storage.buckets order by created_at`);
|
|
131
|
+
return json(200, res.rows.map(bucketJson));
|
|
132
|
+
}
|
|
133
|
+
async getBucket(id) {
|
|
134
|
+
const res = await this.db.query(`select * from storage.buckets where id = $1`, [id]);
|
|
135
|
+
if (res.rows.length === 0)
|
|
136
|
+
return storageError(404, 'Bucket not found', 'Bucket not found');
|
|
137
|
+
return json(200, bucketJson(res.rows[0]));
|
|
138
|
+
}
|
|
139
|
+
async updateBucket(req, ctx, id) {
|
|
140
|
+
const denied = this.requireService(ctx);
|
|
141
|
+
if (denied)
|
|
142
|
+
return denied;
|
|
143
|
+
const body = (await req.json().catch(() => ({})));
|
|
144
|
+
const res = await this.db.query(`update storage.buckets
|
|
145
|
+
set public = coalesce($2, public),
|
|
146
|
+
file_size_limit = $3,
|
|
147
|
+
allowed_mime_types = $4,
|
|
148
|
+
updated_at = now()
|
|
149
|
+
where id = $1 returning id`, [id, body.public ?? null, parseSizeLimit(body.file_size_limit), body.allowed_mime_types ?? null]);
|
|
150
|
+
if (res.rows.length === 0)
|
|
151
|
+
return storageError(404, 'Bucket not found', 'Bucket not found');
|
|
152
|
+
return json(200, { message: 'Successfully updated' });
|
|
153
|
+
}
|
|
154
|
+
async deleteBucket(ctx, id) {
|
|
155
|
+
const denied = this.requireService(ctx);
|
|
156
|
+
if (denied)
|
|
157
|
+
return denied;
|
|
158
|
+
const objects = await this.db.query(`select count(*)::int as count from storage.objects where bucket_id = $1`, [id]);
|
|
159
|
+
if (objects.rows[0].count > 0) {
|
|
160
|
+
return storageError(409, 'Conflict', 'The bucket you tried to delete is not empty');
|
|
161
|
+
}
|
|
162
|
+
const res = await this.db.query(`delete from storage.buckets where id = $1 returning id`, [id]);
|
|
163
|
+
if (res.rows.length === 0)
|
|
164
|
+
return storageError(404, 'Bucket not found', 'Bucket not found');
|
|
165
|
+
return json(200, { message: 'Successfully deleted' });
|
|
166
|
+
}
|
|
167
|
+
async emptyBucket(ctx, id) {
|
|
168
|
+
const denied = this.requireService(ctx);
|
|
169
|
+
if (denied)
|
|
170
|
+
return denied;
|
|
171
|
+
const res = await this.db.query(`delete from storage.objects where bucket_id = $1 returning name`, [id]);
|
|
172
|
+
await this.driver.deleteMany(res.rows.map((r) => `${id}/${r.name}`));
|
|
173
|
+
return json(200, { message: 'Successfully emptied' });
|
|
174
|
+
}
|
|
175
|
+
// ── objects ─────────────────────────────────────────────────────────────
|
|
176
|
+
async loadBucket(id) {
|
|
177
|
+
const res = await this.db.query(`select * from storage.buckets where id = $1`, [id]);
|
|
178
|
+
return res.rows[0] ?? null;
|
|
179
|
+
}
|
|
180
|
+
async upload(req, ctx, bucketId, key) {
|
|
181
|
+
const bucket = await this.loadBucket(bucketId);
|
|
182
|
+
if (!bucket)
|
|
183
|
+
return storageError(404, 'Bucket not found', 'Bucket not found');
|
|
184
|
+
const upsert = (req.headers.get('x-upsert') ?? 'false').toLowerCase() === 'true' || req.method === 'PUT';
|
|
185
|
+
let contentType = req.headers.get('content-type') ?? 'application/octet-stream';
|
|
186
|
+
let cacheControl = req.headers.get('cache-control') ?? 'no-cache';
|
|
187
|
+
let bytes;
|
|
188
|
+
if (contentType.startsWith('multipart/form-data')) {
|
|
189
|
+
// storage-js wraps Blob/File bodies in FormData with an EMPTY field
|
|
190
|
+
// name, which some runtimes' formData() drops — parse bytes ourselves.
|
|
191
|
+
const boundary = contentType.match(/boundary="?([^";]+)"?/)?.[1];
|
|
192
|
+
if (!boundary)
|
|
193
|
+
return storageError(400, 'invalid_request', 'multipart body without boundary');
|
|
194
|
+
const parts = parseMultipart(new Uint8Array(await req.arrayBuffer()), boundary);
|
|
195
|
+
const filePart = parts.find((p) => p.filename !== undefined || p.contentType !== undefined);
|
|
196
|
+
if (!filePart)
|
|
197
|
+
return storageError(400, 'invalid_request', 'no file found in multipart body');
|
|
198
|
+
const cc = parts.find((p) => p.name === 'cacheControl');
|
|
199
|
+
if (cc)
|
|
200
|
+
cacheControl = new TextDecoder().decode(cc.data);
|
|
201
|
+
bytes = filePart.data;
|
|
202
|
+
contentType = filePart.contentType ?? 'application/octet-stream';
|
|
203
|
+
}
|
|
204
|
+
else {
|
|
205
|
+
bytes = new Uint8Array(await req.arrayBuffer());
|
|
206
|
+
}
|
|
207
|
+
if (bucket.file_size_limit != null && bytes.length > Number(bucket.file_size_limit)) {
|
|
208
|
+
return storageError(413, 'Payload too large', 'The object exceeded the maximum allowed size');
|
|
209
|
+
}
|
|
210
|
+
if (bucket.allowed_mime_types && bucket.allowed_mime_types.length > 0) {
|
|
211
|
+
const base = contentType.split(';')[0].trim();
|
|
212
|
+
if (!bucket.allowed_mime_types.some((m) => m === base || (m.endsWith('/*') && base.startsWith(m.slice(0, -1))))) {
|
|
213
|
+
return storageError(415, 'invalid_mime_type', `mime type ${base} is not supported`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const metadata = {
|
|
217
|
+
eTag: `"${crypto.randomUUID()}"`,
|
|
218
|
+
size: bytes.length,
|
|
219
|
+
mimetype: contentType,
|
|
220
|
+
cacheControl,
|
|
221
|
+
lastModified: new Date().toISOString(),
|
|
222
|
+
contentLength: bytes.length,
|
|
223
|
+
httpStatusCode: 200,
|
|
224
|
+
};
|
|
225
|
+
const conflictClause = upsert
|
|
226
|
+
? `on conflict (bucket_id, name) do update
|
|
227
|
+
set metadata = excluded.metadata, owner = excluded.owner, updated_at = now(), version = excluded.version`
|
|
228
|
+
: '';
|
|
229
|
+
try {
|
|
230
|
+
const res = await this.db.withContext(ctx, (q) => q(`insert into storage.objects (bucket_id, name, owner, metadata, version)
|
|
231
|
+
values ($1, $2, $3, $4::jsonb, $5) ${conflictClause} returning id`, [bucketId, key, ctx.claims?.sub ?? null, JSON.stringify(metadata), crypto.randomUUID()]));
|
|
232
|
+
await this.driver.put(`${bucketId}/${key}`, bytes);
|
|
233
|
+
const id = res.rows[0].id;
|
|
234
|
+
return json(200, { Key: `${bucketId}/${key}`, Id: id });
|
|
235
|
+
}
|
|
236
|
+
catch (e) {
|
|
237
|
+
const pg = e;
|
|
238
|
+
if (pg.code === '23505') {
|
|
239
|
+
return storageError(409, 'Duplicate', 'The resource already exists');
|
|
240
|
+
}
|
|
241
|
+
throw e;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
async download(ctx, bucketId, key, head) {
|
|
245
|
+
const res = await this.db.withContext(ctx, (q) => q(`select * from storage.objects where bucket_id = $1 and name = $2`, [bucketId, key]));
|
|
246
|
+
const row = res.rows[0];
|
|
247
|
+
if (!row)
|
|
248
|
+
return storageError(404, 'not_found', 'Object not found');
|
|
249
|
+
return this.serveObject(row, bucketId, key, head);
|
|
250
|
+
}
|
|
251
|
+
async downloadPublic(bucketId, key, head) {
|
|
252
|
+
const bucket = await this.loadBucket(bucketId);
|
|
253
|
+
if (!bucket?.public)
|
|
254
|
+
return storageError(400, 'not_found', 'Bucket is not public');
|
|
255
|
+
const res = await this.db.query(`select * from storage.objects where bucket_id = $1 and name = $2`, [
|
|
256
|
+
bucketId,
|
|
257
|
+
key,
|
|
258
|
+
]);
|
|
259
|
+
const row = res.rows[0];
|
|
260
|
+
if (!row)
|
|
261
|
+
return storageError(404, 'not_found', 'Object not found');
|
|
262
|
+
return this.serveObject(row, bucketId, key, head);
|
|
263
|
+
}
|
|
264
|
+
async serveObject(row, bucketId, key, head) {
|
|
265
|
+
const bytes = await this.driver.get(`${bucketId}/${key}`);
|
|
266
|
+
if (bytes === null)
|
|
267
|
+
return storageError(404, 'not_found', 'Object not found');
|
|
268
|
+
const meta = row.metadata ?? {};
|
|
269
|
+
return new Response(head ? null : bytes, {
|
|
270
|
+
status: 200,
|
|
271
|
+
headers: {
|
|
272
|
+
'content-type': String(meta.mimetype ?? 'application/octet-stream'),
|
|
273
|
+
'content-length': String(bytes.length),
|
|
274
|
+
'cache-control': String(meta.cacheControl ?? 'no-cache'),
|
|
275
|
+
etag: String(meta.eTag ?? '""'),
|
|
276
|
+
'last-modified': new Date(String(meta.lastModified ?? Date.now())).toUTCString(),
|
|
277
|
+
},
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
async removeObjects(req, ctx, bucketId) {
|
|
281
|
+
const body = (await req.json().catch(() => ({})));
|
|
282
|
+
const prefixes = body.prefixes ?? [];
|
|
283
|
+
if (prefixes.length === 0)
|
|
284
|
+
return json(200, []);
|
|
285
|
+
const res = await this.db.withContext(ctx, (q) => q(`delete from storage.objects where bucket_id = $1 and name = any($2::text[]) returning *`, [
|
|
286
|
+
bucketId,
|
|
287
|
+
`{${prefixes.map((p) => `"${p.replaceAll('\\', '\\\\').replaceAll('"', '\\"')}"`).join(',')}}`,
|
|
288
|
+
]));
|
|
289
|
+
const rows = res.rows;
|
|
290
|
+
await this.driver.deleteMany(rows.map((r) => `${bucketId}/${r.name}`));
|
|
291
|
+
return json(200, rows.map((r) => objectJson(r)));
|
|
292
|
+
}
|
|
293
|
+
async removeOne(ctx, bucketId, key) {
|
|
294
|
+
const res = await this.db.withContext(ctx, (q) => q(`delete from storage.objects where bucket_id = $1 and name = $2 returning *`, [bucketId, key]));
|
|
295
|
+
if (res.rows.length === 0)
|
|
296
|
+
return storageError(404, 'not_found', 'Object not found');
|
|
297
|
+
await this.driver.delete(`${bucketId}/${key}`);
|
|
298
|
+
return json(200, { message: 'Successfully deleted' });
|
|
299
|
+
}
|
|
300
|
+
async moveOrCopy(req, ctx, mode) {
|
|
301
|
+
const body = (await req.json().catch(() => ({})));
|
|
302
|
+
if (!body.bucketId || !body.sourceKey || !body.destinationKey) {
|
|
303
|
+
return storageError(400, 'invalid_request', 'bucketId, sourceKey and destinationKey are required');
|
|
304
|
+
}
|
|
305
|
+
const dstBucket = body.destinationBucket ?? body.bucketId;
|
|
306
|
+
const bytes = await this.driver.get(`${body.bucketId}/${body.sourceKey}`);
|
|
307
|
+
if (bytes === null)
|
|
308
|
+
return storageError(404, 'not_found', 'Object not found');
|
|
309
|
+
if (mode === 'move') {
|
|
310
|
+
const res = await this.db.withContext(ctx, (q) => q(`update storage.objects set bucket_id = $3, name = $4, updated_at = now()
|
|
311
|
+
where bucket_id = $1 and name = $2 returning id`, [body.bucketId, body.sourceKey, dstBucket, body.destinationKey]));
|
|
312
|
+
if (res.rows.length === 0)
|
|
313
|
+
return storageError(404, 'not_found', 'Object not found');
|
|
314
|
+
await this.driver.put(`${dstBucket}/${body.destinationKey}`, bytes);
|
|
315
|
+
await this.driver.delete(`${body.bucketId}/${body.sourceKey}`);
|
|
316
|
+
return json(200, { message: 'Successfully moved' });
|
|
317
|
+
}
|
|
318
|
+
const res = await this.db.withContext(ctx, (q) => q(`insert into storage.objects (bucket_id, name, owner, metadata, version)
|
|
319
|
+
select $3, $4, $5, metadata, gen_random_uuid()::text
|
|
320
|
+
from storage.objects where bucket_id = $1 and name = $2
|
|
321
|
+
returning id`, [body.bucketId, body.sourceKey, dstBucket, body.destinationKey, ctx.claims?.sub ?? null]));
|
|
322
|
+
if (res.rows.length === 0)
|
|
323
|
+
return storageError(404, 'not_found', 'Object not found');
|
|
324
|
+
await this.driver.put(`${dstBucket}/${body.destinationKey}`, bytes);
|
|
325
|
+
return json(200, { Id: res.rows[0].id, Key: `${dstBucket}/${body.destinationKey}` });
|
|
326
|
+
}
|
|
327
|
+
async listObjects(req, ctx, bucketId) {
|
|
328
|
+
const body = (await req.json().catch(() => ({})));
|
|
329
|
+
let prefix = body.prefix ?? '';
|
|
330
|
+
if (prefix !== '' && !prefix.endsWith('/'))
|
|
331
|
+
prefix += '/';
|
|
332
|
+
const res = await this.db.withContext(ctx, (q) => q(`select * from storage.objects where bucket_id = $1 and name like $2 order by name`, [
|
|
333
|
+
bucketId,
|
|
334
|
+
`${likeEscape(prefix)}%`,
|
|
335
|
+
]));
|
|
336
|
+
const files = {};
|
|
337
|
+
const folders = new Set();
|
|
338
|
+
for (const row of res.rows) {
|
|
339
|
+
const relative = row.name.slice(prefix.length);
|
|
340
|
+
const slash = relative.indexOf('/');
|
|
341
|
+
if (slash === -1)
|
|
342
|
+
files[relative] = row;
|
|
343
|
+
else
|
|
344
|
+
folders.add(relative.slice(0, slash));
|
|
345
|
+
}
|
|
346
|
+
let entries = [
|
|
347
|
+
...[...folders].map((name) => ({ name, row: null })),
|
|
348
|
+
...Object.entries(files).map(([name, row]) => ({ name, row })),
|
|
349
|
+
];
|
|
350
|
+
if (body.search)
|
|
351
|
+
entries = entries.filter((e) => e.name.includes(body.search));
|
|
352
|
+
const column = body.sortBy?.column ?? 'name';
|
|
353
|
+
const asc = (body.sortBy?.order ?? 'asc') === 'asc';
|
|
354
|
+
entries.sort((a, b) => {
|
|
355
|
+
const av = column === 'name' ? a.name : String(a.row?.[column] ?? '');
|
|
356
|
+
const bv = column === 'name' ? b.name : String(b.row?.[column] ?? '');
|
|
357
|
+
return asc ? av.localeCompare(bv) : bv.localeCompare(av);
|
|
358
|
+
});
|
|
359
|
+
const offset = body.offset ?? 0;
|
|
360
|
+
const limit = body.limit ?? 100;
|
|
361
|
+
const page = entries.slice(offset, offset + limit);
|
|
362
|
+
return json(200, page.map((e) => e.row
|
|
363
|
+
? { ...objectJson(e.row), name: e.name }
|
|
364
|
+
: { name: e.name, id: null, updated_at: null, created_at: null, last_accessed_at: null, metadata: null }));
|
|
365
|
+
}
|
|
366
|
+
async objectInfo(ctx, bucketId, key) {
|
|
367
|
+
const res = await this.db.withContext(ctx, (q) => q(`select * from storage.objects where bucket_id = $1 and name = $2`, [bucketId, key]));
|
|
368
|
+
const row = res.rows[0];
|
|
369
|
+
if (!row)
|
|
370
|
+
return storageError(404, 'not_found', 'Object not found');
|
|
371
|
+
const meta = row.metadata ?? {};
|
|
372
|
+
return json(200, {
|
|
373
|
+
id: row.id,
|
|
374
|
+
name: row.name,
|
|
375
|
+
bucket_id: row.bucket_id,
|
|
376
|
+
size: meta.size ?? null,
|
|
377
|
+
content_type: meta.mimetype ?? null,
|
|
378
|
+
cache_control: meta.cacheControl ?? null,
|
|
379
|
+
etag: meta.eTag ?? null,
|
|
380
|
+
metadata: meta,
|
|
381
|
+
created_at: iso(row.created_at),
|
|
382
|
+
updated_at: iso(row.updated_at),
|
|
383
|
+
last_modified: meta.lastModified ?? null,
|
|
384
|
+
version: null,
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
// ── signed URLs ─────────────────────────────────────────────────────────
|
|
388
|
+
async signUrl(req, ctx, bucketId, key) {
|
|
389
|
+
const body = (await req.json().catch(() => ({})));
|
|
390
|
+
// visibility check under the caller's role
|
|
391
|
+
const res = await this.db.withContext(ctx, (q) => q(`select id from storage.objects where bucket_id = $1 and name = $2`, [bucketId, key]));
|
|
392
|
+
if (res.rows.length === 0)
|
|
393
|
+
return storageError(404, 'not_found', 'Object not found');
|
|
394
|
+
const token = await this.makeSignToken(bucketId, key, body.expiresIn ?? 3600);
|
|
395
|
+
return json(200, { signedURL: `/object/sign/${bucketId}/${encPath(key)}?token=${token}` });
|
|
396
|
+
}
|
|
397
|
+
async signUrls(req, ctx, bucketId) {
|
|
398
|
+
const body = (await req.json().catch(() => ({})));
|
|
399
|
+
const out = [];
|
|
400
|
+
for (const path of body.paths ?? []) {
|
|
401
|
+
const res = await this.db.withContext(ctx, (q) => q(`select id from storage.objects where bucket_id = $1 and name = $2`, [bucketId, path]));
|
|
402
|
+
if (res.rows.length === 0) {
|
|
403
|
+
out.push({ path, error: 'Object not found', signedURL: null });
|
|
404
|
+
}
|
|
405
|
+
else {
|
|
406
|
+
const token = await this.makeSignToken(bucketId, path, body.expiresIn ?? 3600);
|
|
407
|
+
out.push({ path, error: null, signedURL: `/object/sign/${bucketId}/${encPath(path)}?token=${token}` });
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
return json(200, out);
|
|
411
|
+
}
|
|
412
|
+
async redeemSignedUrl(url, bucketId, key) {
|
|
413
|
+
const token = url.searchParams.get('token') ?? '';
|
|
414
|
+
const claims = await verifyJwt(token, this.config.jwtSecret);
|
|
415
|
+
if (!claims || claims.url !== `${bucketId}/${key}`) {
|
|
416
|
+
return storageError(400, 'InvalidJWT', 'The provided token is invalid or expired');
|
|
417
|
+
}
|
|
418
|
+
const res = await this.db.query(`select * from storage.objects where bucket_id = $1 and name = $2`, [
|
|
419
|
+
bucketId,
|
|
420
|
+
key,
|
|
421
|
+
]);
|
|
422
|
+
const row = res.rows[0];
|
|
423
|
+
if (!row)
|
|
424
|
+
return storageError(404, 'not_found', 'Object not found');
|
|
425
|
+
return this.serveObject(row, bucketId, key, false);
|
|
426
|
+
}
|
|
427
|
+
async signUploadUrl(ctx, bucketId, key) {
|
|
428
|
+
const bucket = await this.loadBucket(bucketId);
|
|
429
|
+
if (!bucket)
|
|
430
|
+
return storageError(404, 'Bucket not found', 'Bucket not found');
|
|
431
|
+
const token = await this.makeSignToken(bucketId, key, 7200, ctx.claims?.sub);
|
|
432
|
+
return json(200, {
|
|
433
|
+
url: `/object/upload/sign/${bucketId}/${encPath(key)}?token=${token}`,
|
|
434
|
+
token,
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
async redeemSignedUpload(req, url, bucketId, key) {
|
|
438
|
+
const token = url.searchParams.get('token') ?? '';
|
|
439
|
+
const claims = await verifyJwt(token, this.config.jwtSecret);
|
|
440
|
+
if (!claims || claims.url !== `${bucketId}/${key}`) {
|
|
441
|
+
return storageError(400, 'InvalidJWT', 'The provided token is invalid or expired');
|
|
442
|
+
}
|
|
443
|
+
return this.upload(req, SERVICE_CTX, bucketId, key);
|
|
444
|
+
}
|
|
445
|
+
makeSignToken(bucketId, key, expiresIn, owner) {
|
|
446
|
+
const now = Math.floor(Date.now() / 1000);
|
|
447
|
+
return signJwt({ url: `${bucketId}/${key}`, iat: now, exp: now + expiresIn, owner }, this.config.jwtSecret);
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
function bucketJson(b) {
|
|
451
|
+
return {
|
|
452
|
+
id: b.id,
|
|
453
|
+
name: b.name,
|
|
454
|
+
owner: '',
|
|
455
|
+
public: b.public,
|
|
456
|
+
file_size_limit: b.file_size_limit === null ? null : Number(b.file_size_limit),
|
|
457
|
+
allowed_mime_types: b.allowed_mime_types,
|
|
458
|
+
created_at: iso(b.created_at),
|
|
459
|
+
updated_at: iso(b.updated_at),
|
|
460
|
+
};
|
|
461
|
+
}
|
|
462
|
+
function objectJson(r) {
|
|
463
|
+
return {
|
|
464
|
+
name: r.name,
|
|
465
|
+
bucket_id: r.bucket_id,
|
|
466
|
+
owner: r.owner ?? '',
|
|
467
|
+
id: r.id,
|
|
468
|
+
updated_at: iso(r.updated_at),
|
|
469
|
+
created_at: iso(r.created_at),
|
|
470
|
+
last_accessed_at: iso(r.last_accessed_at),
|
|
471
|
+
metadata: r.metadata ?? {},
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
function parseSizeLimit(v) {
|
|
475
|
+
if (v === null || v === undefined)
|
|
476
|
+
return null;
|
|
477
|
+
if (typeof v === 'number')
|
|
478
|
+
return v;
|
|
479
|
+
const m = v.match(/^(\d+(?:\.\d+)?)\s*(b|kb|mb|gb)?$/i);
|
|
480
|
+
if (!m)
|
|
481
|
+
return null;
|
|
482
|
+
const mult = { b: 1, kb: 1024, mb: 1024 ** 2, gb: 1024 ** 3 }[(m[2] ?? 'b').toLowerCase()];
|
|
483
|
+
return Math.floor(parseFloat(m[1]) * mult);
|
|
484
|
+
}
|
|
485
|
+
/** Minimal byte-safe multipart/form-data parser (works identically on Node, Bun, browsers). */
|
|
486
|
+
export function parseMultipart(bytes, boundary) {
|
|
487
|
+
const enc = new TextEncoder();
|
|
488
|
+
const dec = new TextDecoder();
|
|
489
|
+
const delim = enc.encode(`--${boundary}`);
|
|
490
|
+
const parts = [];
|
|
491
|
+
const indexOf = (needle, from) => {
|
|
492
|
+
outer: for (let i = from; i <= bytes.length - needle.length; i++) {
|
|
493
|
+
for (let j = 0; j < needle.length; j++) {
|
|
494
|
+
if (bytes[i + j] !== needle[j])
|
|
495
|
+
continue outer;
|
|
496
|
+
}
|
|
497
|
+
return i;
|
|
498
|
+
}
|
|
499
|
+
return -1;
|
|
500
|
+
};
|
|
501
|
+
let pos = indexOf(delim, 0);
|
|
502
|
+
while (pos !== -1) {
|
|
503
|
+
const headerStart = pos + delim.length + 2; // skip \r\n (or "--" at the end)
|
|
504
|
+
if (bytes[pos + delim.length] === 0x2d && bytes[pos + delim.length + 1] === 0x2d)
|
|
505
|
+
break;
|
|
506
|
+
const headerEnd = indexOf(enc.encode('\r\n\r\n'), headerStart);
|
|
507
|
+
if (headerEnd === -1)
|
|
508
|
+
break;
|
|
509
|
+
const headerText = dec.decode(bytes.subarray(headerStart, headerEnd));
|
|
510
|
+
const next = indexOf(delim, headerEnd + 4);
|
|
511
|
+
if (next === -1)
|
|
512
|
+
break;
|
|
513
|
+
const data = bytes.subarray(headerEnd + 4, next - 2); // strip trailing \r\n
|
|
514
|
+
const disposition = headerText.match(/content-disposition:[^\r\n]*/i)?.[0] ?? '';
|
|
515
|
+
parts.push({
|
|
516
|
+
name: disposition.match(/[^a-z]name="([^"]*)"/i)?.[1] ?? '',
|
|
517
|
+
filename: disposition.match(/filename="([^"]*)"/i)?.[1],
|
|
518
|
+
contentType: headerText.match(/content-type:\s*([^\r\n;]+)/i)?.[1]?.trim(),
|
|
519
|
+
data: new Uint8Array(data),
|
|
520
|
+
});
|
|
521
|
+
pos = next;
|
|
522
|
+
}
|
|
523
|
+
return parts;
|
|
524
|
+
}
|
|
525
|
+
function likeEscape(s) {
|
|
526
|
+
return s.replaceAll('\\', '\\\\').replaceAll('%', '\\%').replaceAll('_', '\\_');
|
|
527
|
+
}
|
|
528
|
+
function encPath(key) {
|
|
529
|
+
return key.split('/').map(encodeURIComponent).join('/');
|
|
530
|
+
}
|
|
531
|
+
function dec(s) {
|
|
532
|
+
return decodeURIComponent(s);
|
|
533
|
+
}
|
|
534
|
+
//# sourceMappingURL=handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"handler.js","sourceRoot":"","sources":["../../src/storage/handler.ts"],"names":[],"mappings":"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"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { JwtClaims } from './jwt.js';
|
|
2
|
+
export interface MigrationFile {
|
|
3
|
+
/** e.g. "20240101120000_create_posts" (no extension) */
|
|
4
|
+
name: string;
|
|
5
|
+
sql: string;
|
|
6
|
+
}
|
|
7
|
+
export interface BackendConfig {
|
|
8
|
+
/**
|
|
9
|
+
* PGlite data directory. Node: a filesystem path. Browser: "idb://name" or
|
|
10
|
+
* "opfs-ahp://name". Omit for in-memory. Ignored when `engine` is set.
|
|
11
|
+
*/
|
|
12
|
+
dataDir?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Custom database engine (e.g. the native embedded Postgres engine from
|
|
15
|
+
* "tinbase/node"). Default: PGlite on `dataDir`.
|
|
16
|
+
*/
|
|
17
|
+
engine?: import('./db/engine.js').DbEngine;
|
|
18
|
+
/** Secret used to sign/verify every JWT. Defaults to the Supabase local-dev secret. */
|
|
19
|
+
jwtSecret?: string;
|
|
20
|
+
/** External URL of this backend, used as JWT issuer. */
|
|
21
|
+
siteUrl?: string;
|
|
22
|
+
/** Access token lifetime in seconds (default 3600). */
|
|
23
|
+
jwtExpiry?: number;
|
|
24
|
+
/** Migrations to apply on boot (Supabase CLI convention: sorted by name). */
|
|
25
|
+
migrations?: MigrationFile[];
|
|
26
|
+
/** SQL from supabase/seed.sql, applied once after the first migration run. */
|
|
27
|
+
seedSql?: string;
|
|
28
|
+
/** Where object storage bytes live. Default: in-memory. Node CLI passes a fs driver. */
|
|
29
|
+
storageDriver?: StorageDriver;
|
|
30
|
+
/** Print startup/debug logs. */
|
|
31
|
+
log?: (msg: string) => void;
|
|
32
|
+
}
|
|
33
|
+
export declare const DEFAULT_JWT_SECRET = "super-secret-jwt-token-with-at-least-32-characters-long";
|
|
34
|
+
/** Per-request execution context derived from apikey/Authorization headers. */
|
|
35
|
+
export interface RequestContext {
|
|
36
|
+
/** Postgres role to SET LOCAL: anon | authenticated | service_role */
|
|
37
|
+
role: string;
|
|
38
|
+
/** Verified JWT claims (published to request.jwt.claims for RLS). */
|
|
39
|
+
claims: JwtClaims | null;
|
|
40
|
+
}
|
|
41
|
+
export interface StorageDriver {
|
|
42
|
+
put(key: string, data: Uint8Array): Promise<void>;
|
|
43
|
+
get(key: string): Promise<Uint8Array | null>;
|
|
44
|
+
delete(key: string): Promise<void>;
|
|
45
|
+
deleteMany(keys: string[]): Promise<void>;
|
|
46
|
+
}
|
|
47
|
+
export declare class ApiError extends Error {
|
|
48
|
+
status: number;
|
|
49
|
+
body: Record<string, unknown>;
|
|
50
|
+
constructor(status: number, body: Record<string, unknown>);
|
|
51
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const DEFAULT_JWT_SECRET = 'super-secret-jwt-token-with-at-least-32-characters-long';
|
|
2
|
+
export class ApiError extends Error {
|
|
3
|
+
status;
|
|
4
|
+
body;
|
|
5
|
+
constructor(status, body) {
|
|
6
|
+
super(typeof body.message === 'string' ? body.message : JSON.stringify(body));
|
|
7
|
+
this.status = status;
|
|
8
|
+
this.body = body;
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAmCA,MAAM,CAAC,MAAM,kBAAkB,GAAG,yDAAyD,CAAA;AAiB3F,MAAM,OAAO,QAAS,SAAQ,KAAK;IAExB;IACA;IAFT,YACS,MAAc,EACd,IAA6B;QAEpC,KAAK,CAAC,OAAO,IAAI,CAAC,OAAO,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAA;QAHtE,WAAM,GAAN,MAAM,CAAQ;QACd,SAAI,GAAJ,IAAI,CAAyB;IAGtC,CAAC;CACF"}
|