@hot-updater/cloudflare 0.31.4 → 0.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -6,7 +6,7 @@ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
6
6
  var __getOwnPropNames = Object.getOwnPropertyNames;
7
7
  var __getProtoOf = Object.getPrototypeOf;
8
8
  var __hasOwnProp = Object.prototype.hasOwnProperty;
9
- var __commonJSMin = (cb, mod) => () => (mod || (cb((mod = { exports: {} }).exports, mod), cb = null), mod.exports);
9
+ var __commonJSMin = (cb, mod) => () => (mod || cb((mod = { exports: {} }).exports, mod), mod.exports);
10
10
  var __copyProps = (to, from, except, desc) => {
11
11
  if (from && typeof from === "object" || typeof from === "function") for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
12
12
  key = keys[i];
@@ -25,21 +25,25 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
25
25
  let _hot_updater_core = require("@hot-updater/core");
26
26
  let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
27
27
  let cloudflare = require("cloudflare");
28
- cloudflare = __toESM(cloudflare, 1);
28
+ cloudflare = __toESM(cloudflare);
29
29
  let node_fs_promises = require("node:fs/promises");
30
- node_fs_promises = __toESM(node_fs_promises, 1);
30
+ node_fs_promises = __toESM(node_fs_promises);
31
31
  let node_path = require("node:path");
32
- node_path = __toESM(node_path, 1);
32
+ node_path = __toESM(node_path);
33
+ let _aws_sdk_client_s3 = require("@aws-sdk/client-s3");
34
+ let _aws_sdk_lib_storage = require("@aws-sdk/lib-storage");
35
+ let _aws_sdk_s3_request_presigner = require("@aws-sdk/s3-request-presigner");
36
+ let node_os = require("node:os");
37
+ node_os = __toESM(node_os);
33
38
  let node_url = require("node:url");
34
39
  let node_child_process = require("node:child_process");
35
40
  let node_string_decoder = require("node:string_decoder");
36
41
  let node_util = require("node:util");
37
42
  let node_process = require("node:process");
38
- node_process = __toESM(node_process, 1);
43
+ node_process = __toESM(node_process);
39
44
  let node_tty = require("node:tty");
40
- node_tty = __toESM(node_tty, 1);
45
+ node_tty = __toESM(node_tty);
41
46
  let node_timers_promises = require("node:timers/promises");
42
- let node_os = require("node:os");
43
47
  let node_events = require("node:events");
44
48
  let node_v8 = require("node:v8");
45
49
  let node_fs = require("node:fs");
@@ -277,6 +281,11 @@ var import_lib = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((export
277
281
  parser.parsingErrorCode = error.parsingErrorCode;
278
282
  module.exports = parser;
279
283
  })))(), 1);
