@hot-updater/supabase 0.36.7 → 1.0.0-rc.1

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.
Files changed (37) hide show
  1. package/dist/edge.cjs +6 -3
  2. package/dist/edge.d.cts +14 -2
  3. package/dist/edge.d.mts +14 -2
  4. package/dist/edge.mjs +5 -2
  5. package/dist/iac/index.cjs +607 -50
  6. package/dist/iac/index.d.cts +26 -8
  7. package/dist/iac/index.d.mts +26 -8
  8. package/dist/iac/index.mjs +604 -52
  9. package/dist/index.cjs +3 -145
  10. package/dist/index.d.cts +7 -24
  11. package/dist/index.d.mts +7 -24
  12. package/dist/index.mjs +2 -117
  13. package/dist/init/index.cjs +5 -2
  14. package/dist/init/index.d.cts +2 -2
  15. package/dist/init/index.d.mts +2 -2
  16. package/dist/init/index.mjs +5 -2
  17. package/dist/supabaseDatabase-BDIBsXpz.d.cts +13 -0
  18. package/dist/supabaseDatabase-CP9WalBi.d.mts +13 -0
  19. package/dist/supabaseStorage-Cw294tR4.mjs +557 -0
  20. package/dist/supabaseStorage-yP7u4m7E.cjs +568 -0
  21. package/package.json +9 -9
  22. package/supabase/edge-functions/index.ts +9 -13
  23. package/supabase/edge-functions/runtime.docker.integration.spec.ts +417 -202
  24. package/supabase/migrations/20260818000000_hot-updater_1.0.0.sql +583 -0
  25. package/supabase/migrations.spec.ts +127 -46
  26. package/dist/supabaseEdgeFunctionStorage-BRxGvt-r.d.mts +0 -19
  27. package/dist/supabaseEdgeFunctionStorage-BSLlUeqi.cjs +0 -386
  28. package/dist/supabaseEdgeFunctionStorage-CU396KO3.d.cts +0 -19
  29. package/dist/supabaseEdgeFunctionStorage-pV0s_mTF.mjs +0 -356
  30. package/supabase/migrations/20250103114225_init.sql +0 -228
  31. package/supabase/migrations/20250314000000_hot-updater_0.13.0.sql +0 -134
  32. package/supabase/migrations/20250516000000_hot-updater_0.18.0.sql +0 -194
  33. package/supabase/migrations/20251014000000_hot-updater_0.21.0.sql +0 -184
  34. package/supabase/migrations/20260401000000_hot-updater_0.29.0.sql +0 -503
  35. package/supabase/migrations/20260414000000_hot-updater_0.30.0.sql +0 -50
  36. package/supabase/migrations/20260422000000_hot-updater_0.31.0.sql +0 -20
  37. package/supabase/migrations/20260520014100_hot-updater_rls.sql +0 -48
@@ -28,6 +28,7 @@ let node_module = require("node:module");
28
28
  let path = require("path");
29
29
  path = __toESM(path);
30
30
  let _hot_updater_cli_tools = require("@hot-updater/cli-tools");
31
+ let _hot_updater_server = require("@hot-updater/server");
31
32
  let node_url = require("node:url");
32
33
  let node_child_process = require("node:child_process");
33
34
  let node_string_decoder = require("node:string_decoder");
@@ -46,6 +47,8 @@ let node_fs = require("node:fs");
46
47
  let node_stream_promises = require("node:stream/promises");
47
48
  let node_stream = require("node:stream");
48
49
  let node_buffer = require("node:buffer");
50
+ let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
51
+ let _hot_updater_plugin_core_internal = require("@hot-updater/plugin-core/internal");
49
52
  let _supabase_supabase_js = require("@supabase/supabase-js");
50
53
  //#region ../../node_modules/.pnpm/es-toolkit@1.47.0/node_modules/es-toolkit/dist/_internal/globalThis.mjs
