@supacloud/lite 0.31.1 → 0.31.3
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/CHANGELOG.md +19 -0
- package/dist/cli.js +112 -55
- package/dist/index.js +112 -55
- package/dist/runtime/auth/handler.d.ts.map +1 -1
- package/dist/runtime/storage/handler.d.ts.map +1 -1
- package/dist/runtime/storage/image-transform.d.ts +1 -0
- package/dist/runtime/storage/image-transform.d.ts.map +1 -1
- package/package.json +13 -13
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,24 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.31.3](https://github.com/vibeunion/supacloud/compare/supacloud-lite-v0.31.2...supacloud-lite-v0.31.3) (2026-10-17)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **cli:** align verification target resolution ([#2052](https://github.com/vibeunion/supacloud/issues/2052)) ([3cfcc36](https://github.com/vibeunion/supacloud/commit/3cfcc362f87ecdaf82a4df303f5af436875fb36e))
|
|
9
|
+
* **lite:** align default storage size limit ([#2053](https://github.com/vibeunion/supacloud/issues/2053)) ([8414234](https://github.com/vibeunion/supacloud/commit/8414234d72fc42440ea1133646d6b11422097a4a))
|
|
10
|
+
* **lite:** validate image size metadata ([#2046](https://github.com/vibeunion/supacloud/issues/2046)) ([9ea248e](https://github.com/vibeunion/supacloud/commit/9ea248ecca9cebf5b1bba8b70ea50195613d1f3d))
|
|
11
|
+
* **supacloud-lite:** bind email tokens to current account address ([#2047](https://github.com/vibeunion/supacloud/issues/2047)) ([355d08c](https://github.com/vibeunion/supacloud/commit/355d08cdbc7d0d90085a2208557f1decc1d15e82))
|
|
12
|
+
|
|
13
|
+
## [0.31.2](https://github.com/vibeunion/supacloud/compare/supacloud-lite-v0.31.1...supacloud-lite-v0.31.2) (2026-10-17)
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
### Bug Fixes
|
|
17
|
+
|
|
18
|
+
* **cli:** sync published compiler dependency ([#2041](https://github.com/vibeunion/supacloud/issues/2041)) ([be44641](https://github.com/vibeunion/supacloud/commit/be446416b87bf009eec892bc20368e3595d7326a))
|
|
19
|
+
* **lite:** preflight image transformation size ([#2037](https://github.com/vibeunion/supacloud/issues/2037)) ([fd0e790](https://github.com/vibeunion/supacloud/commit/fd0e790a18513dfd7fa1682b7e72c0a147f392cc))
|
|
20
|
+
* recheck password issuance and align published tool dependencies ([#2039](https://github.com/vibeunion/supacloud/issues/2039)) ([250b1af](https://github.com/vibeunion/supacloud/commit/250b1afef3f78d6dd4ab34e94147f65beb8a8677))
|
|
21
|
+
|
|
3
22
|
## [0.31.1](https://github.com/vibeunion/supacloud/compare/supacloud-lite-v0.31.0...supacloud-lite-v0.31.1) (2026-10-17)
|
|
4
23
|
|
|
5
24
|
|
package/dist/cli.js
CHANGED
|
@@ -8,7 +8,7 @@ import { dirname as dirname8, join as join10, resolve as resolve6 } from "path";
|
|
|
8
8
|
// package.json
|
|
9
9
|
var package_default = {
|
|
10
10
|
name: "@supacloud/lite",
|
|
11
|
-
version: "0.31.
|
|
11
|
+
version: "0.31.3",
|
|
12
12
|
description: "Bun-native, single-project Supabase-compatible backend powered by PGlite or native PostgreSQL",
|
|
13
13
|
type: "module",
|
|
14
14
|
license: "Apache-2.0",
|
|
@@ -67,16 +67,16 @@ var package_default = {
|
|
|
67
67
|
"@electric-sql/pglite-pgmq": "0.0.8",
|
|
68
68
|
"@electric-sql/pglite-pgvector": "0.0.11",
|
|
69
69
|
"@electric-sql/pglite-postgis": "0.2.10",
|
|
70
|
-
"@supacloud/db": "0.18.
|
|
70
|
+
"@supacloud/db": "0.18.4",
|
|
71
71
|
"exact-mirror": "1.2.6",
|
|
72
72
|
tar: "^7.5.22",
|
|
73
73
|
typebox: "1.3.37"
|
|
74
74
|
},
|
|
75
75
|
devDependencies: {
|
|
76
|
-
"@supacloud/app": "0.28.
|
|
77
|
-
"@supacloud/contracts": "0.11.
|
|
78
|
-
"@supacloud/compiler": "0.47.
|
|
79
|
-
"@supacloud/elysia": "0.33.
|
|
76
|
+
"@supacloud/app": "0.28.3",
|
|
77
|
+
"@supacloud/contracts": "0.11.5",
|
|
78
|
+
"@supacloud/compiler": "0.47.3",
|
|
79
|
+
"@supacloud/elysia": "0.33.5",
|
|
80
80
|
"@supabase/supabase-js": "^2.117.3",
|
|
81
81
|
"@types/bun": "^1.4.3",
|
|
82
82
|
effect: "4.0.5",
|
|
@@ -85,13 +85,13 @@ var package_default = {
|
|
|
85
85
|
typescript: "^7.0.2"
|
|
86
86
|
},
|
|
87
87
|
overrides: {
|
|
88
|
-
"@supacloud/db": "0.18.
|
|
89
|
-
"@supacloud/app": "0.28.
|
|
90
|
-
"@supacloud/compiler": "0.47.
|
|
91
|
-
"@supacloud/elysia": "0.33.
|
|
92
|
-
"@supacloud/contracts": "0.11.
|
|
93
|
-
"@supacloud/commands": "0.9.
|
|
94
|
-
"@supacloud/delivery": "0.19.
|
|
88
|
+
"@supacloud/db": "0.18.4",
|
|
89
|
+
"@supacloud/app": "0.28.3",
|
|
90
|
+
"@supacloud/compiler": "0.47.3",
|
|
91
|
+
"@supacloud/elysia": "0.33.5",
|
|
92
|
+
"@supacloud/contracts": "0.11.5",
|
|
93
|
+
"@supacloud/commands": "0.9.7",
|
|
94
|
+
"@supacloud/delivery": "0.19.4",
|
|
95
95
|
"@graphql-tools/utils": "^12.0.4"
|
|
96
96
|
},
|
|
97
97
|
engines: {
|
|
@@ -1464,12 +1464,33 @@ class AuthHandler {
|
|
|
1464
1464
|
await this.audit("login_failed", { actorEmail: email, traits: { grant_type: "password" } });
|
|
1465
1465
|
return authError(400, "invalid_credentials", "Invalid login credentials");
|
|
1466
1466
|
}
|
|
1467
|
-
|
|
1468
|
-
|
|
1467
|
+
const response = await this.db.transaction(async (query) => {
|
|
1468
|
+
const currentResult = await query(`select *, coalesce(banned_until > now(), false) as is_banned
|
|
1469
|
+
from auth.users where id = $1 for update`, [user.id]);
|
|
1470
|
+
const current = currentResult.rows[0];
|
|
1471
|
+
if (!current || current.deleted_at !== null || !current.encrypted_password || current.email !== email) {
|
|
1472
|
+
return authError(400, "invalid_credentials", "Invalid login credentials");
|
|
1473
|
+
}
|
|
1474
|
+
if (current.is_banned) {
|
|
1475
|
+
return authError(400, "user_banned", "User is banned");
|
|
1476
|
+
}
|
|
1477
|
+
if (current.encrypted_password !== user.encrypted_password) {
|
|
1478
|
+
return authError(400, "invalid_credentials", "Invalid login credentials");
|
|
1479
|
+
}
|
|
1480
|
+
if (!this.settings.autoconfirm && !current.email_confirmed_at) {
|
|
1481
|
+
return authError(400, "email_not_confirmed", "Email not confirmed");
|
|
1482
|
+
}
|
|
1483
|
+
const signedIn = await query(`update auth.users set last_sign_in_at = now() where id = $1 returning *`, [current.id]);
|
|
1484
|
+
const updated = signedIn.rows[0];
|
|
1485
|
+
if (!updated) {
|
|
1486
|
+
return authError(400, "invalid_credentials", "Invalid login credentials");
|
|
1487
|
+
}
|
|
1488
|
+
return json(200, await this.sessionFor(updated, undefined, undefined, query));
|
|
1489
|
+
});
|
|
1490
|
+
if (response.ok) {
|
|
1491
|
+
await this.audit("login", { actorId: user.id, actorEmail: email, traits: { grant_type: "password" } });
|
|
1469
1492
|
}
|
|
1470
|
-
|
|
1471
|
-
await this.audit("login", { actorId: user.id, actorEmail: user.email, traits: { grant_type: "password" } });
|
|
1472
|
-
return json(200, await this.sessionFor(user));
|
|
1493
|
+
return response;
|
|
1473
1494
|
}
|
|
1474
1495
|
if (grantType === "refresh_token") {
|
|
1475
1496
|
const token = body.refresh_token;
|
|
@@ -1505,16 +1526,6 @@ class AuthHandler {
|
|
|
1505
1526
|
if (body.email && !this.settings.autoconfirm) {
|
|
1506
1527
|
return authError(501, "email_change_confirmation_not_supported", "Email changes that require confirmation are not supported by SupaCloud Lite V1");
|
|
1507
1528
|
}
|
|
1508
|
-
const upgradingAnon = (user.is_anonymous ?? false) && !!body.email;
|
|
1509
|
-
if (body.email) {
|
|
1510
|
-
const email = body.email.toLowerCase().trim();
|
|
1511
|
-
const clash = await this.db.query(`select id from auth.users where email = $1 and id <> $2`, [email, user.id]);
|
|
1512
|
-
if (clash.rows.length > 0) {
|
|
1513
|
-
return authError(422, "email_exists", "A user with this email address has already been registered");
|
|
1514
|
-
}
|
|
1515
|
-
params.push(email);
|
|
1516
|
-
sets.push(`email = $${params.length}, email_confirmed_at = now()`);
|
|
1517
|
-
}
|
|
1518
1529
|
if (body.password) {
|
|
1519
1530
|
if (body.password.length < this.settings.minPasswordLength) {
|
|
1520
1531
|
return authError(422, "weak_password", `Password should be at least ${this.settings.minPasswordLength} characters.`);
|
|
@@ -1526,22 +1537,41 @@ class AuthHandler {
|
|
|
1526
1537
|
params.push(JSON.stringify(body.data));
|
|
1527
1538
|
sets.push(`raw_user_meta_data = coalesce(raw_user_meta_data, '{}'::jsonb) || $${params.length}::jsonb`);
|
|
1528
1539
|
}
|
|
1529
|
-
|
|
1530
|
-
|
|
1531
|
-
|
|
1532
|
-
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
+
const response = await this.db.transaction(async (query) => {
|
|
1541
|
+
const currentResult = await query(`select * from auth.users where id = $1 and deleted_at is null
|
|
1542
|
+
and (banned_until is null or banned_until <= now()) for update`, [user.id]);
|
|
1543
|
+
const current = currentResult.rows[0];
|
|
1544
|
+
if (!current)
|
|
1545
|
+
return authError(401, "no_authorization", "Invalid or expired token");
|
|
1546
|
+
const transactionSets = [...sets];
|
|
1547
|
+
const transactionParams = [...params];
|
|
1548
|
+
const upgradingAnon = (current.is_anonymous ?? false) && !!body.email;
|
|
1549
|
+
if (body.email) {
|
|
1550
|
+
const email = body.email.toLowerCase().trim();
|
|
1551
|
+
const clash = await query(`select id from auth.users where email = $1 and id <> $2`, [email, current.id]);
|
|
1552
|
+
if (clash.rows.length > 0) {
|
|
1553
|
+
return authError(422, "email_exists", "A user with this email address has already been registered");
|
|
1554
|
+
}
|
|
1555
|
+
transactionParams.push(email);
|
|
1556
|
+
transactionSets.push(`email = $${transactionParams.length}, email_confirmed_at = now()`);
|
|
1557
|
+
}
|
|
1558
|
+
if (upgradingAnon) {
|
|
1559
|
+
transactionSets.push(`is_anonymous = false`);
|
|
1560
|
+
transactionSets.push(`raw_app_meta_data = coalesce(raw_app_meta_data, '{}'::jsonb) || '{"provider":"email","providers":["email"]}'::jsonb`);
|
|
1561
|
+
}
|
|
1562
|
+
if (transactionSets.length === 0) {
|
|
1563
|
+
return json(200, await this.userJsonWithRelations(current, query));
|
|
1564
|
+
}
|
|
1565
|
+
transactionParams.push(current.id);
|
|
1566
|
+
const updatedResult = await query(`update auth.users set ${transactionSets.join(", ")}, updated_at = now() where id = $${transactionParams.length} returning *`, transactionParams);
|
|
1567
|
+
const updated = updatedResult.rows[0];
|
|
1568
|
+
if (!updated)
|
|
1569
|
+
return authError(401, "no_authorization", "Invalid or expired token");
|
|
1540
1570
|
if (body.email)
|
|
1541
1571
|
await this.ensureEmailIdentity(updated, query);
|
|
1542
|
-
return this.userJsonWithRelations(updated, query);
|
|
1572
|
+
return json(200, await this.userJsonWithRelations(updated, query));
|
|
1543
1573
|
});
|
|
1544
|
-
return
|
|
1574
|
+
return response;
|
|
1545
1575
|
}
|
|
1546
1576
|
async logout(req, url) {
|
|
1547
1577
|
const claims = await this.claimsFromBearer(req);
|
|
@@ -1795,8 +1825,8 @@ Or sign in with this link: ${link}`
|
|
|
1795
1825
|
return claimedToken ? this.confirmEmailTokenUser(query, claimedToken) : null;
|
|
1796
1826
|
}
|
|
1797
1827
|
async lockAndDeleteEmailToken(query, candidate, redemption) {
|
|
1798
|
-
const eligible = await query(`select id from auth.users where id = $1 and
|
|
1799
|
-
and (banned_until is null or banned_until <= now()) for update`, [candidate.user_id]);
|
|
1828
|
+
const eligible = await query(`select id from auth.users where id = $1 and lower(email) = lower($2)
|
|
1829
|
+
and deleted_at is null and (banned_until is null or banned_until <= now()) for update`, [candidate.user_id, candidate.email]);
|
|
1800
1830
|
if (eligible.rows.length === 0)
|
|
1801
1831
|
return null;
|
|
1802
1832
|
const claimedTokens = await query(`delete from auth.one_time_tokens
|
|
@@ -1859,11 +1889,10 @@ Or sign in with this link: ${link}`
|
|
|
1859
1889
|
async redeemPhoneOtp(phone, code) {
|
|
1860
1890
|
const tokenDigest = `hmac-sha256:v1:${await keyedDigest(this.config.jwtSecret, "supacloud-lite:phone-otp:v1", `${phone}\x00${code}`)}`;
|
|
1861
1891
|
return this.db.transaction(async (query) => {
|
|
1862
|
-
const
|
|
1892
|
+
const candidate = await query(`select user_id from auth.one_time_tokens
|
|
1863
1893
|
where phone = $1 and token_type = 'sms' and token = $2
|
|
1864
|
-
and expires_at > now() and attempts < $3
|
|
1865
|
-
|
|
1866
|
-
const userId = claimed.rows[0]?.user_id;
|
|
1894
|
+
and expires_at > now() and attempts < $3`, [phone, tokenDigest, AuthHandler.MAX_OTP_ATTEMPTS]);
|
|
1895
|
+
const userId = candidate.rows[0]?.user_id;
|
|
1867
1896
|
if (!userId) {
|
|
1868
1897
|
const attempt = await query(`update auth.one_time_tokens set attempts = attempts + 1
|
|
1869
1898
|
where phone = $1 and token_type = 'sms' and expires_at > now()
|
|
@@ -1875,6 +1904,22 @@ Or sign in with this link: ${link}`
|
|
|
1875
1904
|
await query(`delete from auth.one_time_tokens where phone = $1 and expires_at <= now()`, [phone]);
|
|
1876
1905
|
return null;
|
|
1877
1906
|
}
|
|
1907
|
+
const currentUser = await query(`select phone,
|
|
1908
|
+
deleted_at is null and (banned_until is null or banned_until <= now()) as auth_eligible
|
|
1909
|
+
from auth.users where id = $1 for update`, [userId]);
|
|
1910
|
+
const current = currentUser.rows[0];
|
|
1911
|
+
if (!current || current.phone !== phone)
|
|
1912
|
+
return null;
|
|
1913
|
+
if (!current.auth_eligible) {
|
|
1914
|
+
await query(`delete from auth.one_time_tokens where phone = $1`, [phone]);
|
|
1915
|
+
return null;
|
|
1916
|
+
}
|
|
1917
|
+
const claimed = await query(`delete from auth.one_time_tokens
|
|
1918
|
+
where phone = $1 and token_type = 'sms' and token = $2
|
|
1919
|
+
and expires_at > now() and attempts < $3 and user_id = $4
|
|
1920
|
+
returning user_id`, [phone, tokenDigest, AuthHandler.MAX_OTP_ATTEMPTS, userId]);
|
|
1921
|
+
if (claimed.rows.length === 0)
|
|
1922
|
+
return null;
|
|
1878
1923
|
await query(`delete from auth.one_time_tokens where phone = $1`, [phone]);
|
|
1879
1924
|
const users = await query(`update auth.users
|
|
1880
1925
|
set phone_confirmed_at = coalesce(phone_confirmed_at, now()), last_sign_in_at = now(), updated_at = now()
|
|
@@ -2180,6 +2225,9 @@ Or sign in with this link: ${link}`
|
|
|
2180
2225
|
const user = await this.userFromBearer(req);
|
|
2181
2226
|
if (!user)
|
|
2182
2227
|
return authError(401, "no_authorization", "This endpoint requires a Bearer token");
|
|
2228
|
+
if (!this.settings.totpVerifyEnabled) {
|
|
2229
|
+
return authError(422, "mfa_totp_verify_disabled", "TOTP verification is disabled");
|
|
2230
|
+
}
|
|
2183
2231
|
const body = await req.json().catch(() => ({}));
|
|
2184
2232
|
const fr = await this.db.query(`select id, secret, status from auth.mfa_factors where id = $1 and user_id = $2`, [factorId, user.id]);
|
|
2185
2233
|
const factor = fr.rows[0];
|
|
@@ -9066,6 +9114,14 @@ function resolveImageTransformLimits(options = {}) {
|
|
|
9066
9114
|
}
|
|
9067
9115
|
return { maxInputBytes, maxOutputBytes };
|
|
9068
9116
|
}
|
|
9117
|
+
function imageTransformInputTooLarge(maxInputBytes) {
|
|
9118
|
+
return {
|
|
9119
|
+
ok: false,
|
|
9120
|
+
status: 413,
|
|
9121
|
+
error: "ImageTooLarge",
|
|
9122
|
+
message: `The source image exceeds the transformation limit (${maxInputBytes} bytes)`
|
|
9123
|
+
};
|
|
9124
|
+
}
|
|
9069
9125
|
function invalid(message) {
|
|
9070
9126
|
return { ok: false, status: 400, error: "InvalidTransformation", message };
|
|
9071
9127
|
}
|
|
@@ -9209,14 +9265,10 @@ function applyResize(image, metadata, options) {
|
|
|
9209
9265
|
async function transformImage(source, options, knownSourceSize, configuredLimits = {}) {
|
|
9210
9266
|
const limits = resolveImageTransformLimits(configuredLimits);
|
|
9211
9267
|
const actualSourceSize = source instanceof Uint8Array ? source.byteLength : await Promise.resolve(source.size);
|
|
9212
|
-
const
|
|
9268
|
+
const declaredSourceSize = typeof knownSourceSize === "number" && Number.isFinite(knownSourceSize) && knownSourceSize >= 0 ? knownSourceSize : 0;
|
|
9269
|
+
const sourceSize = Math.max(declaredSourceSize, actualSourceSize);
|
|
9213
9270
|
if (sourceSize > limits.maxInputBytes) {
|
|
9214
|
-
return
|
|
9215
|
-
ok: false,
|
|
9216
|
-
status: 413,
|
|
9217
|
-
error: "ImageTooLarge",
|
|
9218
|
-
message: `The source image exceeds the transformation limit (${limits.maxInputBytes} bytes)`
|
|
9219
|
-
};
|
|
9271
|
+
return imageTransformInputTooLarge(limits.maxInputBytes);
|
|
9220
9272
|
}
|
|
9221
9273
|
const image = new Bun.Image(source, { maxPixels: MAX_TRANSFORM_PIXELS });
|
|
9222
9274
|
let metadata;
|
|
@@ -9440,7 +9492,7 @@ function isRenderableActiveType(contentType) {
|
|
|
9440
9492
|
return t === "text/html" || t === "application/xhtml+xml" || t === "image/svg+xml" || t === "application/xml" || t === "text/xml";
|
|
9441
9493
|
}
|
|
9442
9494
|
var TUS_VERSION = "1.0.0";
|
|
9443
|
-
var DEFAULT_FILE_SIZE_LIMIT =
|
|
9495
|
+
var DEFAULT_FILE_SIZE_LIMIT = 500 * 1024 * 1024;
|
|
9444
9496
|
var MULTIPART_OVERHEAD_LIMIT = 1024 * 1024;
|
|
9445
9497
|
var MAX_CONCURRENT_TUS_UPLOADS = 4;
|
|
9446
9498
|
var MAX_COMPLETED_TUS_UPLOADS = 64;
|
|
@@ -9731,6 +9783,11 @@ class StorageHandler {
|
|
|
9731
9783
|
const parsed = parseImageTransform(url.searchParams);
|
|
9732
9784
|
if (!parsed.ok)
|
|
9733
9785
|
return storageError(parsed.status, parsed.error, parsed.message);
|
|
9786
|
+
const declaredSize = objectSize(row);
|
|
9787
|
+
if (declaredSize !== undefined && declaredSize > this.transformLimits.maxInputBytes) {
|
|
9788
|
+
const rejected = imageTransformInputTooLarge(this.transformLimits.maxInputBytes);
|
|
9789
|
+
return storageError(rejected.status, rejected.error, rejected.message);
|
|
9790
|
+
}
|
|
9734
9791
|
let result;
|
|
9735
9792
|
try {
|
|
9736
9793
|
result = await this.imageTransforms.getOrTransform(imageTransformCacheKey(row.version, parsed.value), async () => {
|
package/dist/index.js
CHANGED
|
@@ -88,7 +88,7 @@ function randomToken(bytes = 32) {
|
|
|
88
88
|
// package.json
|
|
89
89
|
var package_default = {
|
|
90
90
|
name: "@supacloud/lite",
|
|
91
|
-
version: "0.31.
|
|
91
|
+
version: "0.31.3",
|
|
92
92
|
description: "Bun-native, single-project Supabase-compatible backend powered by PGlite or native PostgreSQL",
|
|
93
93
|
type: "module",
|
|
94
94
|
license: "Apache-2.0",
|
|
@@ -147,16 +147,16 @@ var package_default = {
|
|
|
147
147
|
"@electric-sql/pglite-pgmq": "0.0.8",
|
|
148
148
|
"@electric-sql/pglite-pgvector": "0.0.11",
|
|
149
149
|
"@electric-sql/pglite-postgis": "0.2.10",
|
|
150
|
-
"@supacloud/db": "0.18.
|
|
150
|
+
"@supacloud/db": "0.18.4",
|
|
151
151
|
"exact-mirror": "1.2.6",
|
|
152
152
|
tar: "^7.5.22",
|
|
153
153
|
typebox: "1.3.37"
|
|
154
154
|
},
|
|
155
155
|
devDependencies: {
|
|
156
|
-
"@supacloud/app": "0.28.
|
|
157
|
-
"@supacloud/contracts": "0.11.
|
|
158
|
-
"@supacloud/compiler": "0.47.
|
|
159
|
-
"@supacloud/elysia": "0.33.
|
|
156
|
+
"@supacloud/app": "0.28.3",
|
|
157
|
+
"@supacloud/contracts": "0.11.5",
|
|
158
|
+
"@supacloud/compiler": "0.47.3",
|
|
159
|
+
"@supacloud/elysia": "0.33.5",
|
|
160
160
|
"@supabase/supabase-js": "^2.117.3",
|
|
161
161
|
"@types/bun": "^1.4.3",
|
|
162
162
|
effect: "4.0.5",
|
|
@@ -165,13 +165,13 @@ var package_default = {
|
|
|
165
165
|
typescript: "^7.0.2"
|
|
166
166
|
},
|
|
167
167
|
overrides: {
|
|
168
|
-
"@supacloud/db": "0.18.
|
|
169
|
-
"@supacloud/app": "0.28.
|
|
170
|
-
"@supacloud/compiler": "0.47.
|
|
171
|
-
"@supacloud/elysia": "0.33.
|
|
172
|
-
"@supacloud/contracts": "0.11.
|
|
173
|
-
"@supacloud/commands": "0.9.
|
|
174
|
-
"@supacloud/delivery": "0.19.
|
|
168
|
+
"@supacloud/db": "0.18.4",
|
|
169
|
+
"@supacloud/app": "0.28.3",
|
|
170
|
+
"@supacloud/compiler": "0.47.3",
|
|
171
|
+
"@supacloud/elysia": "0.33.5",
|
|
172
|
+
"@supacloud/contracts": "0.11.5",
|
|
173
|
+
"@supacloud/commands": "0.9.7",
|
|
174
|
+
"@supacloud/delivery": "0.19.4",
|
|
175
175
|
"@graphql-tools/utils": "^12.0.4"
|
|
176
176
|
},
|
|
177
177
|
engines: {
|
|
@@ -1470,12 +1470,33 @@ class AuthHandler {
|
|
|
1470
1470
|
await this.audit("login_failed", { actorEmail: email, traits: { grant_type: "password" } });
|
|
1471
1471
|
return authError(400, "invalid_credentials", "Invalid login credentials");
|
|
1472
1472
|
}
|
|
1473
|
-
|
|
1474
|
-
|
|
1473
|
+
const response = await this.db.transaction(async (query) => {
|
|
1474
|
+
const currentResult = await query(`select *, coalesce(banned_until > now(), false) as is_banned
|
|
1475
|
+
from auth.users where id = $1 for update`, [user.id]);
|
|
1476
|
+
const current = currentResult.rows[0];
|
|
1477
|
+
if (!current || current.deleted_at !== null || !current.encrypted_password || current.email !== email) {
|
|
1478
|
+
return authError(400, "invalid_credentials", "Invalid login credentials");
|
|
1479
|
+
}
|
|
1480
|
+
if (current.is_banned) {
|
|
1481
|
+
return authError(400, "user_banned", "User is banned");
|
|
1482
|
+
}
|
|
1483
|
+
if (current.encrypted_password !== user.encrypted_password) {
|
|
1484
|
+
return authError(400, "invalid_credentials", "Invalid login credentials");
|
|
1485
|
+
}
|
|
1486
|
+
if (!this.settings.autoconfirm && !current.email_confirmed_at) {
|
|
1487
|
+
return authError(400, "email_not_confirmed", "Email not confirmed");
|
|
1488
|
+
}
|
|
1489
|
+
const signedIn = await query(`update auth.users set last_sign_in_at = now() where id = $1 returning *`, [current.id]);
|
|
1490
|
+
const updated = signedIn.rows[0];
|
|
1491
|
+
if (!updated) {
|
|
1492
|
+
return authError(400, "invalid_credentials", "Invalid login credentials");
|
|
1493
|
+
}
|
|
1494
|
+
return json(200, await this.sessionFor(updated, undefined, undefined, query));
|
|
1495
|
+
});
|
|
1496
|
+
if (response.ok) {
|
|
1497
|
+
await this.audit("login", { actorId: user.id, actorEmail: email, traits: { grant_type: "password" } });
|
|
1475
1498
|
}
|
|
1476
|
-
|
|
1477
|
-
await this.audit("login", { actorId: user.id, actorEmail: user.email, traits: { grant_type: "password" } });
|
|
1478
|
-
return json(200, await this.sessionFor(user));
|
|
1499
|
+
return response;
|
|
1479
1500
|
}
|
|
1480
1501
|
if (grantType === "refresh_token") {
|
|
1481
1502
|
const token = body.refresh_token;
|
|
@@ -1511,16 +1532,6 @@ class AuthHandler {
|
|
|
1511
1532
|
if (body.email && !this.settings.autoconfirm) {
|
|
1512
1533
|
return authError(501, "email_change_confirmation_not_supported", "Email changes that require confirmation are not supported by SupaCloud Lite V1");
|
|
1513
1534
|
}
|
|
1514
|
-
const upgradingAnon = (user.is_anonymous ?? false) && !!body.email;
|
|
1515
|
-
if (body.email) {
|
|
1516
|
-
const email = body.email.toLowerCase().trim();
|
|
1517
|
-
const clash = await this.db.query(`select id from auth.users where email = $1 and id <> $2`, [email, user.id]);
|
|
1518
|
-
if (clash.rows.length > 0) {
|
|
1519
|
-
return authError(422, "email_exists", "A user with this email address has already been registered");
|
|
1520
|
-
}
|
|
1521
|
-
params.push(email);
|
|
1522
|
-
sets.push(`email = $${params.length}, email_confirmed_at = now()`);
|
|
1523
|
-
}
|
|
1524
1535
|
if (body.password) {
|
|
1525
1536
|
if (body.password.length < this.settings.minPasswordLength) {
|
|
1526
1537
|
return authError(422, "weak_password", `Password should be at least ${this.settings.minPasswordLength} characters.`);
|
|
@@ -1532,22 +1543,41 @@ class AuthHandler {
|
|
|
1532
1543
|
params.push(JSON.stringify(body.data));
|
|
1533
1544
|
sets.push(`raw_user_meta_data = coalesce(raw_user_meta_data, '{}'::jsonb) || $${params.length}::jsonb`);
|
|
1534
1545
|
}
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1538
|
-
|
|
1539
|
-
|
|
1540
|
-
|
|
1541
|
-
|
|
1542
|
-
|
|
1543
|
-
|
|
1544
|
-
|
|
1545
|
-
|
|
1546
|
+
const response = await this.db.transaction(async (query) => {
|
|
1547
|
+
const currentResult = await query(`select * from auth.users where id = $1 and deleted_at is null
|
|
1548
|
+
and (banned_until is null or banned_until <= now()) for update`, [user.id]);
|
|
1549
|
+
const current = currentResult.rows[0];
|
|
1550
|
+
if (!current)
|
|
1551
|
+
return authError(401, "no_authorization", "Invalid or expired token");
|
|
1552
|
+
const transactionSets = [...sets];
|
|
1553
|
+
const transactionParams = [...params];
|
|
1554
|
+
const upgradingAnon = (current.is_anonymous ?? false) && !!body.email;
|
|
1555
|
+
if (body.email) {
|
|
1556
|
+
const email = body.email.toLowerCase().trim();
|
|
1557
|
+
const clash = await query(`select id from auth.users where email = $1 and id <> $2`, [email, current.id]);
|
|
1558
|
+
if (clash.rows.length > 0) {
|
|
1559
|
+
return authError(422, "email_exists", "A user with this email address has already been registered");
|
|
1560
|
+
}
|
|
1561
|
+
transactionParams.push(email);
|
|
1562
|
+
transactionSets.push(`email = $${transactionParams.length}, email_confirmed_at = now()`);
|
|
1563
|
+
}
|
|
1564
|
+
if (upgradingAnon) {
|
|
1565
|
+
transactionSets.push(`is_anonymous = false`);
|
|
1566
|
+
transactionSets.push(`raw_app_meta_data = coalesce(raw_app_meta_data, '{}'::jsonb) || '{"provider":"email","providers":["email"]}'::jsonb`);
|
|
1567
|
+
}
|
|
1568
|
+
if (transactionSets.length === 0) {
|
|
1569
|
+
return json(200, await this.userJsonWithRelations(current, query));
|
|
1570
|
+
}
|
|
1571
|
+
transactionParams.push(current.id);
|
|
1572
|
+
const updatedResult = await query(`update auth.users set ${transactionSets.join(", ")}, updated_at = now() where id = $${transactionParams.length} returning *`, transactionParams);
|
|
1573
|
+
const updated = updatedResult.rows[0];
|
|
1574
|
+
if (!updated)
|
|
1575
|
+
return authError(401, "no_authorization", "Invalid or expired token");
|
|
1546
1576
|
if (body.email)
|
|
1547
1577
|
await this.ensureEmailIdentity(updated, query);
|
|
1548
|
-
return this.userJsonWithRelations(updated, query);
|
|
1578
|
+
return json(200, await this.userJsonWithRelations(updated, query));
|
|
1549
1579
|
});
|
|
1550
|
-
return
|
|
1580
|
+
return response;
|
|
1551
1581
|
}
|
|
1552
1582
|
async logout(req, url) {
|
|
1553
1583
|
const claims = await this.claimsFromBearer(req);
|
|
@@ -1801,8 +1831,8 @@ Or sign in with this link: ${link}`
|
|
|
1801
1831
|
return claimedToken ? this.confirmEmailTokenUser(query, claimedToken) : null;
|
|
1802
1832
|
}
|
|
1803
1833
|
async lockAndDeleteEmailToken(query, candidate, redemption) {
|
|
1804
|
-
const eligible = await query(`select id from auth.users where id = $1 and
|
|
1805
|
-
and (banned_until is null or banned_until <= now()) for update`, [candidate.user_id]);
|
|
1834
|
+
const eligible = await query(`select id from auth.users where id = $1 and lower(email) = lower($2)
|
|
1835
|
+
and deleted_at is null and (banned_until is null or banned_until <= now()) for update`, [candidate.user_id, candidate.email]);
|
|
1806
1836
|
if (eligible.rows.length === 0)
|
|
1807
1837
|
return null;
|
|
1808
1838
|
const claimedTokens = await query(`delete from auth.one_time_tokens
|
|
@@ -1865,11 +1895,10 @@ Or sign in with this link: ${link}`
|
|
|
1865
1895
|
async redeemPhoneOtp(phone, code) {
|
|
1866
1896
|
const tokenDigest = `hmac-sha256:v1:${await keyedDigest(this.config.jwtSecret, "supacloud-lite:phone-otp:v1", `${phone}\x00${code}`)}`;
|
|
1867
1897
|
return this.db.transaction(async (query) => {
|
|
1868
|
-
const
|
|
1898
|
+
const candidate = await query(`select user_id from auth.one_time_tokens
|
|
1869
1899
|
where phone = $1 and token_type = 'sms' and token = $2
|
|
1870
|
-
and expires_at > now() and attempts < $3
|
|
1871
|
-
|
|
1872
|
-
const userId = claimed.rows[0]?.user_id;
|
|
1900
|
+
and expires_at > now() and attempts < $3`, [phone, tokenDigest, AuthHandler.MAX_OTP_ATTEMPTS]);
|
|
1901
|
+
const userId = candidate.rows[0]?.user_id;
|
|
1873
1902
|
if (!userId) {
|
|
1874
1903
|
const attempt = await query(`update auth.one_time_tokens set attempts = attempts + 1
|
|
1875
1904
|
where phone = $1 and token_type = 'sms' and expires_at > now()
|
|
@@ -1881,6 +1910,22 @@ Or sign in with this link: ${link}`
|
|
|
1881
1910
|
await query(`delete from auth.one_time_tokens where phone = $1 and expires_at <= now()`, [phone]);
|
|
1882
1911
|
return null;
|
|
1883
1912
|
}
|
|
1913
|
+
const currentUser = await query(`select phone,
|
|
1914
|
+
deleted_at is null and (banned_until is null or banned_until <= now()) as auth_eligible
|
|
1915
|
+
from auth.users where id = $1 for update`, [userId]);
|
|
1916
|
+
const current = currentUser.rows[0];
|
|
1917
|
+
if (!current || current.phone !== phone)
|
|
1918
|
+
return null;
|
|
1919
|
+
if (!current.auth_eligible) {
|
|
1920
|
+
await query(`delete from auth.one_time_tokens where phone = $1`, [phone]);
|
|
1921
|
+
return null;
|
|
1922
|
+
}
|
|
1923
|
+
const claimed = await query(`delete from auth.one_time_tokens
|
|
1924
|
+
where phone = $1 and token_type = 'sms' and token = $2
|
|
1925
|
+
and expires_at > now() and attempts < $3 and user_id = $4
|
|
1926
|
+
returning user_id`, [phone, tokenDigest, AuthHandler.MAX_OTP_ATTEMPTS, userId]);
|
|
1927
|
+
if (claimed.rows.length === 0)
|
|
1928
|
+
return null;
|
|
1884
1929
|
await query(`delete from auth.one_time_tokens where phone = $1`, [phone]);
|
|
1885
1930
|
const users = await query(`update auth.users
|
|
1886
1931
|
set phone_confirmed_at = coalesce(phone_confirmed_at, now()), last_sign_in_at = now(), updated_at = now()
|
|
@@ -2186,6 +2231,9 @@ Or sign in with this link: ${link}`
|
|
|
2186
2231
|
const user = await this.userFromBearer(req);
|
|
2187
2232
|
if (!user)
|
|
2188
2233
|
return authError(401, "no_authorization", "This endpoint requires a Bearer token");
|
|
2234
|
+
if (!this.settings.totpVerifyEnabled) {
|
|
2235
|
+
return authError(422, "mfa_totp_verify_disabled", "TOTP verification is disabled");
|
|
2236
|
+
}
|
|
2189
2237
|
const body = await req.json().catch(() => ({}));
|
|
2190
2238
|
const fr = await this.db.query(`select id, secret, status from auth.mfa_factors where id = $1 and user_id = $2`, [factorId, user.id]);
|
|
2191
2239
|
const factor = fr.rows[0];
|
|
@@ -9060,6 +9108,14 @@ function resolveImageTransformLimits(options = {}) {
|
|
|
9060
9108
|
}
|
|
9061
9109
|
return { maxInputBytes, maxOutputBytes };
|
|
9062
9110
|
}
|
|
9111
|
+
function imageTransformInputTooLarge(maxInputBytes) {
|
|
9112
|
+
return {
|
|
9113
|
+
ok: false,
|
|
9114
|
+
status: 413,
|
|
9115
|
+
error: "ImageTooLarge",
|
|
9116
|
+
message: `The source image exceeds the transformation limit (${maxInputBytes} bytes)`
|
|
9117
|
+
};
|
|
9118
|
+
}
|
|
9063
9119
|
function invalid(message) {
|
|
9064
9120
|
return { ok: false, status: 400, error: "InvalidTransformation", message };
|
|
9065
9121
|
}
|
|
@@ -9203,14 +9259,10 @@ function applyResize(image, metadata, options) {
|
|
|
9203
9259
|
async function transformImage(source, options, knownSourceSize, configuredLimits = {}) {
|
|
9204
9260
|
const limits = resolveImageTransformLimits(configuredLimits);
|
|
9205
9261
|
const actualSourceSize = source instanceof Uint8Array ? source.byteLength : await Promise.resolve(source.size);
|
|
9206
|
-
const
|
|
9262
|
+
const declaredSourceSize = typeof knownSourceSize === "number" && Number.isFinite(knownSourceSize) && knownSourceSize >= 0 ? knownSourceSize : 0;
|
|
9263
|
+
const sourceSize = Math.max(declaredSourceSize, actualSourceSize);
|
|
9207
9264
|
if (sourceSize > limits.maxInputBytes) {
|
|
9208
|
-
return
|
|
9209
|
-
ok: false,
|
|
9210
|
-
status: 413,
|
|
9211
|
-
error: "ImageTooLarge",
|
|
9212
|
-
message: `The source image exceeds the transformation limit (${limits.maxInputBytes} bytes)`
|
|
9213
|
-
};
|
|
9265
|
+
return imageTransformInputTooLarge(limits.maxInputBytes);
|
|
9214
9266
|
}
|
|
9215
9267
|
const image = new Bun.Image(source, { maxPixels: MAX_TRANSFORM_PIXELS });
|
|
9216
9268
|
let metadata;
|
|
@@ -9434,7 +9486,7 @@ function isRenderableActiveType(contentType) {
|
|
|
9434
9486
|
return t === "text/html" || t === "application/xhtml+xml" || t === "image/svg+xml" || t === "application/xml" || t === "text/xml";
|
|
9435
9487
|
}
|
|
9436
9488
|
var TUS_VERSION = "1.0.0";
|
|
9437
|
-
var DEFAULT_FILE_SIZE_LIMIT =
|
|
9489
|
+
var DEFAULT_FILE_SIZE_LIMIT = 500 * 1024 * 1024;
|
|
9438
9490
|
var MULTIPART_OVERHEAD_LIMIT = 1024 * 1024;
|
|
9439
9491
|
var MAX_CONCURRENT_TUS_UPLOADS = 4;
|
|
9440
9492
|
var MAX_COMPLETED_TUS_UPLOADS = 64;
|
|
@@ -9725,6 +9777,11 @@ class StorageHandler {
|
|
|
9725
9777
|
const parsed = parseImageTransform(url.searchParams);
|
|
9726
9778
|
if (!parsed.ok)
|
|
9727
9779
|
return storageError(parsed.status, parsed.error, parsed.message);
|
|
9780
|
+
const declaredSize = objectSize(row);
|
|
9781
|
+
if (declaredSize !== undefined && declaredSize > this.transformLimits.maxInputBytes) {
|
|
9782
|
+
const rejected = imageTransformInputTooLarge(this.transformLimits.maxInputBytes);
|
|
9783
|
+
return storageError(rejected.status, rejected.error, rejected.message);
|
|
9784
|
+
}
|
|
9728
9785
|
let result;
|
|
9729
9786
|
try {
|
|
9730
9787
|
result = await this.imageTransforms.getOrTransform(imageTransformCacheKey(row.version, parsed.value), async () => {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/runtime/auth/handler.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/runtime/auth/handler.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/runtime/storage/handler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAEjD,OAAO,
|
|
1
|
+
{"version":3,"file":"handler.d.ts","sourceRoot":"","sources":["../../../src/runtime/storage/handler.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAA;AAEjD,OAAO,EAML,KAAK,oBAAoB,EAG1B,MAAM,sBAAsB,CAAA;AAE7B,OAAO,KAAK,EAAE,UAAU,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,aAAa,CAAA;AAE5E,uDAAuD;AACvD,MAAM,WAAW,aAAa;IAC5B,uEAAuE;IACvE,SAAS,EAAE,MAAM,CAAA;IACjB,0GAA0G;IAC1G,oBAAoB,CAAC,EAAE,MAAM,CAAA;IAC7B,oBAAoB,CAAC,EAAE,oBAAoB,CAAA;IAC3C,uFAAuF;IACvF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAA;CAChC;AAkJD,qEAAqE;AACrE,qBAAa,cAAc;IAOvB,OAAO,CAAC,EAAE;IACV,OAAO,CAAC,MAAM;IACd,OAAO,CAAC,MAAM;IARhB,OAAO,CAAC,UAAU,CAA+B;IACjD,OAAO,CAAC,YAAY,CAAoB;IACxC,OAAO,CAAC,eAAe,CAA4B;IACnD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAgC;gBAGtD,EAAE,EAAE,QAAQ,EACZ,MAAM,EAAE,aAAa,EACrB,MAAM,EAAE,aAAa;IAK/B,4FAA4F;IACtF,aAAa,CAAC,OAAO,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAazD,8GAA8G;IACxG,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,EAAE,GAAG,GAAG,OAAO,CAAC,QAAQ,CAAC;YAgH9D,YAAY;IAgB1B,OAAO,CAAC,cAAc;YAOR,YAAY;YA2BZ,WAAW;YAKX,SAAS;YAMT,YAAY;YAqBZ,YAAY;YAYZ,WAAW;YAUX,UAAU;YAKV,MAAM;YA0DN,sBAAsB;IA+BpC,gFAAgF;YAClE,aAAa;YAmDb,SAAS;IA8KvB,2EAA2E;YAC7D,SAAS;IA2CvB,OAAO,CAAC,eAAe;IAWvB,OAAO,CAAC,sBAAsB;YAMhB,oBAAoB;YA8CpB,QAAQ;YAMR,uBAAuB;YAavB,cAAc;YAMd,gBAAgB;YAYhB,WAAW;YAWX,aAAa;YAeb,SAAS;YAUT,UAAU;YAiFV,gBAAgB;YAUhB,kBAAkB;YASlB,eAAe;YAIf,gBAAgB;YAKhB,iBAAiB;YAcjB,WAAW;YAuDX,UAAU;YAyBV,OAAO;YAmBP,QAAQ;YAiBR,eAAe;YAMf,gBAAgB;YAehB,aAAa;YAab,kBAAkB;IAehC,OAAO,CAAC,aAAa;CAUtB;AA6ID,UAAU,aAAa;IACrB,IAAI,EAAE,MAAM,CAAA;IACZ,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,IAAI,EAAE,UAAU,CAAA;CACjB;AAED,+FAA+F;AAC/F,wBAAgB,cAAc,CAAC,KAAK,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,GAAG,aAAa,EAAE,CAqCnF"}
|
|
@@ -35,6 +35,7 @@ export interface ImageTransformLimits {
|
|
|
35
35
|
}
|
|
36
36
|
/** Operator-owned limits, never taken from image URL parameters. */
|
|
37
37
|
export declare function resolveImageTransformLimits(options?: ImageTransformLimits): Required<ImageTransformLimits>;
|
|
38
|
+
export declare function imageTransformInputTooLarge(maxInputBytes: number): ImageTransformError;
|
|
38
39
|
/** Parse Supabase Storage image query parameters without decoding the source. */
|
|
39
40
|
export declare function parseImageTransform(query: URLSearchParams): ImageTransformParseResult;
|
|
40
41
|
/** Encode a transform object into the query shape used by render/image URLs. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"image-transform.d.ts","sourceRoot":"","sources":["../../../src/runtime/storage/image-transform.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,MAAM,CAAA;AACrD,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAA;AAErE,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,oBAAoB,CAAA;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,oBAAoB,CAAA;CAC7B;AAED,MAAM,WAAW,4BAA4B;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAA;IACvC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,oBAAoB,CAAA;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,KAAK,CAAA;IACT,MAAM,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,MAAM,yBAAyB,GACjC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,qBAAqB,CAAA;CAAE,GAC1C,mBAAmB,CAAA;AAEvB,MAAM,MAAM,oBAAoB,GAC5B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,UAAU,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACpD,mBAAmB,CAAA;AAgBvB,MAAM,WAAW,oBAAoB;IACnC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,oEAAoE;AACpE,wBAAgB,2BAA2B,CAAC,OAAO,GAAE,oBAAyB,GAAG,QAAQ,CAAC,oBAAoB,CAAC,CAS9G;AA6BD,iFAAiF;AACjF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,eAAe,GAAG,yBAAyB,CAsCrF;AAED,gFAAgF;AAChF,wBAAgB,4BAA4B,CAAC,OAAO,CAAC,EAAE,4BAA4B,GAAG,eAAe,CASpG;AA0DD,iFAAiF;AACjF,wBAAsB,cAAc,CAClC,MAAM,EAAE,UAAU,GAAG,IAAI,EACzB,OAAO,EAAE,qBAAqB,EAC9B,eAAe,CAAC,EAAE,MAAM,EACxB,gBAAgB,GAAE,oBAAyB,GAC1C,OAAO,CAAC,oBAAoB,CAAC,
|
|
1
|
+
{"version":3,"file":"image-transform.d.ts","sourceRoot":"","sources":["../../../src/runtime/storage/image-transform.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,oBAAoB,GAAG,SAAS,GAAG,MAAM,CAAA;AACrD,MAAM,MAAM,oBAAoB,GAAG,QAAQ,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,CAAA;AAErE,MAAM,WAAW,qBAAqB;IACpC,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,EAAE,oBAAoB,CAAA;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,EAAE,oBAAoB,CAAA;CAC7B;AAED,MAAM,WAAW,4BAA4B;IAC3C,KAAK,CAAC,EAAE,MAAM,CAAA;IACd,MAAM,CAAC,EAAE,MAAM,CAAA;IACf,MAAM,CAAC,EAAE,oBAAoB,GAAG,OAAO,CAAA;IACvC,OAAO,CAAC,EAAE,MAAM,CAAA;IAChB,MAAM,CAAC,EAAE,oBAAoB,CAAA;CAC9B;AAED,MAAM,WAAW,mBAAmB;IAClC,EAAE,EAAE,KAAK,CAAA;IACT,MAAM,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,OAAO,EAAE,MAAM,CAAA;CAChB;AAED,MAAM,MAAM,yBAAyB,GACjC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,qBAAqB,CAAA;CAAE,GAC1C,mBAAmB,CAAA;AAEvB,MAAM,MAAM,oBAAoB,GAC5B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,KAAK,EAAE,UAAU,CAAC;IAAC,WAAW,EAAE,MAAM,CAAA;CAAE,GACpD,mBAAmB,CAAA;AAgBvB,MAAM,WAAW,oBAAoB;IACnC,aAAa,CAAC,EAAE,MAAM,CAAA;IACtB,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB;AAED,oEAAoE;AACpE,wBAAgB,2BAA2B,CAAC,OAAO,GAAE,oBAAyB,GAAG,QAAQ,CAAC,oBAAoB,CAAC,CAS9G;AAED,wBAAgB,2BAA2B,CAAC,aAAa,EAAE,MAAM,GAAG,mBAAmB,CAOtF;AA6BD,iFAAiF;AACjF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,eAAe,GAAG,yBAAyB,CAsCrF;AAED,gFAAgF;AAChF,wBAAgB,4BAA4B,CAAC,OAAO,CAAC,EAAE,4BAA4B,GAAG,eAAe,CASpG;AA0DD,iFAAiF;AACjF,wBAAsB,cAAc,CAClC,MAAM,EAAE,UAAU,GAAG,IAAI,EACzB,OAAO,EAAE,qBAAqB,EAC9B,eAAe,CAAC,EAAE,MAAM,EACxB,gBAAgB,GAAE,oBAAyB,GAC1C,OAAO,CAAC,oBAAoB,CAAC,CAyD/B"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@supacloud/lite",
|
|
3
|
-
"version": "0.31.
|
|
3
|
+
"version": "0.31.3",
|
|
4
4
|
"description": "Bun-native, single-project Supabase-compatible backend powered by PGlite or native PostgreSQL",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -59,16 +59,16 @@
|
|
|
59
59
|
"@electric-sql/pglite-pgmq": "0.0.8",
|
|
60
60
|
"@electric-sql/pglite-pgvector": "0.0.11",
|
|
61
61
|
"@electric-sql/pglite-postgis": "0.2.10",
|
|
62
|
-
"@supacloud/db": "0.18.
|
|
62
|
+
"@supacloud/db": "0.18.4",
|
|
63
63
|
"exact-mirror": "1.2.6",
|
|
64
64
|
"tar": "^7.5.22",
|
|
65
65
|
"typebox": "1.3.37"
|
|
66
66
|
},
|
|
67
67
|
"devDependencies": {
|
|
68
|
-
"@supacloud/app": "0.28.
|
|
69
|
-
"@supacloud/contracts": "0.11.
|
|
70
|
-
"@supacloud/compiler": "0.47.
|
|
71
|
-
"@supacloud/elysia": "0.33.
|
|
68
|
+
"@supacloud/app": "0.28.3",
|
|
69
|
+
"@supacloud/contracts": "0.11.5",
|
|
70
|
+
"@supacloud/compiler": "0.47.3",
|
|
71
|
+
"@supacloud/elysia": "0.33.5",
|
|
72
72
|
"@supabase/supabase-js": "^2.117.3",
|
|
73
73
|
"@types/bun": "^1.4.3",
|
|
74
74
|
"effect": "4.0.5",
|
|
@@ -77,13 +77,13 @@
|
|
|
77
77
|
"typescript": "^7.0.2"
|
|
78
78
|
},
|
|
79
79
|
"overrides": {
|
|
80
|
-
"@supacloud/db": "0.18.
|
|
81
|
-
"@supacloud/app": "0.28.
|
|
82
|
-
"@supacloud/compiler": "0.47.
|
|
83
|
-
"@supacloud/elysia": "0.33.
|
|
84
|
-
"@supacloud/contracts": "0.11.
|
|
85
|
-
"@supacloud/commands": "0.9.
|
|
86
|
-
"@supacloud/delivery": "0.19.
|
|
80
|
+
"@supacloud/db": "0.18.4",
|
|
81
|
+
"@supacloud/app": "0.28.3",
|
|
82
|
+
"@supacloud/compiler": "0.47.3",
|
|
83
|
+
"@supacloud/elysia": "0.33.5",
|
|
84
|
+
"@supacloud/contracts": "0.11.5",
|
|
85
|
+
"@supacloud/commands": "0.9.7",
|
|
86
|
+
"@supacloud/delivery": "0.19.4",
|
|
87
87
|
"@graphql-tools/utils": "^12.0.4"
|
|
88
88
|
},
|
|
89
89
|
"engines": {
|