@supacloud/lite 0.23.0 → 0.25.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -49,6 +49,8 @@ async function verifyJwt(token, secret) {
49
49
  if (parts.length !== 3)
50
50
  return null;
51
51
  const [header, payload, signature] = parts;
52
+ if (!header || !payload || !signature)
53
+ return null;
52
54
  try {
53
55
  const head = JSON.parse(decoder.decode(base64UrlToBytes(header)));
54
56
  if (head.alg !== "HS256")
@@ -69,8 +71,11 @@ function decodeJwt(token) {
69
71
  const parts = token.split(".");
70
72
  if (parts.length !== 3)
71
73
  return null;
74
+ const payload = parts[1];
75
+ if (!payload)
76
+ return null;
72
77
  try {
73
- return JSON.parse(decoder.decode(base64UrlToBytes(parts[1])));
78
+ return JSON.parse(decoder.decode(base64UrlToBytes(payload)));
74
79
  } catch {
75
80
  return null;
76
81
  }
@@ -83,7 +88,7 @@ function randomToken(bytes = 32) {
83
88
  // package.json
84
89
  var package_default = {
85
90
  name: "@supacloud/lite",
86
- version: "0.23.0",
91
+ version: "0.25.0",
87
92
  description: "Bun-native, single-project Supabase-compatible backend powered by PGlite or native PostgreSQL",
88
93
  type: "module",
89
94
  license: "Apache-2.0",
@@ -149,7 +154,7 @@ var package_default = {
149
154
  "@supacloud/elysia": "file:../elysia",
150
155
  "@supabase/supabase-js": "^2.117.3",
151
156
  "@types/bun": "^1.4.2",
152
- effect: "3.22.1",
157
+ effect: "4.0.2",
153
158
  elysia: "2.0.0-beta.21",
154
159
  jose: "^6.2.11",
155
160
  typescript: "^7.0.2"
@@ -192,7 +197,7 @@ var SUPACLOUD_LITE_VERSION = package_default.version;
192
197
  function globToRegExp(pattern) {
193
198
  let out = "";
194
199
  for (let i = 0;i < pattern.length; i++) {
195
- const c = pattern[i];
200
+ const c = pattern.charAt(i);
196
201
  if (c === "*") {
197
202
  if (pattern[i + 1] === "*") {
198
203
  out += ".*";
@@ -245,11 +250,11 @@ var PRESETS = {
245
250
  userInfoUrl: "https://openidconnect.googleapis.com/v1/userinfo",
246
251
  scopes: "openid email profile",
247
252
  profileMap: (r) => ({
248
- id: r.sub,
249
- email: r.email,
250
- emailVerified: r.email_verified === true,
251
- name: r.name,
252
- metadata: { avatar_url: r.picture, full_name: r.name }
253
+ id: typeof r["sub"] === "string" ? r["sub"] : "",
254
+ ...typeof r["email"] === "string" ? { email: r["email"] } : {},
255
+ emailVerified: r["email_verified"] === true,
256
+ ...typeof r["name"] === "string" ? { name: r["name"] } : {},
257
+ metadata: { avatar_url: r["picture"], full_name: r["name"] }
253
258
  })
254
259
  },
255
260
  github: {
@@ -257,7 +262,12 @@ var PRESETS = {
257
262
  tokenUrl: "https://github.com/login/oauth/access_token",
258
263
  userInfoUrl: "https://api.github.com/user",
259
264
  scopes: "read:user user:email",
260
- profileMap: (r) => ({ id: String(r.id), email: r.email, name: r.name ?? r.login, metadata: { avatar_url: r.avatar_url, user_name: r.login } })
265
+ profileMap: (r) => ({
266
+ id: String(r["id"]),
267
+ ...typeof r["email"] === "string" ? { email: r["email"] } : {},
268
+ ...typeof r["name"] === "string" || typeof r["login"] === "string" ? { name: typeof r["name"] === "string" ? r["name"] : r["login"] } : {},
269
+ metadata: { avatar_url: r["avatar_url"], user_name: r["login"] }
270
+ })
261
271
  }
262
272
  };
263
273
  function resolveProvider(name, cfg) {
@@ -276,7 +286,11 @@ function resolveProvider(name, cfg) {
276
286
  tokenUrl,
277
287
  userInfoUrl,
278
288
  scopes: cfg.scopes ?? preset.scopes ?? "",
279
- profileMap: cfg.profileMap ?? preset.profileMap ?? ((r) => ({ id: String(r.id ?? r.sub), email: r.email, name: r.name }))
289
+ profileMap: cfg.profileMap ?? preset.profileMap ?? ((r) => ({
290
+ id: String(r["id"] ?? r["sub"]),
291
+ ...typeof r["email"] === "string" ? { email: r["email"] } : {},
292
+ ...typeof r["name"] === "string" ? { name: r["name"] } : {}
293
+ }))
280
294
  };
281
295
  }
282
296
 
@@ -972,41 +986,41 @@ var DEFAULT_AUTH_SETTINGS = {
972
986
  };
973
987
  function sanitize(raw) {
974
988
  const s = { ...DEFAULT_AUTH_SETTINGS };
975
- if (typeof raw.disableSignup === "boolean")
976
- s.disableSignup = raw.disableSignup;
977
- if (typeof raw.anonymousUsers === "boolean")
978
- s.anonymousUsers = raw.anonymousUsers;
979
- if (typeof raw.autoconfirm === "boolean")
980
- s.autoconfirm = raw.autoconfirm;
981
- if (typeof raw.minPasswordLength === "number" && Number.isFinite(raw.minPasswordLength)) {
982
- s.minPasswordLength = Math.max(4, Math.min(72, Math.floor(raw.minPasswordLength)));
983
- }
984
- if (Array.isArray(raw.disabledProviders)) {
985
- s.disabledProviders = raw.disabledProviders.filter((p) => typeof p === "string").slice(0, 50);
986
- }
987
- if (typeof raw.otpLength === "number" && Number.isFinite(raw.otpLength)) {
988
- s.otpLength = Math.max(6, Math.min(10, Math.floor(raw.otpLength)));
989
- }
990
- if (typeof raw.otpExpirySeconds === "number" && Number.isFinite(raw.otpExpirySeconds) && raw.otpExpirySeconds > 0) {
991
- s.otpExpirySeconds = Math.floor(raw.otpExpirySeconds);
992
- }
993
- if (typeof raw.smsEnabled === "boolean")
994
- s.smsEnabled = raw.smsEnabled;
995
- if (typeof raw.smsSignupEnabled === "boolean")
996
- s.smsSignupEnabled = raw.smsSignupEnabled;
997
- if (typeof raw.smsOtpCooldownSeconds === "number" && Number.isFinite(raw.smsOtpCooldownSeconds)) {
998
- s.smsOtpCooldownSeconds = Math.max(0, Math.min(86400, Math.floor(raw.smsOtpCooldownSeconds)));
999
- }
1000
- if (typeof raw.smsTemplate === "string" && raw.smsTemplate.length > 0 && raw.smsTemplate.length <= 1000 && /\{\{\s*\.Code\s*\}\}/.test(raw.smsTemplate)) {
1001
- s.smsTemplate = raw.smsTemplate;
1002
- }
1003
- if (typeof raw.maxEnrolledFactors === "number" && Number.isFinite(raw.maxEnrolledFactors) && raw.maxEnrolledFactors > 0) {
1004
- s.maxEnrolledFactors = Math.floor(raw.maxEnrolledFactors);
1005
- }
1006
- if (typeof raw.totpEnrollEnabled === "boolean")
1007
- s.totpEnrollEnabled = raw.totpEnrollEnabled;
1008
- if (typeof raw.totpVerifyEnabled === "boolean")
1009
- s.totpVerifyEnabled = raw.totpVerifyEnabled;
989
+ if (typeof raw["disableSignup"] === "boolean")
990
+ s.disableSignup = raw["disableSignup"];
991
+ if (typeof raw["anonymousUsers"] === "boolean")
992
+ s.anonymousUsers = raw["anonymousUsers"];
993
+ if (typeof raw["autoconfirm"] === "boolean")
994
+ s.autoconfirm = raw["autoconfirm"];
995
+ if (typeof raw["minPasswordLength"] === "number" && Number.isFinite(raw["minPasswordLength"])) {
996
+ s.minPasswordLength = Math.max(4, Math.min(72, Math.floor(raw["minPasswordLength"])));
997
+ }
998
+ if (Array.isArray(raw["disabledProviders"])) {
999
+ s.disabledProviders = raw["disabledProviders"].filter((p) => typeof p === "string").slice(0, 50);
1000
+ }
1001
+ if (typeof raw["otpLength"] === "number" && Number.isFinite(raw["otpLength"])) {
1002
+ s.otpLength = Math.max(6, Math.min(10, Math.floor(raw["otpLength"])));
1003
+ }
1004
+ if (typeof raw["otpExpirySeconds"] === "number" && Number.isFinite(raw["otpExpirySeconds"]) && raw["otpExpirySeconds"] > 0) {
1005
+ s.otpExpirySeconds = Math.floor(raw["otpExpirySeconds"]);
1006
+ }
1007
+ if (typeof raw["smsEnabled"] === "boolean")
1008
+ s.smsEnabled = raw["smsEnabled"];
1009
+ if (typeof raw["smsSignupEnabled"] === "boolean")
1010
+ s.smsSignupEnabled = raw["smsSignupEnabled"];
1011
+ if (typeof raw["smsOtpCooldownSeconds"] === "number" && Number.isFinite(raw["smsOtpCooldownSeconds"])) {
1012
+ s.smsOtpCooldownSeconds = Math.max(0, Math.min(86400, Math.floor(raw["smsOtpCooldownSeconds"])));
1013
+ }
1014
+ if (typeof raw["smsTemplate"] === "string" && raw["smsTemplate"].length > 0 && raw["smsTemplate"].length <= 1000 && /\{\{\s*\.Code\s*\}\}/.test(raw["smsTemplate"])) {
1015
+ s.smsTemplate = raw["smsTemplate"];
1016
+ }
1017
+ if (typeof raw["maxEnrolledFactors"] === "number" && Number.isFinite(raw["maxEnrolledFactors"]) && raw["maxEnrolledFactors"] > 0) {
1018
+ s.maxEnrolledFactors = Math.floor(raw["maxEnrolledFactors"]);
1019
+ }
1020
+ if (typeof raw["totpEnrollEnabled"] === "boolean")
1021
+ s.totpEnrollEnabled = raw["totpEnrollEnabled"];
1022
+ if (typeof raw["totpVerifyEnabled"] === "boolean")
1023
+ s.totpVerifyEnabled = raw["totpVerifyEnabled"];
1010
1024
  return s;
1011
1025
  }
1012
1026
  async function loadAuthSettings(db, defaults = {}) {
@@ -1047,7 +1061,7 @@ class RateLimiter {
1047
1061
  const cutoff = now - rule.windowMs;
1048
1062
  const recent = (this.hits.get(bucketKey) ?? []).filter((t) => t > cutoff);
1049
1063
  if (recent.length >= rule.limit) {
1050
- const retryMs = recent[0] + rule.windowMs - now;
1064
+ const retryMs = (recent[0] ?? now) + rule.windowMs - now;
1051
1065
  return Math.max(1, Math.ceil(retryMs / 1000));
1052
1066
  }
1053
1067
  recent.push(now);
@@ -1879,13 +1893,14 @@ Or sign in with this link: ${link}`
1879
1893
  const body = await req.json().catch(() => ({}));
1880
1894
  if (!body.email)
1881
1895
  return authError(400, "validation_failed", "email is required");
1896
+ const email = body.email;
1882
1897
  const hashed = body.password ? await hashPassword(body.password) : null;
1883
1898
  const created = await this.db.transaction(async (query) => {
1884
1899
  const res = await query(`insert into auth.users
1885
1900
  (aud, role, email, encrypted_password, email_confirmed_at, raw_app_meta_data, raw_user_meta_data)
1886
1901
  values ('authenticated', 'authenticated', $1, $2, case when $3 then now() else null end, $4, $5)
1887
1902
  returning *`, [
1888
- body.email.toLowerCase().trim(),
1903
+ email.toLowerCase().trim(),
1889
1904
  hashed,
1890
1905
  body.email_confirm ?? true,
1891
1906
  JSON.stringify({ provider: "email", providers: ["email"], ...body.app_metadata ?? {} }),
@@ -2548,11 +2563,11 @@ function installDenoShim() {
2548
2563
  }
2549
2564
  function takeCapturedHandler() {
2550
2565
  const h = captured.handler;
2551
- captured.handler = undefined;
2566
+ delete captured.handler;
2552
2567
  return h;
2553
2568
  }
2554
2569
  function resetCapturedHandler() {
2555
- captured.handler = undefined;
2570
+ delete captured.handler;
2556
2571
  }
2557
2572
 
2558
2573
  // src/runtime/functions/edge-runtime-shim.ts
@@ -2576,7 +2591,7 @@ function installEdgeRuntimeShim() {
2576
2591
  }
2577
2592
  };
2578
2593
  installed = runtime;
2579
- globalThis.EdgeRuntime = runtime;
2594
+ globalThis["EdgeRuntime"] = runtime;
2580
2595
  }
2581
2596
  function runWithBackgroundTasks(options, fn) {
2582
2597
  installEdgeRuntimeShim();
@@ -2948,9 +2963,13 @@ class FunctionsHandler {
2948
2963
  const env = capabilities?.secrets ? filterSecretsEnv(this.env, capabilities.secrets) : this.env;
2949
2964
  const invoke = () => this.invoke(entry.handler, request, ctx, env);
2950
2965
  const inner = () => runWithDenoEnv(env, () => runWithPgredisCache(this.pgredis, invoke));
2951
- const run = capabilities?.outboundHosts ? () => runWithFetchPolicy(capabilities.outboundHosts, inner) : inner;
2952
- const invokeWithBackground = () => runWithBackgroundTasks({ allowed: capabilities?.background !== false, timeoutMs: limits?.waitUntilTimeoutMs }, run);
2953
- const res = timeoutMs !== undefined ? await this.withTimeout(name, timeoutMs, invokeWithBackground, abort) : await invokeWithBackground();
2966
+ const outboundHosts = capabilities?.outboundHosts;
2967
+ const run = outboundHosts ? () => runWithFetchPolicy(outboundHosts, inner) : inner;
2968
+ const invokeWithBackground = () => runWithBackgroundTasks({
2969
+ allowed: capabilities?.background !== false,
2970
+ ...limits?.waitUntilTimeoutMs === undefined ? {} : { timeoutMs: limits.waitUntilTimeoutMs }
2971
+ }, run);
2972
+ const res = timeoutMs !== undefined && abort !== undefined ? await this.withTimeout(name, timeoutMs, invokeWithBackground, abort) : await invokeWithBackground();
2954
2973
  if (!(res instanceof Response)) {
2955
2974
  return json2(500, { error: `function "${name}" did not return a Response` });
2956
2975
  }
@@ -3018,6 +3037,8 @@ function withCountedBody(req, limit) {
3018
3037
  controller.enqueue(chunk);
3019
3038
  }
3020
3039
  });
3040
+ if (!req.body)
3041
+ return new Request(req);
3021
3042
  return new Request(req, { body: req.body.pipeThrough(counter), duplex: "half" });
3022
3043
  }
3023
3044
  function withResponseLimit(name, res, limit) {
@@ -6353,7 +6374,7 @@ async function createPgliteEngine(dataDir, options = {}) {
6353
6374
  let pg;
6354
6375
  try {
6355
6376
  pg = new PGlite({
6356
- dataDir,
6377
+ ...dataDir === undefined ? {} : { dataDir },
6357
6378
  extensions,
6358
6379
  ...standaloneAssets ? {
6359
6380
  pgliteWasmModule: standaloneAssets.pgliteWasmModule,
@@ -6382,7 +6403,7 @@ async function createPgliteEngine(dataDir, options = {}) {
6382
6403
  return {
6383
6404
  async query(sql, params) {
6384
6405
  const res = await pg.query(sql, params);
6385
- return { rows: res.rows, affectedRows: res.affectedRows };
6406
+ return { rows: res.rows, ...res.affectedRows === undefined ? {} : { affectedRows: res.affectedRows } };
6386
6407
  },
6387
6408
  async exec(sql) {
6388
6409
  await pg.exec(sql);
@@ -6392,7 +6413,7 @@ async function createPgliteEngine(dataDir, options = {}) {
6392
6413
  return fn({
6393
6414
  async query(sql, params) {
6394
6415
  const res = await tx.query(sql, params);
6395
- return { rows: res.rows, affectedRows: res.affectedRows };
6416
+ return { rows: res.rows, ...res.affectedRows === undefined ? {} : { affectedRows: res.affectedRows } };
6396
6417
  },
6397
6418
  async exec(sql) {
6398
6419
  await tx.exec(sql);
@@ -6421,8 +6442,8 @@ function getStandaloneAssets() {
6421
6442
  function withEmbeddedBundle(extension, bundlePath) {
6422
6443
  return {
6423
6444
  ...extension,
6424
- setup: async (pg, emscriptenOpts, clientOnly) => ({
6425
- ...await extension.setup(pg, emscriptenOpts, clientOnly),
6445
+ setup: async (...args) => ({
6446
+ ...await extension.setup(...args),
6426
6447
  bundlePath
6427
6448
  })
6428
6449
  };
@@ -6646,12 +6667,17 @@ class Database {
6646
6667
  order by kcu.constraint_name, kcu.ordinal_position`, [schema]);
6647
6668
  const uniqByTable = new Map;
6648
6669
  for (const u of uniq.rows) {
6649
- if (!uniqByTable.has(u.table_name))
6650
- uniqByTable.set(u.table_name, new Map);
6651
- const byConstraint = uniqByTable.get(u.table_name);
6652
- if (!byConstraint.has(u.constraint_name))
6653
- byConstraint.set(u.constraint_name, []);
6654
- byConstraint.get(u.constraint_name).push(u.column_name);
6670
+ let byConstraint = uniqByTable.get(u.table_name);
6671
+ if (!byConstraint) {
6672
+ byConstraint = new Map;
6673
+ uniqByTable.set(u.table_name, byConstraint);
6674
+ }
6675
+ let columns = byConstraint.get(u.constraint_name);
6676
+ if (!columns) {
6677
+ columns = [];
6678
+ byConstraint.set(u.constraint_name, columns);
6679
+ }
6680
+ columns.push(u.column_name);
6655
6681
  }
6656
6682
  const fks = await this.engine.query(`select
6657
6683
  tc.constraint_name,
@@ -6672,22 +6698,27 @@ class Database {
6672
6698
  order by tc.constraint_name, kcu.ordinal_position`, [schema]);
6673
6699
  const pkSet = new Map;
6674
6700
  for (const pk of pks.rows) {
6675
- if (!pkSet.has(pk.table_name))
6676
- pkSet.set(pk.table_name, new Set);
6677
- pkSet.get(pk.table_name).add(pk.column_name);
6701
+ let columns = pkSet.get(pk.table_name);
6702
+ if (!columns) {
6703
+ columns = new Set;
6704
+ pkSet.set(pk.table_name, columns);
6705
+ }
6706
+ columns.add(pk.column_name);
6678
6707
  }
6679
6708
  const tables = new Map;
6680
6709
  for (const c of cols.rows) {
6681
- if (!tables.has(c.table_name)) {
6682
- tables.set(c.table_name, {
6710
+ let table = tables.get(c.table_name);
6711
+ if (!table) {
6712
+ table = {
6683
6713
  schema,
6684
6714
  name: c.table_name,
6685
6715
  columns: [],
6686
6716
  primaryKey: [...pkSet.get(c.table_name) ?? []],
6687
6717
  uniqueKeys: [...uniqByTable.get(c.table_name)?.values() ?? []]
6688
- });
6718
+ };
6719
+ tables.set(c.table_name, table);
6689
6720
  }
6690
- tables.get(c.table_name).columns.push({
6721
+ table.columns.push({
6691
6722
  name: c.column_name,
6692
6723
  udtName: c.udt_name,
6693
6724
  isNullable: c.is_nullable === "YES",
@@ -6859,12 +6890,15 @@ function parseIdentityArgs(identity) {
6859
6890
  parts.push(current);
6860
6891
  return parts.map((part) => {
6861
6892
  const tokens = part.trim().split(/\s+/);
6862
- while (tokens.length > 1 && ["IN", "OUT", "INOUT", "VARIADIC"].includes(tokens[0])) {
6893
+ while (tokens.length > 1 && ["IN", "OUT", "INOUT", "VARIADIC"].includes(tokens[0] ?? "")) {
6863
6894
  tokens.shift();
6864
6895
  }
6896
+ const first = tokens[0];
6897
+ if (first === undefined || first === "")
6898
+ throw new Error("invalid function identity argument");
6865
6899
  if (tokens.length === 1)
6866
- return { name: "", type: tokens[0] };
6867
- const name = tokens[0].replace(/^"|"$/g, "");
6900
+ return { name: "", type: first };
6901
+ const name = first.replace(/^"|"$/g, "");
6868
6902
  return { name, type: tokens.slice(1).join(" ") };
6869
6903
  });
6870
6904
  }
@@ -7176,6 +7210,8 @@ class RealtimeEngine {
7176
7210
  const state = this.presence.get(topic);
7177
7211
  if (state?.has(channel.presenceKey)) {
7178
7212
  const metas = state.get(channel.presenceKey);
7213
+ if (!metas)
7214
+ return;
7179
7215
  state.delete(channel.presenceKey);
7180
7216
  if (state.size === 0)
7181
7217
  this.presence.delete(topic);
@@ -7470,7 +7506,7 @@ class ApiError extends Error {
7470
7506
  status;
7471
7507
  body;
7472
7508
  constructor(status, body) {
7473
- super(typeof body.message === "string" ? body.message : JSON.stringify(body));
7509
+ super(typeof body["message"] === "string" ? body["message"] : JSON.stringify(body));
7474
7510
  this.status = status;
7475
7511
  this.body = body;
7476
7512
  }
@@ -7848,6 +7884,8 @@ class QueryBuilder {
7848
7884
  const cells = columns.map((c) => {
7849
7885
  if (!(c in row)) {
7850
7886
  const col = tinfo.columns.find((x) => x.name === c);
7887
+ if (!col)
7888
+ throw new ApiError(400, { code: "PGRST204", message: `Column ${c} does not exist` });
7851
7889
  return opts.missingDefault && col.hasDefault ? "default" : "null";
7852
7890
  }
7853
7891
  return this.pushParam(params, tinfo, c, row[c]);
@@ -7967,6 +8005,8 @@ class QueryBuilder {
7967
8005
  });
7968
8006
  } else {
7969
8007
  const j = rel.junction;
8008
+ if (!j)
8009
+ throw new Error("many-to-many relationship is missing its junction table");
7970
8010
  const jAlias = this.nextAlias();
7971
8011
  const joinConds = j.fkToTarget.srcColumns.map((src, i) => `${quoteIdent(jAlias)}.${quoteIdent(src)} = ${quoteIdent(childAlias)}.${quoteIdent(j.fkToTarget.tgtColumns[i])}`);
7972
8012
  fromClause = `${this.qualify(rel.targetTable)} as ${quoteIdent(childAlias)} join ${this.qualify(j.table)} as ${quoteIdent(jAlias)} on ${joinConds.join(" and ")}`;
@@ -8232,6 +8272,8 @@ function renderFilter(f, alias) {
8232
8272
  case "phfts":
8233
8273
  case "wfts": {
8234
8274
  const fn = { fts: "to_tsquery", plfts: "plainto_tsquery", phfts: "phraseto_tsquery", wfts: "websearch_to_tsquery" }[f.op];
8275
+ if (!fn)
8276
+ throw new Error(`Unsupported full-text operator: ${f.op}`);
8235
8277
  expr = f.ftsConfig ? `${colExpr} @@ ${fn}(${quoteLiteral(f.ftsConfig)}, ${quoteLiteral(f.value)})` : `${colExpr} @@ ${fn}(${quoteLiteral(f.value)})`;
8236
8278
  break;
8237
8279
  }
@@ -8526,9 +8568,10 @@ class RestHandler {
8526
8568
  if (!opts.returning) {
8527
8569
  return new Response(null, { status: opts.status === 201 ? 201 : 204, headers: countHeader });
8528
8570
  }
8529
- return this.dataResponse(rows, {
8571
+ const responseRows = rows ?? [];
8572
+ return this.dataResponse(responseRows, {
8530
8573
  status: opts.status,
8531
- count: opts.prefer.count !== undefined ? rows.length : null,
8574
+ count: opts.prefer.count !== undefined ? responseRows.length : null,
8532
8575
  offset: 0,
8533
8576
  wantsObject: opts.wantsObject,
8534
8577
  wantsCsv: opts.wantsCsv,
@@ -8639,7 +8682,7 @@ class RestHandler {
8639
8682
  if (item.name === "*") {
8640
8683
  exprs.push(`${quoteIdent(alias)}.*`);
8641
8684
  } else {
8642
- const out = item.alias ?? item.name.split(/->>|->/).pop().trim();
8685
+ const out = item.alias ?? (item.name.split(/->>|->/).pop() ?? item.name).trim();
8643
8686
  const cast = item.cast ? `::${sanitizeCast(item.cast)}` : "";
8644
8687
  exprs.push(`${renderColumnExpr(alias, item.name)}${cast} as ${quoteIdent(out)}`);
8645
8688
  }
@@ -8893,7 +8936,10 @@ function applyResize(image, metadata, options) {
8893
8936
  image.resize(options.width);
8894
8937
  return;
8895
8938
  }
8896
- const proportionalWidth = Math.max(1, Math.round(metadata.width * options.height / metadata.height));
8939
+ const height = options.height;
8940
+ if (height === undefined)
8941
+ return;
8942
+ const proportionalWidth = Math.max(1, Math.round(metadata.width * height / metadata.height));
8897
8943
  image.resize(proportionalWidth);
8898
8944
  }
8899
8945
  async function transformImage(source, options, knownSourceSize) {
@@ -9050,6 +9096,8 @@ class ImageTransformCache {
9050
9096
  if (oldestKey === undefined)
9051
9097
  break;
9052
9098
  const oldest = this.entries.get(oldestKey);
9099
+ if (!oldest)
9100
+ break;
9053
9101
  this.entries.delete(oldestKey);
9054
9102
  this.cachedBytes -= oldest.size;
9055
9103
  }
@@ -9899,8 +9947,9 @@ class StorageHandler {
9899
9947
  ...[...folders].map((name) => ({ name, row: null })),
9900
9948
  ...Object.entries(files).map(([name, row]) => ({ name, row }))
9901
9949
  ];
9902
- if (body.search)
9903
- entries = entries.filter((e) => e.name.includes(body.search));
9950
+ const search = body.search;
9951
+ if (search)
9952
+ entries = entries.filter((e) => e.name.includes(search));
9904
9953
  const column = body.sortBy?.column ?? "name";
9905
9954
  const asc = (body.sortBy?.order ?? "asc") === "asc";
9906
9955
  entries.sort((a, b) => {
@@ -10050,6 +10099,8 @@ function parseSizeLimit(v) {
10050
10099
  if (!m)
10051
10100
  throw new StorageValidationError(`invalid file_size_limit: ${v}`);
10052
10101
  const mult = { b: 1, kb: 1024, mb: 1024 ** 2, gb: 1024 ** 3 }[(m[2] ?? "b").toLowerCase()];
10102
+ if (mult === undefined)
10103
+ throw new StorageValidationError(`invalid file_size_limit: ${v}`);
10053
10104
  return Math.floor(parseFloat(m[1]) * mult);
10054
10105
  }
10055
10106
  function objectMetadata(size, contentType, cacheControl) {
@@ -10348,7 +10399,7 @@ class NetService {
10348
10399
  const res = await guardedFetch(this.fetchImpl, row.url, {
10349
10400
  method: row.method,
10350
10401
  headers,
10351
- body: hasBody ? row.body ?? undefined : undefined,
10402
+ ...hasBody && row.body !== null ? { body: row.body } : {},
10352
10403
  signal: controller.signal
10353
10404
  });
10354
10405
  status = res.status;
@@ -10367,9 +10418,9 @@ class NetService {
10367
10418
  id: row.id,
10368
10419
  method: row.method,
10369
10420
  url: row.url,
10370
- status: status ?? undefined,
10421
+ ...status === null ? {} : { status },
10371
10422
  timedOut,
10372
- error: errorMsg ?? undefined
10423
+ ...errorMsg === null ? {} : { error: errorMsg }
10373
10424
  });
10374
10425
  }
10375
10426
  async record(id, status, contentType, respHeaders, content, timedOut, errorMsg) {
@@ -10822,16 +10873,16 @@ class GraphqlHandler {
10822
10873
  throw new ApiError(415, { message: "GraphQL requests require application/json" });
10823
10874
  }
10824
10875
  const body = JSON.parse(await boundedBody(request, this.maxBytes));
10825
- if (!isObject(body) || typeof body.query !== "string" || !body.query.trim() || body.variables != null && !isObject(body.variables) || body.extensions != null && !isObject(body.extensions) || body.operationName != null && typeof body.operationName !== "string") {
10876
+ if (!isObject(body) || typeof body["query"] !== "string" || !body["query"].trim() || body["variables"] != null && !isObject(body["variables"]) || body["extensions"] != null && !isObject(body["extensions"]) || body["operationName"] != null && typeof body["operationName"] !== "string") {
10826
10877
  throw new ApiError(400, { message: "Invalid GraphQL request" });
10827
10878
  }
10828
- operationName = body.operationName ?? undefined;
10879
+ operationName = body["operationName"] ?? undefined;
10829
10880
  const result = await this.db.withContext(context, async (query) => {
10830
10881
  await query(`select set_config('statement_timeout', $1, true)`, [String(this.timeoutMs)]);
10831
10882
  await query(`select set_config('search_path', $1, true)`, [
10832
10883
  this.schemas.map((schema) => `"${schema.replaceAll('"', '""')}"`).join(",")
10833
10884
  ]);
10834
- return query("select graphql.resolve($1::text, $2::jsonb, $3::text, $4::jsonb) as result", [body.query, JSON.stringify(body.variables ?? {}), body.operationName ?? null, JSON.stringify(body.extensions ?? {})]);
10885
+ return query("select graphql.resolve($1::text, $2::jsonb, $3::text, $4::jsonb) as result", [body["query"], JSON.stringify(body["variables"] ?? {}), body["operationName"] ?? null, JSON.stringify(body["extensions"] ?? {})]);
10835
10886
  });
10836
10887
  const row = result.rows[0];
10837
10888
  if (result.rows.length !== 1 || !isRecord(row) || !isGraphqlEnvelope(row["result"])) {
@@ -10969,9 +11020,12 @@ async function generateTypes(db, schema = "public") {
10969
11020
  const views = new Map;
10970
11021
  for (const c of cols) {
10971
11022
  const target = c.table_kind === "r" ? tables : views;
10972
- if (!target.has(c.table_name))
10973
- target.set(c.table_name, []);
10974
- target.get(c.table_name).push(c);
11023
+ let columns = target.get(c.table_name);
11024
+ if (!columns) {
11025
+ columns = [];
11026
+ target.set(c.table_name, columns);
11027
+ }
11028
+ columns.push(c);
10975
11029
  }
10976
11030
  const tsType = (udt, nullable) => {
10977
11031
  const base = mapType(udt, enumNames, schema);
@@ -11840,7 +11894,11 @@ async function revokeReplicationGrants(tx) {
11840
11894
  }
11841
11895
  }
11842
11896
  async function grantReplicationAllowlist(tx, tables) {
11843
- const schemas = uniqueSorted(tables.map((table) => table.schema));
11897
+ const schemas = uniqueSorted(tables.map((table) => {
11898
+ if (!table.schema)
11899
+ throw new Error(`publication table ${table.name} has no schema`);
11900
+ return table.schema;
11901
+ }));
11844
11902
  for (const schema of schemas) {
11845
11903
  await tx.exec(`GRANT USAGE ON SCHEMA ${quoteIdentifier(schema)} TO ${POWERSYNC_REPLICATION_ROLE}`);
11846
11904
  }
@@ -11944,6 +12002,8 @@ function normalizeCidr(cidr) {
11944
12002
  if (!match)
11945
12003
  throw new Error(`invalid PowerSync client CIDR: ${cidr}`);
11946
12004
  const address = match[1];
12005
+ if (!address)
12006
+ throw new Error(`invalid PowerSync client CIDR: ${cidr}`);
11947
12007
  const family = isIP(address);
11948
12008
  const prefix = Number(match[2]);
11949
12009
  if (family === 0 || prefix < 0 || prefix > (family === 4 ? 32 : 128)) {
@@ -12050,12 +12110,12 @@ class PgWireClient {
12050
12110
  if (code === 0) {} else if (code === 3) {
12051
12111
  if (!needPassword())
12052
12112
  return;
12053
- this.socket.write(message(112, cstring(opts.password)));
12113
+ this.socket.write(message(112, cstring(opts.password ?? "")));
12054
12114
  } else if (code === 5) {
12055
12115
  if (!needPassword())
12056
12116
  return;
12057
12117
  const salt = payload.subarray(4, 8);
12058
- const inner = md5Hex(Buffer.from(opts.password + opts.user, "utf8"));
12118
+ const inner = md5Hex(Buffer.from((opts.password ?? "") + opts.user, "utf8"));
12059
12119
  const token = "md5" + md5Hex(Buffer.concat([Buffer.from(inner, "utf8"), salt]));
12060
12120
  this.socket.write(message(112, cstring(token)));
12061
12121
  } else if (code === 10) {
@@ -12077,6 +12137,10 @@ class PgWireClient {
12077
12137
  reject(new Error("SCRAM: server nonce does not extend client nonce"));
12078
12138
  return;
12079
12139
  }
12140
+ if (!attrs.s || !attrs.i || !opts.password) {
12141
+ reject(new Error("SCRAM: incomplete server challenge"));
12142
+ return;
12143
+ }
12080
12144
  const salt = Buffer.from(attrs.s, "base64");
12081
12145
  const iterations = parseInt(attrs.i, 10);
12082
12146
  const saltedPassword = pbkdf2Sync(opts.password, salt, iterations, 32, "sha256");
@@ -12493,7 +12557,7 @@ function toPgArrayLiteral(array) {
12493
12557
  // src/runtime/node/native/engine.ts
12494
12558
  var DEFAULT_PG_VERSION = "17.7.0";
12495
12559
  var POSTGRES_MIRROR_URL_ERROR = "SUPACLOUD_LITE_POSTGRES_MIRROR must be an absolute HTTPS URL or a loopback HTTP URL";
12496
- var NATIVE_POSTGRES_MAJOR = DEFAULT_PG_VERSION.split(".")[0];
12560
+ var NATIVE_POSTGRES_MAJOR = DEFAULT_PG_VERSION.split(".")[0] ?? "17";
12497
12561
  function nativePostgresMajor(installDir = process.env.SUPACLOUD_LITE_POSTGRES_DIR) {
12498
12562
  if (!installDir)
12499
12563
  return NATIVE_POSTGRES_MAJOR;
@@ -12760,15 +12824,18 @@ ${detail}` : " (no output)"}
12760
12824
  connect,
12761
12825
  onClose: async () => {
12762
12826
  removeExitHandler?.();
12763
- await stopPostgres(postgres, () => postgresExited);
12764
- rmSync(socketDirectory, { recursive: true, force: true });
12827
+ if (postgres)
12828
+ await stopPostgres(postgres, () => postgresExited);
12829
+ if (socketDirectory)
12830
+ rmSync(socketDirectory, { recursive: true, force: true });
12765
12831
  await releaseLock();
12766
12832
  }
12767
12833
  });
12768
12834
  } catch (error) {
12769
12835
  removeExitHandler?.();
12770
- if (postgres)
12771
- await stopPostgres(postgres, () => postgres.exitCode !== null);
12836
+ const processToStop = postgres;
12837
+ if (processToStop)
12838
+ await stopPostgres(processToStop, () => processToStop.exitCode !== null);
12772
12839
  if (socketDirectory)
12773
12840
  rmSync(socketDirectory, { recursive: true, force: true });
12774
12841
  await releaseLock();
@@ -13588,7 +13655,10 @@ ${details}`, { cause: buildThrow });
13588
13655
  throw new Error(buildOutput.logs.map((item) => item.message).join(`
13589
13656
  `) || `failed to bundle ${entryPath}`);
13590
13657
  }
13591
- return buildOutput.outputs[0].path;
13658
+ const output = buildOutput.outputs[0];
13659
+ if (!output)
13660
+ throw new Error(`bundle produced no output for ${entryPath}`);
13661
+ return output.path;
13592
13662
  } catch (buildError) {
13593
13663
  try {
13594
13664
  await rm2(outDir, { recursive: true, force: true });
@@ -13674,7 +13744,8 @@ async function loadFunctionsUnlocked(projectDir, options, mode) {
13674
13744
  const dir = join5(root, name);
13675
13745
  if (!(await stat(dir)).isDirectory())
13676
13746
  continue;
13677
- const candidates = options[name]?.entrypoint ? [join5(projectDir, options[name].entrypoint)] : ["index.ts", "index.tsx", "index.js", "index.mjs"].map((f) => join5(dir, f));
13747
+ const entrypoint = options[name]?.entrypoint;
13748
+ const candidates = entrypoint ? [join5(projectDir, entrypoint)] : ["index.ts", "index.tsx", "index.js", "index.mjs"].map((f) => join5(dir, f));
13678
13749
  for (const path of candidates) {
13679
13750
  try {
13680
13751
  await stat(path);
@@ -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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"}
@@ -11,6 +11,7 @@
11
11
  * - implicit: redirect to redirect_to#access_token=…&refresh_token=…
12
12
  */
13
13
  import type { Database } from '../db/database.js';
14
+ type OAuthRawProfile = Record<string, unknown>;
14
15
  /** Operator-supplied config for one OAuth provider. Endpoint URLs are optional for presets (google, github). */
15
16
  export interface OAuthProviderConfig {
16
17
  /** OAuth client id issued by the provider */
@@ -26,7 +27,7 @@ export interface OAuthProviderConfig {
26
27
  /** space-separated scopes to request; falls back to the preset's */
27
28
  scopes?: string;
28
29
  /** Map the provider's raw userinfo JSON to a normalized profile. */
29
- profileMap?: (raw: any) => OAuthProfile;
30
+ profileMap?: (raw: OAuthRawProfile) => OAuthProfile;
30
31
  }
31
32
  /** Normalized profile extracted from a provider's userinfo response. */
32
33
  export interface OAuthProfile {
@@ -43,7 +44,7 @@ export interface OAuthProfile {
43
44
  }
44
45
  interface ResolvedProvider extends Required<Omit<OAuthProviderConfig, 'profileMap'>> {
45
46
  name: string;
46
- profileMap: (raw: any) => OAuthProfile;
47
+ profileMap: (raw: OAuthRawProfile) => OAuthProfile;
47
48
  }
48
49
  /**
49
50
  * Merge operator config with the built-in preset for `name` into a fully