51
54
  const globalThis_ = typeof globalThis === "object" && globalThis || typeof window === "object" && window || typeof self === "object" && self || typeof global === "object" && global || (function() {
@@ -6276,6 +6279,437 @@ createExeca(mapNode);
6276
6279
  createExeca(mapScriptAsync, {}, deepScriptOptions, setScriptSync);
6277
6280
  const { sendMessage, getOneMessage, getEachMessage, getCancelSignal } = getIpcExport();
6278
6281
  //#endregion
6282
+ //#region src/supabaseConfig.ts
6283
+ const resolveSupabaseServiceRoleKey = (config) => {
6284
+ if (!config.supabaseServiceRoleKey) throw new Error("Supabase service role key is required. Set supabaseServiceRoleKey.");
6285
+ return config.supabaseServiceRoleKey;
6286
+ };
6287
+ //#endregion
6288
+ //#region src/supabaseFilter.ts
6289
+ var InvalidSupabasePredicateError = class extends Error {
6290
+ name = "InvalidSupabasePredicateError";
6291
+ };
6292
+ const encodeValue = (value) => {
6293
+ if (typeof value !== "string") return String(value);
6294
+ return `"${value.replaceAll("\\", "\\\\").replaceAll("\"", "\\\"")}"`;
6295
+ };
6296
+ const encodePattern = (value) => encodeValue(value.replaceAll("*", "\\*").replaceAll("%", "\\%").replaceAll("_", "\\_"));
6297
+ const predicate = (condition) => {
6298
+ const operator = condition.operator ?? "eq";
6299
+ const field = condition.field;
6300
+ switch (operator) {
6301
+ case "eq":
6302
+ case "ne":
6303
+ if (condition.value === null) return `${field}.${operator === "eq" ? "is" : "not.is"}.null`;
6304
+ if (typeof condition.value !== "boolean" && typeof condition.value !== "number" && typeof condition.value !== "string") throw new InvalidSupabasePredicateError();
6305
+ if ("mode" in condition && condition.mode === "insensitive") {
6306
+ const comparison = encodePattern(condition.value);
6307
+ return `${field}.${operator === "eq" ? "ilike" : "not.ilike"}.${comparison}`;
6308
+ }
6309
+ return `${field}.${operator === "eq" ? "eq" : "neq"}.${encodeValue(condition.value)}`;
6310
+ case "gt":
6311
+ case "gte":
6312
+ case "lt":
6313
+ case "lte":
6314
+ if (typeof condition.value !== "number" && typeof condition.value !== "string") throw new InvalidSupabasePredicateError();
6315
+ return `${field}.${operator}.${encodeValue(condition.value)}`;
6316
+ case "in":
6317
+ case "not_in": {
6318
+ if (!Array.isArray(condition.value)) throw new InvalidSupabasePredicateError();
6319
+ if (condition.value.length === 0) return operator === "in" ? `and(${field}.is.null,${field}.not.is.null)` : `or(${field}.is.null,${field}.not.is.null)`;
6320
+ const values = condition.value.map(encodeValue).join(",");
6321
+ return `${field}.${operator === "in" ? "in" : "not.in"}.(${values})`;
6322
+ }
6323
+ case "contains":
6324
+ case "starts_with":
6325
+ case "ends_with": {
6326
+ if (typeof condition.value !== "string") throw new InvalidSupabasePredicateError();
6327
+ const value = encodePattern(condition.value).slice(1, -1);
6328
+ const pattern = operator === "contains" ? `"*${value}*"` : operator === "starts_with" ? `"${value}*"` : `"*${value}"`;
6329
+ return `${field}.${"mode" in condition && condition.mode === "insensitive" ? "ilike" : "like"}.${pattern}`;
6330
+ }
6331
+ }
6332
+ };
6333
+ const buildSupabaseFilter = (where) => {
6334
+ const [first, ...rest] = where ?? [];
6335
+ if (first === void 0) return;
6336
+ let expression = predicate(first);
6337
+ for (const condition of rest) {
6338
+ const next = predicate(condition);
6339
+ expression = condition.connector === "OR" ? `or(${expression},${next})` : `and(${expression},${next})`;
6340
+ }
6341
+ return expression;
6342
+ };
6343
+ //#endregion
6344
+ //#region src/supabaseInfrastructureNames.ts
6345
+ const SUPABASE_V1_FUNCTION_NAME = "hot-updater-v1";
6346
+ const SUPABASE_V1_TABLE_NAMES = {
6347
+ apiKeys: "hot_updater_v1_api_keys",
6348
+ bundleEvents: "hot_updater_v1_bundle_events",
6349
+ bundlePatches: "hot_updater_v1_bundle_patches",
6350
+ bundles: "hot_updater_v1_bundles",
6351
+ channels: "hot_updater_v1_channels",
6352
+ releaseCatalogs: "hot_updater_v1_release_catalogs",
6353
+ releases: "hot_updater_v1_releases",
6354
+ settings: "hot_updater_v1_private_settings"
6355
+ };
6356
+ const SUPABASE_V1_FUNCTION_NAMES = {
6357
+ commit: "hot_updater_v1_commit",
6358
+ deleteChannel: "hot_updater_v1_delete_channel"
6359
+ };
6360
+ //#endregion
6361
+ //#region src/supabaseResult.ts
6362
+ var SupabaseDatabaseError = class extends Error {
6363
+ name = "SupabaseDatabaseError";
6364
+ constructor(operation, cause) {
6365
+ super(`Supabase database operation failed: ${operation}`, { cause });
6366
+ this.operation = operation;
6367
+ }
6368
+ };
6369
+ var SupabaseMissingDataError = class extends Error {
6370
+ name = "SupabaseMissingDataError";
6371
+ constructor(operation) {
6372
+ super(`Supabase database operation returned no row: ${operation}`);
6373
+ this.operation = operation;
6374
+ }
6375
+ };
6376
+ const throwSupabaseError = (operation, error) => {
6377
+ if (error !== null) throw new SupabaseDatabaseError(operation, error);
6378
+ };
6379
+ //#endregion
6380
+ //#region src/supabaseDatabase.ts
6381
+ const isForeignKeyViolation = (error) => typeof error === "object" && error !== null && Reflect.get(error, "code") === "23503";
6382
+ const createSupabaseImplementation = (supabase) => {
6383
+ const implementation = {
6384
+ async create(input) {
6385
+ switch (input.model) {
6386
+ case "bundles": {
6387
+ const { data, error } = await supabase.from(SUPABASE_V1_TABLE_NAMES.bundles).insert(input.data).select("*").single();
6388
+ throwSupabaseError("create bundles", error);
6389
+ if (data === null) throw new SupabaseMissingDataError("create bundles");
6390
+ return data;
6391
+ }
6392
+ case "bundle_patches": {
6393
+ const { data, error } = await supabase.from(SUPABASE_V1_TABLE_NAMES.bundlePatches).insert(input.data).select("*").single();
6394
+ throwSupabaseError("create bundle_patches", error);
6395
+ if (data === null) throw new SupabaseMissingDataError("create bundle_patches");
6396
+ return data;
6397
+ }
6398
+ case "channels": {
6399
+ if (input.onConflict === "ignore") {
6400
+ const { data, error } = await supabase.from(SUPABASE_V1_TABLE_NAMES.channels).upsert(input.data, {
6401
+ onConflict: "name",
6402
+ ignoreDuplicates: true
6403
+ }).select("*").maybeSingle();
6404
+ throwSupabaseError("create channels", error);
6405
+ return data ?? input.data;
6406
+ }
6407
+ const { data, error } = await supabase.from(SUPABASE_V1_TABLE_NAMES.channels).insert(input.data).select("*").single();
6408
+ throwSupabaseError("create channels", error);
6409
+ if (data === null) throw new SupabaseMissingDataError("create channels");
6410
+ return data;
6411
+ }
6412
+ case "bundle_events": {
6413
+ const { data, error } = await supabase.from(SUPABASE_V1_TABLE_NAMES.bundleEvents).insert(input.data).select("*").single();
6414
+ throwSupabaseError("create bundle_events", error);
6415
+ if (data === null) throw new SupabaseMissingDataError("create bundle_events");
6416
+ return data;
6417
+ }
6418
+ case "releases": {
6419
+ const { data, error } = await supabase.from(SUPABASE_V1_TABLE_NAMES.releases).insert(input.data).select("*").single();
6420
+ throwSupabaseError("create releases", error);
6421
+ if (data === null) throw new SupabaseMissingDataError("create releases");
6422
+ return data;
6423
+ }
6424
+ case "release_catalogs": {
6425
+ const { data, error } = await supabase.from(SUPABASE_V1_TABLE_NAMES.releaseCatalogs).insert(input.data).select("*").single();
6426
+ throwSupabaseError("create release_catalogs", error);
6427
+ if (data === null) throw new SupabaseMissingDataError("create release_catalogs");
6428
+ return data;
6429
+ }
6430
+ case "api_keys": {
6431
+ const { data, error } = await (input.onConflict === "ignore" ? supabase.from(SUPABASE_V1_TABLE_NAMES.apiKeys).upsert(input.data, {
6432
+ onConflict: "hash",
6433
+ ignoreDuplicates: true
6434
+ }) : supabase.from(SUPABASE_V1_TABLE_NAMES.apiKeys).insert(input.data)).select("*").maybeSingle();
6435
+ throwSupabaseError("create api_keys", error);
6436
+ if (data === null && input.onConflict !== "ignore") throw new SupabaseMissingDataError("create api_keys");
6437
+ return data ?? input.data;
6438
+ }
6439
+ }
6440
+ },
6441
+ async update(input) {
6442
+ const filter = buildSupabaseFilter(input.where);
6443
+ if (input.model === "api_keys") {
6444
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.apiKeys).update(input.update);
6445
+ if (filter !== void 0) query = query.or(filter);
6446
+ const { data, error } = await query.select("*").maybeSingle();
6447
+ throwSupabaseError("update api_keys", error);
6448
+ return data;
6449
+ }
6450
+ if (input.model === "releases") {
6451
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.releases).update(input.update);
6452
+ if (filter !== void 0) query = query.or(filter);
6453
+ const { data, error } = await query.select("*").maybeSingle();
6454
+ throwSupabaseError("update releases", error);
6455
+ return data;
6456
+ }
6457
+ if (input.model === "release_catalogs") {
6458
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.releaseCatalogs).update(input.update);
6459
+ if (filter !== void 0) query = query.or(filter);
6460
+ const { data, error } = await query.select("*").maybeSingle();
6461
+ throwSupabaseError("update release_catalogs", error);
6462
+ return data;
6463
+ }
6464
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.bundles).update(input.update);
6465
+ if (filter !== void 0) query = query.or(filter);
6466
+ const { data, error } = await query.select("*").maybeSingle();
6467
+ throwSupabaseError("update bundles", error);
6468
+ return data;
6469
+ },
6470
+ async delete(input) {
6471
+ const filter = buildSupabaseFilter(input.where);
6472
+ switch (input.model) {
6473
+ case "bundles": {
6474
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.bundles).delete();
6475
+ if (filter !== void 0) query = query.or(filter);
6476
+ const { error } = await query;
6477
+ throwSupabaseError("delete bundles", error);
6478
+ return;
6479
+ }
6480
+ case "bundle_patches": {
6481
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.bundlePatches).delete();
6482
+ if (filter !== void 0) query = query.or(filter);
6483
+ const { error } = await query;
6484
+ throwSupabaseError("delete bundle_patches", error);
6485
+ return;
6486
+ }
6487
+ case "channels": {
6488
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.channels).delete();
6489
+ if (filter !== void 0) query = query.or(filter);
6490
+ const { error } = await query;
6491
+ if (isForeignKeyViolation(error)) throw new _hot_updater_plugin_core_internal.DatabaseRowReferencedError();
6492
+ throwSupabaseError("delete channels", error);
6493
+ }
6494
+ case "releases": {
6495
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.releases).delete();
6496
+ if (filter !== void 0) query = query.or(filter);
6497
+ const { error } = await query;
6498
+ throwSupabaseError("delete releases", error);
6499
+ }
6500
+ }
6501
+ },
6502
+ async count(input) {
6503
+ if (input.distinct !== void 0) throw new _hot_updater_plugin_core.DatabasePluginInputError("invalid-operation");
6504
+ const filter = buildSupabaseFilter(input.where);
6505
+ switch (input.model) {
6506
+ case "bundles": {
6507
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.bundles).select("*", {
6508
+ count: "exact",
6509
+ head: true
6510
+ });
6511
+ if (filter !== void 0) query = query.or(filter);
6512
+ const { count, error } = await query;
6513
+ throwSupabaseError("count bundles", error);
6514
+ return count ?? 0;
6515
+ }
6516
+ case "bundle_patches": {
6517
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.bundlePatches).select("*", {
6518
+ count: "exact",
6519
+ head: true
6520
+ });
6521
+ if (filter !== void 0) query = query.or(filter);
6522
+ const { count, error } = await query;
6523
+ throwSupabaseError("count bundle_patches", error);
6524
+ return count ?? 0;
6525
+ }
6526
+ case "releases": {
6527
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.releases).select("*", {
6528
+ count: "exact",
6529
+ head: true
6530
+ });
6531
+ if (filter !== void 0) query = query.or(filter);
6532
+ const { count, error } = await query;
6533
+ throwSupabaseError("count releases", error);
6534
+ return count ?? 0;
6535
+ }
6536
+ }
6537
+ },
6538
+ async findOne(input) {
6539
+ const filter = buildSupabaseFilter(input.where);
6540
+ switch (input.model) {
6541
+ case "bundles": {
6542
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.bundles).select("*");
6543
+ if (filter !== void 0) query = query.or(filter);
6544
+ const { data, error } = await query.limit(1).maybeSingle();
6545
+ throwSupabaseError("findOne bundles", error);
6546
+ return data;
6547
+ }
6548
+ case "api_keys": {
6549
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.apiKeys).select("*");
6550
+ if (filter !== void 0) query = query.or(filter);
6551
+ const { data, error } = await query.limit(1).maybeSingle();
6552
+ throwSupabaseError("findOne api_keys", error);
6553
+ return data;
6554
+ }
6555
+ case "channels": {
6556
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.channels).select("*");
6557
+ if (filter !== void 0) query = query.or(filter);
6558
+ const { data, error } = await query.limit(1).maybeSingle();
6559
+ throwSupabaseError("findOne channels", error);
6560
+ return data;
6561
+ }
6562
+ case "bundle_patches": {
6563
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.bundlePatches).select("*");
6564
+ if (filter !== void 0) query = query.or(filter);
6565
+ const { data, error } = await query.limit(1).maybeSingle();
6566
+ throwSupabaseError("findOne bundle_patches", error);
6567
+ return data;
6568
+ }
6569
+ case "releases": {
6570
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.releases).select("*");
6571
+ if (filter !== void 0) query = query.or(filter);
6572
+ const { data, error } = await query.limit(1).maybeSingle();
6573
+ throwSupabaseError("findOne releases", error);
6574
+ return data;
6575
+ }
6576
+ case "release_catalogs": {
6577
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.releaseCatalogs).select("*");
6578
+ if (filter !== void 0) query = query.or(filter);
6579
+ const { data, error } = await query.limit(1).maybeSingle();
6580
+ throwSupabaseError("findOne release_catalogs", error);
6581
+ return data;
6582
+ }
6583
+ }
6584
+ },
6585
+ async findMany(input) {
6586
+ if (input.distinctOn !== void 0) throw new _hot_updater_plugin_core.DatabasePluginInputError("invalid-operation");
6587
+ if (input.limit === 0) return [];
6588
+ const filter = buildSupabaseFilter(input.where);
6589
+ const rangeEnd = input.offset + input.limit - 1;
6590
+ const orderBy = input.orderBy ?? [];
6591
+ switch (input.model) {
6592
+ case "bundles": {
6593
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.bundles).select("*");
6594
+ if (filter !== void 0) query = query.or(filter);
6595
+ for (const clause of orderBy) query = query.order(clause.field, {
6596
+ ascending: clause.direction === "asc",
6597
+ ...clause.nulls ? { nullsFirst: clause.nulls === "first" } : {}
6598
+ });
6599
+ const { data, error } = await query.range(input.offset, rangeEnd);
6600
+ throwSupabaseError("findMany bundles", error);
6601
+ return data ?? [];
6602
+ }
6603
+ case "bundle_events": {
6604
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.bundleEvents).select("*");
6605
+ if (filter !== void 0) query = query.or(filter);
6606
+ for (const clause of orderBy) query = query.order(clause.field, {
6607
+ ascending: clause.direction === "asc",
6608
+ ...clause.nulls ? { nullsFirst: clause.nulls === "first" } : {}
6609
+ });
6610
+ const { data, error } = await query.range(input.offset, rangeEnd);
6611
+ throwSupabaseError("findMany bundle_events", error);
6612
+ return data ?? [];
6613
+ }
6614
+ case "api_keys": {
6615
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.apiKeys).select("*");
6616
+ if (filter !== void 0) query = query.or(filter);
6617
+ for (const clause of orderBy) query = query.order(clause.field, {
6618
+ ascending: clause.direction === "asc",
6619
+ ...clause.nulls ? { nullsFirst: clause.nulls === "first" } : {}
6620
+ });
6621
+ const { data, error } = await query.range(input.offset, rangeEnd);
6622
+ throwSupabaseError("findMany api_keys", error);
6623
+ return data ?? [];
6624
+ }
6625
+ case "bundle_patches": {
6626
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.bundlePatches).select("*");
6627
+ if (filter !== void 0) query = query.or(filter);
6628
+ for (const clause of orderBy) query = query.order(clause.field, {
6629
+ ascending: clause.direction === "asc",
6630
+ ...clause.nulls ? { nullsFirst: clause.nulls === "first" } : {}
6631
+ });
6632
+ const { data, error } = await query.range(input.offset, rangeEnd);
6633
+ throwSupabaseError("findMany bundle_patches", error);
6634
+ return data ?? [];
6635
+ }
6636
+ case "channels": {
6637
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.channels).select("*");
6638
+ if (filter !== void 0) query = query.or(filter);
6639
+ for (const clause of orderBy) query = query.order(clause.field, {
6640
+ ascending: clause.direction === "asc",
6641
+ ...clause.nulls ? { nullsFirst: clause.nulls === "first" } : {}
6642
+ });
6643
+ const { data, error } = await query.range(input.offset, rangeEnd);
6644
+ throwSupabaseError("findMany channels", error);
6645
+ return data ?? [];
6646
+ }
6647
+ case "releases": {
6648
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.releases).select("*");
6649
+ if (filter !== void 0) query = query.or(filter);
6650
+ for (const clause of orderBy) query = query.order(clause.field, {
6651
+ ascending: clause.direction === "asc",
6652
+ ...clause.nulls ? { nullsFirst: clause.nulls === "first" } : {}
6653
+ });
6654
+ const { data, error } = await query.range(input.offset, rangeEnd);
6655
+ throwSupabaseError("findMany releases", error);
6656
+ return data ?? [];
6657
+ }
6658
+ case "release_catalogs": {
6659
+ let query = supabase.from(SUPABASE_V1_TABLE_NAMES.releaseCatalogs).select("*");
6660
+ if (filter !== void 0) query = query.or(filter);
6661
+ for (const clause of orderBy) query = query.order(clause.field, {
6662
+ ascending: clause.direction === "asc",
6663
+ ...clause.nulls ? { nullsFirst: clause.nulls === "first" } : {}
6664
+ });
6665
+ const { data, error } = await query.range(input.offset, rangeEnd);
6666
+ throwSupabaseError("findMany release_catalogs", error);
6667
+ return data ?? [];
6668
+ }
6669
+ }
6670
+ },
6671
+ async insertChannel(input) {
6672
+ const { data: inserted, error: insertError } = await supabase.from(SUPABASE_V1_TABLE_NAMES.channels).upsert(input.row, {
6673
+ onConflict: "name",
6674
+ ignoreDuplicates: true
6675
+ }).select("*").maybeSingle();
6676
+ throwSupabaseError("insert channel", insertError);
6677
+ if (inserted !== null) return {
6678
+ row: inserted,
6679
+ inserted: true
6680
+ };
6681
+ const { data: existing, error: findError } = await supabase.from(SUPABASE_V1_TABLE_NAMES.channels).select("*").eq("name", input.row.name).single();
6682
+ throwSupabaseError("find canonical channel", findError);
6683
+ if (existing === null) throw new SupabaseMissingDataError("find canonical channel");
6684
+ return {
6685
+ row: existing,
6686
+ inserted: false
6687
+ };
6688
+ },
6689
+ async deleteChannel(input) {
6690
+ const { data, error } = await supabase.rpc(SUPABASE_V1_FUNCTION_NAMES.deleteChannel, { p_id: input.id });
6691
+ throwSupabaseError("delete channel", error);
6692
+ if (data === null || typeof data !== "object" || !("deleted" in data) || typeof data.deleted !== "boolean") throw new SupabaseMissingDataError("delete channel");
6693
+ return data;
6694
+ }
6695
+ };
6696
+ implementation.commit = async (input) => {
6697
+ const { data, error } = await supabase.rpc(SUPABASE_V1_FUNCTION_NAMES.commit, { p_commit: input });
6698
+ throwSupabaseError("commit database changes", error);
6699
+ if (data === null || typeof data !== "object" || !("committed" in data) || typeof data.committed !== "boolean") throw new SupabaseMissingDataError("commit database changes");
6700
+ return data;
6701
+ };
6702
+ return implementation;
6703
+ };
6704
+ const supabaseDatabase = (config) => {
6705
+ const adapter = (0, _hot_updater_plugin_core_internal.createDatabasePluginAdapter)("supabaseDatabase", createSupabaseImplementation((0, _supabase_supabase_js.createClient)(config.supabaseUrl, resolveSupabaseServiceRoleKey(config))));
6706
+ return (0, _hot_updater_plugin_core.createDatabasePlugin)({
6707
+ name: "supabaseDatabase",
6708
+ models: adapter.models,
6709
+ commit: adapter.commit
6710
+ });
6711
+ };
6712
+ //#endregion
6279
6713
  //#region iac/init/index.ts
