@supacloud/lite 0.14.0 → 0.16.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/cli.js CHANGED
@@ -1,6 +1,5 @@
1
1
  #!/usr/bin/env bun
2
2
  // @bun
3
- var __require = import.meta.require;
4
3
 
5
4
  // src/cli.ts
6
5
  import { existsSync as existsSync4 } from "fs";
@@ -9,7 +8,7 @@ import { dirname as dirname8, join as join10, resolve as resolve6 } from "path";
9
8
  // package.json
10
9
  var package_default = {
11
10
  name: "@supacloud/lite",
12
- version: "0.14.0",
11
+ version: "0.16.0",
13
12
  description: "Bun-native, single-project Supabase-compatible backend powered by PGlite or native PostgreSQL",
14
13
  type: "module",
15
14
  license: "Apache-2.0",
@@ -69,13 +68,13 @@ var package_default = {
69
68
  "@supacloud/compiler": "^0.13.1",
70
69
  "@supacloud/elysia": "^0.10.0",
71
70
  "@supabase/supabase-js": "^2.115.0",
72
- "@types/bun": "^1.4.0",
71
+ "@types/bun": "^1.4.2",
73
72
  elysia: "^1.4.30",
74
73
  jose: "^6.2.11",
75
74
  typescript: "^7.0.2"
76
75
  },
77
76
  engines: {
78
- bun: ">=1.4.0"
77
+ bun: ">=1.4.2"
79
78
  },
80
79
  publishConfig: {
81
80
  access: "public",
@@ -423,10 +422,15 @@ class OAuthService {
423
422
  JSON.stringify({ provider, providers: [provider] }),
424
423
  JSON.stringify({ sub: profile.id, email: profile.email, full_name: profile.name, ...profile.metadata })
425
424
  ]);
426
- userId = created.rows[0].id;
425
+ const user = created.rows[0];
426
+ if (!user)
427
+ throw new Error("OAuth user creation returned no row");
428
+ userId = user.id;
427
429
  }
428
430
  await this.db.query(`insert into auth.identities (user_id, provider, provider_id, identity_data)
429
431
  values ($1, $2, $3, $4::jsonb)`, [userId, provider, profile.id, JSON.stringify({ sub: profile.id, email: profile.email, ...profile.metadata })]);
432
+ if (!userId)
433
+ throw new Error("OAuth identity has no user ID");
430
434
  return userId;
431
435
  }
432
436
  }
