@hot-updater/supabase 1.2.0-rc.4 → 1.2.0-rc.6

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/edge.cjs CHANGED
@@ -1,4 +1,4 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_supabaseStorage = require("./supabaseStorage-MqoRcaii.cjs");
2
+ const require_supabaseStorage = require("./supabaseStorage-BV6GuUz_.cjs");
3
3
  exports.supabaseDatabase = require_supabaseStorage.supabaseDatabase;
4
4
  exports.supabaseStorage = require_supabaseStorage.supabaseStorage;
package/dist/edge.d.cts CHANGED
@@ -1,2 +1,2 @@
1
- import { i as supabaseDatabase, n as supabaseStorage, r as SupabaseDatabaseConfig, t as SupabaseStorageConfig } from "./supabaseStorage-BryXQ72m.cjs";
1
+ import { i as supabaseDatabase, n as supabaseStorage, r as SupabaseDatabaseConfig, t as SupabaseStorageConfig } from "./supabaseStorage-B131_auF.cjs";
2
2
  export { type SupabaseDatabaseConfig, type SupabaseStorageConfig, supabaseDatabase, supabaseStorage };
package/dist/edge.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { i as supabaseDatabase, n as supabaseStorage, r as SupabaseDatabaseConfig, t as SupabaseStorageConfig } from "./supabaseStorage-BryXQ72m.mjs";
1
+ import { i as supabaseDatabase, n as supabaseStorage, r as SupabaseDatabaseConfig, t as SupabaseStorageConfig } from "./supabaseStorage-B131_auF.mjs";
2
2
  export { type SupabaseDatabaseConfig, type SupabaseStorageConfig, supabaseDatabase, supabaseStorage };
package/dist/edge.mjs CHANGED
@@ -1,2 +1,2 @@
1
- import { n as supabaseDatabase, t as supabaseStorage } from "./supabaseStorage-D4jcGa-l.mjs";
1
+ import { n as supabaseDatabase, t as supabaseStorage } from "./supabaseStorage-8VAuNYHy.mjs";
2
2
  export { supabaseDatabase, supabaseStorage };
package/dist/index.cjs CHANGED
@@ -1,5 +1,5 @@
1
1
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
- const require_supabaseStorage = require("./supabaseStorage-MqoRcaii.cjs");
2
+ const require_supabaseStorage = require("./supabaseStorage-BV6GuUz_.cjs");
3
3
  let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
4
4
  //#region src/supabaseSchema.ts
5
5
  /** Every table the apply RPC may name: models, index tables, settings, and the write guard. */
package/dist/index.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { n as supabaseStorage, r as SupabaseDatabaseConfig, t as SupabaseStorageConfig } from "./supabaseStorage-BryXQ72m.cjs";
1
+ import { n as supabaseStorage, r as SupabaseDatabaseConfig, t as SupabaseStorageConfig } from "./supabaseStorage-B131_auF.cjs";
2
2
  import { ToolingDatabase } from "@hot-updater/plugin-core";
3
3
  //#region src/supabaseMigration.d.ts
4
4
  /**
package/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { n as supabaseStorage, r as SupabaseDatabaseConfig, t as SupabaseStorageConfig } from "./supabaseStorage-BryXQ72m.mjs";
1
+ import { n as supabaseStorage, r as SupabaseDatabaseConfig, t as SupabaseStorageConfig } from "./supabaseStorage-B131_auF.mjs";
2
2
  import { ToolingDatabase } from "@hot-updater/plugin-core";
3
3
  //#region src/supabaseMigration.d.ts
4
4
  /**
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { i as SUPABASE_TABLE_PREFIX, n as supabaseDatabase$1, r as SUPABASE_APPLY_FUNCTION, t as supabaseStorage } from "./supabaseStorage-D4jcGa-l.mjs";
1
+ import { i as SUPABASE_TABLE_PREFIX, n as supabaseDatabase$1, r as SUPABASE_APPLY_FUNCTION, t as supabaseStorage } from "./supabaseStorage-8VAuNYHy.mjs";
2
2
  import { SETTINGS_TABLE, WRITE_GUARD_TABLE, coreSettings, coreTarget, createTableStatements, generateEngineSql, isMultiIndex } from "@hot-updater/plugin-core";
3
3
  //#region src/supabaseSchema.ts
4
4
  /** Every table the apply RPC may name: models, index tables, settings, and the write guard. */
@@ -6333,9 +6333,11 @@ createExeca(mapScriptAsync, {}, deepScriptOptions, setScriptSync);
6333
6333
  const { sendMessage, getOneMessage, getEachMessage, getCancelSignal } = getIpcExport();
6334
6334
  //#endregion
6335
6335
  //#region src/supabaseConfig.ts
