@hot-updater/aws 0.29.2 → 0.29.4

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.
@@ -22,6 +22,8 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
22
22
  enumerable: true
23
23
  }) : target, mod));
24
24
  //#endregion
25
+ let fs = require("fs");
26
+ fs = __toESM(fs);
25
27
  let _aws_sdk_credential_providers = require("@aws-sdk/credential-providers");
26
28
  let _hot_updater_cli_tools = require("@hot-updater/cli-tools");
27
29
  let node_url = require("node:url");
@@ -36,8 +38,6 @@ let node_path = require("node:path");
36
38
  node_path = __toESM(node_path);
37
39
  let path = require("path");
38
40
  path = __toESM(path);
39
- let fs = require("fs");
40
- fs = __toESM(fs);
41
41
  let node_timers_promises = require("node:timers/promises");
42
42
  let node_os = require("node:os");
43
43
  let node_events = require("node:events");
@@ -46,14 +46,14 @@ let node_fs = require("node:fs");
46
46
  let node_stream_promises = require("node:stream/promises");
47
47
  let node_stream = require("node:stream");
48
48
  let node_buffer = require("node:buffer");
49
- let _aws_sdk_client_cloudfront = require("@aws-sdk/client-cloudfront");
50
49
  let crypto = require("crypto");
51
50
  crypto = __toESM(crypto);
51
+ let _aws_sdk_client_cloudfront = require("@aws-sdk/client-cloudfront");
52
52
  let _aws_sdk_client_iam = require("@aws-sdk/client-iam");
53
53
  let _aws_sdk_client_sts = require("@aws-sdk/client-sts");
54
- let _aws_sdk_client_lambda = require("@aws-sdk/client-lambda");
55
54
  let fs_promises = require("fs/promises");
56
55
  fs_promises = __toESM(fs_promises);
56
+ let _aws_sdk_client_lambda = require("@aws-sdk/client-lambda");
57
57
  let _aws_sdk_client_s3 = require("@aws-sdk/client-s3");
58
58
  let _aws_sdk_lib_storage = require("@aws-sdk/lib-storage");
59
59
  let _aws_sdk_client_ssm = require("@aws-sdk/client-ssm");
