@hot-updater/bare 0.32.0 → 0.33.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.
package/dist/index.cjs CHANGED
@@ -22,6 +22,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
22
22
  enumerable: true
23
23
  }) : target, mod));
24
24
  //#endregion
25
+ let crypto = require("crypto");
25
26
  let fs_promises = require("fs/promises");
26
27
  fs_promises = __toESM(fs_promises);
27
28
  let path = require("path");
@@ -621,7 +622,7 @@ const fallbackSymbols = {
621
622
  const figures = isUnicodeSupported() ? mainSymbols : fallbackSymbols;
622
623
  Object.entries(specialMainSymbols);
623
624
  //#endregion
624
- //#region ../../node_modules/.pnpm/yoctocolors@2.1.1/node_modules/yoctocolors/base.js
625
+ //#region ../../node_modules/.pnpm/yoctocolors@2.1.2/node_modules/yoctocolors/base.js
625
626
  const hasColors = node_tty.default?.WriteStream?.prototype?.hasColors?.() ?? false;
626
627
  const format = (open, close) => {
627
628
  if (!hasColors) return (input) => input;
@@ -633,8 +634,9 @@ const format = (open, close) => {
633
634
  if (index === -1) return openCode + string + closeCode;
634
635
  let result = openCode;
635
636
  let lastIndex = 0;
637
+ const replaceCode = (close === 22 ? closeCode : "") + openCode;
636
638
  while (index !== -1) {
637
- result += string.slice(lastIndex, index) + openCode;
639
+ result += string.slice(lastIndex, index) + replaceCode;
638
640
  lastIndex = index + closeCode.length;
639
641
  index = string.indexOf(closeCode, lastIndex);
640
642
  }
@@ -3034,7 +3036,7 @@ function parseMilliseconds(milliseconds) {
3034
3036
  throw new TypeError("Expected a finite number or bigint");
3035
3037
  }
3036
3038
  //#endregion
3037
- //#region ../../node_modules/.pnpm/pretty-ms@9.2.0/node_modules/pretty-ms/index.js
3039
+ //#region ../../node_modules/.pnpm/pretty-ms@9.3.0/node_modules/pretty-ms/index.js
3038
3040
  const isZero = (value) => value === 0 || value === 0n;
3039
3041
  const pluralize = (word, count) => count === 1 || count === 1n ? word : `${word}s`;
3040
3042
  const SECOND_ROUNDING_EPSILON = 1e-7;
@@ -3083,7 +3085,7 @@ function prettyMilliseconds(milliseconds, options) {
3083
3085
  add(Number(parsed.hours), "hour", "h");
3084
3086
  }
3085
3087
  add(Number(parsed.minutes), "minute", "m");
3086
- if (!options.hideSeconds) if (options.separateMilliseconds || options.formatSubMilliseconds || !options.colonNotation && milliseconds < 1e3) {
3088
+ if (!options.hideSeconds) if (options.separateMilliseconds || options.formatSubMilliseconds || !options.colonNotation && milliseconds < 1e3 && !options.subSecondsAsDecimals) {
3087
3089
  const seconds = Number(parsed.seconds);
3088
3090
  const milliseconds = Number(parsed.milliseconds);
3089
3091
  const microseconds = Number(parsed.microseconds);
@@ -6317,12 +6319,111 @@ async function compileHermes({ cwd, sourcemap, inputJsFile }) {
6317
6319
  }
6318
6320
  //#endregion
6319
6321
  //#region src/bare.ts
6322
+ const BARE_BUILD_CACHE_VERSION = 1;
6323
+ function hashText(value) {
6324
+ return (0, crypto.createHash)("sha256").update(value).digest("hex");
6325
+ }
6326
+ async function pathExists(filePath) {
6327
+ try {
6328
+ await fs_promises.default.access(filePath);
6329
+ return true;
6330
+ } catch {
6331
+ return false;
6332
+ }
6333
+ }
6334
+ function resolveCacheRoot(cwd) {
6335
+ const cacheDir = process.env.HOT_UPDATER_BARE_BUILD_CACHE_DIR?.trim();
6336
+ if (!cacheDir) return null;
6337
+ return path.default.resolve(cwd, cacheDir);
6338
+ }
6339
+ function resolveCacheKey({ enableHermes, entryFile, platform, resetCache, sourcemap }) {
6340
+ const inputKey = process.env.HOT_UPDATER_BARE_BUILD_CACHE_KEY?.trim();
6341
+ if (!inputKey) return null;
6342
+ return hashText(JSON.stringify({
6343
+ cacheVersion: BARE_BUILD_CACHE_VERSION,
6344
+ enableHermes,
6345
+ entryFile,
6346
+ inputKey,
6347
+ platform,
6348
+ resetCache,
6349
+ sourcemap
6350
+ }));
6351
+ }
6352
+ function resolveCachePaths({ cwd, enableHermes, entryFile, platform, resetCache, sourcemap }) {
6353
+ const root = resolveCacheRoot(cwd);
6354
+ const key = resolveCacheKey({
6355
+ enableHermes,
6356
+ entryFile,
6357
+ platform,
6358
+ resetCache,
6359
+ sourcemap
6360
+ });
6361
+ if (!root || !key) return null;
6362
+ const entryDir = path.default.join(root, key);
6363
+ return {
6364
+ entryDir,
6365
+ filesDir: path.default.join(entryDir, "files"),
6366
+ key,
6367
+ manifestPath: path.default.join(entryDir, "manifest.json"),
6368
+ root
6369
+ };
6370
+ }
6371
+ async function restoreBundleBuildFromCache({ buildPath, cachePaths }) {
6372
+ if (!await pathExists(cachePaths.manifestPath)) return null;
6373
+ try {
6374
+ const metadata = JSON.parse(await fs_promises.default.readFile(cachePaths.manifestPath, "utf8"));
6375
+ await fs_promises.default.cp(cachePaths.filesDir, buildPath, { recursive: true });
6376
+ _hot_updater_cli_tools.log.normal(`[bare] reused build cache ${cachePaths.key.slice(0, 12)}\n`);
6377
+ return { stdout: typeof metadata.stdout === "string" ? metadata.stdout : null };
6378
+ } catch {
6379
+ return null;
6380
+ }
6381
+ }
6382
+ async function saveBundleBuildToCache({ buildPath, cachePaths, stdout }) {
6383
+ if (await pathExists(cachePaths.manifestPath)) return;
6384
+ const tempDir = path.default.join(cachePaths.root, `${cachePaths.key}.${process.pid}.${Date.now()}.tmp`);
6385
+ await fs_promises.default.rm(tempDir, {
6386
+ recursive: true,
6387
+ force: true
6388
+ });
6389
+ await fs_promises.default.mkdir(path.default.dirname(tempDir), { recursive: true });
6390
+ await fs_promises.default.cp(buildPath, path.default.join(tempDir, "files"), { recursive: true });
6391
+ await fs_promises.default.writeFile(path.default.join(tempDir, "manifest.json"), `${JSON.stringify({
6392
+ cacheVersion: BARE_BUILD_CACHE_VERSION,
6393
+ stdout
6394
+ })}\n`);
6395
+ try {
6396
+ await fs_promises.default.rename(tempDir, cachePaths.entryDir);
6397
+ _hot_updater_cli_tools.log.normal(`[bare] saved build cache ${cachePaths.key.slice(0, 12)}\n`);
6398
+ } catch {
6399
+ await fs_promises.default.rm(tempDir, {
6400
+ recursive: true,
6401
+ force: true
6402
+ });
6403
+ }
6404
+ }
6320
6405
  const runBundle = async ({ entryFile, cwd, platform, buildPath, sourcemap, enableHermes, resetCache }) => {
6321
6406
  const reactNativePath = require.resolve("react-native/package.json", { paths: [cwd] });
6322
6407
  const cliPath = path.default.join(path.default.dirname(reactNativePath), "cli.js");
6323
6408
  const filename = `index.${platform}`;
6324
6409
  const bundleOutput = path.default.join(buildPath, `${filename}.bundle`);
6325
6410
  const bundleId = (0, uuidv7.uuidv7)();
6411
+ const cachePaths = resolveCachePaths({
6412
+ cwd,
6413
+ enableHermes,
6414
+ entryFile,
6415
+ platform,
6416
+ resetCache,
6417
+ sourcemap
6418
+ });
6419
+ const cached = cachePaths ? await restoreBundleBuildFromCache({
6420
+ buildPath,
6421
+ cachePaths
6422
+ }) : null;
6423
+ if (cached) return {
6424
+ bundleId,
6425
+ stdout: cached.stdout
6426
+ };
6326
6427
  const args = [
6327
6428
  "bundle",
6328
6429
  "--assets-dest",
@@ -6355,11 +6456,21 @@ const runBundle = async ({ entryFile, cwd, platform, buildPath, sourcemap, enabl
6355
6456
  inputJsFile: bundleOutput,
6356
6457
  sourcemap
6357
6458
  });
6459
+ if (cachePaths) await saveBundleBuildToCache({
6460
+ buildPath,
6461
+ cachePaths,
6462
+ stdout: hermesVersion
6463
+ });
6358
6464
  return {
6359
6465
  bundleId,
6360
6466
  stdout: hermesVersion
6361
6467
  };
6362
6468
  }
6469
+ if (cachePaths) await saveBundleBuildToCache({
6470
+ buildPath,
6471
+ cachePaths,
6472
+ stdout: null
6473
+ });
6363
6474
  return {
6364
6475
  bundleId,
6365
6476
  stdout: null
package/dist/index.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  import { createRequire } from "node:module";
2
+ import { createHash } from "crypto";
2
3
  import fs from "fs/promises";
3
4
  import path from "path";
4
5
  import { getReactNativeMetadatas, log } from "@hot-updater/cli-tools";
@@ -616,7 +617,7 @@ const fallbackSymbols = {
616
617
  const figures = isUnicodeSupported() ? mainSymbols : fallbackSymbols;
617
618
  Object.entries(specialMainSymbols);
618
619
  //#endregion
619
- //#region ../../node_modules/.pnpm/yoctocolors@2.1.1/node_modules/yoctocolors/base.js
620
+ //#region ../../node_modules/.pnpm/yoctocolors@2.1.2/node_modules/yoctocolors/base.js
620
621
  const hasColors = tty?.WriteStream?.prototype?.hasColors?.() ?? false;
621
622
  const format = (open, close) => {
622
623
  if (!hasColors) return (input) => input;
@@ -628,8 +629,9 @@ const format = (open, close) => {
628
629
  if (index === -1) return openCode + string + closeCode;
629
630
  let result = openCode;
630
631
  let lastIndex = 0;
632
+ const replaceCode = (close === 22 ? closeCode : "") + openCode;
631
633
  while (index !== -1) {
632
- result += string.slice(lastIndex, index) + openCode;
634
+ result += string.slice(lastIndex, index) + replaceCode;
633
635
  lastIndex = index + closeCode.length;
634
636
  index = string.indexOf(closeCode, lastIndex);
635
637
  }
@@ -3029,7 +3031,7 @@ function parseMilliseconds(milliseconds) {
3029
3031
  throw new TypeError("Expected a finite number or bigint");
3030
3032
  }
3031
3033
  //#endregion
3032
- //#region ../../node_modules/.pnpm/pretty-ms@9.2.0/node_modules/pretty-ms/index.js
3034
+ //#region ../../node_modules/.pnpm/pretty-ms@9.3.0/node_modules/pretty-ms/index.js
3033
3035
  const isZero = (value) => value === 0 || value === 0n;
3034
3036
  const pluralize = (word, count) => count === 1 || count === 1n ? word : `${word}s`;
3035
3037
  const SECOND_ROUNDING_EPSILON = 1e-7;
@@ -3078,7 +3080,7 @@ function prettyMilliseconds(milliseconds, options) {
3078
3080
  add(Number(parsed.hours), "hour", "h");
3079
3081
  }
3080
3082
  add(Number(parsed.minutes), "minute", "m");
3081
- if (!options.hideSeconds) if (options.separateMilliseconds || options.formatSubMilliseconds || !options.colonNotation && milliseconds < 1e3) {
3083
+ if (!options.hideSeconds) if (options.separateMilliseconds || options.formatSubMilliseconds || !options.colonNotation && milliseconds < 1e3 && !options.subSecondsAsDecimals) {
3082
3084
  const seconds = Number(parsed.seconds);
3083
3085
  const milliseconds = Number(parsed.milliseconds);
3084
3086
  const microseconds = Number(parsed.microseconds);
@@ -6312,12 +6314,111 @@ async function compileHermes({ cwd, sourcemap, inputJsFile }) {
6312
6314
  }
6313
6315
  //#endregion
6314
6316
  //#region src/bare.ts
6317
+ const BARE_BUILD_CACHE_VERSION = 1;
6318
+ function hashText(value) {
6319
+ return createHash("sha256").update(value).digest("hex");
6320
+ }
6321
+ async function pathExists(filePath) {
6322
+ try {
6323
+ await fs.access(filePath);
6324
+ return true;
6325
+ } catch {
6326
+ return false;
6327
+ }
6328
+ }
6329
+ function resolveCacheRoot(cwd) {
6330
+ const cacheDir = process.env.HOT_UPDATER_BARE_BUILD_CACHE_DIR?.trim();
6331
+ if (!cacheDir) return null;
6332
+ return path.resolve(cwd, cacheDir);
6333
+ }
6334
+ function resolveCacheKey({ enableHermes, entryFile, platform, resetCache, sourcemap }) {
6335
+ const inputKey = process.env.HOT_UPDATER_BARE_BUILD_CACHE_KEY?.trim();
6336
+ if (!inputKey) return null;
6337
+ return hashText(JSON.stringify({
6338
+ cacheVersion: BARE_BUILD_CACHE_VERSION,
6339
+ enableHermes,
6340
+ entryFile,
6341
+ inputKey,
6342
+ platform,
6343
+ resetCache,
6344
+ sourcemap
6345
+ }));
6346
+ }
6347
+ function resolveCachePaths({ cwd, enableHermes, entryFile, platform, resetCache, sourcemap }) {
6348
+ const root = resolveCacheRoot(cwd);
6349
+ const key = resolveCacheKey({
6350
+ enableHermes,
6351
+ entryFile,
6352
+ platform,
6353
+ resetCache,
6354
+ sourcemap
6355
+ });
6356
+ if (!root || !key) return null;
6357
+ const entryDir = path.join(root, key);
6358
+ return {
6359
+ entryDir,
6360
+ filesDir: path.join(entryDir, "files"),
6361
+ key,
6362
+ manifestPath: path.join(entryDir, "manifest.json"),
6363
+ root
6364
+ };
6365
+ }
6366
+ async function restoreBundleBuildFromCache({ buildPath, cachePaths }) {
6367
+ if (!await pathExists(cachePaths.manifestPath)) return null;
6368
+ try {
6369
+ const metadata = JSON.parse(await fs.readFile(cachePaths.manifestPath, "utf8"));
6370
+ await fs.cp(cachePaths.filesDir, buildPath, { recursive: true });
6371
+ log.normal(`[bare] reused build cache ${cachePaths.key.slice(0, 12)}\n`);
6372
+ return { stdout: typeof metadata.stdout === "string" ? metadata.stdout : null };
6373
+ } catch {
6374
+ return null;
6375
+ }
6376
+ }
6377
+ async function saveBundleBuildToCache({ buildPath, cachePaths, stdout }) {
6378
+ if (await pathExists(cachePaths.manifestPath)) return;
6379
+ const tempDir = path.join(cachePaths.root, `${cachePaths.key}.${process.pid}.${Date.now()}.tmp`);
6380
+ await fs.rm(tempDir, {
6381
+ recursive: true,
6382
+ force: true
6383
+ });
6384
+ await fs.mkdir(path.dirname(tempDir), { recursive: true });
6385
+ await fs.cp(buildPath, path.join(tempDir, "files"), { recursive: true });
6386
+ await fs.writeFile(path.join(tempDir, "manifest.json"), `${JSON.stringify({
6387
+ cacheVersion: BARE_BUILD_CACHE_VERSION,
6388
+ stdout
6389
+ })}\n`);
6390
+ try {
6391
+ await fs.rename(tempDir, cachePaths.entryDir);
6392
+ log.normal(`[bare] saved build cache ${cachePaths.key.slice(0, 12)}\n`);
6393
+ } catch {
6394
+ await fs.rm(tempDir, {
6395
+ recursive: true,
6396
+ force: true
6397
+ });
6398
+ }
6399
+ }
6315
6400
  const runBundle = async ({ entryFile, cwd, platform, buildPath, sourcemap, enableHermes, resetCache }) => {
6316
6401
  const reactNativePath = __require.resolve("react-native/package.json", { paths: [cwd] });
6317
6402
  const cliPath = path.join(path.dirname(reactNativePath), "cli.js");
6318
6403
  const filename = `index.${platform}`;
6319
6404
  const bundleOutput = path.join(buildPath, `${filename}.bundle`);
6320
6405
  const bundleId = uuidv7();
6406
+ const cachePaths = resolveCachePaths({
6407
+ cwd,
6408
+ enableHermes,
6409
+ entryFile,
6410
+ platform,
6411
+ resetCache,
6412
+ sourcemap
6413
+ });
6414
+ const cached = cachePaths ? await restoreBundleBuildFromCache({
6415
+ buildPath,
6416
+ cachePaths
6417
+ }) : null;
6418
+ if (cached) return {
6419
+ bundleId,
6420
+ stdout: cached.stdout
6421
+ };
6321
6422
  const args = [
6322
6423
  "bundle",
6323
6424
  "--assets-dest",
@@ -6350,11 +6451,21 @@ const runBundle = async ({ entryFile, cwd, platform, buildPath, sourcemap, enabl
6350
6451
  inputJsFile: bundleOutput,
6351
6452
  sourcemap
6352
6453
  });
6454
+ if (cachePaths) await saveBundleBuildToCache({
6455
+ buildPath,
6456
+ cachePaths,
6457
+ stdout: hermesVersion
6458
+ });
6353
6459
  return {
6354
6460
  bundleId,
6355
6461
  stdout: hermesVersion
6356
6462
  };
6357
6463
  }
6464
+ if (cachePaths) await saveBundleBuildToCache({
6465
+ buildPath,
6466
+ cachePaths,
6467
+ stdout: null
6468
+ });
6358
6469
  return {
6359
6470
  bundleId,
6360
6471
  stdout: null
package/package.json CHANGED
@@ -1,13 +1,16 @@
1
1
  {
2
2
  "name": "@hot-updater/bare",
3
3
  "type": "module",
4
- "version": "0.32.0",
4
+ "version": "0.33.1",
5
5
  "description": "React Native OTA solution for self-hosted",
6
6
  "main": "./dist/index.cjs",
7
7
  "module": "./dist/index.mjs",
8
8
  "types": "./dist/index.d.cts",
9
9
  "license": "MIT",
10
- "repository": "https://github.com/gronxb/hot-updater",
10
+ "repository": {
11
+ "type": "git",
12
+ "url": "https://github.com/gronxb/hot-updater"
13
+ },
11
14
  "author": "gronxb <gron1gh1@gmail.com> (https://github.com/gronxb)",
12
15
  "bugs": {
13
16
  "url": "https://github.com/gronxb/hot-updater/issues"
@@ -22,8 +25,8 @@
22
25
  ],
23
26
  "dependencies": {
24
27
  "uuidv7": "^1.0.2",
25
- "@hot-updater/plugin-core": "0.32.0",
26
- "@hot-updater/cli-tools": "0.32.0"
28
+ "@hot-updater/cli-tools": "0.33.1",
29
+ "@hot-updater/plugin-core": "0.33.1"
27
30
  },
28
31
  "devDependencies": {
29
32
  "@types/node": "^20",
@@ -54,14 +57,14 @@
54
57
  "3.1.1",
55
58
  "4.0.0"
56
59
  ],
57
- "pretty-ms": "9.2.0",
60
+ "pretty-ms": "9.3.0",
58
61
  "shebang-command": "2.0.0",
59
62
  "shebang-regex": "3.0.0",
60
63
  "signal-exit": "4.1.0",
61
64
  "strip-final-newline": "4.0.0",
62
65
  "unicorn-magic": "0.3.0",
63
66
  "which": "2.0.2",
64
- "yoctocolors": "2.1.1"
67
+ "yoctocolors": "2.1.2"
65
68
  },
66
69
  "scripts": {
67
70
  "build": "tsdown",