@hot-updater/aws 1.0.0-rc.45 → 1.0.0-rc.47
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/init/index.cjs +1 -1
- package/dist/init/index.mjs +1 -1
- package/dist/lambda/index.cjs +71 -113
- package/package.json +7 -7
package/dist/init/index.cjs
CHANGED
|
@@ -7800,7 +7800,7 @@ var DynamoDBTableSchemaError = class extends Error {
|
|
|
7800
7800
|
tableName;
|
|
7801
7801
|
name = "DynamoDBTableSchemaError";
|
|
7802
7802
|
constructor(tableName) {
|
|
7803
|
-
super(`DynamoDB table "${tableName}" does not match the Hot Updater schema: a pk and sk key and no secondary index.
|
|
7803
|
+
super(`DynamoDB table "${tableName}" does not match the Hot Updater schema: a pk and sk key and no secondary index. Delete the table and rerun init to create it again.`);
|
|
7804
7804
|
this.tableName = tableName;
|
|
7805
7805
|
}
|
|
7806
7806
|
};
|
package/dist/init/index.mjs
CHANGED
|
@@ -7795,7 +7795,7 @@ var DynamoDBTableSchemaError = class extends Error {
|
|
|
7795
7795
|
tableName;
|
|
7796
7796
|
name = "DynamoDBTableSchemaError";
|
|
7797
7797
|
constructor(tableName) {
|
|
7798
|
-
super(`DynamoDB table "${tableName}" does not match the Hot Updater schema: a pk and sk key and no secondary index.
|
|
7798
|
+
super(`DynamoDB table "${tableName}" does not match the Hot Updater schema: a pk and sk key and no secondary index. Delete the table and rerun init to create it again.`);
|
|
7799
7799
|
this.tableName = tableName;
|
|
7800
7800
|
}
|
|
7801
7801
|
};
|
package/dist/lambda/index.cjs
CHANGED
|
@@ -241,6 +241,13 @@ const isDatabaseJsonValue = (value) => {
|
|
|
241
241
|
const isDatabaseJsonObject = (value) => typeof value === "object" && value !== null && !Array.isArray(value) && isDatabaseJsonValue(value);
|
|
242
242
|
const isDatabaseMetadataObject = (value) => isDatabaseJsonObject(value) && (!Object.hasOwn(value, "app_version") || typeof value["app_version"] === "string");
|
|
243
243
|
//#endregion
|
|
244
|
+
//#region ../plugin-core/dist/databaseMetadata.mjs
|
|
245
|
+
const bundleMetadataToRow = (metadata) => {
|
|
246
|
+
if (metadata === void 0) return {};
|
|
247
|
+
if (!isDatabaseMetadataObject(metadata)) throw new DatabaseAdapterInputError("invalid-data");
|
|
248
|
+
return metadata;
|
|
249
|
+
};
|
|
250
|
+
//#endregion
|
|
244
251
|
//#region ../../packages/protocol/dist/index.mjs
|
|
245
252
|
const LETTER_DASH_NUMBER$2 = "[a-zA-Z0-9-]";
|
|
246
253
|
const NUMERIC_IDENTIFIER$2 = String.raw`0|[1-9]\d*`;
|
|
@@ -354,7 +361,6 @@ function canonicalizeAppVersion(appVersion) {
|
|
|
354
361
|
const version = coerce$1(appVersion);
|
|
355
362
|
return version ? normalizeFull(version) : null;
|
|
356
363
|
}
|
|
357
|
-
const stripBundleArtifactMetadata = (metadata) => metadata;
|
|
358
364
|
const getManifestStorageUri = (bundle) => bundle.manifestStorageUri;
|
|
359
365
|
const getManifestFileHash = (bundle) => bundle.manifestFileHash;
|
|
360
366
|
const getAssetBaseStorageUri = (bundle) => bundle.assetBaseStorageUri;
|
|
@@ -601,14 +607,6 @@ const NIL_UUID = "00000000-0000-0000-0000-000000000000";
|
|
|
601
607
|
const UUID_V7_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
602
608
|
const isUUIDv7 = (value) => typeof value === "string" && UUID_V7_PATTERN.test(value);
|
|
603
609
|
//#endregion
|
|
604
|
-
//#region ../plugin-core/dist/databaseMetadata.mjs
|
|
605
|
-
const bundleMetadataToRow = (metadata) => {
|
|
606
|
-
const value = stripBundleArtifactMetadata(metadata);
|
|
607
|
-
if (value === void 0) return {};
|
|
608
|
-
if (!isDatabaseMetadataObject(value)) throw new DatabaseAdapterInputError("invalid-data");
|
|
609
|
-
return value;
|
|
610
|
-
};
|
|
611
|
-
//#endregion
|
|
612
610
|
//#region ../plugin-core/dist/databaseRows.mjs
|
|
613
611
|
const releaseRowToRelease = (row) => ({
|
|
614
612
|
id: row.id,
|
|
@@ -666,7 +664,7 @@ const rowToBundle = (row, patchRows = []) => {
|
|
|
666
664
|
id: row.id,
|
|
667
665
|
platform: row.platform,
|
|
668
666
|
gitCommitHash: row.git_commit_hash,
|
|
669
|
-
metadata:
|
|
667
|
+
metadata: row.metadata,
|
|
670
668
|
manifestStorageUri: row.manifest_storage_uri,
|
|
671
669
|
manifestFileHash: row.manifest_file_hash,
|
|
672
670
|
assetBaseStorageUri: row.asset_base_storage_uri,
|
|
@@ -674,6 +672,35 @@ const rowToBundle = (row, patchRows = []) => {
|
|
|
674
672
|
};
|
|
675
673
|
};
|
|
676
674
|
//#endregion
|
|
675
|
+
//#region ../plugin-core/dist/uuidv7.mjs
|
|
676
|
+
const extractTimestampFromUUIDv7 = (uuid) => {
|
|
677
|
+
if (!isUUIDv7(uuid)) throw new TypeError("Expected a canonical lowercase UUIDv7");
|
|
678
|
+
const timestampHex = uuid.split("-").join("").slice(0, 12);
|
|
679
|
+
return Number.parseInt(timestampHex, 16);
|
|
680
|
+
};
|
|
681
|
+
function createUUIDv7FromTimestampHex(timestampHex) {
|
|
682
|
+
const randomBytes = /* @__PURE__ */ new Uint8Array(10);
|
|
683
|
+
crypto.getRandomValues(randomBytes);
|
|
684
|
+
const randomHex = Array.from(randomBytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
685
|
+
const randA = randomHex.slice(0, 3);
|
|
686
|
+
const randBHex = randomHex.slice(3, 19);
|
|
687
|
+
const versionAndRandA = `7${randA}`;
|
|
688
|
+
const variantAndFirstRandB = (128 | parseInt(randBHex.slice(0, 2), 16) & 63).toString(16).padStart(2, "0");
|
|
689
|
+
return [
|
|
690
|
+
timestampHex.slice(0, 8),
|
|
691
|
+
timestampHex.slice(8, 12),
|
|
692
|
+
versionAndRandA,
|
|
693
|
+
variantAndFirstRandB + randBHex.slice(2, 4),
|
|
694
|
+
randBHex.slice(4, 16)
|
|
695
|
+
].join("-");
|
|
696
|
+
}
|
|
697
|
+
const createUUIDv7 = () => createUUIDv7FromTimestampHex(Date.now().toString(16).padStart(12, "0"));
|
|
698
|
+
const createUUIDv7After = (floor, nowMs = Date.now()) => {
|
|
699
|
+
const timestamp = Math.max(nowMs, floor === null ? 0 : extractTimestampFromUUIDv7(floor) + 1);
|
|
700
|
+
if (!Number.isSafeInteger(timestamp) || timestamp < 0 || timestamp >= 2 ** 48) throw new RangeError("UUIDv7 timestamp is out of range");
|
|
701
|
+
return createUUIDv7FromTimestampHex(timestamp.toString(16).padStart(12, "0"));
|
|
702
|
+
};
|
|
703
|
+
//#endregion
|
|
677
704
|
//#region ../plugin-core/dist/node_modules/.pnpm/verkit@0.4.0/node_modules/verkit/dist/comparison-DenM3wCn.mjs
|
|
678
705
|
const LETTER_DASH_NUMBER$1 = "[a-zA-Z0-9-]";
|
|
679
706
|
const NUMERIC_IDENTIFIER$1 = String.raw`0|[1-9]\d*`;
|
|
@@ -1020,42 +1047,6 @@ function coerce(value, options = {}) {
|
|
|
1020
1047
|
return tryParse(`${major}.${match[3] || "0"}.${match[4] || "0"}${options.includePrerelease && match[5] ? `-${match[5]}` : ""}${options.includePrerelease && match[6] ? `+${match[6]}` : ""}`, options);
|
|
1021
1048
|
}
|
|
1022
1049
|
//#endregion
|
|
1023
|
-
//#region ../plugin-core/dist/semverSatisfies.mjs
|
|
1024
|
-
const semverSatisfies = (targetAppVersion, currentVersion) => {
|
|
1025
|
-
const currentCoerce = coerce(currentVersion);
|
|
1026
|
-
if (!currentCoerce) return false;
|
|
1027
|
-
return satisfies(currentCoerce, targetAppVersion);
|
|
1028
|
-
};
|
|
1029
|
-
//#endregion
|
|
1030
|
-
//#region ../plugin-core/dist/uuidv7.mjs
|
|
1031
|
-
const extractTimestampFromUUIDv7 = (uuid) => {
|
|
1032
|
-
if (!isUUIDv7(uuid)) throw new TypeError("Expected a canonical lowercase UUIDv7");
|
|
1033
|
-
const timestampHex = uuid.split("-").join("").slice(0, 12);
|
|
1034
|
-
return Number.parseInt(timestampHex, 16);
|
|
1035
|
-
};
|
|
1036
|
-
function createUUIDv7FromTimestampHex(timestampHex) {
|
|
1037
|
-
const randomBytes = /* @__PURE__ */ new Uint8Array(10);
|
|
1038
|
-
crypto.getRandomValues(randomBytes);
|
|
1039
|
-
const randomHex = Array.from(randomBytes).map((b) => b.toString(16).padStart(2, "0")).join("");
|
|
1040
|
-
const randA = randomHex.slice(0, 3);
|
|
1041
|
-
const randBHex = randomHex.slice(3, 19);
|
|
1042
|
-
const versionAndRandA = `7${randA}`;
|
|
1043
|
-
const variantAndFirstRandB = (128 | parseInt(randBHex.slice(0, 2), 16) & 63).toString(16).padStart(2, "0");
|
|
1044
|
-
return [
|
|
1045
|
-
timestampHex.slice(0, 8),
|
|
1046
|
-
timestampHex.slice(8, 12),
|
|
1047
|
-
versionAndRandA,
|
|
1048
|
-
variantAndFirstRandB + randBHex.slice(2, 4),
|
|
1049
|
-
randBHex.slice(4, 16)
|
|
1050
|
-
].join("-");
|
|
1051
|
-
}
|
|
1052
|
-
const createUUIDv7 = () => createUUIDv7FromTimestampHex(Date.now().toString(16).padStart(12, "0"));
|
|
1053
|
-
const createUUIDv7After = (floor, nowMs = Date.now()) => {
|
|
1054
|
-
const timestamp = Math.max(nowMs, floor === null ? 0 : extractTimestampFromUUIDv7(floor) + 1);
|
|
1055
|
-
if (!Number.isSafeInteger(timestamp) || timestamp < 0 || timestamp >= 2 ** 48) throw new RangeError("UUIDv7 timestamp is out of range");
|
|
1056
|
-
return createUUIDv7FromTimestampHex(timestamp.toString(16).padStart(12, "0"));
|
|
1057
|
-
};
|
|
1058
|
-
//#endregion
|
|
1059
1050
|
//#region ../plugin-core/dist/releaseCatalogCompiler.mjs
|
|
1060
1051
|
var ReleaseCatalogCompilationError = class extends Error {
|
|
1061
1052
|
code;
|
|
@@ -1163,29 +1154,23 @@ function validateReleases(releases, strategy) {
|
|
|
1163
1154
|
if (seenIds.has(release.id)) throw new ReleaseCatalogCompilationError("INVALID_RELEASE", `Duplicate Release ID: ${release.id}`);
|
|
1164
1155
|
seenIds.add(release.id);
|
|
1165
1156
|
if (release.strategy !== strategy) throw new ReleaseCatalogCompilationError("INVALID_RELEASE", `Release ${release.id} has the wrong strategy`);
|
|
1166
|
-
if (release.
|
|
1157
|
+
if (release.bundleId === null) throw new ReleaseCatalogCompilationError("INVALID_RELEASE", `Release ${release.id} has no Bundle`);
|
|
1167
1158
|
if (release.targetCohorts.length > 100) throw new ReleaseCatalogCompilationError("TARGET_COHORT_LIMIT", `Release ${release.id} exceeds 100 target cohorts`);
|
|
1168
1159
|
if (strategy === "APP_VERSION" && (release.targetAppVersion === null || release.fingerprintHash !== null)) throw new ReleaseCatalogCompilationError("INVALID_RELEASE", `Release ${release.id} has an invalid app-version target`);
|
|
1169
1160
|
if (strategy === "FINGERPRINT" && (release.fingerprintHash === null || release.targetAppVersion !== null)) throw new ReleaseCatalogCompilationError("INVALID_RELEASE", `Release ${release.id} has an invalid fingerprint target`);
|
|
1170
1161
|
}
|
|
1171
|
-
return enabled
|
|
1162
|
+
return enabled;
|
|
1172
1163
|
}
|
|
1173
1164
|
function collectFrontierReleaseIds(releases) {
|
|
1174
1165
|
if (releases.every((release) => normalizeRolloutCohortCount(release.rolloutCohortCount) >= 1e3)) {
|
|
1175
1166
|
const retained = /* @__PURE__ */ new Set();
|
|
1176
1167
|
const bundleIds = /* @__PURE__ */ new Set();
|
|
1177
|
-
let embedded = false;
|
|
1178
1168
|
for (const release of releases) {
|
|
1179
|
-
if (release.
|
|
1180
|
-
if (!embedded) {
|
|
1181
|
-
embedded = true;
|
|
1182
|
-
retained.add(release.id);
|
|
1183
|
-
}
|
|
1184
|
-
} else if (release.bundleId !== null && bundleIds.size < 11 && !bundleIds.has(release.bundleId)) {
|
|
1169
|
+
if (release.bundleId !== null && !bundleIds.has(release.bundleId)) {
|
|
1185
1170
|
bundleIds.add(release.bundleId);
|
|
1186
1171
|
retained.add(release.id);
|
|
1187
1172
|
}
|
|
1188
|
-
if (
|
|
1173
|
+
if (bundleIds.size >= 11) break;
|
|
1189
1174
|
}
|
|
1190
1175
|
return retained;
|
|
1191
1176
|
}
|
|
@@ -1202,7 +1187,6 @@ function collectFrontierReleaseIds(releases) {
|
|
|
1202
1187
|
normalized,
|
|
1203
1188
|
numeric: normalized === void 0 ? null : getNumericCohortValue(normalized),
|
|
1204
1189
|
bundleIds: /* @__PURE__ */ new Set(),
|
|
1205
|
-
embedded: false,
|
|
1206
1190
|
complete: false
|
|
1207
1191
|
};
|
|
1208
1192
|
});
|
|
@@ -1227,16 +1211,11 @@ function collectFrontierReleaseIds(releases) {
|
|
|
1227
1211
|
for (const index of eligibleStateIndexes) {
|
|
1228
1212
|
const state = cohortStates[index];
|
|
1229
1213
|
if (state.complete) continue;
|
|
1230
|
-
if (release.
|
|
1231
|
-
if (!state.embedded) {
|
|
1232
|
-
state.embedded = true;
|
|
1233
|
-
retained.add(release.id);
|
|
1234
|
-
}
|
|
1235
|
-
} else if (release.bundleId !== null && state.bundleIds.size < 11 && !state.bundleIds.has(release.bundleId)) {
|
|
1214
|
+
if (release.bundleId !== null && !state.bundleIds.has(release.bundleId)) {
|
|
1236
1215
|
state.bundleIds.add(release.bundleId);
|
|
1237
1216
|
retained.add(release.id);
|
|
1238
1217
|
}
|
|
1239
|
-
if (state.
|
|
1218
|
+
if (state.bundleIds.size >= 11) {
|
|
1240
1219
|
state.complete = true;
|
|
1241
1220
|
incompleteStateCount -= 1;
|
|
1242
1221
|
}
|
|
@@ -1421,12 +1400,11 @@ function projectCompiledCatalog(catalog, appVersion) {
|
|
|
1421
1400
|
}
|
|
1422
1401
|
function projectCompiledRollbackCatalog(catalog, appVersion) {
|
|
1423
1402
|
let indexes;
|
|
1424
|
-
if (catalog.strategy === "FINGERPRINT") indexes = catalog.rollbackReleaseIndexes
|
|
1403
|
+
if (catalog.strategy === "FINGERPRINT") indexes = catalog.rollbackReleaseIndexes;
|
|
1425
1404
|
else {
|
|
1426
1405
|
const canonicalVersion = appVersion && canonicalizeAppVersion(appVersion);
|
|
1427
1406
|
if (!canonicalVersion) return [];
|
|
1428
|
-
|
|
1429
|
-
indexes = segment?.rollbackReleaseIndexes ?? segment?.releaseIndexes ?? [];
|
|
1407
|
+
indexes = catalog.segments.find((segment) => versionInSegment(canonicalVersion, segment))?.rollbackReleaseIndexes ?? [];
|
|
1430
1408
|
}
|
|
1431
1409
|
return indexes.map((index) => catalog.releaseDescriptors[index]);
|
|
1432
1410
|
}
|
|
@@ -1451,6 +1429,13 @@ var ReleaseCatalogMutationError = class extends Error {
|
|
|
1451
1429
|
}
|
|
1452
1430
|
};
|
|
1453
1431
|
//#endregion
|
|
1432
|
+
//#region ../plugin-core/dist/semverSatisfies.mjs
|
|
1433
|
+
const semverSatisfies = (targetAppVersion, currentVersion) => {
|
|
1434
|
+
const currentCoerce = coerce(currentVersion);
|
|
1435
|
+
if (!currentCoerce) return false;
|
|
1436
|
+
return satisfies(currentCoerce, targetAppVersion);
|
|
1437
|
+
};
|
|
1438
|
+
//#endregion
|
|
1454
1439
|
//#region ../plugin-core/dist/serverPlugin/definePlugin.mjs
|
|
1455
1440
|
/** Declares a plugin; Hot Updater's own plugins and third-party ones use the same contract. */
|
|
1456
1441
|
const definePlugin = (plugin) => plugin;
|
|
@@ -1941,7 +1926,7 @@ const SETTINGS_TABLE = {
|
|
|
1941
1926
|
const ENGINE_SCHEMA_KEY = "schema.engine";
|
|
1942
1927
|
const CORE_SCHEMA_KEY = "schema.core";
|
|
1943
1928
|
const stored = ({ key, expected, found }) => `"${key}" is ${found === null ? "missing" : `"${found}"`}; expected "${expected}"`;
|
|
1944
|
-
const settingMessage = (adapterName, { key, expected, found }) => `Hot Updater schema setting "${key}" for ${adapterName} is ${found === null ? "missing" : `"${found}"`}; expected "${expected}".
|
|
1929
|
+
const settingMessage = (adapterName, { key, expected, found }) => `Hot Updater schema setting "${key}" for ${adapterName} is ${found === null ? "missing" : `"${found}"`}; expected "${expected}". Run \`hot-updater db migrate\`.`;
|
|
1945
1930
|
/** The plugin a `schema.<id>` setting belongs to; undefined for core's and the engine's. */
|
|
1946
1931
|
const pluginOf = ({ key }) => key.startsWith("schema.") && key !== "schema.engine" && key !== CORE_SCHEMA_KEY ? key.slice(7) : void 0;
|
|
1947
1932
|
const listed = (items) => items.length < 2 ? items.join("") : `${items.slice(0, -1).join(", ")} and ${items.at(-1)}`;
|
|
@@ -2059,26 +2044,13 @@ const METER = Symbol.for("@hot-updater/plugin-core/read-meter");
|
|
|
2059
2044
|
const readMeterOf = (database) => typeof database === "object" && database !== null ? database[METER] : void 0;
|
|
2060
2045
|
//#endregion
|
|
2061
2046
|
//#region ../plugin-core/dist/engine/db/schemaSettings.mjs
|
|
2062
|
-
/** Refuses a database with `schema.core` but no `schema.engine`: it predates the engine. */
|
|
2063
|
-
const assertEngineDatabase = (adapterName, stored) => {
|
|
2064
|
-
if (stored.get("schema.core") && !stored.get("schema.engine")) throw new HotUpdaterSchemaMigrationRequiredError(adapterName, String(stored.get("schema.core").value), {
|
|
2065
|
-
key: ENGINE_SCHEMA_KEY,
|
|
2066
|
-
expected: "1",
|
|
2067
|
-
found: null
|
|
2068
|
-
});
|
|
2069
|
-
};
|
|
2070
2047
|
const storedSettings = async (adapter, keys) => {
|
|
2071
2048
|
const rows = await readSettings(adapter, keys);
|
|
2072
2049
|
return new Map(keys.map((key, position) => [key, rows[position] ?? null]));
|
|
2073
2050
|
};
|
|
2074
|
-
/** Writes the settings rows after every table exists
|
|
2051
|
+
/** Writes the settings rows after every table exists. */
|
|
2075
2052
|
const writeSchemaSettings = async (adapter, adapterName, settings) => {
|
|
2076
|
-
const stored = await storedSettings(adapter,
|
|
2077
|
-
"schema.core",
|
|
2078
|
-
ENGINE_SCHEMA_KEY,
|
|
2079
|
-
...Object.keys(settings)
|
|
2080
|
-
])]);
|
|
2081
|
-
assertEngineDatabase(adapterName, stored);
|
|
2053
|
+
const stored = await storedSettings(adapter, Object.keys(settings));
|
|
2082
2054
|
const ops = Object.entries(settings).flatMap(([key, value]) => {
|
|
2083
2055
|
const row = stored.get(key);
|
|
2084
2056
|
if (row === null || row === void 0) return [{
|
|
@@ -2101,19 +2073,11 @@ const writeSchemaSettings = async (adapter, adapterName, settings) => {
|
|
|
2101
2073
|
}];
|
|
2102
2074
|
});
|
|
2103
2075
|
if (ops.length === 0) return;
|
|
2104
|
-
if (!(await adapter.write(ops)).ok) throw new Error(
|
|
2076
|
+
if (!(await adapter.write(ops)).ok) throw new Error(`${adapterName}: the schema settings changed during the migration; run it again.`);
|
|
2105
2077
|
};
|
|
2106
|
-
/**
|
|
2107
|
-
* Creates or updates every table, then writes the settings rows last. A
|
|
2108
|
-
* pre-engine database is refused before any table changes.
|
|
2109
|
-
*/
|
|
2078
|
+
/** Creates or updates every table, then writes the settings rows last. */
|
|
2110
2079
|
const migrateSchema = async (adapter, adapterName, tables, settings) => {
|
|
2111
2080
|
if (adapter.migrations === void 0) throw new Error(`${adapterName} creates its tables with its own tooling; write only the settings rows.`);
|
|
2112
|
-
const stored = await storedSettings(adapter, ["schema.core", ENGINE_SCHEMA_KEY]).catch((error) => {
|
|
2113
|
-
if (!isMissingSchemaError(error)) throw error;
|
|
2114
|
-
return /* @__PURE__ */ new Map();
|
|
2115
|
-
});
|
|
2116
|
-
assertEngineDatabase(adapterName, stored);
|
|
2117
2081
|
await adapter.migrations.apply([...tables, SETTINGS_TABLE]);
|
|
2118
2082
|
await writeSchemaSettings(adapter, adapterName, settings);
|
|
2119
2083
|
};
|
|
@@ -2398,9 +2362,6 @@ const getEmptyMigrationResult = () => ({
|
|
|
2398
2362
|
execute: async () => {},
|
|
2399
2363
|
getSQL: () => ""
|
|
2400
2364
|
});
|
|
2401
|
-
const assertSupportedMigrationMode = (options) => {
|
|
2402
|
-
if (options.mode === "from-database") throw new Error("Hot Updater migrations support only mode: 'from-schema'.");
|
|
2403
|
-
};
|
|
2404
2365
|
//#endregion
|
|
2405
2366
|
//#region ../plugin-core/dist/engine/db/settingsMigrator.mjs
|
|
2406
2367
|
/** `schema.core`, or a v0 database's `version`. */
|
|
@@ -2408,15 +2369,14 @@ const storedSchemaVersion = (stored) => {
|
|
|
2408
2369
|
const version = stored?.get("schema.core") ?? stored?.get("version");
|
|
2409
2370
|
return typeof version === "string" ? version : void 0;
|
|
2410
2371
|
};
|
|
2411
|
-
/**
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
} : void 0);
|
|
2372
|
+
/**
|
|
2373
|
+
* A v0 database, whose settings hold `version` and no `schema.engine`, is
|
|
2374
|
+
* recreated, never converted.
|
|
2375
|
+
*/
|
|
2376
|
+
const refuseV0Database = (adapterName, stored) => {
|
|
2377
|
+
const version = stored.get("version");
|
|
2378
|
+
if (typeof version !== "string" || stored.has("schema.engine")) return;
|
|
2379
|
+
throw new HotUpdaterSchemaMigrationRequiredError(adapterName, version);
|
|
2420
2380
|
};
|
|
2421
2381
|
//#endregion
|
|
2422
2382
|
//#region ../plugin-core/dist/engine/database/cursor.mjs
|
|
@@ -3479,14 +3439,13 @@ const resolveSchema = (modules) => {
|
|
|
3479
3439
|
* `hot-updater db migrate` for a store whose adapter creates its own tables
|
|
3480
3440
|
* (MongoDB and the key-value stores): the tables and indexes, then the
|
|
3481
3441
|
* settings rows, applied when a setting is missing or different, and refused
|
|
3482
|
-
* on a database
|
|
3442
|
+
* on a v0 database.
|
|
3483
3443
|
*/
|
|
3484
3444
|
const createEngineMigrator = (options) => {
|
|
3485
3445
|
const getVersion = async () => storedSchemaVersion(await options.readSettings());
|
|
3486
3446
|
const makeResult = async (migrate = {}) => {
|
|
3487
|
-
assertSupportedMigrationMode(migrate);
|
|
3488
3447
|
const stored = await options.readSettings();
|
|
3489
|
-
|
|
3448
|
+
refuseV0Database(options.adapterName, stored);
|
|
3490
3449
|
if (Object.entries(options.settings).every(([key, value]) => stored.get(key) === value)) return getEmptyMigrationResult();
|
|
3491
3450
|
return {
|
|
3492
3451
|
operations: [...options.schema.tables.map((table) => ({
|
|
@@ -4591,7 +4550,7 @@ const createKvAdapter = ({ store, tablePrefix = "" }) => {
|
|
|
4591
4550
|
};
|
|
4592
4551
|
//#endregion
|
|
4593
4552
|
//#region ../../packages/server/dist/version.mjs
|
|
4594
|
-
const HOT_UPDATER_SERVER_VERSION = "1.0.0-rc.
|
|
4553
|
+
const HOT_UPDATER_SERVER_VERSION = "1.0.0-rc.47";
|
|
4595
4554
|
//#endregion
|
|
4596
4555
|
//#region ../../packages/server/dist/handlerVersionRoutes.mjs
|
|
4597
4556
|
/**
|
|
@@ -5280,7 +5239,7 @@ const baseBundleIdsOf = (row, range, bundleId, limit) => {
|
|
|
5280
5239
|
for (const { descriptor, index } of newestFirst) {
|
|
5281
5240
|
if (ids.length >= limit) break;
|
|
5282
5241
|
const id = descriptor.bundleId;
|
|
5283
|
-
if (serving.has(index) &&
|
|
5242
|
+
if (serving.has(index) && id !== null && id < bundleId && !ids.includes(id)) ids.push(id);
|
|
5284
5243
|
}
|
|
5285
5244
|
return ids;
|
|
5286
5245
|
};
|
|
@@ -6046,7 +6005,7 @@ const createCoreOperations = (db, { now = Date.now } = {}) => {
|
|
|
6046
6005
|
}),
|
|
6047
6006
|
promoteRelease: (input) => withChannels(async () => {
|
|
6048
6007
|
const checkSource = (source) => {
|
|
6049
|
-
if (source.
|
|
6008
|
+
if (source.bundle_id === null) throw new ReleaseManagementError("TARGET_RELEASE_INVALID", "Only a Bundle Release can be promoted.");
|
|
6050
6009
|
};
|
|
6051
6010
|
checkSource((await db.transaction((tx) => loadTarget(tx, input))).release);
|
|
6052
6011
|
const targetChannel = input.targetChannel.trim();
|
|
@@ -6245,7 +6204,6 @@ const fail = (message) => {
|
|
|
6245
6204
|
const isRecord$6 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
|
|
6246
6205
|
const checkPlugin = (value, at) => {
|
|
6247
6206
|
if (!isRecord$6(value)) return fail(`${at} is not a plugin.`);
|
|
6248
|
-
if ("kind" in value) fail(`${at} has a kind; core is built in and is never passed as a plugin.`);
|
|
6249
6207
|
const unknown = Object.keys(value).find((key) => !PLUGIN_KEYS.has(key));
|
|
6250
6208
|
if (unknown !== void 0) fail(`${at} has an unknown key "${unknown}".`);
|
|
6251
6209
|
const plugin = value;
|
|
@@ -7137,7 +7095,7 @@ const databaseOf = (value) => {
|
|
|
7137
7095
|
if (isAdapter(value.adapter)) return value;
|
|
7138
7096
|
if ("core" in value && "fetchAdmin" in value) throw new HotUpdaterConfigError("standaloneRepository reaches a server's admin API from the CLI and console. createHotUpdater needs the server's own database, such as kyselyAdapter(...).");
|
|
7139
7097
|
}
|
|
7140
|
-
throw new HotUpdaterConfigError("database must be a Hot Updater
|
|
7098
|
+
throw new HotUpdaterConfigError("database must be a Hot Updater database adapter, such as kyselyAdapter(...) or postgres(...).");
|
|
7141
7099
|
};
|
|
7142
7100
|
/** The configured storage, when it is a storage adapter. */
|
|
7143
7101
|
const storageOf = (value) => {
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hot-updater/aws",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.0.0-rc.
|
|
4
|
+
"version": "1.0.0-rc.47",
|
|
5
5
|
"description": "React Native OTA solution for self-hosted",
|
|
6
6
|
"main": "dist/index.cjs",
|
|
7
7
|
"module": "dist/index.mjs",
|
|
@@ -45,9 +45,9 @@
|
|
|
45
45
|
"es-toolkit": "^1.32.0",
|
|
46
46
|
"execa": "9.5.2",
|
|
47
47
|
"mime": "^4.0.4",
|
|
48
|
-
"@hot-updater/protocol": "1.0.0-rc.
|
|
49
|
-
"@hot-updater/mock": "1.0.0-rc.
|
|
50
|
-
"@hot-updater/test-utils": "1.0.0-rc.
|
|
48
|
+
"@hot-updater/protocol": "1.0.0-rc.47",
|
|
49
|
+
"@hot-updater/mock": "1.0.0-rc.47",
|
|
50
|
+
"@hot-updater/test-utils": "1.0.0-rc.47"
|
|
51
51
|
},
|
|
52
52
|
"dependencies": {
|
|
53
53
|
"@aws-sdk/client-cloudfront": "3.1066.0",
|
|
@@ -63,9 +63,9 @@
|
|
|
63
63
|
"@aws-sdk/lib-dynamodb": "3.1066.0",
|
|
64
64
|
"@aws-sdk/s3-request-presigner": "3.1066.0",
|
|
65
65
|
"hono": "4.12.34",
|
|
66
|
-
"@hot-updater/
|
|
67
|
-
"@hot-updater/
|
|
68
|
-
"@hot-updater/
|
|
66
|
+
"@hot-updater/plugin-core": "1.0.0-rc.47",
|
|
67
|
+
"@hot-updater/server": "1.0.0-rc.47",
|
|
68
|
+
"@hot-updater/cli-tools": "1.0.0-rc.47"
|
|
69
69
|
},
|
|
70
70
|
"scripts": {
|
|
71
71
|
"build": "tsdown",
|