284
+ const buildJsonEachInClause = (columnName, values, params) => {
285
+ if (values.length === 0) return "1 = 0";
286
+ params.push(JSON.stringify(values));
287
+ return `${columnName} IN (SELECT value FROM json_each(?))`;
288
+ };
280
289
  async function resolvePage(singlePage) {
281
290
  const results = [];
282
291
  for await (const page of singlePage.iterPages()) {
@@ -300,11 +309,7 @@ function buildWhereClause(conditions) {
300
309
  clauses.push("enabled = ?");
301
310
  params.push(conditions.enabled ? 1 : 0);
302
311
  }
303
- if (conditions.id?.in) if (conditions.id.in.length === 0) clauses.push("1 = 0");
304
- else {
305
- clauses.push(`id IN (${conditions.id.in.map(() => "?").join(", ")})`);
306
- params.push(...conditions.id.in);
307
- }
312
+ if (conditions.id?.in) clauses.push(buildJsonEachInClause("id", conditions.id.in, params));
308
313
  if (conditions.id?.eq) {
309
314
  clauses.push("id = ?");
310
315
  params.push(conditions.id.eq);
@@ -331,11 +336,7 @@ function buildWhereClause(conditions) {
331
336
  clauses.push("target_app_version = ?");
332
337
  params.push(conditions.targetAppVersion);
333
338
  }
334
- if (conditions.targetAppVersionIn) if (conditions.targetAppVersionIn.length === 0) clauses.push("1 = 0");
335
- else {
336
- clauses.push(`target_app_version IN (${conditions.targetAppVersionIn.map(() => "?").join(", ")})`);
337
- params.push(...conditions.targetAppVersionIn);
338
- }
339
+ if (conditions.targetAppVersionIn) clauses.push(buildJsonEachInClause("target_app_version", conditions.targetAppVersionIn, params));
339
340
  if (conditions.fingerprintHash !== void 0) if (conditions.fingerprintHash === null) clauses.push("fingerprint_hash IS NULL");
340
341
  else {
341
342
  clauses.push("fingerprint_hash = ?");
@@ -420,13 +421,13 @@ const d1Database = (0, _hot_updater_plugin_core.createDatabasePlugin)({
420
421
  const sql = (0, import_lib.default)(`
421
422
  SELECT *
422
423
  FROM bundle_patches
423
- WHERE bundle_id IN (${bundleIds.map(() => "?").join(", ")})
424
+ WHERE bundle_id IN (SELECT value FROM json_each(?))
424
425
  ORDER BY order_index ASC, base_bundle_id ASC
425
426
  `);
426
427
  const rows = await resolvePage(await cf.d1.database.query(config.databaseId, {
427
428
  account_id: config.accountId,
428
429
  sql,
429
- params: bundleIds
430
+ params: [JSON.stringify(bundleIds)]
430
431
  }));
431
432
  for (const row of rows) {
432
433
  const current = patchMap.get(row.bundle_id) ?? [];
@@ -669,6 +670,112 @@ const d1Database = (0, _hot_updater_plugin_core.createDatabasePlugin)({
669
670
  }
670
671
  });
671
672
  //#endregion
673
+ //#region src/r2S3Storage.ts
674
+ const ensureExpectedR2Bucket$1 = (bucket, bucketName) => {
675
+ if (bucket !== bucketName) throw new Error(`Bucket name mismatch: expected "${bucketName}", but found "${bucket}".`);
676
+ };
677
+ const isS3ObjectNotFoundError = (error) => {
678
+ if (error instanceof Error) return error.name === "NotFound" || error.name === "NoSuchKey";
679
+ if (typeof error === "object" && error !== null && "$metadata" in error) return error.$metadata?.httpStatusCode === 404;
680
+ return false;
681
+ };
682
+ const createS3Client = (config) => {
683
+ const { accountId, basePath: _basePath, bucketName: _bucketName, endpoint, forcePathStyle, region, ...s3Config } = config;
684
+ return new _aws_sdk_client_s3.S3Client({
685
+ ...s3Config,
686
+ endpoint: endpoint ?? `https://${accountId}.r2.cloudflarestorage.com`,
687
+ forcePathStyle: forcePathStyle ?? true,
688
+ region: region ?? "auto"
689
+ });
690
+ };
691
+ const createS3StorageProfile = (config) => {
692
+ const { bucketName } = config;
693
+ const client = createS3Client(config);
694
+ const getStorageKey = (0, _hot_updater_plugin_core.createStorageKeyBuilder)(config.basePath);
695
+ return {
696
+ async delete(storageUri) {
697
+ const { bucket, key } = (0, _hot_updater_plugin_core.parseStorageUri)(storageUri, "r2");
698
+ ensureExpectedR2Bucket$1(bucket, bucketName);
699
+ await client.send(new _aws_sdk_client_s3.DeleteObjectCommand({
700
+ Bucket: bucketName,
701
+ Key: key
702
+ }));
703
+ },
704
+ async upload(key, filePath) {
705
+ const Body = await node_fs_promises.default.readFile(filePath);
706
+ const ContentType = (0, _hot_updater_plugin_core.getContentType)(filePath);
707
+ const Key = getStorageKey(key, node_path.default.basename(filePath));
708
+ await new _aws_sdk_lib_storage.Upload({
709
+ client,
710
+ params: {
711
+ Body,
712
+ Bucket: bucketName,
713
+ CacheControl: "max-age=31536000",
714
+ ContentType,
715
+ Key
716
+ }
717
+ }).done();
718
+ return { storageUri: `r2://${bucketName}/${Key}` };
719
+ },
720
+ async exists(storageUri) {
721
+ const { bucket, key } = (0, _hot_updater_plugin_core.parseStorageUri)(storageUri, "r2");
722
+ ensureExpectedR2Bucket$1(bucket, bucketName);
723
+ try {
724
+ await client.send(new _aws_sdk_client_s3.HeadObjectCommand({
725
+ Bucket: bucketName,
726
+ Key: key
727
+ }));
728
+ return true;
729
+ } catch (error) {
730
+ if (isS3ObjectNotFoundError(error)) return false;
731
+ throw error;
732
+ }
733
+ },
734
+ async downloadFile(storageUri, filePath) {
735
+ const { bucket, key } = (0, _hot_updater_plugin_core.parseStorageUri)(storageUri, "r2");
736
+ ensureExpectedR2Bucket$1(bucket, bucketName);
737
+ const response = await client.send(new _aws_sdk_client_s3.GetObjectCommand({
738
+ Bucket: bucketName,
739
+ Key: key
740
+ }));
741
+ if (!response.Body) throw new Error("R2 object body is empty");
742
+ await node_fs_promises.default.mkdir(node_path.default.dirname(filePath), { recursive: true });
743
+ await node_fs_promises.default.writeFile(filePath, await response.Body.transformToByteArray());
744
+ }
745
+ };
746
+ };
747
+ const createS3RuntimeStorageProfile = (config) => {
748
+ const { bucketName } = config;
749
+ const client = createS3Client(config);
750
+ return {
751
+ async readText(storageUri) {
752
+ const { bucket, key } = (0, _hot_updater_plugin_core.parseStorageUri)(storageUri, "r2");
753
+ ensureExpectedR2Bucket$1(bucket, bucketName);
754
+ try {
755
+ const response = await client.send(new _aws_sdk_client_s3.GetObjectCommand({
756
+ Bucket: bucketName,
757
+ Key: key
758
+ }));
759
+ if (!response.Body) return null;
760
+ return response.Body.transformToString();
761
+ } catch (error) {
762
+ if (isS3ObjectNotFoundError(error)) return null;
763
+ throw error;
764
+ }
765
+ },
766
+ async getDownloadUrl(storageUri) {
767
+ const { bucket, key } = (0, _hot_updater_plugin_core.parseStorageUri)(storageUri, "r2");
768
+ ensureExpectedR2Bucket$1(bucket, bucketName);
769
+ const signedUrl = await (0, _aws_sdk_s3_request_presigner.getSignedUrl)(client, new _aws_sdk_client_s3.GetObjectCommand({
770
+ Bucket: bucketName,
771
+ Key: key
772
+ }), { expiresIn: 3600 });
773
+ if (!signedUrl) throw new Error("Failed to presign R2 URL");
774
+ return { fileUrl: signedUrl };
775
+ }
776
+ };
777
+ };
778
+ //#endregion
672
779
  //#region ../../node_modules/.pnpm/is-plain-obj@4.1.0/node_modules/is-plain-obj/index.js
673
780
  function isPlainObject(value) {
674
781
  if (typeof value !== "object" || value === null) return false;
@@ -6842,55 +6949,108 @@ const createWrangler = ({ stdio, accountId, cloudflareApiToken, cwd }) => {
6842
6949
  return (...command) => $("npx", ["wrangler", ...command]);
6843
6950
  };
6844
6951
  //#endregion
6952
+ //#region src/r2WranglerStorage.ts
6953
+ const ensureExpectedR2Bucket = (bucket, bucketName) => {
6954
+ if (bucket !== bucketName) throw new Error(`Bucket name mismatch: expected "${bucketName}", but found "${bucket}".`);
6955
+ };
6956
+ const isR2ObjectNotFoundError = (error) => {
6957
+ const output = [
6958
+ error.stderr,
6959
+ error.stdout,
6960
+ error.shortMessage,
6961
+ error.message
6962
+ ].filter(Boolean).join("\n").toLowerCase();
6963
+ return output.includes("not found") || output.includes("no such object") || output.includes("does not exist");
6964
+ };
6965
+ const createWranglerStorageProfile = (config) => {
6966
+ const { bucketName, cloudflareApiToken, accountId } = config;
6967
+ const wrangler = createWrangler({
6968
+ accountId,
6969
+ cloudflareApiToken,
6970
+ cwd: process.cwd()
6971
+ });
6972
+ const getStorageKey = (0, _hot_updater_plugin_core.createStorageKeyBuilder)(config.basePath);
6973
+ return {
6974
+ async delete(storageUri) {
6975
+ const { bucket, key } = (0, _hot_updater_plugin_core.parseStorageUri)(storageUri, "r2");
6976
+ ensureExpectedR2Bucket(bucket, bucketName);
6977
+ try {
6978
+ await wrangler("r2", "object", "delete", [bucketName, key].join("/"), "--remote");
6979
+ } catch {
6980
+ throw new Error("Can not delete bundle");
6981
+ }
6982
+ },
6983
+ async upload(key, filePath) {
6984
+ const contentType = (0, _hot_updater_plugin_core.getContentType)(filePath);
6985
+ const Key = getStorageKey(key, node_path.default.basename(filePath));
6986
+ try {
6987
+ const { stderr, exitCode } = await wrangler("r2", "object", "put", [bucketName, Key].join("/"), "--file", filePath, "--content-type", contentType, "--remote");
6988
+ if (exitCode !== 0 && stderr) throw new Error(stderr);
6989
+ } catch (error) {
6990
+ if (error instanceof ExecaError) throw new Error(error.stderr || error.stdout);
6991
+ throw error;
6992
+ }
6993
+ return { storageUri: `r2://${bucketName}/${Key}` };
6994
+ },
6995
+ async exists(storageUri) {
6996
+ const { bucket, key } = (0, _hot_updater_plugin_core.parseStorageUri)(storageUri, "r2");
6997
+ ensureExpectedR2Bucket(bucket, bucketName);
6998
+ const tempDir = await node_fs_promises.default.mkdtemp(node_path.default.join(node_os.default.tmpdir(), "hot-updater-r2-exists-"));
6999
+ const tempFilePath = node_path.default.join(tempDir, "object");
7000
+ try {
7001
+ await wrangler("r2", "object", "get", [bucketName, key].join("/"), "--file", tempFilePath, "--remote");
7002
+ return true;
7003
+ } catch (error) {
7004
+ if (error instanceof ExecaError && isR2ObjectNotFoundError(error)) return false;
7005
+ throw error;
7006
+ } finally {
7007
+ await node_fs_promises.default.rm(tempDir, {
7008
+ force: true,
7009
+ recursive: true
7010
+ });
7011
+ }
7012
+ },
7013
+ async downloadFile(storageUri, filePath) {
7014
+ const { bucket, key } = (0, _hot_updater_plugin_core.parseStorageUri)(storageUri, "r2");
7015
+ ensureExpectedR2Bucket(bucket, bucketName);
7016
+ try {
7017
+ await node_fs_promises.default.mkdir(node_path.default.dirname(filePath), { recursive: true });
7018
+ const { stderr, exitCode } = await wrangler("r2", "object", "get", [bucketName, key].join("/"), "--file", filePath, "--remote");
7019
+ if (exitCode !== 0 && stderr) throw new Error(stderr);
7020
+ } catch (error) {
7021
+ if (error instanceof ExecaError) throw new Error(error.stderr || error.stdout);
7022
+ throw error;
7023
+ }
7024
+ }
7025
+ };
7026
+ };
7027
+ const createWranglerRuntimeStorageProfile = () => {
7028
+ const error = /* @__PURE__ */ new Error("r2Storage runtime profile requires R2 S3 credentials. Wrangler-based R2 access is only supported by the node profile.");
7029
+ return {
7030
+ async readText() {
7031
+ throw error;
7032
+ },
7033
+ async getDownloadUrl() {
7034
+ throw error;
7035
+ }
7036
+ };
7037
+ };
7038
+ //#endregion
6845
7039
  //#region src/r2Storage.ts
6846
- /**
6847
- * Cloudflare R2 storage plugin for Hot Updater.
6848
- */
6849
- const r2Storage = (0, _hot_updater_plugin_core.createNodeStoragePlugin)({
7040
+ const hasS3Credentials = (config) => {
7041
+ return Boolean(config.credentials);
7042
+ };
7043
+ const r2Storage = (0, _hot_updater_plugin_core.createUniversalStoragePlugin)({
6850
7044
  name: "r2Storage",
6851
7045
  supportedProtocol: "r2",
6852
7046
  factory: (config) => {
6853
- const { bucketName, cloudflareApiToken, accountId } = config;
6854
- const wrangler = createWrangler({
6855
- accountId,
6856
- cloudflareApiToken,
6857
- cwd: process.cwd()
6858
- });
6859
- const getStorageKey = (0, _hot_updater_plugin_core.createStorageKeyBuilder)(config.basePath);
7047
+ if (hasS3Credentials(config)) return {
7048
+ node: createS3StorageProfile(config),
7049
+ runtime: createS3RuntimeStorageProfile(config)
7050
+ };
6860
7051
  return {
6861
- async delete(storageUri) {
6862
- const { bucket, key } = (0, _hot_updater_plugin_core.parseStorageUri)(storageUri, "r2");
6863
- if (bucket !== bucketName) throw new Error(`Bucket name mismatch: expected "${bucketName}", but found "${bucket}".`);
6864
- try {
6865
- await wrangler("r2", "object", "delete", [bucketName, key].join("/"), "--remote");
6866
- } catch {
6867
- throw new Error("Can not delete bundle");
6868
- }
6869
- },
6870
- async upload(key, filePath) {
6871
- const contentType = (0, _hot_updater_plugin_core.getContentType)(filePath);
6872
- const Key = getStorageKey(key, node_path.default.basename(filePath));
6873
- try {
6874
- const { stderr, exitCode } = await wrangler("r2", "object", "put", [bucketName, Key].join("/"), "--file", filePath, "--content-type", contentType, "--remote");
6875
- if (exitCode !== 0 && stderr) throw new Error(stderr);
6876
- } catch (error) {
6877
- if (error instanceof ExecaError) throw new Error(error.stderr || error.stdout);
6878
- throw error;
6879
- }
6880
- return { storageUri: `r2://${bucketName}/${Key}` };
6881
- },
6882
- async downloadFile(storageUri, filePath) {
6883
- const { bucket, key } = (0, _hot_updater_plugin_core.parseStorageUri)(storageUri, "r2");
6884
- if (bucket !== bucketName) throw new Error(`Bucket name mismatch: expected "${bucketName}", but found "${bucket}".`);
6885
- try {
6886
- await node_fs_promises.default.mkdir(node_path.default.dirname(filePath), { recursive: true });
6887
- const { stderr, exitCode } = await wrangler("r2", "object", "get", [bucketName, key].join("/"), "--file", filePath, "--remote");
6888
- if (exitCode !== 0 && stderr) throw new Error(stderr);
6889
- } catch (error) {
6890
- if (error instanceof ExecaError) throw new Error(error.stderr || error.stdout);
6891
- throw error;
6892
- }
6893
- }
7052
+ node: createWranglerStorageProfile(config),
7053
+ runtime: createWranglerRuntimeStorageProfile()
6894
7054
  };
6895
7055
  }
6896
7056
  });
package/dist/index.d.cts CHANGED
@@ -1,24 +1,64 @@
1
+ import * as _$_hot_updater_plugin_core0 from "@hot-updater/plugin-core";
2
+ import { StoragePluginHooks, UniversalStoragePlugin } from "@hot-updater/plugin-core";
3
+ import { S3ClientConfig } from "@aws-sdk/client-s3";
4
+
1
5
  //#region src/d1Database.d.ts
2
6
  interface D1DatabaseConfig {
3
7
  databaseId: string;
4
8
  accountId: string;
5
9
  cloudflareApiToken: string;
6
10
  }
7
- declare const d1Database: (config: D1DatabaseConfig, hooks?: import("@hot-updater/plugin-core").DatabasePluginHooks) => () => import("@hot-updater/plugin-core").DatabasePlugin<unknown>;
11
+ declare const d1Database: (config: D1DatabaseConfig, hooks?: _$_hot_updater_plugin_core0.DatabasePluginHooks) => () => _$_hot_updater_plugin_core0.DatabasePlugin<unknown>;
8
12
  //#endregion
9
- //#region src/r2Storage.d.ts
10
- interface R2StorageConfig {
11
- cloudflareApiToken: string;
13
+ //#region src/r2S3Storage.d.ts
14
+ interface R2S3StorageConfig extends S3ClientConfig {
15
+ accountId: string;
16
+ bucketName: string;
17
+ credentials: NonNullable<S3ClientConfig["credentials"]>;
18
+ /**
19
+ * Base path where bundles will be stored in the bucket
20
+ */
21
+ basePath?: string;
22
+ }
23
+ //#endregion
24
+ //#region src/r2WranglerStorage.d.ts
25
+ /**
26
+ * @deprecated `cloudflareApiToken` uses the Wrangler CLI for R2 operations,
27
+ * which is slower than direct S3-compatible API access. Create R2
28
+ * S3-compatible credentials in the Cloudflare dashboard and pass them with
29
+ * `r2Storage({ credentials })` instead.
30
+ */
31
+ interface R2WranglerStorageConfig {
12
32
  accountId: string;
13
33
  bucketName: string;
34
+ /**
35
+ * @deprecated This token keeps R2 access on the slower Wrangler CLI path.
36
+ * Create R2 S3-compatible credentials in the Cloudflare dashboard and use
37
+ * `credentials` instead.
38
+ */
39
+ cloudflareApiToken: string;
14
40
  /**
15
41
  * Base path where bundles will be stored in the bucket
16
42
  */
17
43
  basePath?: string;
44
+ credentials?: never;
18
45
  }
46
+ //#endregion
47
+ //#region src/r2Storage.d.ts
48
+ type R2StorageConfig = R2S3StorageConfig | R2WranglerStorageConfig;
19
49
  /**
20
50
  * Cloudflare R2 storage plugin for Hot Updater.
21
51
  */
22
- declare const r2Storage: (config: R2StorageConfig, hooks?: import("@hot-updater/plugin-core").StoragePluginHooks) => () => import("@hot-updater/plugin-core").NodeStoragePlugin;
52
+ interface R2Storage {
53
+ (config: R2S3StorageConfig, hooks?: StoragePluginHooks): () => UniversalStoragePlugin;
54
+ /**
55
+ * @deprecated `cloudflareApiToken` uses the Wrangler CLI for R2 operations,
56
+ * which is slower than direct S3-compatible API access. Create R2
57
+ * S3-compatible credentials in the Cloudflare dashboard and pass them with
58
+ * `r2Storage({ credentials })` instead.
59
+ */
60
+ (config: R2WranglerStorageConfig, hooks?: StoragePluginHooks): () => UniversalStoragePlugin;
61
+ }
62
+ declare const r2Storage: R2Storage;
23
63
  //#endregion
24
- export { D1DatabaseConfig, R2StorageConfig, d1Database, r2Storage };
64
+ export { D1DatabaseConfig, type R2S3StorageConfig, R2StorageConfig, type R2WranglerStorageConfig, d1Database, r2Storage };
package/dist/index.d.mts CHANGED
@@ -1,24 +1,64 @@
1
+ import * as _$_hot_updater_plugin_core0 from "@hot-updater/plugin-core";
2
+ import { StoragePluginHooks, UniversalStoragePlugin } from "@hot-updater/plugin-core";
3
+ import { S3ClientConfig } from "@aws-sdk/client-s3";
4
+
1
5
  //#region src/d1Database.d.ts
2
6
  interface D1DatabaseConfig {
3
7
  databaseId: string;
4
8
  accountId: string;
5
9
  cloudflareApiToken: string;
6
10
  }
7
- declare const d1Database: (config: D1DatabaseConfig, hooks?: import("@hot-updater/plugin-core").DatabasePluginHooks) => () => import("@hot-updater/plugin-core").DatabasePlugin<unknown>;
11
+ declare const d1Database: (config: D1DatabaseConfig, hooks?: _$_hot_updater_plugin_core0.DatabasePluginHooks) => () => _$_hot_updater_plugin_core0.DatabasePlugin<unknown>;
8
12
  //#endregion
9
- //#region src/r2Storage.d.ts
10
- interface R2StorageConfig {
11
- cloudflareApiToken: string;
13
+ //#region src/r2S3Storage.d.ts
14
+ interface R2S3StorageConfig extends S3ClientConfig {
15
+ accountId: string;
16
+ bucketName: string;
17
+ credentials: NonNullable<S3ClientConfig["credentials"]>;
18
+ /**
19
+ * Base path where bundles will be stored in the bucket
20
+ */
21
+ basePath?: string;
22
+ }
23
+ //#endregion
24
+ //#region src/r2WranglerStorage.d.ts
25
+ /**
26
+ * @deprecated `cloudflareApiToken` uses the Wrangler CLI for R2 operations,
27
+ * which is slower than direct S3-compatible API access. Create R2
28
+ * S3-compatible credentials in the Cloudflare dashboard and pass them with
29
+ * `r2Storage({ credentials })` instead.
30
+ */
31
+ interface R2WranglerStorageConfig {
12
32
  accountId: string;
13
33
  bucketName: string;
34
+ /**
35
+ * @deprecated This token keeps R2 access on the slower Wrangler CLI path.
36
+ * Create R2 S3-compatible credentials in the Cloudflare dashboard and use
37
+ * `credentials` instead.
38
+ */
39
+ cloudflareApiToken: string;
14
40
  /**
15
41
  * Base path where bundles will be stored in the bucket
16
42
  */
17
43
  basePath?: string;
44
+ credentials?: never;
18
45
  }
46
+ //#endregion
47
+ //#region src/r2Storage.d.ts
48
+ type R2StorageConfig = R2S3StorageConfig | R2WranglerStorageConfig;
19
49
  /**
20
50
  * Cloudflare R2 storage plugin for Hot Updater.
21
51
  */
22
- declare const r2Storage: (config: R2StorageConfig, hooks?: import("@hot-updater/plugin-core").StoragePluginHooks) => () => import("@hot-updater/plugin-core").NodeStoragePlugin;
52
+ interface R2Storage {
53
+ (config: R2S3StorageConfig, hooks?: StoragePluginHooks): () => UniversalStoragePlugin;
54
+ /**
55
+ * @deprecated `cloudflareApiToken` uses the Wrangler CLI for R2 operations,
56
+ * which is slower than direct S3-compatible API access. Create R2
57
+ * S3-compatible credentials in the Cloudflare dashboard and pass them with
58
+ * `r2Storage({ credentials })` instead.
59
+ */
60
+ (config: R2WranglerStorageConfig, hooks?: StoragePluginHooks): () => UniversalStoragePlugin;
61
+ }
62
+ declare const r2Storage: R2Storage;
23
63
  //#endregion
24
- export { D1DatabaseConfig, R2StorageConfig, d1Database, r2Storage };
64
+ export { D1DatabaseConfig, type R2S3StorageConfig, R2StorageConfig, type R2WranglerStorageConfig, d1Database, r2Storage };