6280
6714
  const SUPABASE_DATABASE_PASSWORD_PROJECT_ID_ENV_KEY = "HOT_UPDATER_SUPABASE_DB_PASSWORD_PROJECT_ID";
6281
6715
  const SUPABASE_REGION_VALUES = [
@@ -6362,9 +6796,9 @@ const initProvider = {
6362
6796
  envKey: "HOT_UPDATER_SUPABASE_FUNCTION_NAME",
6363
6797
  help: "Edge Function name",
6364
6798
  prompt: {
6365
- defaultValue: "update-server",
6799
+ defaultValue: SUPABASE_V1_FUNCTION_NAME,
6366
6800
  message: "Enter a name for the edge function",
6367
- placeholder: "update-server",
6801
+ placeholder: SUPABASE_V1_FUNCTION_NAME,
6368
6802
  type: "text"
6369
6803
  },
6370
6804
  validate: isSupabaseFunctionName
@@ -6386,6 +6820,12 @@ const initProvider = {
6386
6820
  const supabaseApi = (supabaseUrl, supabaseServiceRoleKey) => {
6387
6821
  const supabase = (0, _supabase_supabase_js.createClient)(supabaseUrl, supabaseServiceRoleKey);
6388
6822
  return {
6823
+ getInfrastructureState: async () => {
6824
+ const marker = await supabase.from(SUPABASE_V1_TABLE_NAMES.settings).select("value").eq("key", "schema.core").maybeSingle();
6825
+ if (!marker.error) return marker.data?.value === "1.0.0" ? "v1" : "incompatible";
6826
+ if (marker.error.code === "42P01" || marker.error.code === "PGRST205") return "fresh";
6827
+ throw marker.error;
6828
+ },
6389
6829
  listBuckets: async () => {
6390
6830
  const { data, error } = await supabase.storage.listBuckets();
6391
6831
  if (error) throw error;
@@ -6400,10 +6840,6 @@ const supabaseApi = (supabaseUrl, supabaseServiceRoleKey) => {
6400
6840
  const { data, error } = await supabase.storage.createBucket(bucketName, options);
6401
6841
  if (error) throw error;
6402
6842
  return data;
6403
- },
6404
- updateBucket: async (bucketId, options) => {
6405
- const { error } = await supabase.storage.updateBucket(bucketId, options);
6406
- if (error) throw error;
6407
6843
  }
6408
6844
  };
6409
6845
  };
@@ -6489,30 +6925,9 @@ const inputSupabaseAccessToken = async (accessToken) => {
6489
6925
  };
6490
6926
  //#endregion
6491
6927
  //#region iac/supabaseBucketPrivacy.ts
6492
- var PublicSupabaseBucketError = class extends _hot_updater_cli_tools.InitError {
6493
- name = "PublicSupabaseBucketError";
6494
- constructor(bucketName) {
6495
- super([
6496
- `Supabase bucket "${bucketName}" is public.`,
6497
- "Make the bucket private in Supabase Storage, then rerun init.",
6498
- "Alternatively, rerun without --from-env-file to approve the change interactively."
6499
- ].join("\n"));
6500
- this.bucketName = bucketName;
6501
- }
6502
- };
6503
- const ensureSupabaseBucketPrivate = async ({ api, nonInteractive, selection }) => {
6928
+ const preserveSupabaseBucketPrivacy = ({ selection }) => {
6504
6929
  if (selection.create || !selection.isPublic) return;
6505
- if (nonInteractive) throw new PublicSupabaseBucketError(selection.name);
6506
- const confirmed = await _hot_updater_cli_tools.p.confirm({
6507
- message: `Bucket "${selection.name}" is public. Make it private?`,
6508
- initialValue: true
6509
- });
6510
- if (_hot_updater_cli_tools.p.isCancel(confirmed) || !confirmed) {
6511
- _hot_updater_cli_tools.p.log.info("Init cancelled.");
6512
- process.exit(1);
6513
- }
6514
- await api.updateBucket(selection.id, { public: false });
6515
- _hot_updater_cli_tools.p.log.success(`Bucket "${selection.name}" is now private.`);
6930
+ _hot_updater_cli_tools.p.log.warn(`Bucket "${selection.name}" is public. Its access level will be preserved for existing apps.`);
6516
6931
  };
6517
6932
  //#endregion
6518
6933
  //#region iac/supabaseCli.ts
@@ -6581,12 +6996,26 @@ const linkSupabase = async (workdir, { accessToken, projectId, dbPassword }) =>
6581
6996
  };
6582
6997
  const pushDB = async (workdir, { accessToken, dbPassword }) => {
6583
6998
  try {
6999
+ await execa("npx", [
7000
+ "supabase",
7001
+ "migration",
7002
+ "fetch",
7003
+ "--linked",
7004
+ "--yes",
7005
+ "--workdir",
7006
+ workdir
7007
+ ], {
7008
+ cwd: workdir,
7009
+ env: getSupabaseCommandEnv(accessToken, dbPassword)
7010
+ });
6584
7011
  const dbPush = await execa("npx", [
6585
7012
  "supabase",
6586
7013
  "db",
6587
7014
  "push",
6588
7015
  "--include-all",
6589
- "--yes"
7016
+ "--yes",
7017
+ "--workdir",
7018
+ workdir
6590
7019
  ], {
6591
7020
  cwd: workdir,
6592
7021
  env: getSupabaseCommandEnv(accessToken, dbPassword),
@@ -6604,6 +7033,20 @@ const pushDB = async (workdir, { accessToken, dbPassword }) => {
6604
7033
  }
6605
7034
  };
6606
7035
  //#endregion
7036
+ //#region iac/supabaseInfrastructureState.ts
7037
+ const assertSupabaseInfrastructureCanInitialize = async (api, projectId) => {
7038
+ if (await api.getInfrastructureState() === "incompatible") throw new _hot_updater_cli_tools.InitError(`Supabase v1 infrastructure in project ${projectId} is incomplete or uses an unsupported database version.`);
7039
+ };
7040
+ const assertSupabaseFunctionCanInitialize = async ({ fetchImpl, functionName, functionSlugs, projectId }) => {
7041
+ if (!functionSlugs.includes(functionName)) return;
7042
+ await (0, _hot_updater_cli_tools.assertInfrastructureGenerationAtUrl)({
7043
+ fetchImpl,
7044
+ provider: "Supabase",
7045
+ resource: `Edge Function ${functionName}`,
7046
+ versionUrl: `https://${projectId}.supabase.co/functions/v1/${encodeURIComponent(functionName)}/version`
7047
+ });
7048
+ };
7049
+ //#endregion
6607
7050
  //#region iac/supabaseDeploymentInputs.ts
6608
7051
  const assertSupabaseNonInteractiveInputs = async (inputs, nonInteractive, validateCliLogin = hasValidSupabaseCliLogin) => {
6609
7052
  (0, _hot_updater_cli_tools.assertInitProviderInputs)({
@@ -6745,6 +7188,14 @@ const supabaseCliManagementApi = () => ({
6745
7188
  slug: organization.slug
6746
7189
  }] : []);
6747
7190
  },
7191
+ listFunctions: async (projectId) => parseSupabaseFunctionSlugs(await runSupabaseCli([
7192
+ "functions",
7193
+ "list",
7194
+ "--project-ref",
7195
+ projectId,
7196
+ "--output",
7197
+ "json"
7198
+ ])),
6748
7199
  createProject: async ({ name, organizationSlug, region }) => {
6749
7200
  await execa("npx", [
6750
7201
  "-y",
@@ -6792,6 +7243,13 @@ const supabaseCliManagementApi = () => ({
6792
7243
  const SUPABASE_MANAGEMENT_API_URL = "https://api.supabase.com/v1";
6793
7244
  const SUPABASE_MANAGEMENT_API_TIMEOUT_MS = 3e4;
6794
7245
  const isRecord = (value) => typeof value === "object" && value !== null;
7246
+ const parseSupabaseFunctionSlugs = (body) => {
7247
+ if (!Array.isArray(body)) throw new Error("Supabase functions response was invalid.");
7248
+ return body.map((item) => {
7249
+ if (!isRecord(item) || typeof item.slug !== "string") throw new Error("Supabase functions response was invalid.");
7250
+ return item.slug;
7251
+ });
7252
+ };
6795
7253
  var SupabaseManagementApiStatusError = class extends Error {};
6796
7254
  const projectCreationMayHaveSucceededError = (message = "Supabase project creation could not be confirmed.", cause) => new Error(`${message} The request may have succeeded; check the organization's projects before retrying init.`, { cause });
6797
7255
  const request = async (accessToken, path, init) => {
@@ -6832,6 +7290,7 @@ const supabaseManagementApi = (accessToken) => accessToken === void 0 ? supabase
6832
7290
  slug: organization.slug
6833
7291
  }] : []);
6834
7292
  },
7293
+ listFunctions: async (projectId) => parseSupabaseFunctionSlugs(await request(accessToken, `/projects/${encodeURIComponent(projectId)}/functions`)),
6835
7294
  createProject: async ({ databasePassword, name, organizationSlug, region }) => {
6836
7295
  const body = await request(accessToken, "/projects", {
6837
7296
  body: {
@@ -6864,6 +7323,11 @@ const SUPABASE_PROJECT_READY_STATUS = "ACTIVE_HEALTHY";
6864
7323
  const SUPABASE_PROJECT_PROVISIONING_STATUS = "COMING_UP";
6865
7324
  const SUPABASE_PROJECT_READINESS_MAX_ATTEMPTS = 300;
6866
7325
  const SUPABASE_PROJECT_READINESS_POLL_INTERVAL_MS = 1e3;
7326
+ const SUPABASE_STORAGE_READINESS_MAX_ATTEMPTS = 300;
7327
+ const SUPABASE_STORAGE_READINESS_POLL_INTERVAL_MS = 1e3;
7328
+ const SUPABASE_SCHEMA_READINESS_MAX_ATTEMPTS = 60;
7329
+ const SUPABASE_SCHEMA_READINESS_POLL_INTERVAL_MS = 1e3;
7330
+ const LEGACY_SUPABASE_CATALOG_CDN_URL_ENV_KEY = "HOT_UPDATER_SUPABASE_CATALOG_CDN_URL";
6867
7331
  const STATIC_IMPORT_SPECIFIER_PATTERN = /^\s*(?:import|export)\s+(?:type\s+)?(?:[^"'`]+?\s+from\s+)?["']([^"']+)["'];?/gm;
6868
7332
  const DYNAMIC_IMPORT_SPECIFIER_PATTERN = /\bimport\s*\(\s*["']([^"']+)["']\s*\)/g;
6869
7333
  const getConfigScaffold = (build) => {
@@ -6912,10 +7376,28 @@ function App() {
6912
7376
  return null; // Replace with your app root
6913
7377
  }
6914
7378
 
6915
- export default HotUpdater.wrap({
7379
+ HotUpdater.init({
6916
7380
  baseURL: "%%source%%",
6917
- updateStrategy: "appVersion", // or "fingerprint"
6918
- })(App);`;
7381
+ requestHeaders: {
7382
+ "x-api-key": %%apiKey%%,
7383
+ },
7384
+ });
7385
+
7386
+ // Call HotUpdater.checkForUpdate({ updateStrategy: "appVersion" })
7387
+ // when your app is ready to check.
7388
+ export default App;`;
7389
+ const getSupabaseReactNativeSource = ({ apiKey, functionName, projectId }) => (0, _hot_updater_cli_tools.transformTemplate)(SOURCE_TEMPLATE, {
7390
+ apiKey: JSON.stringify(apiKey),
7391
+ source: `https://${projectId}.supabase.co/functions/v1/${functionName}`
7392
+ });
7393
+ const reportSupabaseOriginCatalogReady = () => {
7394
+ _hot_updater_cli_tools.p.log.success("Release catalog endpoint is ready in origin-only mode.");
7395
+ _hot_updater_cli_tools.p.log.info("Catalog checks still invoke the Supabase Edge Function.");
7396
+ };
7397
+ const reportSupabaseApiKey = (apiKey) => {
7398
+ _hot_updater_cli_tools.p.note(apiKey, "API Key");
7399
+ _hot_updater_cli_tools.p.log.message("Store this API key separately in a secure place.");
7400
+ };
6919
7401
  const resolvePackageExportPath = async (packageName, exportName) => {
6920
7402
  const packageJsonPath = require$1.resolve(`${packageName}/package.json`);
6921
7403
  const exportTarget = JSON.parse(await fs_promises.default.readFile(packageJsonPath, "utf-8")).exports?.[exportName];
@@ -7017,10 +7499,11 @@ const buildEdgeFunctionImports = async (targetDir) => {
7017
7499
  for (const nestedSpecifier of nestedSpecifiers) {
7018
7500
  if (imports[nestedSpecifier]) continue;
7019
7501
  if (nestedSpecifier.startsWith(WORKSPACE_PACKAGE_PREFIX)) {
7502
+ const [scope, name, ...subpath] = nestedSpecifier.split("/");
7020
7503
  await addWorkspacePackage({
7021
7504
  importSpecifier: nestedSpecifier,
7022
- packageName: nestedSpecifier,
7023
- exportName: "."
7505
+ packageName: `${scope}/${name}`,
7506
+ exportName: subpath.length === 0 ? "." : `./${subpath.join("/")}`
7024
7507
  });
7025
7508
  continue;
7026
7509
  }
@@ -7034,7 +7517,7 @@ const buildEdgeFunctionImports = async (targetDir) => {
7034
7517
  exportName: "."
7035
7518
  });
7036
7519
  const supabasePackage = await addWorkspacePackage({
7037
- importSpecifier: "@hot-updater/supabase",
7520
+ importSpecifier: "@hot-updater/supabase/edge",
7038
7521
  packageName: "@hot-updater/supabase",
7039
7522
  exportName: "./edge"
7040
7523
  });
@@ -7103,6 +7586,17 @@ const selectProject = async (preferredProjectId, nonInteractive = false, accessT
7103
7586
  project: selectedProject
7104
7587
  };
7105
7588
  };
7589
+ const isMissingSupabaseStorageTenantError = (error) => error instanceof Error && /Missing tenant config for tenant/u.test(error.message) && (Reflect.get(error, "status") === 400 || Reflect.get(error, "statusCode") === "400");
7590
+ const retryWhileSupabaseStorageTenantIsProvisioning = async (operation) => {
7591
+ for (let attempt = 1; attempt <= SUPABASE_STORAGE_READINESS_MAX_ATTEMPTS; attempt++) try {
7592
+ return await operation();
7593
+ } catch (error) {
7594
+ if (!isMissingSupabaseStorageTenantError(error) || attempt === SUPABASE_STORAGE_READINESS_MAX_ATTEMPTS) throw error;
7595
+ if (attempt === 1) _hot_updater_cli_tools.p.log.info("Waiting for Supabase Storage to become ready...");
7596
+ await delay(SUPABASE_STORAGE_READINESS_POLL_INTERVAL_MS);
7597
+ }
7598
+ throw new Error("Supabase Storage did not become ready.");
7599
+ };
7106
7600
  const selectBucket = async (api, preferredBucketName, nonInteractive = false) => {
7107
7601
  let buckets = [];
7108
7602
  let retryCount = 0;
@@ -7175,18 +7669,21 @@ const selectBucket = async (api, preferredBucketName, nonInteractive = false) =>
7175
7669
  };
7176
7670
  const createSelectedBucket = async (api, selection) => {
7177
7671
  if (!selection.create) return selection;
7178
- await api.createBucket(selection.name, { public: false });
7672
+ await retryWhileSupabaseStorageTenantIsProvisioning(() => api.createBucket(selection.name, { public: false }));
7179
7673
  _hot_updater_cli_tools.p.log.success(`Bucket "${selection.name}" created successfully.`);
7180
- const bucket = (await api.listBuckets()).find((item) => item.name === selection.name);
7674
+ const bucket = (await retryWhileSupabaseStorageTenantIsProvisioning(() => api.listBuckets())).find((item) => item.name === selection.name);
7181
7675
  if (!bucket) throw new Error("Failed to create and select new bucket");
7182
7676
  return {
7183
7677
  id: bucket.id,
7184
7678
  name: bucket.name
7185
7679
  };
7186
7680
  };
7187
- const deployEdgeFunction = async (accessToken, workdir, projectId, functionName) => {
7681
+ const deployEdgeFunction = async (accessToken, workdir, projectId, functionName, bucketName) => {
7188
7682
  const edgeFunctionsLibPath = path.default.join(workdir, "supabase", "edge-functions");
7189
- const edgeFunctionsCode = (0, _hot_updater_cli_tools.transformEnv)(path.default.join(edgeFunctionsLibPath, "index.ts"), { FUNCTION_NAME: functionName });
7683
+ const edgeFunctionsCode = (0, _hot_updater_cli_tools.transformEnv)(path.default.join(edgeFunctionsLibPath, "index.ts"), {
7684
+ BUCKET_NAME: bucketName,
7685
+ FUNCTION_NAME: functionName
7686
+ });
7190
7687
  if (!isSupabaseFunctionName(functionName)) throw new Error("Invalid Supabase Edge Function name.");
7191
7688
  const functionsDir = path.default.resolve(workdir, "supabase", "functions");
7192
7689
  const targetDir = path.default.resolve(functionsDir, functionName);
@@ -7233,6 +7730,15 @@ const waitForSupabaseProjectReady = async ({ getProjectStatus, maxAttempts = SUP
7233
7730
  }
7234
7731
  throw new Error(`Timed out while waiting for the Supabase project. Last status: ${lastStatus ?? "unknown"}.`);
7235
7732
  };
7733
+ const waitForSupabaseSchemaReady = async ({ getInfrastructureState, maxAttempts = SUPABASE_SCHEMA_READINESS_MAX_ATTEMPTS, pollIntervalMs = SUPABASE_SCHEMA_READINESS_POLL_INTERVAL_MS }) => {
7734
+ for (let attempt = 0; attempt < maxAttempts; attempt++) {
7735
+ const state = await getInfrastructureState();
7736
+ if (state === "v1") return;
7737
+ if (state === "incompatible") throw new Error("Supabase database schema is incompatible after migration.");
7738
+ if (attempt < maxAttempts - 1) await delay(pollIntervalMs);
7739
+ }
7740
+ throw new Error("Timed out while waiting for the Supabase database schema cache.");
7741
+ };
7236
7742
  const getSupabaseProjectAccess = async ({ accessToken, managementApi, project, waitForProject }) => {
7237
7743
  const getServiceRoleApiKey = async () => {
7238
7744
  const keysProcess = await execa("npx", [
@@ -7279,11 +7785,30 @@ const getSupabaseProjectAccess = async ({ accessToken, managementApi, project, w
7279
7785
  serviceRoleApiKey
7280
7786
  };
7281
7787
  };
7282
- const runInit = async ({ build, envFile }) => {
7788
+ const withSupabaseCliMetadataCleanup = async (cwd, operation) => {
7789
+ const cliDirectory = path.default.join(cwd, "supabase");
7790
+ let shouldCleanup = false;
7791
+ try {
7792
+ await fs_promises.default.access(cliDirectory);
7793
+ } catch (error) {
7794
+ if (!(error instanceof Error) || Reflect.get(error, "code") !== "ENOENT") throw error;
7795
+ shouldCleanup = true;
7796
+ }
7797
+ try {
7798
+ return await operation();
7799
+ } finally {
7800
+ if (shouldCleanup) await fs_promises.default.rm(cliDirectory, {
7801
+ recursive: true,
7802
+ force: true
7803
+ });
7804
+ }
7805
+ };
7806
+ const runInitWithoutCliMetadata = async ({ build, envFile }) => {
7283
7807
  const nonInteractive = envFile !== void 0;
7284
7808
  const initEnvSources = await (0, _hot_updater_cli_tools.readHotUpdaterInitEnv)(process.cwd(), envFile);
7285
7809
  const { inputEnv, managedEnv } = initEnvSources;
7286
- const savedInputs = resolveSupabaseInitInputs((0, _hot_updater_cli_tools.getHotUpdaterInitInputEnv)(initEnvSources, nonInteractive), {
7810
+ const initInputEnv = (0, _hot_updater_cli_tools.getHotUpdaterInitInputEnv)(initEnvSources, nonInteractive);
7811
+ const savedInputs = resolveSupabaseInitInputs(initInputEnv, {
7287
7812
  inputEnv,
7288
7813
  managedEnv
7289
7814
  });
@@ -7322,11 +7847,15 @@ const runInit = async ({ build, envFile }) => {
7322
7847
  name: projectCreationInputs.bucketName
7323
7848
  };
7324
7849
  else throw new Error("Failed to plan the Supabase storage bucket.");
7325
- if (projectAccess) await ensureSupabaseBucketPrivate({
7326
- api: projectAccess.api,
7327
- nonInteractive,
7328
- selection: bucketSelection
7329
- });
7850
+ if (projectAccess) {
7851
+ await assertSupabaseInfrastructureCanInitialize(projectAccess.api, project.id);
7852
+ await assertSupabaseFunctionCanInitialize({
7853
+ functionName,
7854
+ functionSlugs: await managementApi.listFunctions(project.id),
7855
+ projectId: project.id
7856
+ });
7857
+ preserveSupabaseBucketPrivacy({ selection: bucketSelection });
7858
+ }
7330
7859
  const inputsBeforeProvisioning = {
7331
7860
  ...savedInputs,
7332
7861
  ...projectCreationInputs,
@@ -7376,7 +7905,7 @@ const runInit = async ({ build, envFile }) => {
7376
7905
  });
7377
7906
  const persistDatabasePassword = persistCredentialInputs && dbPassword !== "";
7378
7907
  if (persistDatabasePassword) providerEnv[SUPABASE_DATABASE_PASSWORD_PROJECT_ID_ENV_KEY] = project.id;
7379
- await (0, _hot_updater_cli_tools.makeEnv)(providerEnv, ".env.hotupdater", { removeKeys: persistDatabasePassword ? [] : [databasePasswordKey, SUPABASE_DATABASE_PASSWORD_PROJECT_ID_ENV_KEY] });
7908
+ await (0, _hot_updater_cli_tools.makeEnv)(providerEnv, ".env.hotupdater", { removeKeys: [LEGACY_SUPABASE_CATALOG_CDN_URL_ENV_KEY, ...persistDatabasePassword ? [] : [databasePasswordKey, SUPABASE_DATABASE_PASSWORD_PROJECT_ID_ENV_KEY]] });
7380
7909
  const bucket = await createSelectedBucket(projectAccess.api, bucketSelection);
7381
7910
  await (0, _hot_updater_cli_tools.makeEnv)({
7382
7911
  [initProvider.inputs.projectId.envKey]: project.id,
@@ -7401,7 +7930,23 @@ const runInit = async ({ build, envFile }) => {
7401
7930
  accessToken,
7402
7931
  dbPassword
7403
7932
  });
7404
- await deployEdgeFunction(accessToken, tmpDir, project.id, functionName);
7933
+ await waitForSupabaseSchemaReady({ getInfrastructureState: projectAccess.api.getInfrastructureState });
7934
+ const databasePlugin = supabaseDatabase({
7935
+ supabaseServiceRoleKey: projectAccess.serviceRoleApiKey,
7936
+ supabaseUrl: `https://${project.id}.supabase.co`
7937
+ });
7938
+ let apiKey;
7939
+ try {
7940
+ apiKey = (await (0, _hot_updater_server.provisionApiKey)({
7941
+ apiKeys: databasePlugin.models.apiKeys,
7942
+ existingApiKey: initInputEnv.HOT_UPDATER_API_KEY,
7943
+ name: "Supabase init"
7944
+ })).apiKey;
7945
+ await (0, _hot_updater_cli_tools.makeEnv)({ HOT_UPDATER_API_KEY: apiKey });
7946
+ } finally {
7947
+ await databasePlugin.dispose?.();
7948
+ }
7949
+ await deployEdgeFunction(accessToken, tmpDir, project.id, functionName, bucket.name);
7405
7950
  await removeTmpDir();
7406
7951
  const configWriteResult = await (0, _hot_updater_cli_tools.writeHotUpdaterConfig)(getConfigScaffold(build));
7407
7952
  await assertSkippedConfigDoesNotUseLegacySupabaseKey(configWriteResult);
@@ -7409,16 +7954,28 @@ const runInit = async ({ build, envFile }) => {
7409
7954
  if (configWriteResult.status === "created") _hot_updater_cli_tools.p.log.success("Generated 'hot-updater.config.ts' file with Supabase settings.");
7410
7955
  else if (configWriteResult.status === "merged") _hot_updater_cli_tools.p.log.success("Updated 'hot-updater.config.ts' file with Supabase settings.");
7411
7956
  else _hot_updater_cli_tools.p.log.warn(`Kept existing 'hot-updater.config.ts' unchanged: ${configWriteResult.reason}`);
7412
- _hot_updater_cli_tools.p.note((0, _hot_updater_cli_tools.transformTemplate)(SOURCE_TEMPLATE, { source: `https://${project.id}.supabase.co/functions/v1/${functionName}` }));
7957
+ _hot_updater_cli_tools.p.note(getSupabaseReactNativeSource({
7958
+ apiKey,
7959
+ functionName,
7960
+ projectId: project.id
7961
+ }));
7962
+ reportSupabaseApiKey(apiKey);
7963
+ reportSupabaseOriginCatalogReady();
7413
7964
  _hot_updater_cli_tools.p.log.message(`Next step: ${(0, _hot_updater_cli_tools.link)("https://hot-updater.dev/docs/managed/supabase#step-4-add-hotupdater-to-your-project")}`);
7414
7965
  _hot_updater_cli_tools.p.log.success("Done! 🎉");
7415
7966
  };
7967
+ const runInit = (options) => withSupabaseCliMetadataCleanup(process.cwd(), () => runInitWithoutCliMetadata(options));
7416
7968
  //#endregion
7417
7969
  exports.createSelectedBucket = createSelectedBucket;
7418
7970
  exports.getLegacySupabaseConfigReference = getLegacySupabaseConfigReference;
7419
7971
  exports.getSupabaseProjectAccess = getSupabaseProjectAccess;
7972
+ exports.getSupabaseReactNativeSource = getSupabaseReactNativeSource;
7973
+ exports.reportSupabaseApiKey = reportSupabaseApiKey;
7974
+ exports.reportSupabaseOriginCatalogReady = reportSupabaseOriginCatalogReady;
7420
7975
  exports.resolveEdgeFunctionDenoConfig = resolveEdgeFunctionDenoConfig;
7421
7976
  exports.runInit = runInit;
7422
7977
  exports.selectBucket = selectBucket;
7423
7978
  exports.selectProject = selectProject;
7424
7979
  exports.waitForSupabaseProjectReady = waitForSupabaseProjectReady;
7980
+ exports.waitForSupabaseSchemaReady = waitForSupabaseSchemaReady;
7981
+ exports.withSupabaseCliMetadataCleanup = withSupabaseCliMetadataCleanup;