@@ -639,10 +643,10 @@ class QrCode {
639
643
  const bytes = new TextEncoder().encode(text);
640
644
  let version = 1;
641
645
  for (;version <= 40; version++) {
642
- const dataCapacityBits2 = getNumDataCodewords(version) * 8;
646
+ const dataCapacityBits = getNumDataCodewords(version) * 8;
643
647
  const ccBits = version < 10 ? 8 : 16;
644
648
  const usedBits = 4 + ccBits + bytes.length * 8;
645
- if (usedBits <= dataCapacityBits2)
649
+ if (usedBits <= dataCapacityBits)
646
650
  break;
647
651
  }
648
652
  if (version > 40)
@@ -1334,10 +1338,10 @@ class AuthHandler {
1334
1338
  if (!this.settings.anonymousUsers) {
1335
1339
  return authError(422, "anonymous_provider_disabled", "Anonymous sign-ins are disabled");
1336
1340
  }
1337
- const res2 = await this.db.query(`insert into auth.users (aud, role, raw_app_meta_data, raw_user_meta_data, is_anonymous, last_sign_in_at)
1341
+ const res = await this.db.query(`insert into auth.users (aud, role, raw_app_meta_data, raw_user_meta_data, is_anonymous, last_sign_in_at)
1338
1342
  values ('authenticated', 'authenticated', '{}', $1, true, now())
1339
1343
  returning *`, [JSON.stringify(body.data ?? {})]);
1340
- return json(200, await this.sessionFor(res2.rows[0]));
1344
+ return json(200, await this.sessionFor(res.rows[0]));
1341
1345
  }
1342
1346
  if (this.settings.disableSignup) {
1343
1347
  return authError(422, "signup_disabled", "Signups not allowed for this instance");
@@ -3931,45 +3935,202 @@ AS $$
3931
3935
  DECLARE
3932
3936
  normalized_queue_name text := lower(btrim(queue_name));
3933
3937
  BEGIN
3934
- IF normalized_queue_name IS NULL
3935
- OR left(normalized_queue_name, char_length('supacloud_internal_')) = 'supacloud_internal_' THEN
3938
+ IF left(normalized_queue_name, char_length('supacloud_internal_')) = 'supacloud_internal_' THEN
3936
3939
  RAISE EXCEPTION 'SUPACLOUD_QUEUE_NAME_RESERVED' USING ERRCODE = '42501';
3937
3940
  END IF;
3938
- RETURN normalized_queue_name;
3941
+ IF queue_name IS NULL OR queue_name !~ '^[a-z0-9][a-z0-9_-]{0,127}$' THEN
3942
+ RAISE EXCEPTION 'SUPACLOUD_QUEUE_NAME_INVALID' USING ERRCODE = '22023';
3943
+ END IF;
3944
+ RETURN queue_name;
3945
+ END;
3946
+ $$;
3947
+
3948
+ -- Return-type changes require replacement. Do not CASCADE through user dependencies.
3949
+ DO $pgmq_receipt_types$
3950
+ BEGIN
3951
+ IF EXISTS (
3952
+ SELECT 1 FROM pg_catalog.pg_proc
3953
+ WHERE oid = to_regprocedure('pgmq_public.send(text,jsonb,integer)')
3954
+ AND prorettype = 'bigint'::regtype
3955
+ ) THEN
3956
+ DROP FUNCTION pgmq_public.send(text,jsonb,integer);
3957
+ END IF;
3958
+ IF EXISTS (
3959
+ SELECT 1 FROM pg_catalog.pg_proc
3960
+ WHERE oid = to_regprocedure('pgmq_public.send_batch(text,jsonb[],integer)')
3961
+ AND prorettype = 'bigint'::regtype
3962
+ ) THEN
3963
+ DROP FUNCTION pgmq_public.send_batch(text,jsonb[],integer);
3964
+ END IF;
3965
+ IF EXISTS (
3966
+ SELECT 1 FROM pg_catalog.pg_proc
3967
+ WHERE oid = to_regprocedure('pgmq_public.read(text,integer,integer)')
3968
+ AND prorettype = 'pgmq.message_record'::regtype
3969
+ ) THEN
3970
+ DROP FUNCTION pgmq_public.read(text,integer,integer);
3971
+ END IF;
3972
+ IF EXISTS (
3973
+ SELECT 1 FROM pg_catalog.pg_proc
3974
+ WHERE oid = to_regprocedure('pgmq_public.pop(text)')
3975
+ AND prorettype = 'pgmq.message_record'::regtype
3976
+ ) THEN
3977
+ DROP FUNCTION pgmq_public.pop(text);
3978
+ END IF;
3979
+ END
3980
+ $pgmq_receipt_types$;
3981
+
3982
+ CREATE OR REPLACE FUNCTION pgmq_public.require_seconds(value integer)
3983
+ RETURNS integer LANGUAGE plpgsql IMMUTABLE SET search_path = ''
3984
+ AS $$
3985
+ BEGIN
3986
+ IF value IS NULL OR value < 0 THEN
3987
+ RAISE EXCEPTION 'SUPACLOUD_QUEUE_SECONDS_INVALID' USING ERRCODE = '22023';
3988
+ END IF;
3989
+ RETURN value;
3990
+ END;
3991
+ $$;
3992
+
3993
+ CREATE OR REPLACE FUNCTION pgmq_public.require_read_count(value integer)
3994
+ RETURNS integer LANGUAGE plpgsql IMMUTABLE SET search_path = ''
3995
+ AS $$
3996
+ BEGIN
3997
+ IF value IS NULL OR value < 1 OR value > 10000 THEN
3998
+ RAISE EXCEPTION 'SUPACLOUD_QUEUE_COUNT_INVALID' USING ERRCODE = '22023';
3999
+ END IF;
4000
+ RETURN value;
4001
+ END;
4002
+ $$;
4003
+
4004
+ CREATE OR REPLACE FUNCTION pgmq_public.require_message_id(value bigint)
4005
+ RETURNS bigint LANGUAGE plpgsql IMMUTABLE SET search_path = ''
4006
+ AS $$
4007
+ BEGIN
4008
+ IF value IS NULL OR value < 1 THEN
4009
+ RAISE EXCEPTION 'SUPACLOUD_QUEUE_MESSAGE_ID_INVALID' USING ERRCODE = '22023';
4010
+ END IF;
4011
+ RETURN value;
4012
+ END;
4013
+ $$;
4014
+
4015
+ CREATE OR REPLACE FUNCTION pgmq_public.message_node_count(value jsonb)
4016
+ RETURNS integer LANGUAGE plpgsql IMMUTABLE SET search_path = ''
4017
+ AS $$
4018
+ DECLARE
4019
+ node_count integer;
4020
+ maximum_depth integer;
4021
+ BEGIN
4022
+ IF value IS NULL THEN
4023
+ RAISE EXCEPTION 'SUPACLOUD_QUEUE_MESSAGE_INVALID' USING ERRCODE = '22023';
4024
+ END IF;
4025
+ IF octet_length(convert_to(value::text, 'UTF8')) > 1048576 THEN
4026
+ RAISE EXCEPTION 'SUPACLOUD_QUEUE_PAYLOAD_TOO_LARGE' USING ERRCODE = '22023';
4027
+ END IF;
4028
+ WITH RECURSIVE tree(item, depth) AS (
4029
+ SELECT value, 0
4030
+ UNION ALL
4031
+ SELECT child.item, tree.depth + 1
4032
+ FROM tree
4033
+ CROSS JOIN LATERAL (
4034
+ SELECT element AS item
4035
+ FROM jsonb_array_elements(CASE WHEN jsonb_typeof(tree.item) = 'array' THEN tree.item ELSE '[]'::jsonb END) AS element
4036
+ UNION ALL
4037
+ SELECT entry.value AS item
4038
+ FROM jsonb_each(CASE WHEN jsonb_typeof(tree.item) = 'object' THEN tree.item ELSE '{}'::jsonb END) AS entry
4039
+ ) AS child
4040
+ WHERE tree.depth < 65
4041
+ )
4042
+ SELECT count(*)::integer, max(depth) INTO node_count, maximum_depth
4043
+ FROM (SELECT depth FROM tree LIMIT 10001) AS bounded;
4044
+ IF node_count > 10000 OR maximum_depth > 64 THEN
4045
+ RAISE EXCEPTION 'SUPACLOUD_QUEUE_STRUCTURE_TOO_LARGE' USING ERRCODE = '22023';
4046
+ END IF;
4047
+ RETURN node_count;
4048
+ END;
4049
+ $$;
4050
+
4051
+ CREATE OR REPLACE FUNCTION pgmq_public.require_message(value jsonb)
4052
+ RETURNS jsonb LANGUAGE plpgsql IMMUTABLE SET search_path = ''
4053
+ AS $$
4054
+ BEGIN
4055
+ PERFORM pgmq_public.message_node_count(value);
4056
+ RETURN value;
4057
+ END;
4058
+ $$;
4059
+
4060
+ CREATE OR REPLACE FUNCTION pgmq_public.require_messages(values_ jsonb[])
4061
+ RETURNS jsonb[] LANGUAGE plpgsql IMMUTABLE SET search_path = ''
4062
+ AS $$
4063
+ DECLARE
4064
+ item jsonb;
4065
+ total_bytes bigint := 0;
4066
+ total_nodes integer := 0;
4067
+ BEGIN
4068
+ IF values_ IS NULL OR cardinality(values_) < 1 OR cardinality(values_) > 10000
4069
+ OR array_ndims(values_) <> 1 OR array_lower(values_, 1) <> 1 THEN
4070
+ RAISE EXCEPTION 'SUPACLOUD_QUEUE_BATCH_INVALID' USING ERRCODE = '22023';
4071
+ END IF;
4072
+ FOREACH item IN ARRAY values_ LOOP
4073
+ total_nodes := total_nodes + pgmq_public.message_node_count(item);
4074
+ IF total_nodes > 100000 THEN
4075
+ RAISE EXCEPTION 'SUPACLOUD_QUEUE_STRUCTURE_TOO_LARGE' USING ERRCODE = '22023';
4076
+ END IF;
4077
+ total_bytes := total_bytes + octet_length(convert_to(item::text, 'UTF8'));
4078
+ IF total_bytes > 8388608 THEN
4079
+ RAISE EXCEPTION 'SUPACLOUD_QUEUE_PAYLOAD_TOO_LARGE' USING ERRCODE = '22023';
4080
+ END IF;
4081
+ END LOOP;
4082
+ RETURN values_;
3939
4083
  END;
3940
4084
  $$;
3941
4085
 
3942
4086
  CREATE OR REPLACE FUNCTION pgmq_public.send(queue_name text, message jsonb, sleep_seconds integer DEFAULT 0)
3943
- RETURNS SETOF bigint
4087
+ RETURNS SETOF text
3944
4088
  LANGUAGE sql
3945
4089
  VOLATILE
3946
4090
  SECURITY DEFINER
3947
4091
  SET search_path = ''
3948
- AS $$ SELECT * FROM pgmq.send(pgmq_public.require_public_queue(queue_name), message, sleep_seconds); $$;
4092
+ AS $$ SELECT receipt.msg_id::text FROM pgmq.send(pgmq_public.require_public_queue(queue_name), pgmq_public.require_message(message), pgmq_public.require_seconds(sleep_seconds)) AS receipt(msg_id); $$;
3949
4093
 
3950
4094
  CREATE OR REPLACE FUNCTION pgmq_public.send_batch(queue_name text, messages jsonb[], sleep_seconds integer DEFAULT 0)
3951
- RETURNS SETOF bigint
4095
+ RETURNS SETOF text
3952
4096
  LANGUAGE sql
3953
4097
  VOLATILE
3954
4098
  SECURITY DEFINER
3955
4099
  SET search_path = ''
3956
- AS $$ SELECT * FROM pgmq.send_batch(pgmq_public.require_public_queue(queue_name), messages, sleep_seconds); $$;
4100
+ AS $$ SELECT receipt.msg_id::text FROM pgmq.send_batch(pgmq_public.require_public_queue(queue_name), pgmq_public.require_messages(messages), pgmq_public.require_seconds(sleep_seconds)) AS receipt(msg_id); $$;
3957
4101
 
3958
4102
  CREATE OR REPLACE FUNCTION pgmq_public.read(queue_name text, sleep_seconds integer, n integer)
3959
- RETURNS SETOF pgmq.message_record
4103
+ RETURNS TABLE (
4104
+ msg_id text, read_ct integer, enqueued_at timestamptz,
4105
+ last_read_at timestamptz, vt timestamptz, message jsonb, headers jsonb
4106
+ )
3960
4107
  LANGUAGE sql
3961
4108
  VOLATILE
3962
4109
  SECURITY DEFINER
3963
4110
  SET search_path = ''
3964
- AS $$ SELECT * FROM pgmq.read(pgmq_public.require_public_queue(queue_name), sleep_seconds, n); $$;
4111
+ AS $$
4112
+ SELECT receipt.msg_id::text, receipt.read_ct, receipt.enqueued_at,
4113
+ (to_jsonb(receipt)->>'last_read_at')::timestamptz, receipt.vt,
4114
+ receipt.message, to_jsonb(receipt)->'headers'
4115
+ FROM pgmq.read(pgmq_public.require_public_queue(queue_name),
4116
+ pgmq_public.require_seconds(sleep_seconds), pgmq_public.require_read_count(n)) AS receipt;
4117
+ $$;
3965
4118
 
3966
4119
  CREATE OR REPLACE FUNCTION pgmq_public.pop(queue_name text)
3967
- RETURNS SETOF pgmq.message_record
4120
+ RETURNS TABLE (
4121
+ msg_id text, read_ct integer, enqueued_at timestamptz,
4122
+ last_read_at timestamptz, vt timestamptz, message jsonb, headers jsonb
4123
+ )
3968
4124
  LANGUAGE sql
3969
4125
  VOLATILE
3970
4126
  SECURITY DEFINER
3971
4127
  SET search_path = ''
3972
- AS $$ SELECT * FROM pgmq.pop(pgmq_public.require_public_queue(queue_name)); $$;
4128
+ AS $$
4129
+ SELECT receipt.msg_id::text, receipt.read_ct, receipt.enqueued_at,
4130
+ (to_jsonb(receipt)->>'last_read_at')::timestamptz, receipt.vt,
4131
+ receipt.message, to_jsonb(receipt)->'headers'
4132
+ FROM pgmq.pop(pgmq_public.require_public_queue(queue_name)) AS receipt;
4133
+ $$;
3973
4134
 
3974
4135
  CREATE OR REPLACE FUNCTION pgmq_public.archive(queue_name text, message_id bigint)
3975
4136
  RETURNS boolean
@@ -3977,7 +4138,7 @@ LANGUAGE sql
3977
4138
  VOLATILE
3978
4139
  SECURITY DEFINER
3979
4140
  SET search_path = ''
3980
- AS $$ SELECT pgmq.archive(pgmq_public.require_public_queue(queue_name), message_id); $$;
4141
+ AS $$ SELECT pgmq.archive(pgmq_public.require_public_queue(queue_name), pgmq_public.require_message_id(message_id)); $$;
3981
4142
 
3982
4143
  CREATE OR REPLACE FUNCTION pgmq_public."delete"(queue_name text, message_id bigint)
3983
4144
  RETURNS boolean
@@ -3985,10 +4146,12 @@ LANGUAGE sql
3985
4146
  VOLATILE
3986
4147
  SECURITY DEFINER
3987
4148
  SET search_path = ''
3988
- AS $$ SELECT pgmq.delete(pgmq_public.require_public_queue(queue_name), message_id); $$;
4149
+ AS $$ SELECT pgmq.delete(pgmq_public.require_public_queue(queue_name), pgmq_public.require_message_id(message_id)); $$;
3989
4150
 
3990
4151
  REVOKE ALL ON ALL FUNCTIONS IN SCHEMA pgmq_public FROM PUBLIC;
3991
4152
  GRANT EXECUTE ON ALL FUNCTIONS IN SCHEMA pgmq_public TO anon, authenticated, service_role;
4153
+
4154
+ NOTIFY pgrst, 'reload schema';
3992
4155
  -- supacloud:sql-module:pgmq-public:end
3993
4156
  `;
3994
4157
  var WORKFLOWS_SQL = `
@@ -4611,7 +4774,12 @@ BEGIN
4611
4774
  OR (retry_receipt ->> 'delaySeconds')::integer IS DISTINCT FROM p_delay_seconds THEN
4612
4775
  RAISE EXCEPTION 'SUPACLOUD_WORKFLOW_IDEMPOTENCY_CONFLICT' USING ERRCODE = '23505';
4613
4776
  END IF;
4614
- RETURN supacloud_workflows.snapshot(current_step.run_id, true);
4777
+ retry_receipt := retry_receipt || jsonb_build_object(
4778
+ 'stepId', current_step.id,
4779
+ 'attempt', p_attempt
4780
+ );
4781
+ RETURN supacloud_workflows.snapshot(current_step.run_id, true)
4782
+ || jsonb_build_object('retryReceipt', retry_receipt);
4615
4783
  END IF;
4616
4784
  IF normalized_worker_id IS NULL
4617
4785
  OR p_message_id IS NULL
@@ -4639,19 +4807,22 @@ BEGIN
4639
4807
  IF NOT FOUND THEN
4640
4808
  RAISE EXCEPTION 'SUPACLOUD_WORKFLOW_RUN_NOT_ACTIVE' USING ERRCODE = '55000';
4641
4809
  END IF;
4810
+ retry_receipt := jsonb_build_object(
4811
+ 'operation', 'retry',
4812
+ 'stepId', current_step.id,
4813
+ 'messageId', p_message_id::text,
4814
+ 'attempt', p_attempt,
4815
+ 'workerId', normalized_worker_id,
4816
+ 'errorMessage', normalized_error,
4817
+ 'delaySeconds', p_delay_seconds
4818
+ );
4642
4819
  INSERT INTO supacloud_workflows.events (
4643
4820
  run_id, step_id, event_type, attempt, details
4644
4821
  ) VALUES (
4645
- current_step.run_id, current_step.id, 'step_dead_lettered', p_attempt,
4646
- jsonb_build_object(
4647
- 'operation', 'retry',
4648
- 'messageId', p_message_id::text,
4649
- 'workerId', normalized_worker_id,
4650
- 'errorMessage', normalized_error,
4651
- 'delaySeconds', p_delay_seconds
4652
- )
4822
+ current_step.run_id, current_step.id, 'step_dead_lettered', p_attempt, retry_receipt
4653
4823
  );
4654
- RETURN supacloud_workflows.snapshot(current_step.run_id, false);
4824
+ RETURN supacloud_workflows.snapshot(current_step.run_id, false)
4825
+ || jsonb_build_object('retryReceipt', retry_receipt);
4655
4826
  END IF;
4656
4827
 
4657
4828
  SELECT EXISTS (
@@ -4664,19 +4835,22 @@ BEGIN
4664
4835
  SET status = 'queued', error_message = normalized_error,
4665
4836
  retry_delay_seconds = p_delay_seconds, updated_at = now()
4666
4837
  WHERE id = current_step.id;
4838
+ retry_receipt := jsonb_build_object(
4839
+ 'operation', 'retry',
4840
+ 'stepId', current_step.id,
4841
+ 'messageId', p_message_id::text,
4842
+ 'attempt', p_attempt,
4843
+ 'workerId', normalized_worker_id,
4844
+ 'errorMessage', normalized_error,
4845
+ 'delaySeconds', p_delay_seconds
4846
+ );
4667
4847
  INSERT INTO supacloud_workflows.events (
4668
4848
  run_id, step_id, event_type, attempt, details
4669
4849
  ) VALUES (
4670
- current_step.run_id, current_step.id, 'step_retried', p_attempt,
4671
- jsonb_build_object(
4672
- 'operation', 'retry',
4673
- 'messageId', p_message_id::text,
4674
- 'workerId', normalized_worker_id,
4675
- 'errorMessage', normalized_error,
4676
- 'delaySeconds', p_delay_seconds
4677
- )
4850
+ current_step.run_id, current_step.id, 'step_retried', p_attempt, retry_receipt
4678
4851
  );
4679
- RETURN supacloud_workflows.snapshot(current_step.run_id, false);
4852
+ RETURN supacloud_workflows.snapshot(current_step.run_id, false)
4853
+ || jsonb_build_object('retryReceipt', retry_receipt);
4680
4854
  END;
4681
4855
  $$;
4682
4856
 
@@ -5087,6 +5261,8 @@ CREATE TABLE IF NOT EXISTS supacloud_commands.receipts (
5087
5261
  CREATE INDEX IF NOT EXISTS supacloud_commands_target_idx
5088
5262
  ON supacloud_commands.receipts (target_type, target_id, created_at DESC, id);
5089
5263
 
5264
+ ALTER TABLE supacloud_commands.receipts ADD COLUMN IF NOT EXISTS tenant_id text;
5265
+
5090
5266
  CREATE OR REPLACE FUNCTION supacloud_commands.snapshot(
5091
5267
  p_command_id uuid,
5092
5268
  p_idempotent boolean DEFAULT false
@@ -5098,6 +5274,7 @@ LANGUAGE sql STABLE SECURITY DEFINER SET search_path = '' AS $$
5098
5274
  'targetType', receipt.target_type,
5099
5275
  'targetId', receipt.target_id,
5100
5276
  'actorId', receipt.actor_id,
5277
+ 'tenantId', receipt.tenant_id,
5101
5278
  'payloadFingerprint', receipt.payload_fingerprint,
5102
5279
  'createdAt', receipt.created_at,
5103
5280
  'idempotent', p_idempotent,
@@ -5125,6 +5302,8 @@ DECLARE
5125
5302
  normalized_target_id text;
5126
5303
  fingerprint text;
5127
5304
  existing supacloud_commands.receipts%ROWTYPE;
5305
+ tenant_id text;
5306
+ existing_execution jsonb;
5128
5307
  BEGIN
5129
5308
  IF jsonb_typeof(request) IS DISTINCT FROM 'object' THEN
5130
5309
  RAISE EXCEPTION 'SUPACLOUD_COMMAND_INVALID' USING ERRCODE = '22023';
@@ -5135,6 +5314,11 @@ BEGIN
5135
5314
  RAISE EXCEPTION 'SUPACLOUD_COMMAND_INVALID' USING ERRCODE = '22023';
5136
5315
  END IF;
5137
5316
  command_id := command_id_text::uuid;
5317
+ tenant_id := request->>'tenantId';
5318
+ IF request ? 'tenantId' AND (jsonb_typeof(request->'tenantId') IS DISTINCT FROM 'string'
5319
+ OR tenant_id !~ '^[A-Za-z0-9._:@|-]{1,200}$') THEN
5320
+ RAISE EXCEPTION 'SUPACLOUD_COMMAND_INVALID' USING ERRCODE = '22023';
5321
+ END IF;
5138
5322
  IF request ? 'actorId' AND request ->> 'actorId' IS NOT NULL THEN
5139
5323
  actor_id := (request ->> 'actorId')::uuid;
5140
5324
  END IF;
@@ -5162,12 +5346,20 @@ BEGIN
5162
5346
  OR existing.target_type <> normalized_target_type
5163
5347
  OR existing.target_id <> normalized_target_id
5164
5348
  OR existing.actor_id IS DISTINCT FROM actor_id
5349
+ OR existing.tenant_id IS DISTINCT FROM tenant_id
5165
5350
  OR existing.payload <> payload
5166
5351
  OR existing.payload_fingerprint <> fingerprint THEN
5167
5352
  RAISE EXCEPTION 'SUPACLOUD_COMMAND_IDEMPOTENCY_CONFLICT' USING ERRCODE = '23505';
5168
5353
  END IF;
5169
5354
  RETURN supacloud_commands.snapshot(command_id, true);
5170
5355
  END IF;
5356
+ IF to_regprocedure('supacloud_commands.execution_status(jsonb)') IS NOT NULL THEN
5357
+ EXECUTE 'SELECT supacloud_commands.execution_status($1)' INTO existing_execution
5358
+ USING jsonb_build_object('commandId',command_id);
5359
+ IF existing_execution IS NOT NULL THEN
5360
+ RAISE EXCEPTION 'SUPACLOUD_COMMAND_IDEMPOTENCY_CONFLICT' USING ERRCODE = '23505';
5361
+ END IF;
5362
+ END IF;
5171
5363
 
5172
5364
  PERFORM supacloud_workflows.start_run(
5173
5365
  command_id,
@@ -5188,10 +5380,10 @@ BEGIN
5188
5380
 
5189
5381
  INSERT INTO supacloud_commands.receipts (
5190
5382
  id, command_type, target_type, target_id, actor_id, payload,
5191
- payload_fingerprint, workflow_run_id
5383
+ payload_fingerprint, workflow_run_id, tenant_id
5192
5384
  ) VALUES (
5193
5385
  command_id, normalized_command_type, normalized_target_type,
5194
- normalized_target_id, actor_id, payload, fingerprint, command_id
5386
+ normalized_target_id, actor_id, payload, fingerprint, command_id, tenant_id
5195
5387
  );
5196
5388
  RETURN supacloud_commands.snapshot(command_id, false);
5197
5389
  EXCEPTION
@@ -5200,33 +5392,79 @@ EXCEPTION
5200
5392
  END;
5201
5393
  $$;
5202
5394
 
5203
- CREATE OR REPLACE FUNCTION public.supacloud_command_submit(request jsonb)
5204
- RETURNS jsonb
5205
- LANGUAGE sql VOLATILE SECURITY DEFINER SET search_path = '' AS $$
5206
- SELECT supacloud_commands.submit(request)
5207
- $$;
5208
-
5209
- CREATE OR REPLACE FUNCTION public.supacloud_command_get(request jsonb)
5395
+ CREATE OR REPLACE FUNCTION supacloud_commands.status(request jsonb)
5210
5396
  RETURNS jsonb
5211
5397
  LANGUAGE plpgsql STABLE SECURITY DEFINER SET search_path = '' AS $$
5212
5398
  DECLARE
5213
5399
  command_id_text text;
5400
+ execution jsonb;
5401
+ submission jsonb;
5402
+ field text;
5214
5403
  BEGIN
5215
5404
  IF jsonb_typeof(request) IS DISTINCT FROM 'object' THEN
5216
5405
  RAISE EXCEPTION 'SUPACLOUD_COMMAND_GET_INVALID' USING ERRCODE = '22023';
5217
5406
  END IF;
5407
+ IF request ? 'commandId' THEN
5408
+ IF jsonb_typeof(request->'commandId') IS DISTINCT FROM 'string'
5409
+ OR request->>'commandId' !~* '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$'
5410
+ OR EXISTS(SELECT FROM jsonb_object_keys(request) AS k WHERE k <> 'commandId') THEN
5411
+ RAISE EXCEPTION 'SUPACLOUD_COMMAND_GET_INVALID' USING ERRCODE = '22023';
5412
+ END IF;
5413
+ request := jsonb_build_object('commandId',(request->>'commandId')::uuid::text);
5414
+ ELSE
5415
+ IF EXISTS(SELECT FROM jsonb_object_keys(request) AS k WHERE k NOT IN ('tenantId','actorId','command','operationId')) THEN
5416
+ RAISE EXCEPTION 'SUPACLOUD_COMMAND_GET_INVALID' USING ERRCODE = '22023';
5417
+ END IF;
5418
+ FOREACH field IN ARRAY ARRAY['tenantId','actorId','command','operationId'] LOOP
5419
+ IF jsonb_typeof(request->field) IS DISTINCT FROM 'string' OR request->>field !~ '^[A-Za-z0-9._:@|-]{1,200}$' THEN
5420
+ RAISE EXCEPTION 'SUPACLOUD_COMMAND_GET_INVALID' USING ERRCODE = '22023';
5421
+ END IF;
5422
+ END LOOP;
5423
+ END IF;
5424
+ IF to_regprocedure('supacloud_commands.execution_status(jsonb)') IS NOT NULL THEN
5425
+ EXECUTE 'SELECT supacloud_commands.execution_status($1)' INTO execution USING request;
5426
+ IF execution IS NOT NULL THEN RETURN execution; END IF;
5427
+ END IF;
5428
+ IF NOT (request ? 'commandId') THEN
5429
+ IF jsonb_typeof(request->'tenantId') IS DISTINCT FROM 'string'
5430
+ OR jsonb_typeof(request->'actorId') IS DISTINCT FROM 'string'
5431
+ OR jsonb_typeof(request->'command') IS DISTINCT FROM 'string'
5432
+ OR jsonb_typeof(request->'operationId') IS DISTINCT FROM 'string' THEN
5433
+ RAISE EXCEPTION 'SUPACLOUD_COMMAND_GET_INVALID' USING ERRCODE = '22023';
5434
+ END IF;
5435
+ RETURN NULL;
5436
+ END IF;
5218
5437
  command_id_text := request ->> 'commandId';
5219
5438
  IF command_id_text IS NULL
5220
5439
  OR command_id_text !~* '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$' THEN
5221
5440
  RAISE EXCEPTION 'SUPACLOUD_COMMAND_GET_INVALID' USING ERRCODE = '22023';
5222
5441
  END IF;
5223
- RETURN supacloud_commands.snapshot(command_id_text::uuid, false);
5442
+ submission := supacloud_commands.snapshot(command_id_text::uuid, false);
5443
+ IF submission IS NULL THEN RETURN NULL; END IF;
5444
+ RETURN jsonb_build_object('kind','submission','commandId',command_id_text::uuid,
5445
+ 'execution',NULL,'workflow',jsonb_build_object(
5446
+ 'runId',submission->'workflow'->'runId','status',submission->'workflow'->'status'));
5224
5447
  EXCEPTION
5225
5448
  WHEN invalid_parameter_value OR invalid_text_representation THEN
5226
5449
  RAISE EXCEPTION 'SUPACLOUD_COMMAND_GET_INVALID' USING ERRCODE = '22023';
5227
5450
  END;
5228
5451
  $$;
5229
5452
 
5453
+ CREATE OR REPLACE FUNCTION public.supacloud_command_submit(request jsonb)
5454
+ RETURNS jsonb
5455
+ LANGUAGE plpgsql VOLATILE SECURITY DEFINER SET search_path = '' AS $$
5456
+ BEGIN
5457
+ PERFORM supacloud_commands.submit(request);
5458
+ RETURN supacloud_commands.status(jsonb_build_object('commandId',request->>'commandId'));
5459
+ END
5460
+ $$;
5461
+
5462
+ CREATE OR REPLACE FUNCTION public.supacloud_command_get(request jsonb)
5463
+ RETURNS jsonb
5464
+ LANGUAGE sql STABLE SECURITY DEFINER SET search_path = '' AS $$
5465
+ SELECT supacloud_commands.status(request)
5466
+ $$;
5467
+
5230
5468
  REVOKE ALL ON ALL TABLES IN SCHEMA supacloud_commands
5231
5469
  FROM PUBLIC, anon, authenticated, service_role;
5232
5470
  REVOKE ALL ON ALL FUNCTIONS IN SCHEMA supacloud_commands
@@ -6894,9 +7132,9 @@ class RealtimeEngine {
6894
7132
  return;
6895
7133
  const [, joinRefLen, refLen, topicLen, eventLen, metaLen, encoding] = bytes;
6896
7134
  let offset = 7;
6897
- const decoder2 = new TextDecoder;
7135
+ const decoder = new TextDecoder;
6898
7136
  const read = (len) => {
6899
- const out = decoder2.decode(bytes.subarray(offset, offset + len));
7137
+ const out = decoder.decode(bytes.subarray(offset, offset + len));
6900
7138
  offset += len;
6901
7139
  return out;
6902
7140
  };
@@ -6909,7 +7147,7 @@ class RealtimeEngine {
6909
7147
  const payload = {
6910
7148
  type: "broadcast",
6911
7149
  event: userEvent,
6912
- payload: encoding === 1 ? safeJsonParse(decoder2.decode(payloadBytes)) : payloadBytes
7150
+ payload: encoding === 1 ? safeJsonParse(decoder.decode(payloadBytes)) : payloadBytes
6913
7151
  };
6914
7152
  this.handleBroadcast(conn, {
6915
7153
  topic,
@@ -7220,24 +7458,24 @@ function parseQuery(searchParams) {
7220
7458
  const segments = key.split(".");
7221
7459
  const last = segments[segments.length - 1];
7222
7460
  if (last === "order") {
7223
- const path2 = segments.slice(0, -1);
7461
+ const path = segments.slice(0, -1);
7224
7462
  for (const term of splitTopLevel(value, ",")) {
7225
- q.order.push(parseOrderTerm(term.trim(), path2));
7463
+ q.order.push(parseOrderTerm(term.trim(), path));
7226
7464
  }
7227
7465
  continue;
7228
7466
  }
7229
7467
  if (last === "limit" || last === "offset") {
7230
- const path2 = segments.slice(0, -1).join(".");
7468
+ const path = segments.slice(0, -1).join(".");
7231
7469
  const n = parseInt(value, 10);
7232
7470
  if (Number.isNaN(n) || n < 0)
7233
7471
  throw new ParseError(`invalid ${last}: ${value}`);
7234
- (last === "limit" ? q.limits : q.offsets).set(path2, n);
7472
+ (last === "limit" ? q.limits : q.offsets).set(path, n);
7235
7473
  continue;
7236
7474
  }
7237
7475
  if (last === "or" || last === "and") {
7238
7476
  const negated = segments[segments.length - 2] === "not";
7239
- const path2 = segments.slice(0, negated ? -2 : -1);
7240
- q.conditions.push(parseLogicTree(last, value, path2, negated));
7477
+ const path = segments.slice(0, negated ? -2 : -1);
7478
+ q.conditions.push(parseLogicTree(last, value, path, negated));
7241
7479
  continue;
7242
7480
  }
7243
7481
  if (RESERVED.has(key))
@@ -7677,13 +7915,13 @@ class QueryBuilder {
7677
7915
  if (c.kind !== "column" || c.name === "*") {
7678
7916
  throw new ParseError("spread embeds support explicit columns only");
7679
7917
  }
7680
- const expr2 = renderColumnExpr(childAlias, c.name);
7918
+ const expr = renderColumnExpr(childAlias, c.name);
7681
7919
  const cast = c.cast ? `::${sanitizeCast(c.cast)}` : "";
7682
7920
  const out = c.alias ?? defaultAliasFor(c.name);
7683
- return toOne ? `(select ${expr2}${cast} from ${fromClause}${where}) as ${quoteIdent(out)}` : `coalesce((select json_agg(${expr2}${cast}${order}) from ${fromClause}${where}), ${AGG_EMPTY}) as ${quoteIdent(out)}`;
7921
+ return toOne ? `(select ${expr}${cast} from ${fromClause}${where}) as ${quoteIdent(out)}` : `coalesce((select json_agg(${expr}${cast}${order}) from ${fromClause}${where}), ${AGG_EMPTY}) as ${quoteIdent(out)}`;
7684
7922
  });
7685
- const innerCond2 = embed.inner ? `exists (select 1 from ${fromClause}${where})` : undefined;
7686
- return { exprs, innerCond: innerCond2 };
7923
+ const innerCond = embed.inner ? `exists (select 1 from ${fromClause}${where})` : undefined;
7924
+ return { exprs, innerCond };
7687
7925
  }
7688
7926
  const sub = `select ${childExprs.join(", ")} from ${fromClause}${where}${order}${limitOffset}`;
7689
7927
  const expr = rel.single === true ? `(select row_to_json(_sub) from (${sub}) _sub) as ${quoteIdent(outName)}` : `coalesce((select json_agg(row_to_json(_sub)) from (${sub}) _sub), ${AGG_EMPTY}) as ${quoteIdent(outName)}`;
@@ -8142,12 +8380,12 @@ class RestHandler {
8142
8380
  const built = builder.buildSelect(table, { count: prefer.count !== undefined });
8143
8381
  const { rows, count } = await this.db.withContext(ctx, async (query) => {
8144
8382
  const res = await query(built.sql, built.params);
8145
- let count2 = null;
8383
+ let count = null;
8146
8384
  if (built.countSql) {
8147
8385
  const c = await query(built.countSql, []);
8148
- count2 = c.rows[0].count;
8386
+ count = c.rows[0].count;
8149
8387
  }
8150
- return { rows: res.rows[0].body, count: count2 };
8388
+ return { rows: res.rows[0].body, count };
8151
8389
  });
8152
8390
  const offset = q.offsets.get("") ?? 0;
8153
8391
  return this.dataResponse(rows, {
@@ -8343,12 +8581,12 @@ class RestHandler {
8343
8581
  const countSql = prefer.count !== undefined ? `select count(*)::int as count from ${call} as ${quoteIdent(alias)}${where}` : undefined;
8344
8582
  const { rows, count } = await this.db.withContext(ctx, async (query) => {
8345
8583
  const res = await query(sql, []);
8346
- let count2 = null;
8584
+ let count = null;
8347
8585
  if (countSql) {
8348
8586
  const c = await query(countSql, []);
8349
- count2 = c.rows[0].count;
8587
+ count = c.rows[0].count;
8350
8588
  }
8351
- return { rows: res.rows[0].body, count: count2 };
8589
+ return { rows: res.rows[0].body, count };
8352
8590
  });
8353
8591
  return this.dataResponse(rows, {
8354
8592
  status: 200,
@@ -8664,7 +8902,7 @@ class Semaphore {
8664
8902
  this.active += 1;
8665
8903
  return;
8666
8904
  }
8667
- await new Promise((resolve2) => this.waiters.push(resolve2));
8905
+ await new Promise((resolve) => this.waiters.push(resolve));
8668
8906
  }
8669
8907
  release() {
8670
8908
  const next = this.waiters.shift();
@@ -8870,22 +9108,22 @@ class StorageHandler {
8870
9108
  }
8871
9109
  if (parts[0] === "render" && parts[1] === "image" && parts.length >= 5) {
8872
9110
  const kind = parts[2];
8873
- const bucket2 = parts[3];
8874
- const key2 = parts.slice(4).join("/");
9111
+ const bucket = parts[3];
9112
+ const key = parts.slice(4).join("/");
8875
9113
  if (kind === "public" && (method === "GET" || method === "HEAD")) {
8876
- const source = await this.loadPublicObject(bucket2, key2);
9114
+ const source = await this.loadPublicObject(bucket, key);
8877
9115
  if (source instanceof Response)
8878
9116
  return source;
8879
9117
  return await this.transformImageResponse(source, url, method === "HEAD");
8880
9118
  }
8881
9119
  if (kind === "authenticated" && (method === "GET" || method === "HEAD")) {
8882
- const source = await this.loadAuthenticatedObject(ctx, bucket2, key2);
9120
+ const source = await this.loadAuthenticatedObject(ctx, bucket, key);
8883
9121
  if (source instanceof Response)
8884
9122
  return source;
8885
9123
  return await this.transformImageResponse(source, url, method === "HEAD");
8886
9124
  }
8887
9125
  if (kind === "sign" && method === "GET") {
8888
- const source = await this.loadSignedObject(url, bucket2, key2);
9126
+ const source = await this.loadSignedObject(url, bucket, key);
8889
9127
  if (source instanceof Response)
8890
9128
  return source;
8891
9129
  return await this.transformImageResponse(source, url, false);
@@ -8919,12 +9157,12 @@ class StorageHandler {
8919
9157
  return await this.redeemSignedUrl(url, parts[2], parts.slice(3).join("/"));
8920
9158
  }
8921
9159
  if (parts[1] === "upload" && parts[2] === "sign" && parts.length >= 5) {
8922
- const bucket2 = parts[3];
8923
- const key2 = parts.slice(4).join("/");
9160
+ const bucket = parts[3];
9161
+ const key = parts.slice(4).join("/");
8924
9162
  if (method === "POST")
8925
- return await this.signUploadUrl(ctx, bucket2, key2);
9163
+ return await this.signUploadUrl(ctx, bucket, key);
8926
9164
  if (method === "PUT")
8927
- return await this.redeemSignedUpload(req, url, bucket2, key2);
9165
+ return await this.redeemSignedUpload(req, url, bucket, key);
8928
9166
  }
8929
9167
  if (parts[1] === "info" && parts.length >= 4 && method === "GET") {
8930
9168
  return await this.objectInfo(ctx, parts[2], parts.slice(3).join("/"));
@@ -8959,8 +9197,8 @@ class StorageHandler {
8959
9197
  async withMutation(operation) {
8960
9198
  const previous = this.mutationTail;
8961
9199
  let release;
8962
- this.mutationTail = new Promise((resolve2) => {
8963
- release = resolve2;
9200
+ this.mutationTail = new Promise((resolve) => {
9201
+ release = resolve;
8964
9202
  });
8965
9203
  await previous;
8966
9204
  try {
@@ -9212,8 +9450,8 @@ class StorageHandler {
9212
9450
  return storageError(409, "Duplicate", "The resource already exists");
9213
9451
  throw error;
9214
9452
  }
9215
- const uploadId2 = crypto.randomUUID();
9216
- this.tusUploads.set(uploadId2, {
9453
+ const uploadId = crypto.randomUUID();
9454
+ this.tusUploads.set(uploadId, {
9217
9455
  bucketId,
9218
9456
  key,
9219
9457
  contentType,
@@ -9229,13 +9467,13 @@ class StorageHandler {
9229
9467
  return new Response(null, {
9230
9468
  status: 201,
9231
9469
  headers: tus({
9232
- location: `${url.origin}/storage/v1/upload/resumable/${uploadId2}`,
9470
+ location: `${url.origin}/storage/v1/upload/resumable/${uploadId}`,
9233
9471
  "upload-offset": "0",
9234
9472
  "upload-length": "0"
9235
9473
  })
9236
9474
  });
9237
9475
  }
9238
- const activeUploads = [...this.tusUploads.values()].filter((upload3) => upload3.completedAt === undefined).length;
9476
+ const activeUploads = [...this.tusUploads.values()].filter((upload) => upload.completedAt === undefined).length;
9239
9477
  if (activeUploads >= MAX_CONCURRENT_TUS_UPLOADS) {
9240
9478
  return storageError(429, "too_many_requests", "Too many resumable uploads are active");
9241
9479
  }
@@ -9243,7 +9481,7 @@ class StorageHandler {
9243
9481
  if (preflightError)
9244
9482
  return preflightError;
9245
9483
  const uploadId = crypto.randomUUID();
9246
- const upload2 = {
9484
+ const upload = {
9247
9485
  bucketId,
9248
9486
  key,
9249
9487
  contentType,
@@ -9254,7 +9492,7 @@ class StorageHandler {
9254
9492
  chunks: [],
9255
9493
  ctx
9256
9494
  };
9257
- this.tusUploads.set(uploadId, upload2);
9495
+ this.tusUploads.set(uploadId, upload);
9258
9496
  if ((req.headers.get("content-type") ?? "").includes("application/offset+octet-stream")) {
9259
9497
  const chunk = await readLimitedBody(req, length);
9260
9498
  if (chunk === null) {
@@ -9262,7 +9500,7 @@ class StorageHandler {
9262
9500
  return storageError(400, "invalid_request", "chunk exceeds the declared Upload-Length");
9263
9501
  }
9264
9502
  if (chunk.length > 0) {
9265
- const err = await this.appendTus(uploadId, upload2, 0, chunk);
9503
+ const err = await this.appendTus(uploadId, upload, 0, chunk);
9266
9504
  if (err)
9267
9505
  return err;
9268
9506
  }
@@ -9271,7 +9509,7 @@ class StorageHandler {
9271
9509
  status: 201,
9272
9510
  headers: tus({
9273
9511
  location: `${url.origin}/storage/v1/upload/resumable/${uploadId}`,
9274
- "upload-offset": String(upload2.offset)
9512
+ "upload-offset": String(upload.offset)
9275
9513
  })
9276
9514
  });
9277
9515
  }
@@ -11197,8 +11435,8 @@ ${msg.text}` : `[mail] to=${msg.to} subject="${msg.subject}"`));
11197
11435
  headers: { "content-type": "application/json" }
11198
11436
  }));
