hot-updater 1.0.0 → 1.0.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.mjs +240 -76
- package/dist/infra-templates/aws/lambda/index.cjs +1 -1
- package/dist/infra-templates/aws/template.json +10 -10
- package/dist/infra-templates/cloudflare/template.json +10 -10
- package/dist/infra-templates/cloudflare/worker/dist/README.md +1 -1
- package/dist/infra-templates/cloudflare/worker/dist/index.js +1 -1
- package/dist/infra-templates/cloudflare/worker/dist/index.js.map +2 -2
- package/dist/infra-templates/firebase/ENVIRONMENT.md +2 -1
- package/dist/infra-templates/firebase/SETUP.md +19 -8
- package/dist/infra-templates/firebase/app/hot-updater.config.bare.ts +1 -0
- package/dist/infra-templates/firebase/app/hot-updater.config.expo.ts +1 -0
- package/dist/infra-templates/firebase/app/hot-updater.config.rock.ts +1 -0
- package/dist/infra-templates/firebase/app/hotUpdater.ts +1 -0
- package/dist/infra-templates/firebase/firebase/firebase.json +2 -1
- package/dist/infra-templates/firebase/firebase/functions/index.cjs +8 -4
- package/dist/infra-templates/firebase/template.json +17 -11
- package/dist/infra-templates/supabase/supabase/functions/hot-updater-v1/_hot-updater/hot-updater-protocol/dist/index.cjs +5 -0
- package/dist/infra-templates/supabase/supabase/functions/hot-updater-v1/_hot-updater/hot-updater-protocol/dist/index.d.cts +14 -0
- package/dist/infra-templates/supabase/supabase/functions/hot-updater-v1/_hot-updater/hot-updater-protocol/dist/index.d.mts +14 -0
- package/dist/infra-templates/supabase/supabase/functions/hot-updater-v1/_hot-updater/hot-updater-protocol/dist/index.mjs +5 -0
- package/dist/infra-templates/supabase/supabase/functions/hot-updater-v1/_hot-updater/hot-updater-server/dist/package.cjs +1 -1
- package/dist/infra-templates/supabase/supabase/functions/hot-updater-v1/_hot-updater/hot-updater-server/dist/package.mjs +1 -1
- package/dist/infra-templates/supabase/template.json +10 -10
- package/package.json +20 -20
package/dist/index.mjs
CHANGED
|
@@ -3870,26 +3870,112 @@ async function handleAgentInfra(operation, options) {
|
|
|
3870
3870
|
await handleInfraScaffold(operation, options);
|
|
3871
3871
|
}
|
|
3872
3872
|
//#endregion
|
|
3873
|
-
//#region src/utils/version/
|
|
3874
|
-
|
|
3875
|
-
|
|
3876
|
-
|
|
3877
|
-
|
|
3878
|
-
|
|
3879
|
-
|
|
3880
|
-
|
|
3873
|
+
//#region src/utils/version/appVersionCandidates.ts
|
|
3874
|
+
/** One version only when every candidate declares the same literal. */
|
|
3875
|
+
const resolveFromCandidates = (candidates) => {
|
|
3876
|
+
const versions = new Set(candidates.map((candidate) => candidate.version));
|
|
3877
|
+
const [version] = versions;
|
|
3878
|
+
return {
|
|
3879
|
+
version: versions.size === 1 && version ? version : null,
|
|
3880
|
+
candidates
|
|
3881
|
+
};
|
|
3881
3882
|
};
|
|
3882
|
-
|
|
3883
|
-
const
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
|
|
3887
|
-
|
|
3888
|
-
|
|
3889
|
-
|
|
3883
|
+
/** Several candidates and no single version: the caller must pick one. */
|
|
3884
|
+
const isAmbiguousAppVersion = ({ version, candidates }) => version === null && candidates.length > 1;
|
|
3885
|
+
const formatAppVersionCandidates = (candidates) => candidates.map(({ label, version }) => `${label}: ${version ?? "unresolved"}`).join(", ");
|
|
3886
|
+
//#endregion
|
|
3887
|
+
//#region src/utils/version/getAndroidVersion.ts
|
|
3888
|
+
const stripComments = (source) => source.replace(/\/\*[\s\S]*?\*\//g, "").replace(/^\s*\/\/.*$/gm, "");
|
|
3889
|
+
/** The body of the `{ ... }` block that opens at or after `from`. */
|
|
3890
|
+
const readBlock = (source, from) => {
|
|
3891
|
+
const open = source.indexOf("{", from);
|
|
3892
|
+
if (open === -1) return null;
|
|
3893
|
+
let depth = 0;
|
|
3894
|
+
for (let index = open; index < source.length; index++) {
|
|
3895
|
+
if (source[index] === "{") depth++;
|
|
3896
|
+
if (source[index] === "}" && --depth === 0) return {
|
|
3897
|
+
body: source.slice(open + 1, index),
|
|
3898
|
+
end: index + 1
|
|
3899
|
+
};
|
|
3890
3900
|
}
|
|
3891
3901
|
return null;
|
|
3892
3902
|
};
|
|
3903
|
+
/** The top-level `name { ... }` blocks in a block body. */
|
|
3904
|
+
const readNamedBlocks = (body) => {
|
|
3905
|
+
const blocks = [];
|
|
3906
|
+
const header = /(?:create\(\s*["']([\w-]+)["']\s*\)|([\w-]+))\s*\{/g;
|
|
3907
|
+
let match;
|
|
3908
|
+
while (match = header.exec(body)) {
|
|
3909
|
+
const block = readBlock(body, match.index);
|
|
3910
|
+
if (!block) break;
|
|
3911
|
+
blocks.push({
|
|
3912
|
+
name: match[1] ?? match[2],
|
|
3913
|
+
body: block.body
|
|
3914
|
+
});
|
|
3915
|
+
header.lastIndex = block.end;
|
|
3916
|
+
}
|
|
3917
|
+
return blocks;
|
|
3918
|
+
};
|
|
3919
|
+
/** The first block called `name`, in file order, at any depth. */
|
|
3920
|
+
const findBlock = (source, name) => readNamedBlocks(source).flatMap((block) => block.name === name ? [block] : [findBlock(block.body, name)]).find((block) => block !== void 0);
|
|
3921
|
+
/** A literal setting declared directly in a block body; null when not literal. */
|
|
3922
|
+
const readSetting = (body, setting) => {
|
|
3923
|
+
const match = readNamedBlocks(body).reduce((rest, block) => rest.replace(block.body, ""), body).match(new RegExp(`\\b${setting}\\b\\s*=?\\s*(?:(['"])([^'"]*)\\1|(\\S+))`));
|
|
3924
|
+
if (!match) return void 0;
|
|
3925
|
+
return match[2] || null;
|
|
3926
|
+
};
|
|
3927
|
+
const capitalize = (value) => value.charAt(0).toUpperCase() + value.slice(1);
|
|
3928
|
+
/**
|
|
3929
|
+
* Whether a variant builds a flavor: `stagingRelease` builds `staging`, and
|
|
3930
|
+
* with flavor dimensions `brandAStagingRelease` builds `brandA` and `staging`.
|
|
3931
|
+
*/
|
|
3932
|
+
const variantBuildsFlavor = (variant, flavor) => new RegExp(`${capitalize(flavor)}(?=[A-Z]|$)`).test(capitalize(variant));
|
|
3933
|
+
/**
|
|
3934
|
+
* Reads versionName from defaultConfig and from each product flavor, so an
|
|
3935
|
+
* app whose flavors (brands, environments) override the version is reported
|
|
3936
|
+
* as ambiguous instead of resolving to the first versionName in the file.
|
|
3937
|
+
*/
|
|
3938
|
+
const getAndroidVersionFromAppBuildGradle = async (scope = {}) => {
|
|
3939
|
+
const buildGradlePath = path.join(getCwd(), "android", scope.appModuleName ?? "app", "build.gradle");
|
|
3940
|
+
let buildGradle;
|
|
3941
|
+
try {
|
|
3942
|
+
buildGradle = stripComments(await fs$3.readFile(buildGradlePath, "utf8"));
|
|
3943
|
+
} catch {
|
|
3944
|
+
return {
|
|
3945
|
+
version: null,
|
|
3946
|
+
candidates: []
|
|
3947
|
+
};
|
|
3948
|
+
}
|
|
3949
|
+
const android = findBlock(buildGradle, "android")?.body ?? "";
|
|
3950
|
+
const defaultConfig = findBlock(android, "defaultConfig");
|
|
3951
|
+
const defaultVersion = defaultConfig ? readSetting(defaultConfig.body, "versionName") : void 0;
|
|
3952
|
+
const flavorsBlock = findBlock(android, "productFlavors");
|
|
3953
|
+
const flavors = (flavorsBlock ? readNamedBlocks(flavorsBlock.body) : []).map((flavor) => ({
|
|
3954
|
+
name: flavor.name,
|
|
3955
|
+
applicationId: readSetting(flavor.body, "applicationId"),
|
|
3956
|
+
versionName: readSetting(flavor.body, "versionName")
|
|
3957
|
+
}));
|
|
3958
|
+
const defaultCandidate = defaultVersion === void 0 ? [] : [{
|
|
3959
|
+
label: "defaultConfig",
|
|
3960
|
+
version: defaultVersion
|
|
3961
|
+
}];
|
|
3962
|
+
const flavorCandidates = (flavorList) => flavorList.flatMap((flavor) => flavor.versionName === void 0 ? [] : [{
|
|
3963
|
+
label: `${flavor.name} flavor`,
|
|
3964
|
+
version: flavor.versionName
|
|
3965
|
+
}]);
|
|
3966
|
+
const { variant, applicationId } = scope;
|
|
3967
|
+
if (variant || applicationId) {
|
|
3968
|
+
const builtFlavors = flavors.filter((flavor) => applicationId !== void 0 && flavor.applicationId === applicationId || variant !== void 0 && variantBuildsFlavor(variant, flavor.name));
|
|
3969
|
+
if (builtFlavors.length > 0) {
|
|
3970
|
+
const overrides = flavorCandidates(builtFlavors);
|
|
3971
|
+
return resolveFromCandidates(overrides.length > 0 ? overrides : defaultCandidate);
|
|
3972
|
+
}
|
|
3973
|
+
}
|
|
3974
|
+
const overrides = flavorCandidates(flavors);
|
|
3975
|
+
const everyFlavorOverrides = flavors.length > 0 && overrides.length === flavors.length;
|
|
3976
|
+
return resolveFromCandidates([...everyFlavorOverrides ? [] : defaultCandidate, ...overrides]);
|
|
3977
|
+
};
|
|
3978
|
+
const resolveAndroidAppVersion = (scope) => getAndroidVersionFromAppBuildGradle(scope);
|
|
3893
3979
|
//#endregion
|
|
3894
3980
|
//#region ../../node_modules/.pnpm/@bacons+xcode@1.0.0-alpha.33/node_modules/@bacons/xcode/build/api/utils/constants.js
|
|
3895
3981
|
var require_constants = /* @__PURE__ */ __commonJSMin(((exports) => {
|
|
@@ -19406,81 +19492,138 @@ const isFileExist = async (path) => {
|
|
|
19406
19492
|
return false;
|
|
19407
19493
|
}
|
|
19408
19494
|
};
|
|
19409
|
-
const
|
|
19495
|
+
const isResolved = (value) => typeof value === "string" && value.length > 0 && !value.includes("$(");
|
|
19496
|
+
const readInfoPlistVersion = async (plistPath) => {
|
|
19410
19497
|
try {
|
|
19411
|
-
const iosAppTargetDirectory = getIosAppTargetDirectoryName();
|
|
19412
|
-
if (!iosAppTargetDirectory) return null;
|
|
19413
|
-
const plistPath = path.join(getCwd(), "ios", iosAppTargetDirectory, "Info.plist");
|
|
19414
19498
|
if (!await isFileExist(plistPath)) return null;
|
|
19415
19499
|
const fileBuffer = await fs$3.readFile(plistPath);
|
|
19416
19500
|
const appVersion = parsePlist(fileBuffer)["CFBundleShortVersionString"];
|
|
19417
|
-
|
|
19418
|
-
return appVersion;
|
|
19501
|
+
return isResolved(appVersion) ? appVersion : null;
|
|
19419
19502
|
} catch {
|
|
19420
19503
|
return null;
|
|
19421
19504
|
}
|
|
19422
19505
|
};
|
|
19423
|
-
const
|
|
19506
|
+
const getIOSVersionFromInfoPlist = async () => {
|
|
19507
|
+
const iosAppTargetDirectory = getIosAppTargetDirectoryName();
|
|
19508
|
+
if (!iosAppTargetDirectory) return null;
|
|
19509
|
+
return readInfoPlistVersion(path.join(getCwd(), "ios", iosAppTargetDirectory, "Info.plist"));
|
|
19510
|
+
};
|
|
19511
|
+
const APPLICATION_PRODUCT_TYPE = "com.apple.product-type.application";
|
|
19512
|
+
/**
|
|
19513
|
+
* Reads MARKETING_VERSION per application target, so a project whose targets
|
|
19514
|
+
* (brands, environments) ship different versions is reported as ambiguous
|
|
19515
|
+
* instead of resolving to whichever configuration comes first in the file.
|
|
19516
|
+
*/
|
|
19517
|
+
const getIOSVersionFromXcodeProject = async (scope = {}) => {
|
|
19518
|
+
const notFound = {
|
|
19519
|
+
version: null,
|
|
19520
|
+
candidates: []
|
|
19521
|
+
};
|
|
19424
19522
|
try {
|
|
19523
|
+
const iosDirectory = path.join(getCwd(), "ios");
|
|
19425
19524
|
const [xcodeprojPath] = import_out.default.globSync("*.xcodeproj/project.pbxproj", {
|
|
19426
|
-
cwd:
|
|
19525
|
+
cwd: iosDirectory,
|
|
19427
19526
|
absolute: true,
|
|
19428
19527
|
onlyFiles: true
|
|
19429
19528
|
});
|
|
19430
|
-
if (!xcodeprojPath) return
|
|
19431
|
-
const
|
|
19432
|
-
|
|
19433
|
-
|
|
19434
|
-
|
|
19435
|
-
|
|
19436
|
-
|
|
19437
|
-
|
|
19438
|
-
|
|
19439
|
-
|
|
19440
|
-
|
|
19529
|
+
if (!xcodeprojPath) return notFound;
|
|
19530
|
+
const project = import_build.XcodeProject.open(xcodeprojPath).toJSON();
|
|
19531
|
+
const objects = project.objects ?? {};
|
|
19532
|
+
const configurationName = scope.configuration ?? "Release";
|
|
19533
|
+
const findConfiguration = (listId) => (listId ? objects[listId]?.buildConfigurations ?? [] : []).map((id) => objects[id]).find((config) => config?.name === configurationName);
|
|
19534
|
+
const rootProject = project.rootObject ? objects[project.rootObject] : void 0;
|
|
19535
|
+
const projectSettings = findConfiguration(rootProject?.buildConfigurationList)?.buildSettings ?? {};
|
|
19536
|
+
const appTargets = (rootProject?.targets ?? []).map((id) => objects[id]).filter((target) => target?.isa === "PBXNativeTarget" && target.productType === APPLICATION_PRODUCT_TYPE).map((target) => {
|
|
19537
|
+
const settings = {
|
|
19538
|
+
...projectSettings,
|
|
19539
|
+
...findConfiguration(target.buildConfigurationList)?.buildSettings
|
|
19540
|
+
};
|
|
19541
|
+
const infoPlistFile = typeof settings.INFOPLIST_FILE === "string" ? settings.INFOPLIST_FILE.replace("$(SRCROOT)", iosDirectory) : void 0;
|
|
19542
|
+
return {
|
|
19543
|
+
name: target.name ?? "unknown",
|
|
19544
|
+
bundleIdentifier: settings.PRODUCT_BUNDLE_IDENTIFIER,
|
|
19545
|
+
marketingVersion: settings.MARKETING_VERSION,
|
|
19546
|
+
infoPlistPath: isResolved(infoPlistFile) ? path.resolve(iosDirectory, infoPlistFile) : void 0
|
|
19547
|
+
};
|
|
19548
|
+
});
|
|
19549
|
+
if (appTargets.length === 0) {
|
|
19550
|
+
const candidates = Object.values(objects).filter((object) => object?.isa === "XCBuildConfiguration" && object.name === configurationName && object.buildSettings?.MARKETING_VERSION !== void 0).map((object) => ({
|
|
19551
|
+
label: configurationName,
|
|
19552
|
+
version: isResolved(object?.buildSettings?.MARKETING_VERSION) ? object.buildSettings.MARKETING_VERSION : null
|
|
19553
|
+
}));
|
|
19554
|
+
return resolveFromCandidates(candidates);
|
|
19555
|
+
}
|
|
19556
|
+
const scopedTargets = scope.scheme || scope.bundleIdentifier ? appTargets.filter((target) => target.name === scope.scheme || scope.bundleIdentifier !== void 0 && target.bundleIdentifier === scope.bundleIdentifier) : [];
|
|
19557
|
+
const targets = scopedTargets.length > 0 ? scopedTargets : appTargets;
|
|
19558
|
+
return resolveFromCandidates(await Promise.all(targets.map(async (target) => ({
|
|
19559
|
+
label: `${target.name} (${configurationName})`,
|
|
19560
|
+
version: (target.infoPlistPath ? await readInfoPlistVersion(target.infoPlistPath) : null) ?? (isResolved(target.marketingVersion) ? target.marketingVersion : null)
|
|
19561
|
+
}))));
|
|
19441
19562
|
} catch {
|
|
19442
|
-
return
|
|
19563
|
+
return notFound;
|
|
19443
19564
|
}
|
|
19444
19565
|
};
|
|
19445
|
-
|
|
19446
|
-
|
|
19447
|
-
|
|
19448
|
-
|
|
19449
|
-
|
|
19450
|
-
|
|
19451
|
-
|
|
19452
|
-
|
|
19453
|
-
|
|
19454
|
-
|
|
19455
|
-
|
|
19456
|
-
|
|
19457
|
-
|
|
19566
|
+
/**
|
|
19567
|
+
* The iOS app version: Info.plist first, project.pbxproj as a fallback.
|
|
19568
|
+
*
|
|
19569
|
+
* CFBundleShortVersionString is the version the built app actually reports,
|
|
19570
|
+
* so it is the more correct source (#84). It is also far cheaper: reading
|
|
19571
|
+
* Info.plist is a small file read, whereas the pbxproj parser is synchronous
|
|
19572
|
+
* and blocks the event loop for the length of the parse. On a large
|
|
19573
|
+
* project.pbxproj that can take minutes. The React Native template ships
|
|
19574
|
+
* Info.plist with CFBundleShortVersionString set to "$(MARKETING_VERSION)",
|
|
19575
|
+
* which the plist parser cannot resolve, so the real version only lives in
|
|
19576
|
+
* project.pbxproj for most projects.
|
|
19577
|
+
*/
|
|
19578
|
+
const resolveIOSAppVersion = async (scope) => {
|
|
19579
|
+
const plistVersion = await getIOSVersionFromInfoPlist();
|
|
19580
|
+
if (plistVersion) return {
|
|
19581
|
+
version: plistVersion,
|
|
19582
|
+
candidates: [{
|
|
19583
|
+
label: "Info.plist",
|
|
19584
|
+
version: plistVersion
|
|
19585
|
+
}]
|
|
19586
|
+
};
|
|
19587
|
+
return getIOSVersionFromXcodeProject(scope);
|
|
19458
19588
|
};
|
|
19459
19589
|
//#endregion
|
|
19460
19590
|
//#region src/utils/version/getNativeAppVersion.ts
|
|
19461
|
-
|
|
19591
|
+
/**
|
|
19592
|
+
* The version the native project builds, with every place it is declared.
|
|
19593
|
+
* A project that builds several apps (Xcode targets, product flavors) with
|
|
19594
|
+
* different versions resolves to null unless `scope` names the one built.
|
|
19595
|
+
*/
|
|
19596
|
+
const resolveNativeAppVersion = async (platform, scope = {}) => {
|
|
19462
19597
|
switch (platform) {
|
|
19463
|
-
case "ios": return
|
|
19464
|
-
case "android": return
|
|
19465
|
-
default: return
|
|
19598
|
+
case "ios": return resolveIOSAppVersion(scope.ios);
|
|
19599
|
+
case "android": return resolveAndroidAppVersion(scope.android);
|
|
19600
|
+
default: return {
|
|
19601
|
+
version: null,
|
|
19602
|
+
candidates: []
|
|
19603
|
+
};
|
|
19466
19604
|
}
|
|
19467
19605
|
};
|
|
19606
|
+
const getNativeAppVersion = async (platform, scope) => (await resolveNativeAppVersion(platform, scope)).version;
|
|
19468
19607
|
//#endregion
|
|
19469
19608
|
//#region src/commands/appVersion.ts
|
|
19470
19609
|
const readAppVersions = async () => {
|
|
19471
|
-
const [
|
|
19610
|
+
const [android, ios] = await Promise.all([resolveNativeAppVersion("android"), resolveNativeAppVersion("ios")]);
|
|
19472
19611
|
return {
|
|
19473
|
-
android
|
|
19474
|
-
ios
|
|
19612
|
+
android,
|
|
19613
|
+
ios
|
|
19475
19614
|
};
|
|
19476
19615
|
};
|
|
19616
|
+
const formatVersion = (resolved) => isAmbiguousAppVersion(resolved) ? ui.warning(`several (${formatAppVersionCandidates(resolved.candidates)}); deploy needs -t`) : ui.version(resolved.version);
|
|
19477
19617
|
const handleAppVersion = async (options = {}) => {
|
|
19478
19618
|
const versions = await readAppVersions();
|
|
19479
19619
|
if (options.json) {
|
|
19480
|
-
console.log(JSON.stringify(
|
|
19620
|
+
console.log(JSON.stringify({
|
|
19621
|
+
android: versions.android.version,
|
|
19622
|
+
ios: versions.ios.version
|
|
19623
|
+
}, null, 2));
|
|
19481
19624
|
return;
|
|
19482
19625
|
}
|
|
19483
|
-
p.log.message(ui.block("App version", [ui.kv("Android",
|
|
19626
|
+
p.log.message(ui.block("App version", [ui.kv("Android", formatVersion(versions.android)), ui.kv("iOS", formatVersion(versions.ios))]));
|
|
19484
19627
|
};
|
|
19485
19628
|
//#endregion
|
|
19486
19629
|
//#region ../../node_modules/.pnpm/is-plain-obj@4.1.0/node_modules/is-plain-obj/index.js
|
|
@@ -25767,11 +25910,25 @@ async function prepareNativeBuild(options) {
|
|
|
25767
25910
|
} else if (config.updateStrategy === "appVersion") {
|
|
25768
25911
|
const s = p.spinner();
|
|
25769
25912
|
s.start(`Get native app version (${platform})`);
|
|
25770
|
-
const
|
|
25913
|
+
const iosScheme = config.nativeBuild.ios[scheme];
|
|
25914
|
+
const androidScheme = config.nativeBuild.android[scheme];
|
|
25915
|
+
const resolved = await resolveNativeAppVersion(platform, {
|
|
25916
|
+
ios: iosScheme && {
|
|
25917
|
+
scheme: iosScheme.scheme,
|
|
25918
|
+
bundleIdentifier: iosScheme.bundleIdentifier,
|
|
25919
|
+
configuration: iosScheme.configuration
|
|
25920
|
+
},
|
|
25921
|
+
android: androidScheme && {
|
|
25922
|
+
variant: androidScheme.variant,
|
|
25923
|
+
applicationId: androidScheme.applicationId ?? androidScheme.packageName,
|
|
25924
|
+
appModuleName: androidScheme.appModuleName
|
|
25925
|
+
}
|
|
25926
|
+
});
|
|
25927
|
+
const appVersion = resolved.version;
|
|
25771
25928
|
s.stop(`App Version(${platform}): ${appVersion}`);
|
|
25772
25929
|
target.appVersion = appVersion;
|
|
25773
25930
|
if (!target.appVersion) {
|
|
25774
|
-
p.log.error(`Failed to retrieve native app version of ${platform}`);
|
|
25931
|
+
p.log.error(isAmbiguousAppVersion(resolved) ? platform === "ios" ? `nativeBuild.ios.${scheme} (scheme ${iosScheme?.scheme}, bundleIdentifier ${iosScheme?.bundleIdentifier}) does not pick one of the app targets in project.pbxproj, which declare different versions (${formatAppVersionCandidates(resolved.candidates)}). Make its scheme match the name of the app target it builds.` : `nativeBuild.android.${scheme} (variant ${androidScheme?.variant ?? "Release"}) does not pick one of the product flavors that set versionName, which declare different versions (${formatAppVersionCandidates(resolved.candidates)}). Set its variant to the flavor it builds, such as brandARelease.` : `Failed to retrieve native app version of ${platform}`);
|
|
25775
25932
|
return null;
|
|
25776
25933
|
}
|
|
25777
25934
|
}
|
|
@@ -26913,18 +27070,23 @@ async function validateSigningConfig(config, options = {}) {
|
|
|
26913
27070
|
}
|
|
26914
27071
|
//#endregion
|
|
26915
27072
|
//#region src/utils/version/getDefaultTargetAppVersion.ts
|
|
27073
|
+
/**
|
|
27074
|
+
* The target app version deploy defaults to, as a range. `version` is null
|
|
27075
|
+
* when the native files declare none, or several (see `candidates`).
|
|
27076
|
+
*/
|
|
26916
27077
|
const getDefaultTargetAppVersion = async (platform) => {
|
|
26917
|
-
|
|
26918
|
-
|
|
26919
|
-
|
|
26920
|
-
|
|
26921
|
-
|
|
26922
|
-
|
|
26923
|
-
}
|
|
26924
|
-
if (!version) return null;
|
|
26925
|
-
if (!(/^\d+\.\d+$/.test(version) || normalizeRange(version))) return null;
|
|
27078
|
+
const resolved = await resolveNativeAppVersion(platform);
|
|
27079
|
+
let version = resolved.version;
|
|
27080
|
+
if (!version) return resolved;
|
|
27081
|
+
if (!(/^\d+\.\d+$/.test(version) || normalizeRange(version))) return {
|
|
27082
|
+
...resolved,
|
|
27083
|
+
version: null
|
|
27084
|
+
};
|
|
26926
27085
|
if (version.split(".").length - 1 === 1) version = `${version}.x`;
|
|
26927
|
-
return
|
|
27086
|
+
return {
|
|
27087
|
+
...resolved,
|
|
27088
|
+
version
|
|
27089
|
+
};
|
|
26928
27090
|
};
|
|
26929
27091
|
//#endregion
|
|
26930
27092
|
//#region src/commands/deployTransaction.ts
|
|
@@ -27250,18 +27412,20 @@ const deployPlatform = async ({ config, core, database, deferAutoPatches, option
|
|
|
27250
27412
|
target.fingerprintHash = newFingerprint.hash;
|
|
27251
27413
|
s.stop(`Fingerprint(${platform}): ${newFingerprint.hash}`);
|
|
27252
27414
|
} else {
|
|
27253
|
-
const defaultTargetAppVersion = await getDefaultTargetAppVersion(platform);
|
|
27415
|
+
const defaultTargetAppVersion = options.targetAppVersion ? null : await getDefaultTargetAppVersion(platform);
|
|
27416
|
+
const ambiguousVersions = defaultTargetAppVersion && isAmbiguousAppVersion(defaultTargetAppVersion) ? formatAppVersionCandidates(defaultTargetAppVersion.candidates) : null;
|
|
27417
|
+
const defaultVersion = defaultTargetAppVersion?.version ?? null;
|
|
27254
27418
|
const targetAppVersion = options.targetAppVersion ?? (options.interactive ? await p.text({
|
|
27255
|
-
message: "Target app version",
|
|
27256
|
-
placeholder:
|
|
27257
|
-
initialValue:
|
|
27419
|
+
message: ambiguousVersions ? `Target app version (the native project builds several versions: ${ambiguousVersions})` : "Target app version",
|
|
27420
|
+
placeholder: defaultVersion ?? "1.0.0",
|
|
27421
|
+
initialValue: defaultVersion ?? (ambiguousVersions ? "" : "1.0.0"),
|
|
27258
27422
|
validate: (value) => {
|
|
27259
27423
|
if (!value || !normalizeRange(value)) return "Invalid semver format (e.g. 1.0.0, 1.x.x)";
|
|
27260
27424
|
}
|
|
27261
|
-
}) :
|
|
27425
|
+
}) : defaultVersion);
|
|
27262
27426
|
if (p.isCancel(targetAppVersion)) return null;
|
|
27263
27427
|
if (!targetAppVersion) {
|
|
27264
|
-
p.log.error("Target app version not found in native files (Info.plist for iOS, build.gradle for Android). Pass -t <targetAppVersion> explicitly, or check your native config.");
|
|
27428
|
+
p.log.error(ambiguousVersions ? `The native project builds several app versions (${ambiguousVersions}), so the target app version for this deploy cannot be read from it. Pass -t <targetAppVersion> for the app this deploy targets.` : "Target app version not found in native files (Info.plist or project.pbxproj for iOS, build.gradle for Android). Pass -t <targetAppVersion> explicitly, or check your native config.");
|
|
27265
27429
|
return null;
|
|
27266
27430
|
}
|
|
27267
27431
|
target.appVersion = targetAppVersion;
|
|
@@ -4550,7 +4550,7 @@ const createKvAdapter = ({ store, tablePrefix = "" }) => {
|
|
|
4550
4550
|
};
|
|
4551
4551
|
//#endregion
|
|
4552
4552
|
//#region ../../packages/server/dist/version.mjs
|
|
4553
|
-
const HOT_UPDATER_SERVER_VERSION = "1.0.
|
|
4553
|
+
const HOT_UPDATER_SERVER_VERSION = "1.0.1";
|
|
4554
4554
|
//#endregion
|
|
4555
4555
|
//#region ../../packages/server/dist/handlerVersionRoutes.mjs
|
|
4556
4556
|
/**
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"provider": "aws",
|
|
4
|
-
"cliVersion": "1.0.
|
|
5
|
-
"providerVersion": "1.0.
|
|
6
|
-
"serverVersion": "1.0.
|
|
4
|
+
"cliVersion": "1.0.1",
|
|
5
|
+
"providerVersion": "1.0.1",
|
|
6
|
+
"serverVersion": "1.0.1",
|
|
7
7
|
"infrastructureGeneration": 1,
|
|
8
8
|
"clientAuth": {
|
|
9
9
|
"plugin": "apiKeys",
|
|
@@ -65,13 +65,13 @@
|
|
|
65
65
|
}
|
|
66
66
|
],
|
|
67
67
|
"packages": {
|
|
68
|
-
"hot-updater": "1.0.
|
|
69
|
-
"@hot-updater/server": "1.0.
|
|
70
|
-
"@hot-updater/react-native": "1.0.
|
|
71
|
-
"@hot-updater/aws": "1.0.
|
|
72
|
-
"@hot-updater/bare": "1.0.
|
|
73
|
-
"@hot-updater/rock": "1.0.
|
|
74
|
-
"@hot-updater/expo": "1.0.
|
|
68
|
+
"hot-updater": "1.0.1",
|
|
69
|
+
"@hot-updater/server": "1.0.1",
|
|
70
|
+
"@hot-updater/react-native": "1.0.1",
|
|
71
|
+
"@hot-updater/aws": "1.0.1",
|
|
72
|
+
"@hot-updater/bare": "1.0.1",
|
|
73
|
+
"@hot-updater/rock": "1.0.1",
|
|
74
|
+
"@hot-updater/expo": "1.0.1",
|
|
75
75
|
"@aws-sdk/credential-providers": "3.1066.0"
|
|
76
76
|
},
|
|
77
77
|
"requiredInputs": {
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schemaVersion": 1,
|
|
3
3
|
"provider": "cloudflare",
|
|
4
|
-
"cliVersion": "1.0.
|
|
5
|
-
"providerVersion": "1.0.
|
|
6
|
-
"serverVersion": "1.0.
|
|
4
|
+
"cliVersion": "1.0.1",
|
|
5
|
+
"providerVersion": "1.0.1",
|
|
6
|
+
"serverVersion": "1.0.1",
|
|
7
7
|
"infrastructureGeneration": 1,
|
|
8
8
|
"clientAuth": {
|
|
9
9
|
"plugin": "apiKeys",
|
|
@@ -61,13 +61,13 @@
|
|
|
61
61
|
}
|
|
62
62
|
],
|
|
63
63
|
"packages": {
|
|
64
|
-
"hot-updater": "1.0.
|
|
65
|
-
"@hot-updater/server": "1.0.
|
|
66
|
-
"@hot-updater/react-native": "1.0.
|
|
67
|
-
"@hot-updater/cloudflare": "1.0.
|
|
68
|
-
"@hot-updater/bare": "1.0.
|
|
69
|
-
"@hot-updater/rock": "1.0.
|
|
70
|
-
"@hot-updater/expo": "1.0.
|
|
64
|
+
"hot-updater": "1.0.1",
|
|
65
|
+
"@hot-updater/server": "1.0.1",
|
|
66
|
+
"@hot-updater/react-native": "1.0.1",
|
|
67
|
+
"@hot-updater/cloudflare": "1.0.1",
|
|
68
|
+
"@hot-updater/bare": "1.0.1",
|
|
69
|
+
"@hot-updater/rock": "1.0.1",
|
|
70
|
+
"@hot-updater/expo": "1.0.1"
|
|
71
71
|
},
|
|
72
72
|
"requiredInputs": {
|
|
73
73
|
"workerName": null,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
This folder contains the built output assets for the worker "hot-updater" generated at 2026-10-
|
|
1
|
+
This folder contains the built output assets for the worker "hot-updater" generated at 2026-10-12T01:32:33.502Z.
|
|
@@ -4510,7 +4510,7 @@ var createSqlAdapter = /* @__PURE__ */ __name(({ executor, tablePrefix = "", max
|
|
|
4510
4510
|
}, "createSqlAdapter");
|
|
4511
4511
|
|
|
4512
4512
|
// ../../packages/server/dist/package.mjs
|
|
4513
|
-
var version = "1.0.
|
|
4513
|
+
var version = "1.0.1";
|
|
4514
4514
|
|
|
4515
4515
|
// ../../packages/server/dist/version.mjs
|
|
4516
4516
|
var HOT_UPDATER_SERVER_VERSION = version;
|