@@ -6626,7 +6626,7 @@ var CloudFrontManager = class {
6626
6626
  while (retryCount < 600) try {
6627
6627
  if ((await cloudfrontClient.getDistribution({ Id: distributionId })).Distribution?.Status === "Deployed") return "CloudFront distribution deployment completed.";
6628
6628
  throw new Error("Retry");
6629
- } catch (_err) {
6629
+ } catch {
6630
6630
  if (retryCount++ >= 5) message(`CloudFront distribution is still in progress. This may take a few minutes. (${retryCount})`);
6631
6631
  await delay(1e3);
6632
6632
  }
@@ -7181,6 +7181,11 @@ const regionLocationMap = {
7181
7181
  };
7182
7182
  //#endregion
7183
7183
  //#region iac/s3.ts
7184
+ function normalizeBucketRegion(region) {
7185
+ if (region == null) return "us-east-1";
7186
+ if (region === "EU") return "eu-west-1";
7187
+ return region;
7188
+ }
7184
7189
  var S3Manager = class {
7185
7190
  credentials;
7186
7191
  constructor(credentials) {
@@ -7193,10 +7198,10 @@ var S3Manager = class {
7193
7198
  });
7194
7199
  const buckets = (await s3Client.listBuckets({})).Buckets ?? [];
7195
7200
  return await Promise.all(buckets.filter((bucket) => bucket.Name).map(async (bucket) => {
7196
- const { LocationConstraint: region } = await s3Client.getBucketLocation({ Bucket: bucket.Name });
7201
+ const { LocationConstraint } = await s3Client.getBucketLocation({ Bucket: bucket.Name });
7197
7202
  return {
7198
7203
  name: bucket.Name,
7199
- region
7204
+ region: normalizeBucketRegion(LocationConstraint)
7200
7205
  };
7201
7206
  }));
7202
7207
  }
@@ -1,4 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
+ import fs from "fs";
2
3
  import { fromSSO } from "@aws-sdk/credential-providers";
3
4
  import { ConfigBuilder, colors, copyDirToTmp, createZip, ensureInstallPackages, getCwd, link, makeEnv, p, transformEnv, transformTemplate } from "@hot-updater/cli-tools";
4
5
  import { fileURLToPath } from "node:url";
@@ -9,7 +10,6 @@ import process$1, { execArgv, execPath, hrtime, platform } from "node:process";
9
10
  import tty from "node:tty";
10
11
  import path from "node:path";
11
12
  import path$1 from "path";
12
- import fs from "fs";
13
13
  import { scheduler, setImmediate, setTimeout as setTimeout$1 } from "node:timers/promises";
14
14
  import { constants } from "node:os";
15
15
  import { EventEmitter, addAbortListener, on, once, setMaxListeners } from "node:events";
@@ -18,12 +18,12 @@ import { appendFileSync, createReadStream, createWriteStream, readFileSync, stat
18
18
  import { finished } from "node:stream/promises";
19
19
  import { Duplex, PassThrough, Readable, Transform, Writable, getDefaultHighWaterMark } from "node:stream";
20
20
  import { Buffer as Buffer$1 } from "node:buffer";
21
- import { CloudFront } from "@aws-sdk/client-cloudfront";
22
21
  import crypto from "crypto";
22
+ import { CloudFront } from "@aws-sdk/client-cloudfront";
23
23
  import { IAM } from "@aws-sdk/client-iam";
24
24
  import { STS } from "@aws-sdk/client-sts";
25
- import { Lambda } from "@aws-sdk/client-lambda";
26
25
  import fs$1 from "fs/promises";
26
+ import { Lambda } from "@aws-sdk/client-lambda";
27
27
  import { CopyObjectCommand, DeleteObjectCommand, GetObjectCommand, ListObjectsV2Command, S3 } from "@aws-sdk/client-s3";
28
28
  import { Upload } from "@aws-sdk/lib-storage";
29
29
  import { ParameterNotFound, SSM } from "@aws-sdk/client-ssm";
@@ -6620,7 +6620,7 @@ var CloudFrontManager = class {
6620
6620
  while (retryCount < 600) try {
6621
6621
  if ((await cloudfrontClient.getDistribution({ Id: distributionId })).Distribution?.Status === "Deployed") return "CloudFront distribution deployment completed.";
6622
6622
  throw new Error("Retry");
6623
- } catch (_err) {
6623
+ } catch {
6624
6624
  if (retryCount++ >= 5) message(`CloudFront distribution is still in progress. This may take a few minutes. (${retryCount})`);
6625
6625
  await delay(1e3);
6626
6626
  }
@@ -7175,6 +7175,11 @@ const regionLocationMap = {
7175
7175
  };
7176
7176
  //#endregion
7177
7177
  //#region iac/s3.ts
7178
+ function normalizeBucketRegion(region) {
7179
+ if (region == null) return "us-east-1";
7180
+ if (region === "EU") return "eu-west-1";
7181
+ return region;
7182
+ }
7178
7183
  var S3Manager = class {
7179
7184
  credentials;
7180
7185
  constructor(credentials) {
@@ -7187,10 +7192,10 @@ var S3Manager = class {
7187
7192
  });
7188
7193
  const buckets = (await s3Client.listBuckets({})).Buckets ?? [];
7189
7194
  return await Promise.all(buckets.filter((bucket) => bucket.Name).map(async (bucket) => {
7190
- const { LocationConstraint: region } = await s3Client.getBucketLocation({ Bucket: bucket.Name });
7195
+ const { LocationConstraint } = await s3Client.getBucketLocation({ Bucket: bucket.Name });
7191
7196
  return {
7192
7197
  name: bucket.Name,
7193
- region
7198
+ region: normalizeBucketRegion(LocationConstraint)
7194
7199
  };
7195
7200
  }));
7196
7201
  }
package/dist/index.cjs CHANGED
@@ -25,11 +25,11 @@ let _aws_sdk_client_cloudfront = require("@aws-sdk/client-cloudfront");
25
25
  let _aws_sdk_client_s3 = require("@aws-sdk/client-s3");
26
26
  let _aws_sdk_lib_storage = require("@aws-sdk/lib-storage");
27
27
  let _hot_updater_plugin_core = require("@hot-updater/plugin-core");
28
- let _aws_sdk_s3_request_presigner = require("@aws-sdk/s3-request-presigner");
29
28
  let fs_promises = require("fs/promises");
30
29
  fs_promises = __toESM(fs_promises);
31
30
  let path = require("path");
32
31
  path = __toESM(path);
32
+ let _aws_sdk_s3_request_presigner = require("@aws-sdk/s3-request-presigner");
33
33
  let _aws_sdk_client_ssm = require("@aws-sdk/client-ssm");
34
34
  let _aws_sdk_cloudfront_signer = require("@aws-sdk/cloudfront-signer");
35
35
  //#region ../../node_modules/.pnpm/mime@4.0.4/node_modules/mime/dist/types/other.js
package/dist/index.mjs CHANGED
@@ -2,9 +2,9 @@ import { CloudFrontClient, CreateInvalidationCommand, GetInvalidationCommand } f
2
2
  import { DeleteObjectCommand, DeleteObjectsCommand, GetObjectCommand, ListObjectsV2Command, NoSuchKey, S3Client } from "@aws-sdk/client-s3";
3
3
  import { Upload } from "@aws-sdk/lib-storage";
4
4
  import { createBlobDatabasePlugin, createStorageKeyBuilder, createStoragePlugin, getContentType, parseStorageUri } from "@hot-updater/plugin-core";
5
- import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
6
5
  import fs from "fs/promises";
7
6
  import path from "path";
7
+ import { getSignedUrl } from "@aws-sdk/s3-request-presigner";
8
8
  import { SSM } from "@aws-sdk/client-ssm";
9
9
  import { getSignedUrl as getSignedUrl$1 } from "@aws-sdk/cloudfront-signer";
10
10
  //#region ../../node_modules/.pnpm/mime@4.0.4/node_modules/mime/dist/types/other.js
@@ -29,11 +29,11 @@ node_crypto = __toESM(node_crypto);
29
29
  let _aws_sdk_client_cloudfront = require("@aws-sdk/client-cloudfront");
30
30
  let _aws_sdk_client_s3 = require("@aws-sdk/client-s3");
31
31
  let _aws_sdk_lib_storage = require("@aws-sdk/lib-storage");
32
- let _aws_sdk_s3_request_presigner = require("@aws-sdk/s3-request-presigner");
33
32
  let fs_promises = require("fs/promises");
34
33
  fs_promises = __toESM(fs_promises);
35
34
  let path = require("path");
36
35
  path = __toESM(path);
36
+ let _aws_sdk_s3_request_presigner = require("@aws-sdk/s3-request-presigner");
37
37
  let _aws_sdk_client_ssm = require("@aws-sdk/client-ssm");
38
38
  let _aws_sdk_cloudfront_signer = require("@aws-sdk/cloudfront-signer");
39
39
  //#region ../../packages/core/dist/index.mjs
@@ -1610,12 +1610,12 @@ function mergeBundleUpdate(baseBundle, patch) {
1610
1610
  */
1611
1611
  function createDatabasePlugin(options) {
1612
1612
  return (config, hooks) => {
1613
+ let cachedMethods = null;
1614
+ const getMethods = () => {
1615
+ if (!cachedMethods) cachedMethods = options.factory(config);
1616
+ return cachedMethods;
1617
+ };
1613
1618
  return () => {
1614
- let cachedMethods = null;
1615
- const getMethods = () => {
1616
- if (!cachedMethods) cachedMethods = options.factory(config);
1617
- return cachedMethods;
1618
- };
1619
1619
  const changedMap = /* @__PURE__ */ new Map();
1620
1620
  const markChanged = (operation, data) => {
1621
1621
  changedMap.set(data.id, {
@@ -1646,8 +1646,8 @@ function createDatabasePlugin(options) {
1646
1646
  const params = { changedSets: Array.from(changedMap.values()) };
1647
1647
  if (context === void 0) await methods.commitBundle(params);
1648
1648
  else await methods.commitBundle(params, context);
1649
- await hooks?.onDatabaseUpdated?.();
1650
1649
  changedMap.clear();
1650
+ await hooks?.onDatabaseUpdated?.();
1651
1651
  },
1652
1652
  async updateBundle(targetBundleId, newBundle, context) {
1653
1653
  const pendingChange = changedMap.get(targetBundleId);
@@ -3074,6 +3074,11 @@ function getSemverNormalizedVersions(version) {
3074
3074
  if (coerced.minor === 0 && coerced.patch === 0) versions.add(`${coerced.major}`);
3075
3075
  return Array.from(versions);
3076
3076
  }
3077
+ function resolveStorageTarget({ targetAppVersion, fingerprintHash }) {
3078
+ const target = normalizeTargetAppVersion(targetAppVersion) ?? fingerprintHash;
3079
+ if (!target) throw new Error("target not found");
3080
+ return target;
3081
+ }
3077
3082
  /**
3078
3083
  * Creates a blob storage-based database plugin with lazy initialization.
3079
3084
  *
@@ -3209,8 +3214,7 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
3209
3214
  if (data.targetAppVersion !== void 0) isTargetAppVersionChanged = true;
3210
3215
  if (operation === "update" && data.channel !== void 0) isChannelChanged = true;
3211
3216
  if (operation === "insert") {
3212
- const target = normalizeTargetAppVersion(data.targetAppVersion) ?? data.fingerprintHash;
3213
- if (!target) throw new Error("target not found");
3217
+ const target = resolveStorageTarget(data);
3214
3218
  const key = `${data.channel}/${data.platform}/${target}/update.json`;
3215
3219
  const bundleWithKey = {
3216
3220
  ...data,
@@ -3239,20 +3243,16 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
3239
3243
  if (!bundle) bundle = bundlesMap.get(data.id);
3240
3244
  if (!bundle) throw new Error("targetBundleId not found");
3241
3245
  if (operation === "update") {
3242
- const newChannel = data.channel !== void 0 ? data.channel : bundle.channel;
3243
- const newPlatform = data.platform !== void 0 ? data.platform : bundle.platform;
3244
- const target = data.fingerprintHash ?? bundle.fingerprintHash ?? normalizeTargetAppVersion(data.targetAppVersion) ?? normalizeTargetAppVersion(bundle.targetAppVersion);
3245
- if (!target) throw new Error("target not found");
3246
- const newKey = `${newChannel}/${newPlatform}/${target}/update.json`;
3246
+ const updatedBundle = {
3247
+ ...bundle,
3248
+ ...data
3249
+ };
3250
+ const newKey = `${updatedBundle.channel}/${updatedBundle.platform}/${resolveStorageTarget(updatedBundle)}/update.json`;
3247
3251
  if (newKey !== bundle._updateJsonKey) {
3248
3252
  const oldKey = bundle._updateJsonKey;
3249
3253
  removalsByKey[oldKey] = removalsByKey[oldKey] || [];
3250
3254
  removalsByKey[oldKey].push(bundle.id);
3251
3255
  changedBundlesByKey[newKey] = changedBundlesByKey[newKey] || [];
3252
- const updatedBundle = {
3253
- ...bundle,
3254
- ...data
3255
- };
3256
3256
  updatedBundle._oldUpdateJsonKey = oldKey;
3257
3257
  updatedBundle._updateJsonKey = newKey;
3258
3258
  bundlesMap.set(data.id, updatedBundle);
@@ -3272,10 +3272,6 @@ const createBlobDatabasePlugin = ({ name, factory }) => {
3272
3272
  continue;
3273
3273
  }
3274
3274
  const currentKey = bundle._updateJsonKey;
3275
- const updatedBundle = {
3276
- ...bundle,
3277
- ...data
3278
- };
3279
3275
  bundlesMap.set(data.id, updatedBundle);
3280
3276
  pendingBundlesMap.set(data.id, updatedBundle);
3281
3277
  changedBundlesByKey[currentKey] = changedBundlesByKey[currentKey] || [];
@@ -3456,9 +3452,17 @@ const INIT_BUNDLE_ROLLBACK_UPDATE_INFO = {
3456
3452
  storageUri: null,
3457
3453
  fileHash: null
3458
3454
  };
3459
- function createPluginDatabaseCore(plugin, resolveFileUrl) {
3455
+ function createPluginDatabaseCore(getPlugin, resolveFileUrl, options) {
3456
+ const runWithMutationPlugin = async (operation) => {
3457
+ const plugin = options?.createMutationPlugin?.() ?? getPlugin();
3458
+ try {
3459
+ return await operation(plugin);
3460
+ } finally {
3461
+ if (options?.createMutationPlugin) await options.cleanupMutationPlugin?.(plugin);
3462
+ }
3463
+ };
3460
3464
  const getSortedBundlePage = async (options, context) => {
3461
- const result = await plugin.getBundles({
3465
+ const result = await getPlugin().getBundles({
3462
3466
  ...options,
3463
3467
  orderBy: options.orderBy ?? DESC_ORDER
3464
3468
  }, context);
@@ -3512,7 +3516,7 @@ function createPluginDatabaseCore(plugin, resolveFileUrl) {
3512
3516
  return {
3513
3517
  api: {
3514
3518
  async getBundleById(id, context) {
3515
- return plugin.getBundleById(id, context);
3519
+ return getPlugin().getBundleById(id, context);
3516
3520
  },
3517
3521
  async getUpdateInfo(args, context) {
3518
3522
  const channel = args.channel ?? "production";
@@ -3553,27 +3557,33 @@ function createPluginDatabaseCore(plugin, resolveFileUrl) {
3553
3557
  };
3554
3558
  },
3555
3559
  async getChannels(context) {
3556
- return plugin.getChannels(context);
3560
+ return getPlugin().getChannels(context);
3557
3561
  },
3558
3562
  async getBundles(options, context) {
3559
- return plugin.getBundles(options, context);
3563
+ return getPlugin().getBundles(options, context);
3560
3564
  },
3561
3565
  async insertBundle(bundle, context) {
3562
- await plugin.appendBundle(bundle, context);
3563
- await plugin.commitBundle(context);
3566
+ await runWithMutationPlugin(async (plugin) => {
3567
+ await plugin.appendBundle(bundle, context);
3568
+ await plugin.commitBundle(context);
3569
+ });
3564
3570
  },
3565
3571
  async updateBundleById(bundleId, newBundle, context) {
3566
- await plugin.updateBundle(bundleId, newBundle, context);
3567
- await plugin.commitBundle(context);
3572
+ await runWithMutationPlugin(async (plugin) => {
3573
+ await plugin.updateBundle(bundleId, newBundle, context);
3574
+ await plugin.commitBundle(context);
3575
+ });
3568
3576
  },
3569
3577
  async deleteBundleById(bundleId, context) {
3570
- const bundle = await plugin.getBundleById(bundleId, context);
3571
- if (!bundle) return;
3572
- await plugin.deleteBundle(bundle, context);
3573
- await plugin.commitBundle(context);
3578
+ await runWithMutationPlugin(async (plugin) => {
3579
+ const bundle = await plugin.getBundleById(bundleId, context);
3580
+ if (!bundle) return;
3581
+ await plugin.deleteBundle(bundle, context);
3582
+ await plugin.commitBundle(context);
3583
+ });
3574
3584
  }
3575
3585
  },
3576
- adapterName: plugin.name,
3586
+ adapterName: getPlugin().name,
3577
3587
  createMigrator: () => {
3578
3588
  throw new Error("createMigrator is only available for Kysely/Prisma/Drizzle database adapters.");
3579
3589
  },
@@ -3750,7 +3760,7 @@ const handleGetBundles = async (_params, request, api, context) => {
3750
3760
  limit,
3751
3761
  offset
3752
3762
  }, context);
3753
- return new Response(JSON.stringify(result.data), {
3763
+ return new Response(JSON.stringify(result), {
3754
3764
  status: 200,
3755
3765
  headers: { "Content-Type": "application/json" }
3756
3766
  });
@@ -3783,8 +3793,8 @@ const handleDeleteBundle = async (params, _request, api, context) => {
3783
3793
  });
3784
3794
  };
3785
3795
  const handleGetChannels = async (_params, _request, api, context) => {
3786
- const channels = await api.getChannels(context);
3787
- return new Response(JSON.stringify({ channels }), {
3796
+ const response = { data: { channels: await api.getChannels(context) } };
3797
+ return new Response(JSON.stringify(response), {
3788
3798
  status: 200,
3789
3799
  headers: { "Content-Type": "application/json" }
3790
3800
  });
@@ -3865,6 +3875,7 @@ const normalizeBasePath = (basePath) => {
3865
3875
  //#endregion
3866
3876
  //#region ../../packages/server/src/runtime.ts
3867
3877
  function createHotUpdater(options) {
3878
+ const database = options.database;
3868
3879
  const basePath = normalizeBasePath(options.basePath ?? "/api");
3869
3880
  const storagePlugins = (options.storages ?? options.storagePlugins ?? []).map((plugin) => typeof plugin === "function" ? plugin() : plugin);
3870
3881
  const resolveStoragePluginUrl = async (storageUri, context) => {
@@ -3877,8 +3888,9 @@ function createHotUpdater(options) {
3877
3888
  if (!fileUrl) throw new Error("Storage plugin returned empty fileUrl");
3878
3889
  return fileUrl;
3879
3890
  };
3880
- if (!isDatabasePluginFactory(options.database) && !isDatabasePlugin(options.database)) throw new Error("@hot-updater/server/runtime only supports database plugins.");
3881
- const core = createPluginDatabaseCore(isDatabasePluginFactory(options.database) ? options.database() : options.database, resolveStoragePluginUrl);
3891
+ if (!isDatabasePluginFactory(database) && !isDatabasePlugin(database)) throw new Error("@hot-updater/server/runtime only supports database plugins.");
3892
+ const plugin = isDatabasePluginFactory(database) ? database() : database;
3893
+ const core = createPluginDatabaseCore(() => plugin, resolveStoragePluginUrl, isDatabasePluginFactory(database) ? { createMutationPlugin: () => database() } : void 0);
3882
3894
  const api = {
3883
3895
  ...core.api,
3884
3896
  handler: createHandler(core.api, {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@hot-updater/aws",
3
3
  "type": "module",
4
- "version": "0.29.2",
4
+ "version": "0.29.4",
5
5
  "description": "React Native OTA solution for self-hosted",
6
6
  "main": "dist/index.cjs",
7
7
  "module": "dist/index.mjs",
@@ -42,10 +42,10 @@
42
42
  "es-toolkit": "^1.32.0",
43
43
  "execa": "9.5.2",
44
44
  "mime": "^4.0.4",
45
- "@hot-updater/core": "0.29.2",
46
- "@hot-updater/js": "0.29.2",
47
- "@hot-updater/mock": "0.29.2",
48
- "@hot-updater/test-utils": "0.29.2"
45
+ "@hot-updater/core": "0.29.4",
46
+ "@hot-updater/js": "0.29.4",
47
+ "@hot-updater/mock": "0.29.4",
48
+ "@hot-updater/test-utils": "0.29.4"
49
49
  },
50
50
  "dependencies": {
51
51
  "@aws-sdk/client-cloudfront": "3.1008.0",
@@ -60,9 +60,9 @@
60
60
  "@aws-sdk/lib-storage": "3.1008.0",
61
61
  "hono": "4.12.9",
62
62
  "aws-lambda": "1.0.7",
63
- "@hot-updater/cli-tools": "0.29.2",
64
- "@hot-updater/plugin-core": "0.29.2",
65
- "@hot-updater/server": "0.29.2"
63
+ "@hot-updater/cli-tools": "0.29.4",
64
+ "@hot-updater/plugin-core": "0.29.4",
65
+ "@hot-updater/server": "0.29.4"
66
66
  },
67
67
  "scripts": {
68
68
  "build": "tsdown",