11199
11437
  }
11200
- const ctx2 = { role: String(keyClaims.role ?? "anon"), claims: keyClaims };
11201
- return withCors(await auth.handle(req, ctx2, url));
11438
+ const ctx = { role: String(keyClaims.role ?? "anon"), claims: keyClaims };
11439
+ return withCors(await auth.handle(req, ctx, url));
11202
11440
  }
11203
11441
  if (path.startsWith("/functions/v1/")) {
11204
11442
  const functionName = path.replace(/^\/functions\/v1\/?/, "").split("/")[0];
@@ -11407,9 +11645,9 @@ function validatePublicationTables(tables) {
11407
11645
  if (missing.length > 0) {
11408
11646
  throw new Error(`PowerSync publication tables do not exist: ${missing.join(", ")}`);
11409
11647
  }
11410
- const unsupported2 = tables.filter((table) => table.present && !["r", "p"].includes(table.relkind ?? ""));
11411
- if (unsupported2.length > 0) {
11412
- throw new Error(`PowerSync publication only accepts ordinary or partitioned tables: ${unsupported2.map((table) => table.name).join(", ")}`);
11648
+ const unsupported = tables.filter((table) => table.present && !["r", "p"].includes(table.relkind ?? ""));
11649
+ if (unsupported.length > 0) {
11650
+ throw new Error(`PowerSync publication only accepts ordinary or partitioned tables: ${unsupported.map((table) => table.name).join(", ")}`);
11413
11651
  }
11414
11652
  }
11415
11653
  async function configureReplicationRole(tx, passwordValue) {
@@ -11617,7 +11855,7 @@ class PgWireClient {
11617
11855
  return client;
11618
11856
  }
11619
11857
  open(opts) {
11620
- return new Promise((resolve3, reject) => {
11858
+ return new Promise((resolve, reject) => {
11621
11859
  let startupComplete = false;
11622
11860
  this.socket = opts.socketPath ? createConnection(opts.socketPath) : createConnection(opts.port ?? 5432, opts.host ?? "127.0.0.1");
11623
11861
  this.socket.setTimeout(1e4, () => this.socket.destroy(new Error("PostgreSQL handshake timed out")));
@@ -11721,7 +11959,7 @@ class PgWireClient {
11721
11959
  this.buffer = Buffer.concat([this.buffer, c]);
11722
11960
  this.processMessages();
11723
11961
  });
11724
- resolve3();
11962
+ resolve();
11725
11963
  return;
11726
11964
  }
11727
11965
  }
@@ -11730,10 +11968,10 @@ class PgWireClient {
11730
11968
  });
11731
11969
  }
11732
11970
  run(send) {
11733
- const op = this.queue.then(() => new Promise((resolve3, reject) => {
11971
+ const op = this.queue.then(() => new Promise((resolve, reject) => {
11734
11972
  if (this.closed)
11735
11973
  return reject(new Error("connection closed"));
11736
- this.pending = { resolve: resolve3, reject, results: [], columns: [], error: null };
11974
+ this.pending = { resolve, reject, results: [], columns: [], error: null };
11737
11975
  send();
11738
11976
  }));
11739
11977
  this.queue = op.catch(() => {});
@@ -11764,11 +12002,11 @@ class PgWireClient {
11764
12002
  return results[0] ?? { rows: [] };
11765
12003
  }
11766
12004
  close() {
11767
- return new Promise((resolve3) => {
12005
+ return new Promise((resolve) => {
11768
12006
  if (this.closed)
11769
- return resolve3();
12007
+ return resolve();
11770
12008
  this.socket.write(message(88, Buffer.alloc(0)));
11771
- this.socket.end(() => resolve3());
12009
+ this.socket.end(() => resolve());
11772
12010
  });
11773
12011
  }
11774
12012
  nextMessage() {
@@ -11939,10 +12177,10 @@ function decodeValue(text, oid) {
11939
12177
  case 1114:
11940
12178
  return new Date(text.replace(" ", "T") + "Z");
11941
12179
  case 1184: {
11942
- let iso3 = text.replace(" ", "T");
11943
- if (/[+-]\d\d$/.test(iso3))
11944
- iso3 += ":00";
11945
- return new Date(iso3);
12180
+ let iso = text.replace(" ", "T");
12181
+ if (/[+-]\d\d$/.test(iso))
12182
+ iso += ":00";
12183
+ return new Date(iso);
11946
12184
  }
11947
12185
  case 1000:
11948
12186
  return parsePgArray(text).map((v) => v === "t");
@@ -12031,9 +12269,9 @@ async function buildWireEngine(options) {
12031
12269
  return queryMutex.run(async () => {
12032
12270
  await queryClient.exec("begin");
12033
12271
  try {
12034
- const response2 = await callback(transactionClient);
12272
+ const response = await callback(transactionClient);
12035
12273
  await queryClient.exec("commit");
12036
- return response2;
12274
+ return response;
12037
12275
  } catch (error) {
12038
12276
  await queryClient.exec("rollback").catch(() => {});
12039
12277
  throw error;
@@ -12262,15 +12500,15 @@ async function fetchRelease(url) {
12262
12500
  let lastError;
12263
12501
  for (let attempt = 1;attempt <= 3; attempt++) {
12264
12502
  try {
12265
- const response2 = await fetch(url, { signal: AbortSignal.timeout(30000) });
12266
- if (response2.ok || response2.status < 500)
12267
- return response2;
12268
- lastError = new Error(`failed to download ${url}: HTTP ${response2.status}`);
12503
+ const response = await fetch(url, { signal: AbortSignal.timeout(30000) });
12504
+ if (response.ok || response.status < 500)
12505
+ return response;
12506
+ lastError = new Error(`failed to download ${url}: HTTP ${response.status}`);
12269
12507
  } catch (error) {
12270
12508
  lastError = error;
12271
12509
  }
12272
12510
  if (attempt < 3)
12273
- await new Promise((resolve3) => setTimeout(resolve3, attempt * 500));
12511
+ await new Promise((resolve) => setTimeout(resolve, attempt * 500));
12274
12512
  }
12275
12513
  throw lastError instanceof Error ? lastError : new Error(`failed to download ${url}`);
12276
12514
  }
@@ -12362,7 +12600,7 @@ ${detail}` : " (no output)"}
12362
12600
  ` + `data dir: ${opts.dataDir}
12363
12601
  ` + "If a previous run is still holding it, stop it; or delete the data dir to start fresh.");
12364
12602
  }
12365
- await new Promise((resolve3) => setTimeout(resolve3, 150));
12603
+ await new Promise((resolve) => setTimeout(resolve, 150));
12366
12604
  }
12367
12605
  }
12368
12606
  throw new Error(`timed out waiting for embedded postgres at ${socketPath}`);
@@ -12390,14 +12628,14 @@ async function stopPostgres(postgres, hasExited) {
12390
12628
  if (hasExited())
12391
12629
  return;
12392
12630
  postgres.kill("SIGINT");
12393
- await new Promise((resolve3) => {
12631
+ await new Promise((resolve) => {
12394
12632
  const killTimeout = setTimeout(() => {
12395
12633
  postgres.kill("SIGKILL");
12396
- resolve3();
12634
+ resolve();
12397
12635
  }, 5000);
12398
12636
  postgres.once("exit", () => {
12399
12637
  clearTimeout(killTimeout);
12400
- resolve3();
12638
+ resolve();
12401
12639
  });
12402
12640
  });
12403
12641
  }
@@ -12693,7 +12931,7 @@ function isFixedSearchPath(searchPath) {
12693
12931
  function reconcileModule(module, catalog) {
12694
12932
  const issues = [];
12695
12933
  const ownedTables = new Set(module.tables);
12696
- const push = (severity, code, object, message2) => issues.push({ severity, code, object, message: message2 });
12934
+ const push = (severity, code, object, message) => issues.push({ severity, code, object, message });
12697
12935
  for (const policy of module.policies) {
12698
12936
  const [schema, table] = splitQualifiedName(policy.table);
12699
12937
  const found = catalog.policies.some((cp) => cp.schema === schema && cp.table === table && cp.name === policy.name);
@@ -12825,7 +13063,7 @@ function lintSql(sql, file) {
12825
13063
  }
12826
13064
  return issues;
12827
13065
  }
12828
- async function lintModule(module, readFile2) {
13066
+ async function lintModule(module, readFile) {
12829
13067
  const issues = [];
12830
13068
  const sources = new Set;
12831
13069
  for (const decl of [
@@ -12838,7 +13076,7 @@ async function lintModule(module, readFile2) {
12838
13076
  }
12839
13077
  const contents = new Map;
12840
13078
  await Promise.all([...sources].map(async (path) => {
12841
- contents.set(path, await readFile2(path));
13079
+ contents.set(path, await readFile(path));
12842
13080
  }));
12843
13081
  for (const [file, sql] of contents) {
12844
13082
  issues.push(...lintSql(sql, file));
@@ -12894,12 +13132,12 @@ function keys(row, expected) {
12894
13132
  }
12895
13133
  }
12896
13134
  function validTarget(value) {
12897
- const target2 = record(value);
12898
- keys(target2, ["environment", "projectRef"]);
12899
- if (typeof target2.environment !== "string" || !/^[a-z][a-z0-9-]{0,62}$/.test(target2.environment) || typeof target2.projectRef !== "string" || !/^[a-z0-9][a-z0-9_-]{0,62}$/.test(target2.projectRef)) {
13135
+ const target = record(value);
13136
+ keys(target, ["environment", "projectRef"]);
13137
+ if (typeof target.environment !== "string" || !/^[a-z][a-z0-9-]{0,62}$/.test(target.environment) || typeof target.projectRef !== "string" || !/^[a-z0-9][a-z0-9_-]{0,62}$/.test(target.projectRef)) {
12900
13138
  throw new Error("Invalid migration binding target");
12901
13139
  }
12902
- return target2;
13140
+ return target;
12903
13141
  }
12904
13142
  function validFile(file) {
12905
13143
  return typeof file === "string" && /^[a-zA-Z0-9_./-]+\.sql$/.test(file) && !file.startsWith("/") && file.split("/").every((part) => part && part !== "." && part !== "..");
@@ -12911,7 +13149,7 @@ function parseMigrationBindingManifest(value) {
12911
13149
  throw new Error("Invalid migration binding manifest");
12912
13150
  }
12913
13151
  const targets = manifest.targets.map(validTarget);
12914
- if (new Set(targets.map((target2) => target2.environment)).size !== targets.length) {
13152
+ if (new Set(targets.map((target) => target.environment)).size !== targets.length) {
12915
13153
  throw new Error("Duplicate migration binding environment");
12916
13154
  }
12917
13155
  const files = new Set;
@@ -12958,8 +13196,8 @@ function bindingValue(parameter, values) {
12958
13196
  }
12959
13197
  function renderMigrationBindings(options) {
12960
13198
  const manifest = parseMigrationBindingManifest(options.manifest);
12961
- const target2 = validTarget(options.target);
12962
- if (!manifest.targets.some((candidate) => candidate.environment === target2.environment && candidate.projectRef === target2.projectRef)) {
13199
+ const target = validTarget(options.target);
13200
+ if (!manifest.targets.some((candidate) => candidate.environment === target.environment && candidate.projectRef === target.projectRef)) {
12963
13201
  throw new Error("Migration binding target is not registered in the manifest");
12964
13202
  }
12965
13203
  const sources = new Map;
@@ -13014,7 +13252,7 @@ function renderMigrationBindings(options) {
13014
13252
  migrations,
13015
13253
  attestation: {
13016
13254
  schema: "supacloud.migration-binding-attestation.v1",
13017
- ...target2,
13255
+ ...target,
13018
13256
  manifestSha256: migrationBindingSha256(JSON.stringify(manifest)),
13019
13257
  files: files.sort((left, right) => left.file.localeCompare(right.file))
13020
13258
  }
@@ -13432,8 +13670,8 @@ function getDurationSeconds(table, key) {
13432
13670
  return;
13433
13671
  const m = v.trim().match(/^(\d+)\s*(s|m|h)$/i);
13434
13672
  if (!m) {
13435
- const n2 = parseInt(v, 10);
13436
- return Number.isFinite(n2) ? n2 : undefined;
13673
+ const n = parseInt(v, 10);
13674
+ return Number.isFinite(n) ? n : undefined;
13437
13675
  }
13438
13676
  const n = parseInt(m[1], 10);
13439
13677
  const unit = m[2].toLowerCase();
@@ -13711,9 +13949,9 @@ function readFunctions(root, mode) {
13711
13949
  const enabled = getBool(t, "enabled");
13712
13950
  if (enabled !== undefined)
13713
13951
  opts.enabled = enabled;
13714
- const verifyJwt2 = getBool(t, "verify_jwt");
13715
- if (verifyJwt2 !== undefined)
13716
- opts.verifyJwt = verifyJwt2;
13952
+ const verifyJwt = getBool(t, "verify_jwt");
13953
+ if (verifyJwt !== undefined)
13954
+ opts.verifyJwt = verifyJwt;
13717
13955
  const entrypoint = getString(t, "entrypoint");
13718
13956
  if (entrypoint !== undefined)
13719
13957
  opts.entrypoint = entrypoint;
@@ -13891,8 +14129,8 @@ async function serveBun(backend, opts = {}) {
13891
14129
  }, { vsn: ws.data.vsn });
13892
14130
  ws.data.session = session;
13893
14131
  },
13894
- message(ws, message2) {
13895
- ws.data.session?.onMessage(typeof message2 === "string" ? message2 : new Uint8Array(message2));
14132
+ message(ws, message) {
14133
+ ws.data.session?.onMessage(typeof message === "string" ? message : new Uint8Array(message));
13896
14134
  },
13897
14135
  close(ws) {
13898
14136
  ws.data.session?.onClose();
@@ -13953,8 +14191,8 @@ class FsStorageDriver {
13953
14191
  async delete(key) {
13954
14192
  await rm2(this.resolve(key), { force: true });
13955
14193
  }
13956
- async deleteMany(keys2) {
13957
- for (const k of keys2)
14194
+ async deleteMany(keys) {
14195
+ for (const k of keys)
13958
14196
  await this.delete(k);
13959
14197
  }
13960
14198
  }
@@ -14283,8 +14521,8 @@ class S3StorageDriver {
14283
14521
  async delete(key) {
14284
14522
  await this.client.file(this.objectKey(key)).delete();
14285
14523
  }
14286
- async deleteMany(keys2) {
14287
- for (const key of keys2) {
14524
+ async deleteMany(keys) {
14525
+ for (const key of keys) {
14288
14526
  await this.delete(key);
14289
14527
  }
14290
14528
  }
@@ -14334,12 +14572,12 @@ async function assertResetPathsSafe(paths) {
14334
14572
  ["storage", paths.storageDir]
14335
14573
  ];
14336
14574
  for (const [label, targetPath] of targets) {
14337
- const target2 = resolve4(targetPath);
14338
- const relativePath = relative(stateDir, target2);
14575
+ const target = resolve4(targetPath);
14576
+ const relativePath = relative(stateDir, target);
14339
14577
  if (!relativePath || relativePath.startsWith("..") || isAbsolute(relativePath)) {
14340
- throw new Error(`refusing to reset ${label} path outside the state directory: ${target2}`);
14578
+ throw new Error(`refusing to reset ${label} path outside the state directory: ${target}`);
14341
14579
  }
14342
- await assertResetTargetCanonical(stateDir, canonicalStateDir, target2, label);
14580
+ await assertResetTargetCanonical(stateDir, canonicalStateDir, target, label);
14343
14581
  }
14344
14582
  }
14345
14583
  async function requiredResetEntry(path) {
@@ -14366,8 +14604,8 @@ async function assertResetSecretsValid(path) {
14366
14604
  throw new Error(RESET_INVALID_SECRETS_ERROR);
14367
14605
  }
14368
14606
  }
14369
- async function assertResetTargetCanonical(stateDir, canonicalStateDir, target2, label) {
14370
- let current = target2;
14607
+ async function assertResetTargetCanonical(stateDir, canonicalStateDir, target, label) {
14608
+ let current = target;
14371
14609
  while (current !== stateDir) {
14372
14610
  try {
14373
14611
  if ((await lstat2(current)).isSymbolicLink()) {
@@ -14379,18 +14617,18 @@ async function assertResetTargetCanonical(stateDir, canonicalStateDir, target2,
14379
14617
  }
14380
14618
  const parent = dirname6(current);
14381
14619
  if (parent === current)
14382
- throw new Error(`refusing to reset ${label} path outside the state directory: ${target2}`);
14620
+ throw new Error(`refusing to reset ${label} path outside the state directory: ${target}`);
14383
14621
  current = parent;
14384
14622
  }
14385
- const existingAncestor = await nearestExistingAncestor(target2);
14386
- const canonicalTarget = resolve4(await realpath2(existingAncestor), relative(existingAncestor, target2));
14623
+ const existingAncestor = await nearestExistingAncestor(target);
14624
+ const canonicalTarget = resolve4(await realpath2(existingAncestor), relative(existingAncestor, target));
14387
14625
  const canonicalRelative = relative(canonicalStateDir, canonicalTarget);
14388
14626
  if (!canonicalRelative || canonicalRelative.startsWith("..") || isAbsolute(canonicalRelative)) {
14389
- throw new Error(`refusing to reset ${label} path outside the canonical state directory: ${target2}`);
14627
+ throw new Error(`refusing to reset ${label} path outside the canonical state directory: ${target}`);
14390
14628
  }
14391
14629
  }
14392
- async function nearestExistingAncestor(target2) {
14393
- let current = target2;
14630
+ async function nearestExistingAncestor(target) {
14631
+ let current = target;
14394
14632
  while (true) {
14395
14633
  try {
14396
14634
  await lstat2(current);
@@ -14401,7 +14639,7 @@ async function nearestExistingAncestor(target2) {
14401
14639
  }
14402
14640
  const parent = dirname6(current);
14403
14641
  if (parent === current)
14404
- throw new Error(`unable to resolve an existing ancestor for ${target2}`);
14642
+ throw new Error(`unable to resolve an existing ancestor for ${target}`);
14405
14643
  current = parent;
14406
14644
  }
14407
14645
  }
@@ -14429,14 +14667,14 @@ async function ensureProjectSecrets(paths) {
14429
14667
  `, { mode: 384, flag: "wx" });
14430
14668
  await link(temporaryFile, paths.secretsFile);
14431
14669
  stored = candidate;
14432
- } catch (error2) {
14433
- if (error2.code !== "EEXIST")
14434
- throw error2;
14670
+ } catch (error) {
14671
+ if (error.code !== "EEXIST")
14672
+ throw error;
14435
14673
  stored = validateSecrets(JSON.parse(await readFile7(paths.secretsFile, "utf8")));
14436
14674
  } finally {
14437
- await unlink2(temporaryFile).catch((error2) => {
14438
- if (error2.code !== "ENOENT")
14439
- throw error2;
14675
+ await unlink2(temporaryFile).catch((error) => {
14676
+ if (error.code !== "ENOENT")
14677
+ throw error;
14440
14678
  });
14441
14679
  }
14442
14680
  }
@@ -14938,10 +15176,10 @@ async function stageDirectory(root, destination) {
14938
15176
  throw error;
14939
15177
  }
14940
15178
  await mkdir6(destination, { recursive: true });
14941
- const walk = async (current, target2) => {
15179
+ const walk = async (current, target) => {
14942
15180
  for (const entry of await readdir3(current, { withFileTypes: true })) {
14943
15181
  const fullPath = join9(current, entry.name);
14944
- const targetPath = join9(target2, entry.name);
15182
+ const targetPath = join9(target, entry.name);
14945
15183
  if (entry.isSymbolicLink())
14946
15184
  throw new Error(`snapshot refuses symbolic link: ${fullPath}`);
14947
15185
  if (entry.isDirectory()) {
@@ -14956,9 +15194,9 @@ async function stageDirectory(root, destination) {
14956
15194
  };
14957
15195
  await walk(root, destination);
14958
15196
  }
14959
- async function stageFile(source, target2) {
14960
- await mkdir6(dirname7(target2), { recursive: true });
14961
- await copyFile(source, target2);
15197
+ async function stageFile(source, target) {
15198
+ await mkdir6(dirname7(target), { recursive: true });
15199
+ await copyFile(source, target);
14962
15200
  }
14963
15201
  async function readManifest(payloadRoot) {
14964
15202
  let parsed;
@@ -15030,9 +15268,9 @@ async function assertRestoreTargets(paths, manifest, force) {
15030
15268
  if (manifest.includesLocalStorage && !isWithin(paths.stateDir, paths.storageDir))
15031
15269
  targets.push(paths.storageDir);
15032
15270
  if (!force) {
15033
- for (const target2 of targets) {
15034
- if (await directoryHasEntries(target2))
15035
- throw new Error(`restore target is not empty: ${target2}; pass --force to replace it`);
15271
+ for (const target of targets) {
15272
+ if (await directoryHasEntries(target))
15273
+ throw new Error(`restore target is not empty: ${target}; pass --force to replace it`);
15036
15274
  }
15037
15275
  }
15038
15276
  }
@@ -15045,28 +15283,28 @@ async function directoryHasEntries(path) {
15045
15283
  throw error;
15046
15284
  }
15047
15285
  }
15048
- async function applyDirectorySwap(source, target2, force, rollbackId, swaps) {
15049
- const targetInfo = await existingInfo(target2);
15286
+ async function applyDirectorySwap(source, target, force, rollbackId, swaps) {
15287
+ const targetInfo = await existingInfo(target);
15050
15288
  if (targetInfo && !targetInfo.isDirectory())
15051
- throw new Error(`restore target is not a directory: ${target2}`);
15052
- const swap = { target: target2 };
15289
+ throw new Error(`restore target is not a directory: ${target}`);
15290
+ const swap = { target };
15053
15291
  if (targetInfo) {
15054
15292
  if (!force) {
15055
- if (await directoryHasEntries(target2))
15056
- throw new Error(`restore target is not empty: ${target2}; pass --force to replace it`);
15057
- await rm5(target2, { recursive: true, force: true });
15293
+ if (await directoryHasEntries(target))
15294
+ throw new Error(`restore target is not empty: ${target}; pass --force to replace it`);
15295
+ await rm5(target, { recursive: true, force: true });
15058
15296
  } else {
15059
- swap.rollbackPath = join9(dirname7(target2), `.${target2.split(sep2).pop() ?? "state"}.restore-${rollbackId}`);
15060
- await rename2(target2, swap.rollbackPath);
15297
+ swap.rollbackPath = join9(dirname7(target), `.${target.split(sep2).pop() ?? "state"}.restore-${rollbackId}`);
15298
+ await rename2(target, swap.rollbackPath);
15061
15299
  }
15062
15300
  }
15063
15301
  try {
15064
- await mkdir6(dirname7(target2), { recursive: true });
15065
- await rename2(source, target2);
15302
+ await mkdir6(dirname7(target), { recursive: true });
15303
+ await rename2(source, target);
15066
15304
  swaps.push(swap);
15067
15305
  } catch (error) {
15068
15306
  if (swap.rollbackPath)
15069
- await rename2(swap.rollbackPath, target2).catch(() => {});
15307
+ await rename2(swap.rollbackPath, target).catch(() => {});
15070
15308
  throw error;
15071
15309
  }
15072
15310
  }
@@ -15086,17 +15324,17 @@ async function existingInfo(path) {
15086
15324
  throw error;
15087
15325
  }
15088
15326
  }
15089
- async function copyEntry(source, target2) {
15327
+ async function copyEntry(source, target) {
15090
15328
  const info = await lstat3(source);
15091
15329
  if (info.isSymbolicLink())
15092
15330
  throw new Error(`snapshot refuses symbolic link: ${source}`);
15093
15331
  if (info.isDirectory()) {
15094
- await mkdir6(target2, { recursive: true });
15332
+ await mkdir6(target, { recursive: true });
15095
15333
  for (const entry of await readdir3(source))
15096
- await copyEntry(join9(source, entry), join9(target2, entry));
15334
+ await copyEntry(join9(source, entry), join9(target, entry));
15097
15335
  } else if (info.isFile()) {
15098
- await mkdir6(dirname7(target2), { recursive: true });
15099
- await Bun.write(target2, Bun.file(source));
15336
+ await mkdir6(dirname7(target), { recursive: true });
15337
+ await Bun.write(target, Bun.file(source));
15100
15338
  } else
15101
15339
  throw new Error(`snapshot refuses unsupported filesystem entry: ${source}`);
15102
15340
  }
@@ -15251,13 +15489,13 @@ async function main() {
15251
15489
  }
15252
15490
  if (options.command === "keys") {
15253
15491
  const secrets = await ensureProjectSecrets(paths);
15254
- const keys2 = await mintProjectKeys(secrets.jwtSecret);
15492
+ const keys = await mintProjectKeys(secrets.jwtSecret);
15255
15493
  const privilegedKey = options.serviceRole ? `
15256
15494
  service_role key:
15257
- ${keys2.serviceRoleKey}` : `
15495
+ ${keys.serviceRoleKey}` : `
15258
15496
  Use --service-role to print the privileged key.`;
15259
15497
  await writeStandardOutput(`anon key:
15260
- ${keys2.anonKey}
15498
+ ${keys.anonKey}
15261
15499
  ${privilegedKey}
15262
15500
  `);
15263
15501
  return;
@@ -15278,7 +15516,7 @@ ${privilegedKey}
15278
15516
  if (options.positionals[0] && options.positionals[0] !== "types" && options.positionals[0] !== "typescript") {
15279
15517
  throw new Error(`unknown gen subcommand: ${options.positionals[0]}`);
15280
15518
  }
15281
- const project2 = await createProjectBackend({
15519
+ const project = await createProjectBackend({
15282
15520
  ...options,
15283
15521
  applyMigrations: false,
15284
15522
  includeFunctions: false,
@@ -15289,7 +15527,7 @@ ${privilegedKey}
15289
15527
  log: quietLog
15290
15528
  });
15291
15529
  try {
15292
- const source = await generateTypes(project2.backend.db, "public");
15530
+ const source = await generateTypes(project.backend.db, "public");
15293
15531
  if (options.output) {
15294
15532
  await mkdir7(dirname8(options.output), { recursive: true });
15295
15533
  await writeFile7(options.output, source);
@@ -15298,12 +15536,12 @@ ${privilegedKey}
15298
15536
  } else
15299
15537
  await writeStandardOutput(source);
15300
15538
  } finally {
15301
- await project2.backend.close();
15539
+ await project.backend.close();
15302
15540
  }
15303
15541
  return;
15304
15542
  }
15305
15543
  if (options.command === "inspect") {
15306
- const project2 = await createProjectBackend({
15544
+ const project = await createProjectBackend({
15307
15545
  ...options,
15308
15546
  applyMigrations: false,
15309
15547
  includeFunctions: false,
@@ -15314,9 +15552,9 @@ ${privilegedKey}
15314
15552
  log: quietLog
15315
15553
  });
15316
15554
  try {
15317
- await printInspection(await inspectDb(project2.backend.db, "public"));
15555
+ await printInspection(await inspectDb(project.backend.db, "public"));
15318
15556
  } finally {
15319
- await project2.backend.close();
15557
+ await project.backend.close();
15320
15558
  }
15321
15559
  return;
15322
15560
  }
@@ -15354,7 +15592,7 @@ ${privilegedKey}
15354
15592
  return;
15355
15593
  }
15356
15594
  if (options.command === "migrate" || options.command === "status") {
15357
- const project2 = await createProjectBackend({
15595
+ const project = await createProjectBackend({
15358
15596
  ...options,
15359
15597
  applyMigrations: options.command === "migrate",
15360
15598
  includeFunctions: false,
@@ -15366,13 +15604,13 @@ ${privilegedKey}
15366
15604
  log: quietLog
15367
15605
  });
15368
15606
  try {
15369
- const applied = await project2.backend.db.listAppliedMigrations();
15607
+ const applied = await project.backend.db.listAppliedMigrations();
15370
15608
  if (options.json) {
15371
15609
  await writeStandardOutput(`${JSON.stringify({
15372
15610
  schema: "supacloud.lite-migrations.v1",
15373
15611
  command: options.command,
15374
15612
  applied,
15375
- binding_attestation: project2.bindingAttestation ?? null
15613
+ binding_attestation: project.bindingAttestation ?? null
15376
15614
  }, null, 2)}
15377
15615
  `);
15378
15616
  return;
@@ -15382,13 +15620,13 @@ ${privilegedKey}
15382
15620
  await writeStandardOutput(`${output}
15383
15621
  `);
15384
15622
  } finally {
15385
- await project2.backend.close();
15623
+ await project.backend.close();
15386
15624
  }
15387
15625
  return;
15388
15626
  }
15389
15627
  if (options.command !== "start")
15390
15628
  throw new Error(`unknown command: ${options.command}`);
15391
- const project = await startProjectServer({ ...options, log: (message2) => console.log(` ${message2}`) });
15629
+ const project = await startProjectServer({ ...options, log: (message) => console.log(` ${message}`) });
15392
15630
  const shutdown = waitForShutdown(() => project.close());
15393
15631
  await writeStandardOutput(`
15394
15632
  SupaCloud Lite running
@@ -15420,7 +15658,7 @@ async function runDbCommand(options) {
15420
15658
  if (paths.dataDir)
15421
15659
  await rm6(paths.dataDir, { recursive: true, force: true });
15422
15660
  await rm6(paths.storageDir, { recursive: true, force: true });
15423
- const project2 = await createProjectBackend({
15661
+ const project = await createProjectBackend({
15424
15662
  ...options,
15425
15663
  includeFunctions: false,
15426
15664
  includeWebhooks: false,
@@ -15430,11 +15668,11 @@ async function runDbCommand(options) {
15430
15668
  log: quietLog
15431
15669
  });
15432
15670
  try {
15433
- const applied = await project2.backend.db.listAppliedMigrations();
15671
+ const applied = await project.backend.db.listAppliedMigrations();
15434
15672
  await writeStandardOutput(`reset complete: ${applied.length} migration(s) applied
15435
15673
  `);
15436
15674
  } finally {
15437
- await project2.backend.close();
15675
+ await project.backend.close();
15438
15676
  }
15439
15677
  return;
15440
15678
  }
@@ -15504,7 +15742,7 @@ async function runDbCommand(options) {
15504
15742
  }
15505
15743
  if (subcommand === "check") {
15506
15744
  const moduleFile = options.moduleFile ?? join10(paths.projectDir, "supabase", "db", "modules.ts");
15507
- const project2 = await createProjectBackend({
15745
+ const project = await createProjectBackend({
15508
15746
  ...options,
15509
15747
  applyMigrations: false,
15510
15748
  includeFunctions: false,
@@ -15516,14 +15754,14 @@ async function runDbCommand(options) {
15516
15754
  });
15517
15755
  try {
15518
15756
  const executor = {
15519
- query: async (sql, params) => (await project2.backend.db.query(sql, params)).rows
15757
+ query: async (sql, params) => (await project.backend.db.query(sql, params)).rows
15520
15758
  };
15521
15759
  const result = await checkDatabaseModules({ moduleFile, executor });
15522
15760
  await writeStandardOutput(formatDatabaseModuleCheck(result));
15523
15761
  if (!result.ok)
15524
15762
  throw new Error("db check found error-level issues");
15525
15763
  } finally {
15526
- await project2.backend.close();
15764
+ await project.backend.close();
15527
15765
  }
15528
15766
  return;
15529
15767
  }