6336
- const resolveSupabaseServiceRoleKey = (config) => {
6337
- if (!config.supabaseServiceRoleKey) throw new Error("Supabase service role key is required. Set supabaseServiceRoleKey.");
6338
- return config.supabaseServiceRoleKey;
6336
+ const resolveSupabaseServiceRoleKey = async (config) => {
6337
+ const { supabaseServiceRoleKey } = config;
6338
+ const key = typeof supabaseServiceRoleKey === "function" ? await supabaseServiceRoleKey() : supabaseServiceRoleKey;
6339
+ if (!key) throw new Error("Supabase service role key is required. Set supabaseServiceRoleKey.");
6340
+ return key;
6339
6341
  };
6340
6342
  //#endregion
6341
6343
  //#region src/supabaseInfrastructureNames.ts
@@ -6375,9 +6377,16 @@ const withCode = (error) => Object.assign(new Error(error.message, { cause: erro
6375
6377
  */
6376
6378
  const supabaseExecutor = (client) => {
6377
6379
  let created;
6378
- const clientOf = () => typeof client === "function" ? created ??= client() : client;
6380
+ const clientOf = async () => {
6381
+ if (typeof client !== "function") return client;
6382
+ created ??= Promise.resolve().then(client).catch((error) => {
6383
+ created = void 0;
6384
+ throw error;
6385
+ });
6386
+ return created;
6387
+ };
6379
6388
  const apply = async (statements) => {
6380
- const { data, error } = await clientOf().rpc(SUPABASE_APPLY_FUNCTION, { p_statements: statements.map(toApplyStatement) });
6389
+ const { data, error } = await (await clientOf()).rpc(SUPABASE_APPLY_FUNCTION, { p_statements: statements.map(toApplyStatement) });
6381
6390
  if (error) throw withCode(error);
6382
6391
  return data;
6383
6392
  };
@@ -6400,7 +6409,7 @@ const supabaseExecutor = (client) => {
6400
6409
  */
6401
6410
  const supabaseDatabase = (config) => {
6402
6411
  const { migrations: _migrations, ...adapter } = (0, _hot_updater_plugin_core.createSqlAdapter)({
6403
- executor: supabaseExecutor(() => (0, _supabase_supabase_js.createClient)(config.supabaseUrl, resolveSupabaseServiceRoleKey(config))),
6412
+ executor: supabaseExecutor(async () => (0, _supabase_supabase_js.createClient)(config.supabaseUrl, await resolveSupabaseServiceRoleKey(config))),
6404
6413
  tablePrefix: SUPABASE_TABLE_PREFIX
6405
6414
  });
6406
6415
  return (0, _hot_updater_plugin_core.createEngineDatabase)({
@@ -6410,27 +6419,39 @@ const supabaseDatabase = (config) => {
6410
6419
  };
6411
6420
  //#endregion
6412
6421
  //#region iac/configTemplate.ts
6413
- const getConfigScaffold = (build) => {
6414
- return (0, _hot_updater_cli_tools.createHotUpdaterConfigScaffoldFromBuilder)(new _hot_updater_cli_tools.ConfigBuilder().setBuildType(build).setStorage({
6422
+ /**
6423
+ * The config init writes. With the `resources` init set up, it names them,
6424
+ * and reads the service role key with `secretEnv`, from the environment and
6425
+ * `.env.hotupdater`, then the config's `secrets` adapter. Without them, as
6426
+ * the agent scaffold writes it, it reads every value from the environment.
6427
+ */
6428
+ const getConfigScaffold = (build, resources) => {
6429
+ const supabaseUrl = resources === void 0 ? "process.env.HOT_UPDATER_SUPABASE_URL!" : JSON.stringify(resources.supabaseUrl);
6430
+ const serviceRoleKey = resources === void 0 ? "process.env.HOT_UPDATER_SUPABASE_SERVICE_ROLE_KEY!" : `async () =>
6431
+ (await deploySecrets()).HOT_UPDATER_SUPABASE_SERVICE_ROLE_KEY`;
6432
+ const storageConfig = {
6415
6433
  imports: [{
6416
6434
  pkg: "@hot-updater/supabase",
6417
6435
  named: ["supabaseStorage"]
6418
6436
  }],
6419
6437
  configString: `supabaseStorage({
6420
- supabaseUrl: process.env.HOT_UPDATER_SUPABASE_URL!,
6421
- supabaseServiceRoleKey: process.env.HOT_UPDATER_SUPABASE_SERVICE_ROLE_KEY!,
6422
- bucketName: process.env.HOT_UPDATER_SUPABASE_BUCKET_NAME!,
6438
+ supabaseUrl: ${supabaseUrl},
6439
+ supabaseServiceRoleKey: ${serviceRoleKey},
6440
+ bucketName: ${resources === void 0 ? "process.env.HOT_UPDATER_SUPABASE_BUCKET_NAME!" : JSON.stringify(resources.bucketName)},
6423
6441
  })`
6424
- }).setDatabase({
6442
+ };
6443
+ const databaseConfig = {
6425
6444
  imports: [{
6426
6445
  pkg: "@hot-updater/supabase",
6427
6446
  named: ["supabaseDatabase"]
6428
6447
  }],
6429
6448
  configString: `supabaseDatabase({
6430
- supabaseUrl: process.env.HOT_UPDATER_SUPABASE_URL!,
6431
- supabaseServiceRoleKey: process.env.HOT_UPDATER_SUPABASE_SERVICE_ROLE_KEY!,
6449
+ supabaseUrl: ${supabaseUrl},
6450
+ supabaseServiceRoleKey: ${serviceRoleKey},
6432
6451
  })`
6433
- }).setPlugins({
6452
+ };
6453
+ const helperStatements = resources === void 0 ? [] : [(0, _hot_updater_cli_tools.secretEnvHelper)("deploySecrets", ["HOT_UPDATER_SUPABASE_SERVICE_ROLE_KEY"])];
6454
+ const builder = new _hot_updater_cli_tools.ConfigBuilder().setBuildType(build).setStorage(storageConfig).setDatabase(databaseConfig).setPlugins({
6434
6455
  imports: [{
6435
6456
  pkg: "hot-updater/plugins",
6436
6457
  named: [
@@ -6440,7 +6461,12 @@ const getConfigScaffold = (build) => {
6440
6461
  ]
6441
6462
  }],
6442
6463
  configString: "[apiKeys(), insights(), remoteConfig()]"
6443
- }));
6464
+ });
6465
+ if (resources !== void 0) builder.addImport({
6466
+ pkg: "hot-updater",
6467
+ named: ["secretEnv"]
6468
+ }).setIntermediateCode(helperStatements.map(({ code }) => code).join("\n\n"));
6469
+ return (0, _hot_updater_cli_tools.createHotUpdaterConfigScaffoldFromBuilder)(builder, { helperStatements });
6444
6470
  };
6445
6471
  //#endregion
6446
6472
  //#region iac/init/index.ts
@@ -6546,7 +6572,8 @@ const initProvider = {
6546
6572
  type: "password"
6547
6573
  }
6548
6574
  }
6549
- }
6575
+ },
6576
+ secrets: ["HOT_UPDATER_SUPABASE_SERVICE_ROLE_KEY"]
6550
6577
  };
6551
6578
  //#endregion
6552
6579
  //#region iac/supabaseApi.ts
@@ -7515,9 +7542,9 @@ const withSupabaseCliMetadataCleanup = async (cwd, operation) => {
7515
7542
  });
7516
7543
  }
7517
7544
  };
7518
- const runInitWithoutCliMetadata = async ({ build, envFile }) => {
7545
+ const runInitWithoutCliMetadata = async ({ build, envFile, secretsEnv }) => {
7519
7546
  const nonInteractive = envFile !== void 0;
7520
- const initEnvSources = await (0, _hot_updater_cli_tools.readHotUpdaterInitEnv)(process.cwd(), envFile);
7547
+ const initEnvSources = await (0, _hot_updater_cli_tools.readHotUpdaterInitEnv)(process.cwd(), envFile, secretsEnv);
7521
7548
  const { inputEnv, managedEnv } = initEnvSources;
7522
7549
  const initInputEnv = (0, _hot_updater_cli_tools.getHotUpdaterInitInputEnv)(initEnvSources, nonInteractive);
7523
7550
  const savedInputs = resolveSupabaseInitInputs(initInputEnv, {
@@ -7596,6 +7623,7 @@ const runInitWithoutCliMetadata = async ({ build, envFile }) => {
7596
7623
  const { tmpDir, removeTmpDir } = await (0, _hot_updater_cli_tools.copyDirToTmp)(scaffoldLibPath, "supabase");
7597
7624
  let credential;
7598
7625
  let clientPlugins = [];
7626
+ let resources;
7599
7627
  try {
7600
7628
  await stageEdgeFunction({
7601
7629
  bucketName: bucketSelection.name,
@@ -7637,6 +7665,10 @@ const runInitWithoutCliMetadata = async ({ build, envFile }) => {
7637
7665
  [initProvider.inputs.bucketName.envKey]: bucket.name,
7638
7666
  HOT_UPDATER_SUPABASE_URL: `https://${project.id}.supabase.co`
7639
7667
  });
7668
+ resources = {
7669
+ supabaseUrl: `https://${project.id}.supabase.co`,
7670
+ bucketName: bucket.name
7671
+ };
7640
7672
  await linkSupabase(tmpDir, {
7641
7673
  accessToken,
7642
7674
  projectId: project.id,
@@ -7674,7 +7706,7 @@ const runInitWithoutCliMetadata = async ({ build, envFile }) => {
7674
7706
  await removeTmpDir();
7675
7707
  }
7676
7708
  _hot_updater_cli_tools.p.log.success("Generated '.env.hotupdater' file with Supabase settings.");
7677
- await (0, _hot_updater_cli_tools.writeHotUpdaterFiles)(getConfigScaffold(build), {
7709
+ await (0, _hot_updater_cli_tools.writeHotUpdaterFiles)(getConfigScaffold(build, resources), {
7678
7710
  cwd: process.cwd(),
7679
7711
  settings: "Supabase"
7680
7712
  });
@@ -99,6 +99,7 @@ declare const initProvider: {
99
99
  };
100
100
  };
101
101
  };
102
+ readonly secrets: readonly ["HOT_UPDATER_SUPABASE_SERVICE_ROLE_KEY"];
102
103
  };
103
104
  //#endregion
104
105
  //#region iac/supabaseManagementApi.d.ts
@@ -99,6 +99,7 @@ declare const initProvider: {
99
99
  };
100
100
  };
101
101
  };
102
+ readonly secrets: readonly ["HOT_UPDATER_SUPABASE_SERVICE_ROLE_KEY"];
102
103
  };
103
104
  //#endregion
104
105
  //#region iac/supabaseManagementApi.d.ts
@@ -1,7 +1,7 @@
1
1
  import { createRequire } from "node:module";
2
2
  import fs from "fs/promises";
3
3
  import path from "path";
4
- import { ConfigBuilder, InitError, MissingInitInputsError, assembleServer, assertInfrastructureGenerationAtUrl, assertInitInputs, assertInitProviderInputs, confirmInitInputPersistence, copyDirToTmp, createHotUpdaterConfigScaffoldFromBuilder, getHotUpdaterEnvValue, getHotUpdaterInitInputEnv, getInitProviderEnvVars, getInitProviderTextPromptValues, link, makeEnv, moduleSpecifiersOf, p, printAppSetup, provisionClientCredential, readHotUpdaterInitEnv, resolveInitProviderInput, resolvePackageVersion, transformEnv, transformTemplate, writeHotUpdaterFiles } from "@hot-updater/cli-tools";
4
+ import { ConfigBuilder, InitError, MissingInitInputsError, assembleServer, assertInfrastructureGenerationAtUrl, assertInitInputs, assertInitProviderInputs, confirmInitInputPersistence, copyDirToTmp, createHotUpdaterConfigScaffoldFromBuilder, getHotUpdaterEnvValue, getHotUpdaterInitInputEnv, getInitProviderEnvVars, getInitProviderTextPromptValues, link, makeEnv, moduleSpecifiersOf, p, printAppSetup, provisionClientCredential, readHotUpdaterInitEnv, resolveInitProviderInput, resolvePackageVersion, secretEnvHelper, transformEnv, transformTemplate, writeHotUpdaterFiles } from "@hot-updater/cli-tools";
5
5
  import { apiKeys, insights, remoteConfig } from "@hot-updater/server/plugins";
6
6
  import { fileURLToPath } from "node:url";
7
7
  import { ChildProcess, execFile, spawn, spawnSync } from "node:child_process";
@@ -6328,9 +6328,11 @@ createExeca(mapScriptAsync, {}, deepScriptOptions, setScriptSync);
6328
6328
  const { sendMessage, getOneMessage, getEachMessage, getCancelSignal } = getIpcExport();
6329
6329
  //#endregion
6330
6330
  //#region src/supabaseConfig.ts
6331
- const resolveSupabaseServiceRoleKey = (config) => {
6332
- if (!config.supabaseServiceRoleKey) throw new Error("Supabase service role key is required. Set supabaseServiceRoleKey.");
6333
- return config.supabaseServiceRoleKey;
6331
+ const resolveSupabaseServiceRoleKey = async (config) => {
6332
+ const { supabaseServiceRoleKey } = config;
6333
+ const key = typeof supabaseServiceRoleKey === "function" ? await supabaseServiceRoleKey() : supabaseServiceRoleKey;
6334
+ if (!key) throw new Error("Supabase service role key is required. Set supabaseServiceRoleKey.");
6335
+ return key;
6334
6336
  };
6335
6337
  //#endregion
6336
6338
  //#region src/supabaseInfrastructureNames.ts
@@ -6370,9 +6372,16 @@ const withCode = (error) => Object.assign(new Error(error.message, { cause: erro
6370
6372
  */
6371
6373
  const supabaseExecutor = (client) => {
6372
6374
  let created;
6373
- const clientOf = () => typeof client === "function" ? created ??= client() : client;
6375
+ const clientOf = async () => {
6376
+ if (typeof client !== "function") return client;
6377
+ created ??= Promise.resolve().then(client).catch((error) => {
6378
+ created = void 0;
6379
+ throw error;
6380
+ });
6381
+ return created;
6382
+ };
6374
6383
  const apply = async (statements) => {
6375
- const { data, error } = await clientOf().rpc(SUPABASE_APPLY_FUNCTION, { p_statements: statements.map(toApplyStatement) });
6384
+ const { data, error } = await (await clientOf()).rpc(SUPABASE_APPLY_FUNCTION, { p_statements: statements.map(toApplyStatement) });
6376
6385
  if (error) throw withCode(error);
6377
6386
  return data;
6378
6387
  };
@@ -6395,7 +6404,7 @@ const supabaseExecutor = (client) => {
6395
6404
  */
6396
6405
  const supabaseDatabase = (config) => {
6397
6406
  const { migrations: _migrations, ...adapter } = createSqlAdapter({
6398
- executor: supabaseExecutor(() => createClient(config.supabaseUrl, resolveSupabaseServiceRoleKey(config))),
6407
+ executor: supabaseExecutor(async () => createClient(config.supabaseUrl, await resolveSupabaseServiceRoleKey(config))),
6399
6408
  tablePrefix: SUPABASE_TABLE_PREFIX
6400
6409
  });
6401
6410
  return createEngineDatabase({
@@ -6405,27 +6414,39 @@ const supabaseDatabase = (config) => {
6405
6414
  };
6406
6415
  //#endregion
6407
6416
  //#region iac/configTemplate.ts
6408
- const getConfigScaffold = (build) => {
6409
- return createHotUpdaterConfigScaffoldFromBuilder(new ConfigBuilder().setBuildType(build).setStorage({
6417
+ /**
6418
+ * The config init writes. With the `resources` init set up, it names them,
6419
+ * and reads the service role key with `secretEnv`, from the environment and
6420
+ * `.env.hotupdater`, then the config's `secrets` adapter. Without them, as
6421
+ * the agent scaffold writes it, it reads every value from the environment.
6422
+ */
6423
+ const getConfigScaffold = (build, resources) => {
6424
+ const supabaseUrl = resources === void 0 ? "process.env.HOT_UPDATER_SUPABASE_URL!" : JSON.stringify(resources.supabaseUrl);
6425
+ const serviceRoleKey = resources === void 0 ? "process.env.HOT_UPDATER_SUPABASE_SERVICE_ROLE_KEY!" : `async () =>
6426
+ (await deploySecrets()).HOT_UPDATER_SUPABASE_SERVICE_ROLE_KEY`;
6427
+ const storageConfig = {
6410
6428
  imports: [{
6411
6429
  pkg: "@hot-updater/supabase",
6412
6430
  named: ["supabaseStorage"]
6413
6431
  }],
6414
6432
  configString: `supabaseStorage({
6415
- supabaseUrl: process.env.HOT_UPDATER_SUPABASE_URL!,
6416
- supabaseServiceRoleKey: process.env.HOT_UPDATER_SUPABASE_SERVICE_ROLE_KEY!,
6417
- bucketName: process.env.HOT_UPDATER_SUPABASE_BUCKET_NAME!,
6433
+ supabaseUrl: ${supabaseUrl},
6434
+ supabaseServiceRoleKey: ${serviceRoleKey},
6435
+ bucketName: ${resources === void 0 ? "process.env.HOT_UPDATER_SUPABASE_BUCKET_NAME!" : JSON.stringify(resources.bucketName)},
6418
6436
  })`
6419
- }).setDatabase({
6437
+ };
6438
+ const databaseConfig = {
6420
6439
  imports: [{
6421
6440
  pkg: "@hot-updater/supabase",
6422
6441
  named: ["supabaseDatabase"]
6423
6442
  }],
6424
6443
  configString: `supabaseDatabase({
6425
- supabaseUrl: process.env.HOT_UPDATER_SUPABASE_URL!,
6426
- supabaseServiceRoleKey: process.env.HOT_UPDATER_SUPABASE_SERVICE_ROLE_KEY!,
6444
+ supabaseUrl: ${supabaseUrl},
6445
+ supabaseServiceRoleKey: ${serviceRoleKey},
6427
6446
  })`
6428
- }).setPlugins({
6447
+ };
6448
+ const helperStatements = resources === void 0 ? [] : [secretEnvHelper("deploySecrets", ["HOT_UPDATER_SUPABASE_SERVICE_ROLE_KEY"])];
6449
+ const builder = new ConfigBuilder().setBuildType(build).setStorage(storageConfig).setDatabase(databaseConfig).setPlugins({
6429
6450
  imports: [{
6430
6451
  pkg: "hot-updater/plugins",
6431
6452
  named: [
@@ -6435,7 +6456,12 @@ const getConfigScaffold = (build) => {
6435
6456
  ]
6436
6457
  }],
6437
6458
  configString: "[apiKeys(), insights(), remoteConfig()]"
6438
- }));
6459
+ });
6460
+ if (resources !== void 0) builder.addImport({
6461
+ pkg: "hot-updater",
6462
+ named: ["secretEnv"]
6463
+ }).setIntermediateCode(helperStatements.map(({ code }) => code).join("\n\n"));
6464
+ return createHotUpdaterConfigScaffoldFromBuilder(builder, { helperStatements });
6439
6465
  };
6440
6466
  //#endregion
6441
6467
  //#region iac/init/index.ts
@@ -6541,7 +6567,8 @@ const initProvider = {
6541
6567
  type: "password"
6542
6568
  }
6543
6569
  }
6544
- }
6570
+ },
6571
+ secrets: ["HOT_UPDATER_SUPABASE_SERVICE_ROLE_KEY"]
6545
6572
  };
6546
6573
  //#endregion
6547
6574
  //#region iac/supabaseApi.ts
@@ -7510,9 +7537,9 @@ const withSupabaseCliMetadataCleanup = async (cwd, operation) => {
7510
7537
  });
7511
7538
  }
7512
7539
  };
7513
- const runInitWithoutCliMetadata = async ({ build, envFile }) => {
7540
+ const runInitWithoutCliMetadata = async ({ build, envFile, secretsEnv }) => {
7514
7541
  const nonInteractive = envFile !== void 0;
7515
- const initEnvSources = await readHotUpdaterInitEnv(process.cwd(), envFile);
7542
+ const initEnvSources = await readHotUpdaterInitEnv(process.cwd(), envFile, secretsEnv);
7516
7543
  const { inputEnv, managedEnv } = initEnvSources;
7517
7544
  const initInputEnv = getHotUpdaterInitInputEnv(initEnvSources, nonInteractive);
7518
7545
  const savedInputs = resolveSupabaseInitInputs(initInputEnv, {
@@ -7591,6 +7618,7 @@ const runInitWithoutCliMetadata = async ({ build, envFile }) => {
7591
7618
  const { tmpDir, removeTmpDir } = await copyDirToTmp(scaffoldLibPath, "supabase");
7592
7619
  let credential;
7593
7620
  let clientPlugins = [];
7621
+ let resources;
7594
7622
  try {
7595
7623
  await stageEdgeFunction({
7596
7624
  bucketName: bucketSelection.name,
@@ -7632,6 +7660,10 @@ const runInitWithoutCliMetadata = async ({ build, envFile }) => {
7632
7660
  [initProvider.inputs.bucketName.envKey]: bucket.name,
7633
7661
  HOT_UPDATER_SUPABASE_URL: `https://${project.id}.supabase.co`
7634
7662
  });
7663
+ resources = {
7664
+ supabaseUrl: `https://${project.id}.supabase.co`,
7665
+ bucketName: bucket.name
7666
+ };
7635
7667
  await linkSupabase(tmpDir, {
7636
7668
  accessToken,
7637
7669
  projectId: project.id,
@@ -7669,7 +7701,7 @@ const runInitWithoutCliMetadata = async ({ build, envFile }) => {
7669
7701
  await removeTmpDir();
7670
7702
  }
7671
7703
  p.log.success("Generated '.env.hotupdater' file with Supabase settings.");
7672
- await writeHotUpdaterFiles(getConfigScaffold(build), {
7704
+ await writeHotUpdaterFiles(getConfigScaffold(build, resources), {
7673
7705
  cwd: process.cwd(),
7674
7706
  settings: "Supabase"
7675
7707
  });
@@ -1,9 +1,11 @@
1
1
  import { SETTINGS_TABLE, createEngineDatabase, createSqlAdapter, createStorageAdapter, createStorageKeyBuilder, createStorageUri, parseStorageUri } from "@hot-updater/plugin-core";
2
2
  import { createClient } from "@supabase/supabase-js";
3
3
  //#region src/supabaseConfig.ts
4
- const resolveSupabaseServiceRoleKey = (config) => {
5
- if (!config.supabaseServiceRoleKey) throw new Error("Supabase service role key is required. Set supabaseServiceRoleKey.");
6
- return config.supabaseServiceRoleKey;
4
+ const resolveSupabaseServiceRoleKey = async (config) => {
5
+ const { supabaseServiceRoleKey } = config;
6
+ const key = typeof supabaseServiceRoleKey === "function" ? await supabaseServiceRoleKey() : supabaseServiceRoleKey;
7
+ if (!key) throw new Error("Supabase service role key is required. Set supabaseServiceRoleKey.");
8
+ return key;
7
9
  };
8
10
  //#endregion
9
11
  //#region src/supabaseInfrastructureNames.ts
@@ -42,9 +44,16 @@ const withCode = (error) => Object.assign(new Error(error.message, { cause: erro
42
44
  */
43
45
  const supabaseExecutor = (client) => {
44
46
  let created;
45
- const clientOf = () => typeof client === "function" ? created ??= client() : client;
47
+ const clientOf = async () => {
48
+ if (typeof client !== "function") return client;
49
+ created ??= Promise.resolve().then(client).catch((error) => {
50
+ created = void 0;
51
+ throw error;
52
+ });
53
+ return created;
54
+ };
46
55
  const apply = async (statements) => {
47
- const { data, error } = await clientOf().rpc(SUPABASE_APPLY_FUNCTION, { p_statements: statements.map(toApplyStatement) });
56
+ const { data, error } = await (await clientOf()).rpc(SUPABASE_APPLY_FUNCTION, { p_statements: statements.map(toApplyStatement) });
48
57
  if (error) throw withCode(error);
49
58
  return data;
50
59
  };
@@ -67,7 +76,7 @@ const supabaseExecutor = (client) => {
67
76
  */
68
77
  const supabaseDatabase = (config) => {
69
78
  const { migrations: _migrations, ...adapter } = createSqlAdapter({
70
- executor: supabaseExecutor(() => createClient(config.supabaseUrl, resolveSupabaseServiceRoleKey(config))),
79
+ executor: supabaseExecutor(async () => createClient(config.supabaseUrl, await resolveSupabaseServiceRoleKey(config))),
71
80
  tablePrefix: SUPABASE_TABLE_PREFIX
72
81
  });
73
82
  return createEngineDatabase({
@@ -170,10 +179,13 @@ const utf8 = new TextEncoder();
170
179
  const toObjectName = (key) => key.replace(ESCAPED_CHARACTER, (character) => Array.from(utf8.encode(character), (byte) => `!${byte.toString(16).toUpperCase().padStart(2, "0")}`).join(""));
171
180
  const supabaseStorage = (config) => {
172
181
  let client;
173
- const bucket = () => (client ??= createClient(config.supabaseUrl, resolveSupabaseServiceRoleKey(config))).storage.from(config.bucketName);
182
+ const bucket = async () => (await (client ??= resolveSupabaseServiceRoleKey(config).then((key) => createClient(config.supabaseUrl, key), (error) => {
183
+ client = void 0;
184
+ throw error;
185
+ }))).storage.from(config.bucketName);
174
186
  const getStorageKey = createStorageKeyBuilder(config.basePath);
175
187
  const resolveSignedUrl = createSupabaseSignedUrlBatcher({
176
- createSignedUrls: (_bucketName, keys, expiresIn) => bucket().createSignedUrls(keys, expiresIn),
188
+ createSignedUrls: async (_bucketName, keys, expiresIn) => (await bucket()).createSignedUrls(keys, expiresIn),
177
189
  expiresIn: config.signedUrlExpiresIn ?? 3600,
178
190
  formatObjectPath: (_bucketName, key) => key
179
191
  });
@@ -187,7 +199,7 @@ const supabaseStorage = (config) => {
187
199
  protocol: "supabase-storage",
188
200
  async put({ key, body, contentLength, contentType }) {
189
201
  const storageKey = getStorageKey(key);
190
- const { error } = await bucket().upload(toObjectName(storageKey), body, {
202
+ const { error } = await (await bucket()).upload(toObjectName(storageKey), body, {
191
203
  contentType,
192
204
  cacheControl: "max-age=31536000",
193
205
  upsert: true,
@@ -203,7 +215,7 @@ const supabaseStorage = (config) => {
203
215
  },
204
216
  async get({ storageUri }) {
205
217
  const { key } = parseAndValidate(storageUri);
206
- const { data, error } = await bucket().download(toObjectName(key));
218
+ const { data, error } = await (await bucket()).download(toObjectName(key));
207
219
  if (error) {
208
220
  if (await isMissingObjectError(error)) return { response: null };
209
221
  throw new Error(`Failed to download storage object: ${error.message}`);
@@ -216,7 +228,7 @@ const supabaseStorage = (config) => {
216
228
  },
217
229
  async exists({ storageUri }) {
218
230
  const { key } = parseAndValidate(storageUri);
219
- const { data, error } = await bucket().exists(toObjectName(key));
231
+ const { data, error } = await (await bucket()).exists(toObjectName(key));
220
232
  if (error) {
221
233
  if (isMissingExistsError(error)) return { exists: false };
222
234
  throw error;
@@ -225,7 +237,7 @@ const supabaseStorage = (config) => {
225
237
  },
226
238
  async delete({ storageUri }) {
227
239
  const { key } = parseAndValidate(storageUri);
228
- const { error } = await bucket().remove([toObjectName(key)]);
240
+ const { error } = await (await bucket()).remove([toObjectName(key)]);
229
241
  if (error && !isNotFoundError(error)) throw new Error(`Failed to delete storage object: ${error.message}`);
230
242
  return { deleted: true };
231
243
  }
@@ -2,7 +2,12 @@ import { EngineDatabase, StorageAdapterWith } from "@hot-updater/plugin-core";
2
2
  //#region src/supabaseConfig.d.ts
3
3
  type SupabaseServiceRoleConfig = {
4
4
  supabaseUrl: string;
5
- supabaseServiceRoleKey: string;
5
+ /**
6
+ * The project's service role key, or a function that returns it, such as
7
+ * one that reads it with `secretEnv`: called on the first request, so a
8
+ * config loads without the key.
9
+ */
10
+ supabaseServiceRoleKey: string | (() => string | Promise<string>);
6
11
  };
7
12
  //#endregion
8
13
  //#region src/supabaseDatabase.d.ts
@@ -2,7 +2,12 @@ import { EngineDatabase, StorageAdapterWith } from "@hot-updater/plugin-core";
2
2
  //#region src/supabaseConfig.d.ts
3
3
  type SupabaseServiceRoleConfig = {
4
4
  supabaseUrl: string;
5
- supabaseServiceRoleKey: string;
5
+ /**
6
+ * The project's service role key, or a function that returns it, such as
7
+ * one that reads it with `secretEnv`: called on the first request, so a
8
+ * config loads without the key.
9
+ */
10
+ supabaseServiceRoleKey: string | (() => string | Promise<string>);
6
11
  };
7
12
  //#endregion
8
13
  //#region src/supabaseDatabase.d.ts
@@ -1,9 +1,11 @@
1
1
  let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
2
2
  let _supabase_supabase_js = require("@supabase/supabase-js");
3
3
  //#region src/supabaseConfig.ts
4
- const resolveSupabaseServiceRoleKey = (config) => {
5
- if (!config.supabaseServiceRoleKey) throw new Error("Supabase service role key is required. Set supabaseServiceRoleKey.");
6
- return config.supabaseServiceRoleKey;
4
+ const resolveSupabaseServiceRoleKey = async (config) => {
5
+ const { supabaseServiceRoleKey } = config;
6
+ const key = typeof supabaseServiceRoleKey === "function" ? await supabaseServiceRoleKey() : supabaseServiceRoleKey;
7
+ if (!key) throw new Error("Supabase service role key is required. Set supabaseServiceRoleKey.");
8
+ return key;
7
9
  };
8
10
  //#endregion
9
11
  //#region src/supabaseInfrastructureNames.ts
@@ -42,9 +44,16 @@ const withCode = (error) => Object.assign(new Error(error.message, { cause: erro
42
44
  */
43
45
  const supabaseExecutor = (client) => {
44
46
  let created;
45
- const clientOf = () => typeof client === "function" ? created ??= client() : client;
47
+ const clientOf = async () => {
48
+ if (typeof client !== "function") return client;
49
+ created ??= Promise.resolve().then(client).catch((error) => {
50
+ created = void 0;
51
+ throw error;
52
+ });
53
+ return created;
54
+ };
46
55
  const apply = async (statements) => {
47
- const { data, error } = await clientOf().rpc(SUPABASE_APPLY_FUNCTION, { p_statements: statements.map(toApplyStatement) });
56
+ const { data, error } = await (await clientOf()).rpc(SUPABASE_APPLY_FUNCTION, { p_statements: statements.map(toApplyStatement) });
48
57
  if (error) throw withCode(error);
49
58
  return data;
50
59
  };
@@ -67,7 +76,7 @@ const supabaseExecutor = (client) => {
67
76
  */
68
77
  const supabaseDatabase = (config) => {
69
78
  const { migrations: _migrations, ...adapter } = (0, _hot_updater_plugin_core.createSqlAdapter)({
70
- executor: supabaseExecutor(() => (0, _supabase_supabase_js.createClient)(config.supabaseUrl, resolveSupabaseServiceRoleKey(config))),
79
+ executor: supabaseExecutor(async () => (0, _supabase_supabase_js.createClient)(config.supabaseUrl, await resolveSupabaseServiceRoleKey(config))),
71
80
  tablePrefix: SUPABASE_TABLE_PREFIX
72
81
  });
73
82
  return (0, _hot_updater_plugin_core.createEngineDatabase)({
@@ -170,10 +179,13 @@ const utf8 = new TextEncoder();
170
179
  const toObjectName = (key) => key.replace(ESCAPED_CHARACTER, (character) => Array.from(utf8.encode(character), (byte) => `!${byte.toString(16).toUpperCase().padStart(2, "0")}`).join(""));
171
180
  const supabaseStorage = (config) => {
172
181
  let client;
173
- const bucket = () => (client ??= (0, _supabase_supabase_js.createClient)(config.supabaseUrl, resolveSupabaseServiceRoleKey(config))).storage.from(config.bucketName);
182
+ const bucket = async () => (await (client ??= resolveSupabaseServiceRoleKey(config).then((key) => (0, _supabase_supabase_js.createClient)(config.supabaseUrl, key), (error) => {
183
+ client = void 0;
184
+ throw error;
185
+ }))).storage.from(config.bucketName);
174
186
  const getStorageKey = (0, _hot_updater_plugin_core.createStorageKeyBuilder)(config.basePath);
175
187
  const resolveSignedUrl = createSupabaseSignedUrlBatcher({
176
- createSignedUrls: (_bucketName, keys, expiresIn) => bucket().createSignedUrls(keys, expiresIn),
188
+ createSignedUrls: async (_bucketName, keys, expiresIn) => (await bucket()).createSignedUrls(keys, expiresIn),
177
189
  expiresIn: config.signedUrlExpiresIn ?? 3600,
178
190
  formatObjectPath: (_bucketName, key) => key
179
191
  });
@@ -187,7 +199,7 @@ const supabaseStorage = (config) => {
187
199
  protocol: "supabase-storage",
188
200
  async put({ key, body, contentLength, contentType }) {
189
201
  const storageKey = getStorageKey(key);
190
- const { error } = await bucket().upload(toObjectName(storageKey), body, {
202
+ const { error } = await (await bucket()).upload(toObjectName(storageKey), body, {
191
203
  contentType,
192
204
  cacheControl: "max-age=31536000",
193
205
  upsert: true,
@@ -203,7 +215,7 @@ const supabaseStorage = (config) => {
203
215
  },
204
216
  async get({ storageUri }) {
205
217
  const { key } = parseAndValidate(storageUri);
206
- const { data, error } = await bucket().download(toObjectName(key));
218
+ const { data, error } = await (await bucket()).download(toObjectName(key));
207
219
  if (error) {
208
220
  if (await isMissingObjectError(error)) return { response: null };
209
221
  throw new Error(`Failed to download storage object: ${error.message}`);
@@ -216,7 +228,7 @@ const supabaseStorage = (config) => {
216
228
  },
217
229
  async exists({ storageUri }) {
218
230
  const { key } = parseAndValidate(storageUri);
219
- const { data, error } = await bucket().exists(toObjectName(key));
231
+ const { data, error } = await (await bucket()).exists(toObjectName(key));
220
232
  if (error) {
221
233
  if (isMissingExistsError(error)) return { exists: false };
222
234
  throw error;
@@ -225,7 +237,7 @@ const supabaseStorage = (config) => {
225
237
  },
226
238
  async delete({ storageUri }) {
227
239
  const { key } = parseAndValidate(storageUri);
228
- const { error } = await bucket().remove([toObjectName(key)]);
240
+ const { error } = await (await bucket()).remove([toObjectName(key)]);
229
241
  if (error && !isNotFoundError(error)) throw new Error(`Failed to delete storage object: ${error.message}`);
230
242
  return { deleted: true };
231
243
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@hot-updater/supabase",
3
3
  "type": "module",
4
- "version": "1.2.0-rc.4",
4
+ "version": "1.2.0-rc.6",
5
5
  "description": "React Native OTA solution for self-hosted",
6
6
  "main": "dist/index.cjs",
7
7
  "module": "dist/index.mjs",
@@ -51,10 +51,10 @@
51
51
  "@supabase/supabase-js": "2.76.1",
52
52
  "hono": "4.12.34",
53
53
  "uuidv7": "^1.0.2",
54
- "@hot-updater/plugin-core": "1.2.0-rc.4",
55
- "@hot-updater/cli-tools": "1.2.0-rc.4",
56
- "@hot-updater/server": "1.2.0-rc.4",
57
- "@hot-updater/protocol": "1.2.0-rc.4"
54
+ "@hot-updater/protocol": "1.2.0-rc.6",
55
+ "@hot-updater/plugin-core": "1.2.0-rc.6",
56
+ "@hot-updater/cli-tools": "1.2.0-rc.6",
57
+ "@hot-updater/server": "1.2.0-rc.6"
58
58
  },
59
59
  "devDependencies": {
60
60
  "@electric-sql/pglite": "0.4.1",
@@ -64,9 +64,9 @@
64
64
  "execa": "9.5.2",
65
65
  "@types/node": "^20",
66
66
  "mime": "^4.0.4",
67
- "@hot-updater/mock": "1.2.0-rc.4",
68
- "@hot-updater/test-utils": "1.2.0-rc.4",
69
- "@hot-updater/postgres": "1.2.0-rc.4"
67
+ "@hot-updater/mock": "1.2.0-rc.6",
68
+ "@hot-updater/test-utils": "1.2.0-rc.6",
69
+ "@hot-updater/postgres": "1.2.0-rc.6"
70
70
  },
71
71
  "scripts": {
72
72
  "build": "tsdown",