@hot-updater/protocol 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/index.cjs +5 -15
- package/dist/index.d.cts +8 -6
- package/dist/index.d.mts +8 -6
- package/dist/index.mjs +6 -15
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -126,7 +126,6 @@ const resolveBaseURL = async (baseURL) => {
|
|
|
126
126
|
};
|
|
127
127
|
//#endregion
|
|
128
128
|
//#region src/bundleArtifacts.ts
|
|
129
|
-
const stripBundleArtifactMetadata = (metadata) => metadata;
|
|
130
129
|
const getManifestStorageUri = (bundle) => bundle.manifestStorageUri;
|
|
131
130
|
const getManifestFileHash = (bundle) => bundle.manifestFileHash;
|
|
132
131
|
const getAssetBaseStorageUri = (bundle) => bundle.assetBaseStorageUri;
|
|
@@ -503,7 +502,7 @@ function selectDesiredRelease(catalog, input) {
|
|
|
503
502
|
const crashedBundleIds = new Set(input.crashedBundleIds);
|
|
504
503
|
const activeReleaseId = input.activeReleaseId ?? null;
|
|
505
504
|
const hasActiveBundle = input.currentBundleId !== input.builtInBundleId;
|
|
506
|
-
const isSafeBundleRelease = (release) => release.
|
|
505
|
+
const isSafeBundleRelease = (release) => release.bundleId !== null && !crashedBundleIds.has(release.bundleId) && release.bundleId >= input.minimumReleaseId;
|
|
507
506
|
const desiredBundle = (release, status) => ({
|
|
508
507
|
bundleId: release.bundleId,
|
|
509
508
|
kind: "BUNDLE",
|
|
@@ -515,17 +514,9 @@ function selectDesiredRelease(catalog, input) {
|
|
|
515
514
|
if (!isReleaseEligibleForCohort(release, input.cohort)) continue;
|
|
516
515
|
if (activeReleaseId !== null && release.releaseId <= activeReleaseId || activeReleaseId === null && hasActiveBundle && (release.bundleId === null || release.bundleId <= input.currentBundleId)) continue;
|
|
517
516
|
if (isSafeBundleRelease(release)) return desiredBundle(release, "UPDATE");
|
|
518
|
-
if (release.bundleId !== null) continue;
|
|
519
|
-
return {
|
|
520
|
-
bundleId: input.builtInBundleId,
|
|
521
|
-
kind: "EMBEDDED",
|
|
522
|
-
release,
|
|
523
|
-
releaseId: release.releaseId,
|
|
524
|
-
status: "ROLLBACK"
|
|
525
|
-
};
|
|
526
517
|
}
|
|
527
518
|
if (activeReleaseId !== null || hasActiveBundle) {
|
|
528
|
-
const rollbackReleases = catalog
|
|
519
|
+
const { rollbackReleases } = catalog;
|
|
529
520
|
const current = rollbackReleases.find((release) => release.releaseId === activeReleaseId || activeReleaseId === null && release.bundleId === input.currentBundleId);
|
|
530
521
|
if (current !== void 0 && isSafeBundleRelease(current) && isReleaseEligibleForCohort(current, input.cohort)) return desiredBundle(current, "UPDATE");
|
|
531
522
|
const rollback = rollbackReleases.find((release) => isSafeBundleRelease(release) && (activeReleaseId !== null ? release.releaseId < activeReleaseId : release.bundleId < input.currentBundleId));
|
|
@@ -745,7 +736,7 @@ const isStringArray = (value) => Array.isArray(value) && value.every((entry) =>
|
|
|
745
736
|
const isValidReleaseDescriptor = (value) => {
|
|
746
737
|
if (value === null || typeof value !== "object") return false;
|
|
747
738
|
const descriptor = value;
|
|
748
|
-
return isUUIDv7(descriptor.releaseId) &&
|
|
739
|
+
return isUUIDv7(descriptor.releaseId) && descriptor.kind === "BUNDLE" && typeof descriptor.bundleId === "string" && Number.isSafeInteger(descriptor.rolloutCohortCount) && descriptor.rolloutCohortCount >= 0 && descriptor.rolloutCohortCount <= 1e3 && isStringArray(descriptor.targetCohorts) && descriptor.targetCohorts.length <= 100 && typeof descriptor.shouldForceUpdate === "boolean" && (descriptor.message === null || typeof descriptor.message === "string");
|
|
749
740
|
};
|
|
750
741
|
/** Whether the catalog is the expected scope's. */
|
|
751
742
|
const hasExpectedReleaseCatalogScope = (catalog, expected) => {
|
|
@@ -766,9 +757,9 @@ const parseReleaseCatalog = (body, expectedScope) => {
|
|
|
766
757
|
if (getUtf8ByteLength(body) > MAX_RELEASE_CATALOG_WIRE_BYTES) return null;
|
|
767
758
|
try {
|
|
768
759
|
const catalog = JSON.parse(body);
|
|
769
|
-
if (catalog.schemaVersion !== 1 || typeof catalog.catalogId !== "string" || catalog.catalogId.length === 0 || typeof catalog.scopeKey !== "string" || !Number.isSafeInteger(catalog.generation) || (catalog.generation ?? 0) < 1 || typeof catalog.catalogHash !== "string" || !/^sha256:[0-9a-f]{64}$/.test(catalog.catalogHash) || catalog.fallbackPolicy !== "BUILTIN_IF_ACTIVE_INELIGIBLE" || !Array.isArray(catalog.releases) || !catalog.releases.every(isValidReleaseDescriptor) ||
|
|
760
|
+
if (catalog.schemaVersion !== 1 || typeof catalog.catalogId !== "string" || catalog.catalogId.length === 0 || typeof catalog.scopeKey !== "string" || !Number.isSafeInteger(catalog.generation) || (catalog.generation ?? 0) < 1 || typeof catalog.catalogHash !== "string" || !/^sha256:[0-9a-f]{64}$/.test(catalog.catalogHash) || catalog.fallbackPolicy !== "BUILTIN_IF_ACTIVE_INELIGIBLE" || !Array.isArray(catalog.releases) || !catalog.releases.every(isValidReleaseDescriptor) || !Array.isArray(catalog.rollbackReleases) || !catalog.rollbackReleases.every(isValidReleaseDescriptor)) return null;
|
|
770
761
|
if (!hasExpectedReleaseCatalogScope(catalog, expectedScope)) return null;
|
|
771
|
-
if (new Set([...catalog.releases, ...catalog.rollbackReleases
|
|
762
|
+
if (new Set([...catalog.releases, ...catalog.rollbackReleases].flatMap((release) => release.targetCohorts)).size > 512) return null;
|
|
772
763
|
return catalog;
|
|
773
764
|
} catch {
|
|
774
765
|
return null;
|
|
@@ -830,4 +821,3 @@ exports.parseReleaseCatalogScopeKey = parseReleaseCatalogScopeKey;
|
|
|
830
821
|
exports.pluginStorageKey = pluginStorageKey;
|
|
831
822
|
exports.resolveBaseURL = resolveBaseURL;
|
|
832
823
|
exports.selectDesiredRelease = selectDesiredRelease;
|
|
833
|
-
exports.stripBundleArtifactMetadata = stripBundleArtifactMetadata;
|
package/dist/index.d.cts
CHANGED
|
@@ -108,7 +108,6 @@ interface ArtifactInfo {
|
|
|
108
108
|
}
|
|
109
109
|
//#endregion
|
|
110
110
|
//#region src/bundleArtifacts.d.ts
|
|
111
|
-
declare const stripBundleArtifactMetadata: (metadata: BundleMetadata | undefined) => BundleMetadata | undefined;
|
|
112
111
|
declare const getManifestStorageUri: (bundle: Pick<Bundle, "manifestStorageUri">) => string;
|
|
113
112
|
declare const getManifestFileHash: (bundle: Pick<Bundle, "manifestFileHash">) => string;
|
|
114
113
|
declare const getAssetBaseStorageUri: (bundle: Pick<Bundle, "assetBaseStorageUri">) => string;
|
|
@@ -131,7 +130,7 @@ declare const getPatchStorageUri: (bundle: Pick<Bundle, "patches">) => string;
|
|
|
131
130
|
*/
|
|
132
131
|
type UpdateStrategy = "fingerprint" | "appVersion";
|
|
133
132
|
/** How an update moves the app's selection. */
|
|
134
|
-
type ReleaseTransitionKind = "INSTALL" | "ADOPT_RELEASE" | "
|
|
133
|
+
type ReleaseTransitionKind = "INSTALL" | "ADOPT_RELEASE" | "USE_BUILTIN";
|
|
135
134
|
/** The launch outcome native reports once per JavaScript runtime. */
|
|
136
135
|
type AppReadyResult = {
|
|
137
136
|
/** No update was applied or recovered at this launch. */
|
|
@@ -404,7 +403,7 @@ declare const MAX_CRASHED_BUNDLES = 10;
|
|
|
404
403
|
declare const MAX_TARGET_COHORTS_PER_RELEASE = 100;
|
|
405
404
|
declare const MAX_DISTINCT_TARGET_COHORTS_PER_SCOPE = 512;
|
|
406
405
|
declare const MAX_COMPILED_CATALOG_BYTES: number;
|
|
407
|
-
type ReleaseKind = "BUNDLE"
|
|
406
|
+
type ReleaseKind = "BUNDLE";
|
|
408
407
|
type ReleaseStrategy = "APP_VERSION" | "FINGERPRINT";
|
|
409
408
|
type ReleaseOperation = "DEPLOY" | "PROMOTE" | "ROLLBACK";
|
|
410
409
|
type SelectionKind = ReleaseKind | "BUILTIN";
|
|
@@ -446,8 +445,11 @@ interface ReleaseCatalog {
|
|
|
446
445
|
readonly fallbackPolicy: typeof RELEASE_CATALOG_FALLBACK_POLICY;
|
|
447
446
|
/** Release descriptors ordered newest first. */
|
|
448
447
|
readonly releases: readonly ReleaseCatalogDescriptor[];
|
|
449
|
-
/**
|
|
450
|
-
|
|
448
|
+
/**
|
|
449
|
+
* Enabled compatible Releases ordered newest first, where a device keeps its
|
|
450
|
+
* active Release or rolls back to the newest Release before it.
|
|
451
|
+
*/
|
|
452
|
+
readonly rollbackReleases: readonly ReleaseCatalogDescriptor[];
|
|
451
453
|
}
|
|
452
454
|
interface CatalogHighWater {
|
|
453
455
|
readonly generation: number;
|
|
@@ -576,4 +578,4 @@ declare function isCohortEligibleForUpdate(bundleId: string, cohort: string | nu
|
|
|
576
578
|
declare const NIL_UUID = "00000000-0000-0000-0000-000000000000";
|
|
577
579
|
declare const isUUIDv7: (value: unknown) => value is string;
|
|
578
580
|
//#endregion
|
|
579
|
-
export { ARTIFACT_PROTOCOL_VERSION, AppReadyResult, ArtifactAsset, ArtifactAssetFile, ArtifactInfo, Bundle, BundleDownloadedInfo, BundleMetadata, BundlePatchArtifact, CatalogAcceptance, CatalogHighWater, ChangedAssetPatch, ClientPluginApi, ClientPluginApis, DEFAULT_ROLLOUT_COHORT_COUNT, DesiredRelease, ExpectedReleaseCatalogScope, HotUpdaterBaseURL, HotUpdaterClientContext, HotUpdaterClientHooks, HotUpdaterClientPlugin, HotUpdaterClientSetup, HotUpdaterClientStorage, INVALID_COHORT_ERROR_MESSAGE, MAX_COHORT_LENGTH, MAX_COMPILED_CATALOG_BYTES, MAX_CRASHED_BUNDLES, MAX_DISTINCT_TARGET_COHORTS_PER_SCOPE, MAX_RELEASE_CATALOG_WIRE_BYTES, MAX_TARGET_COHORTS_PER_RELEASE, ManifestArchive, NIL_UUID, NUMERIC_COHORT_SIZE, PersistedSelectionReceipt, Platform, PluginHookName, PluginHookPayload, PluginHost, PluginHostConfig, PluginHostEnvironment, RELEASE_CATALOG_FALLBACK_POLICY, RELEASE_CATALOG_SCHEMA_VERSION, Release, ReleaseCatalog, ReleaseCatalogDescriptor, ReleaseCatalogScopeKeyInput, ReleaseKind, ReleaseOperation, ReleaseSelectionContextInput, ReleaseSelectionInput, ReleaseStrategy, ReleaseTransitionAuthorization, ReleaseTransitionKind, SelectionKind, UpdateCheckResult, UpdateError, UpdateErrorReason, UpdateErrorResource, UpdateErrorStage, UpdateErrorTransport, UpdateHttpResponse, UpdateStatus, UpdateStrategy, assertCanonicalChannelName, assessCatalogAcceptance, authorizeReleaseTransition, canonicalizeAppVersion, createPluginHost, createReleaseCatalogScopeKey, createReleaseSelectionContextHash, decodeChannelKey, defineClientPlugin, encodeChannelKey, getAssetBaseStorageUri, getBundlePatch, getBundlePatches, getDefaultNumericCohort, getManifestFileHash, getManifestStorageUri, getNumericCohortRolloutPosition, getNumericCohortValue, getPatchBaseBundleId, getPatchBaseFileHash, getPatchFileHash, getPatchStorageUri, getRolledOutNumericCohorts, getUtf8ByteLength, hasExpectedReleaseCatalogScope, isCohortEligibleForUpdate, isCustomCohort, isNumericCohort, isReleaseEligibleForCohort, isUUIDv7, isValidCohort, normalizeChannelName, normalizeCohortValue, normalizeRolloutCohortCount, parseReleaseCatalog, parseReleaseCatalogScopeKey, pluginStorageKey, resolveBaseURL, selectDesiredRelease
|
|
581
|
+
export { ARTIFACT_PROTOCOL_VERSION, AppReadyResult, ArtifactAsset, ArtifactAssetFile, ArtifactInfo, Bundle, BundleDownloadedInfo, BundleMetadata, BundlePatchArtifact, CatalogAcceptance, CatalogHighWater, ChangedAssetPatch, ClientPluginApi, ClientPluginApis, DEFAULT_ROLLOUT_COHORT_COUNT, DesiredRelease, ExpectedReleaseCatalogScope, HotUpdaterBaseURL, HotUpdaterClientContext, HotUpdaterClientHooks, HotUpdaterClientPlugin, HotUpdaterClientSetup, HotUpdaterClientStorage, INVALID_COHORT_ERROR_MESSAGE, MAX_COHORT_LENGTH, MAX_COMPILED_CATALOG_BYTES, MAX_CRASHED_BUNDLES, MAX_DISTINCT_TARGET_COHORTS_PER_SCOPE, MAX_RELEASE_CATALOG_WIRE_BYTES, MAX_TARGET_COHORTS_PER_RELEASE, ManifestArchive, NIL_UUID, NUMERIC_COHORT_SIZE, PersistedSelectionReceipt, Platform, PluginHookName, PluginHookPayload, PluginHost, PluginHostConfig, PluginHostEnvironment, RELEASE_CATALOG_FALLBACK_POLICY, RELEASE_CATALOG_SCHEMA_VERSION, Release, ReleaseCatalog, ReleaseCatalogDescriptor, ReleaseCatalogScopeKeyInput, ReleaseKind, ReleaseOperation, ReleaseSelectionContextInput, ReleaseSelectionInput, ReleaseStrategy, ReleaseTransitionAuthorization, ReleaseTransitionKind, SelectionKind, UpdateCheckResult, UpdateError, UpdateErrorReason, UpdateErrorResource, UpdateErrorStage, UpdateErrorTransport, UpdateHttpResponse, UpdateStatus, UpdateStrategy, assertCanonicalChannelName, assessCatalogAcceptance, authorizeReleaseTransition, canonicalizeAppVersion, createPluginHost, createReleaseCatalogScopeKey, createReleaseSelectionContextHash, decodeChannelKey, defineClientPlugin, encodeChannelKey, getAssetBaseStorageUri, getBundlePatch, getBundlePatches, getDefaultNumericCohort, getManifestFileHash, getManifestStorageUri, getNumericCohortRolloutPosition, getNumericCohortValue, getPatchBaseBundleId, getPatchBaseFileHash, getPatchFileHash, getPatchStorageUri, getRolledOutNumericCohorts, getUtf8ByteLength, hasExpectedReleaseCatalogScope, isCohortEligibleForUpdate, isCustomCohort, isNumericCohort, isReleaseEligibleForCohort, isUUIDv7, isValidCohort, normalizeChannelName, normalizeCohortValue, normalizeRolloutCohortCount, parseReleaseCatalog, parseReleaseCatalogScopeKey, pluginStorageKey, resolveBaseURL, selectDesiredRelease };
|
package/dist/index.d.mts
CHANGED
|
@@ -108,7 +108,6 @@ interface ArtifactInfo {
|
|
|
108
108
|
}
|
|
109
109
|
//#endregion
|
|
110
110
|
//#region src/bundleArtifacts.d.ts
|
|
111
|
-
declare const stripBundleArtifactMetadata: (metadata: BundleMetadata | undefined) => BundleMetadata | undefined;
|
|
112
111
|
declare const getManifestStorageUri: (bundle: Pick<Bundle, "manifestStorageUri">) => string;
|
|
113
112
|
declare const getManifestFileHash: (bundle: Pick<Bundle, "manifestFileHash">) => string;
|
|
114
113
|
declare const getAssetBaseStorageUri: (bundle: Pick<Bundle, "assetBaseStorageUri">) => string;
|
|
@@ -131,7 +130,7 @@ declare const getPatchStorageUri: (bundle: Pick<Bundle, "patches">) => string;
|
|
|
131
130
|
*/
|
|
132
131
|
type UpdateStrategy = "fingerprint" | "appVersion";
|
|
133
132
|
/** How an update moves the app's selection. */
|
|
134
|
-
type ReleaseTransitionKind = "INSTALL" | "ADOPT_RELEASE" | "
|
|
133
|
+
type ReleaseTransitionKind = "INSTALL" | "ADOPT_RELEASE" | "USE_BUILTIN";
|
|
135
134
|
/** The launch outcome native reports once per JavaScript runtime. */
|
|
136
135
|
type AppReadyResult = {
|
|
137
136
|
/** No update was applied or recovered at this launch. */
|
|
@@ -404,7 +403,7 @@ declare const MAX_CRASHED_BUNDLES = 10;
|
|
|
404
403
|
declare const MAX_TARGET_COHORTS_PER_RELEASE = 100;
|
|
405
404
|
declare const MAX_DISTINCT_TARGET_COHORTS_PER_SCOPE = 512;
|
|
406
405
|
declare const MAX_COMPILED_CATALOG_BYTES: number;
|
|
407
|
-
type ReleaseKind = "BUNDLE"
|
|
406
|
+
type ReleaseKind = "BUNDLE";
|
|
408
407
|
type ReleaseStrategy = "APP_VERSION" | "FINGERPRINT";
|
|
409
408
|
type ReleaseOperation = "DEPLOY" | "PROMOTE" | "ROLLBACK";
|
|
410
409
|
type SelectionKind = ReleaseKind | "BUILTIN";
|
|
@@ -446,8 +445,11 @@ interface ReleaseCatalog {
|
|
|
446
445
|
readonly fallbackPolicy: typeof RELEASE_CATALOG_FALLBACK_POLICY;
|
|
447
446
|
/** Release descriptors ordered newest first. */
|
|
448
447
|
readonly releases: readonly ReleaseCatalogDescriptor[];
|
|
449
|
-
/**
|
|
450
|
-
|
|
448
|
+
/**
|
|
449
|
+
* Enabled compatible Releases ordered newest first, where a device keeps its
|
|
450
|
+
* active Release or rolls back to the newest Release before it.
|
|
451
|
+
*/
|
|
452
|
+
readonly rollbackReleases: readonly ReleaseCatalogDescriptor[];
|
|
451
453
|
}
|
|
452
454
|
interface CatalogHighWater {
|
|
453
455
|
readonly generation: number;
|
|
@@ -576,4 +578,4 @@ declare function isCohortEligibleForUpdate(bundleId: string, cohort: string | nu
|
|
|
576
578
|
declare const NIL_UUID = "00000000-0000-0000-0000-000000000000";
|
|
577
579
|
declare const isUUIDv7: (value: unknown) => value is string;
|
|
578
580
|
//#endregion
|
|
579
|
-
export { ARTIFACT_PROTOCOL_VERSION, AppReadyResult, ArtifactAsset, ArtifactAssetFile, ArtifactInfo, Bundle, BundleDownloadedInfo, BundleMetadata, BundlePatchArtifact, CatalogAcceptance, CatalogHighWater, ChangedAssetPatch, ClientPluginApi, ClientPluginApis, DEFAULT_ROLLOUT_COHORT_COUNT, DesiredRelease, ExpectedReleaseCatalogScope, HotUpdaterBaseURL, HotUpdaterClientContext, HotUpdaterClientHooks, HotUpdaterClientPlugin, HotUpdaterClientSetup, HotUpdaterClientStorage, INVALID_COHORT_ERROR_MESSAGE, MAX_COHORT_LENGTH, MAX_COMPILED_CATALOG_BYTES, MAX_CRASHED_BUNDLES, MAX_DISTINCT_TARGET_COHORTS_PER_SCOPE, MAX_RELEASE_CATALOG_WIRE_BYTES, MAX_TARGET_COHORTS_PER_RELEASE, ManifestArchive, NIL_UUID, NUMERIC_COHORT_SIZE, PersistedSelectionReceipt, Platform, PluginHookName, PluginHookPayload, PluginHost, PluginHostConfig, PluginHostEnvironment, RELEASE_CATALOG_FALLBACK_POLICY, RELEASE_CATALOG_SCHEMA_VERSION, Release, ReleaseCatalog, ReleaseCatalogDescriptor, ReleaseCatalogScopeKeyInput, ReleaseKind, ReleaseOperation, ReleaseSelectionContextInput, ReleaseSelectionInput, ReleaseStrategy, ReleaseTransitionAuthorization, ReleaseTransitionKind, SelectionKind, UpdateCheckResult, UpdateError, UpdateErrorReason, UpdateErrorResource, UpdateErrorStage, UpdateErrorTransport, UpdateHttpResponse, UpdateStatus, UpdateStrategy, assertCanonicalChannelName, assessCatalogAcceptance, authorizeReleaseTransition, canonicalizeAppVersion, createPluginHost, createReleaseCatalogScopeKey, createReleaseSelectionContextHash, decodeChannelKey, defineClientPlugin, encodeChannelKey, getAssetBaseStorageUri, getBundlePatch, getBundlePatches, getDefaultNumericCohort, getManifestFileHash, getManifestStorageUri, getNumericCohortRolloutPosition, getNumericCohortValue, getPatchBaseBundleId, getPatchBaseFileHash, getPatchFileHash, getPatchStorageUri, getRolledOutNumericCohorts, getUtf8ByteLength, hasExpectedReleaseCatalogScope, isCohortEligibleForUpdate, isCustomCohort, isNumericCohort, isReleaseEligibleForCohort, isUUIDv7, isValidCohort, normalizeChannelName, normalizeCohortValue, normalizeRolloutCohortCount, parseReleaseCatalog, parseReleaseCatalogScopeKey, pluginStorageKey, resolveBaseURL, selectDesiredRelease
|
|
581
|
+
export { ARTIFACT_PROTOCOL_VERSION, AppReadyResult, ArtifactAsset, ArtifactAssetFile, ArtifactInfo, Bundle, BundleDownloadedInfo, BundleMetadata, BundlePatchArtifact, CatalogAcceptance, CatalogHighWater, ChangedAssetPatch, ClientPluginApi, ClientPluginApis, DEFAULT_ROLLOUT_COHORT_COUNT, DesiredRelease, ExpectedReleaseCatalogScope, HotUpdaterBaseURL, HotUpdaterClientContext, HotUpdaterClientHooks, HotUpdaterClientPlugin, HotUpdaterClientSetup, HotUpdaterClientStorage, INVALID_COHORT_ERROR_MESSAGE, MAX_COHORT_LENGTH, MAX_COMPILED_CATALOG_BYTES, MAX_CRASHED_BUNDLES, MAX_DISTINCT_TARGET_COHORTS_PER_SCOPE, MAX_RELEASE_CATALOG_WIRE_BYTES, MAX_TARGET_COHORTS_PER_RELEASE, ManifestArchive, NIL_UUID, NUMERIC_COHORT_SIZE, PersistedSelectionReceipt, Platform, PluginHookName, PluginHookPayload, PluginHost, PluginHostConfig, PluginHostEnvironment, RELEASE_CATALOG_FALLBACK_POLICY, RELEASE_CATALOG_SCHEMA_VERSION, Release, ReleaseCatalog, ReleaseCatalogDescriptor, ReleaseCatalogScopeKeyInput, ReleaseKind, ReleaseOperation, ReleaseSelectionContextInput, ReleaseSelectionInput, ReleaseStrategy, ReleaseTransitionAuthorization, ReleaseTransitionKind, SelectionKind, UpdateCheckResult, UpdateError, UpdateErrorReason, UpdateErrorResource, UpdateErrorStage, UpdateErrorTransport, UpdateHttpResponse, UpdateStatus, UpdateStrategy, assertCanonicalChannelName, assessCatalogAcceptance, authorizeReleaseTransition, canonicalizeAppVersion, createPluginHost, createReleaseCatalogScopeKey, createReleaseSelectionContextHash, decodeChannelKey, defineClientPlugin, encodeChannelKey, getAssetBaseStorageUri, getBundlePatch, getBundlePatches, getDefaultNumericCohort, getManifestFileHash, getManifestStorageUri, getNumericCohortRolloutPosition, getNumericCohortValue, getPatchBaseBundleId, getPatchBaseFileHash, getPatchFileHash, getPatchStorageUri, getRolledOutNumericCohorts, getUtf8ByteLength, hasExpectedReleaseCatalogScope, isCohortEligibleForUpdate, isCustomCohort, isNumericCohort, isReleaseEligibleForCohort, isUUIDv7, isValidCohort, normalizeChannelName, normalizeCohortValue, normalizeRolloutCohortCount, parseReleaseCatalog, parseReleaseCatalogScopeKey, pluginStorageKey, resolveBaseURL, selectDesiredRelease };
|
package/dist/index.mjs
CHANGED
|
@@ -125,7 +125,6 @@ const resolveBaseURL = async (baseURL) => {
|
|
|
125
125
|
};
|
|
126
126
|
//#endregion
|
|
127
127
|
//#region src/bundleArtifacts.ts
|
|
128
|
-
const stripBundleArtifactMetadata = (metadata) => metadata;
|
|
129
128
|
const getManifestStorageUri = (bundle) => bundle.manifestStorageUri;
|
|
130
129
|
const getManifestFileHash = (bundle) => bundle.manifestFileHash;
|
|
131
130
|
const getAssetBaseStorageUri = (bundle) => bundle.assetBaseStorageUri;
|
|
@@ -502,7 +501,7 @@ function selectDesiredRelease(catalog, input) {
|
|
|
502
501
|
const crashedBundleIds = new Set(input.crashedBundleIds);
|
|
503
502
|
const activeReleaseId = input.activeReleaseId ?? null;
|
|
504
503
|
const hasActiveBundle = input.currentBundleId !== input.builtInBundleId;
|
|
505
|
-
const isSafeBundleRelease = (release) => release.
|
|
504
|
+
const isSafeBundleRelease = (release) => release.bundleId !== null && !crashedBundleIds.has(release.bundleId) && release.bundleId >= input.minimumReleaseId;
|
|
506
505
|
const desiredBundle = (release, status) => ({
|
|
507
506
|
bundleId: release.bundleId,
|
|
508
507
|
kind: "BUNDLE",
|
|
@@ -514,17 +513,9 @@ function selectDesiredRelease(catalog, input) {
|
|
|
514
513
|
if (!isReleaseEligibleForCohort(release, input.cohort)) continue;
|
|
515
514
|
if (activeReleaseId !== null && release.releaseId <= activeReleaseId || activeReleaseId === null && hasActiveBundle && (release.bundleId === null || release.bundleId <= input.currentBundleId)) continue;
|
|
516
515
|
if (isSafeBundleRelease(release)) return desiredBundle(release, "UPDATE");
|
|
517
|
-
if (release.bundleId !== null) continue;
|
|
518
|
-
return {
|
|
519
|
-
bundleId: input.builtInBundleId,
|
|
520
|
-
kind: "EMBEDDED",
|
|
521
|
-
release,
|
|
522
|
-
releaseId: release.releaseId,
|
|
523
|
-
status: "ROLLBACK"
|
|
524
|
-
};
|
|
525
516
|
}
|
|
526
517
|
if (activeReleaseId !== null || hasActiveBundle) {
|
|
527
|
-
const rollbackReleases = catalog
|
|
518
|
+
const { rollbackReleases } = catalog;
|
|
528
519
|
const current = rollbackReleases.find((release) => release.releaseId === activeReleaseId || activeReleaseId === null && release.bundleId === input.currentBundleId);
|
|
529
520
|
if (current !== void 0 && isSafeBundleRelease(current) && isReleaseEligibleForCohort(current, input.cohort)) return desiredBundle(current, "UPDATE");
|
|
530
521
|
const rollback = rollbackReleases.find((release) => isSafeBundleRelease(release) && (activeReleaseId !== null ? release.releaseId < activeReleaseId : release.bundleId < input.currentBundleId));
|
|
@@ -744,7 +735,7 @@ const isStringArray = (value) => Array.isArray(value) && value.every((entry) =>
|
|
|
744
735
|
const isValidReleaseDescriptor = (value) => {
|
|
745
736
|
if (value === null || typeof value !== "object") return false;
|
|
746
737
|
const descriptor = value;
|
|
747
|
-
return isUUIDv7(descriptor.releaseId) &&
|
|
738
|
+
return isUUIDv7(descriptor.releaseId) && descriptor.kind === "BUNDLE" && typeof descriptor.bundleId === "string" && Number.isSafeInteger(descriptor.rolloutCohortCount) && descriptor.rolloutCohortCount >= 0 && descriptor.rolloutCohortCount <= 1e3 && isStringArray(descriptor.targetCohorts) && descriptor.targetCohorts.length <= 100 && typeof descriptor.shouldForceUpdate === "boolean" && (descriptor.message === null || typeof descriptor.message === "string");
|
|
748
739
|
};
|
|
749
740
|
/** Whether the catalog is the expected scope's. */
|
|
750
741
|
const hasExpectedReleaseCatalogScope = (catalog, expected) => {
|
|
@@ -765,9 +756,9 @@ const parseReleaseCatalog = (body, expectedScope) => {
|
|
|
765
756
|
if (getUtf8ByteLength(body) > MAX_RELEASE_CATALOG_WIRE_BYTES) return null;
|
|
766
757
|
try {
|
|
767
758
|
const catalog = JSON.parse(body);
|
|
768
|
-
if (catalog.schemaVersion !== 1 || typeof catalog.catalogId !== "string" || catalog.catalogId.length === 0 || typeof catalog.scopeKey !== "string" || !Number.isSafeInteger(catalog.generation) || (catalog.generation ?? 0) < 1 || typeof catalog.catalogHash !== "string" || !/^sha256:[0-9a-f]{64}$/.test(catalog.catalogHash) || catalog.fallbackPolicy !== "BUILTIN_IF_ACTIVE_INELIGIBLE" || !Array.isArray(catalog.releases) || !catalog.releases.every(isValidReleaseDescriptor) ||
|
|
759
|
+
if (catalog.schemaVersion !== 1 || typeof catalog.catalogId !== "string" || catalog.catalogId.length === 0 || typeof catalog.scopeKey !== "string" || !Number.isSafeInteger(catalog.generation) || (catalog.generation ?? 0) < 1 || typeof catalog.catalogHash !== "string" || !/^sha256:[0-9a-f]{64}$/.test(catalog.catalogHash) || catalog.fallbackPolicy !== "BUILTIN_IF_ACTIVE_INELIGIBLE" || !Array.isArray(catalog.releases) || !catalog.releases.every(isValidReleaseDescriptor) || !Array.isArray(catalog.rollbackReleases) || !catalog.rollbackReleases.every(isValidReleaseDescriptor)) return null;
|
|
769
760
|
if (!hasExpectedReleaseCatalogScope(catalog, expectedScope)) return null;
|
|
770
|
-
if (new Set([...catalog.releases, ...catalog.rollbackReleases
|
|
761
|
+
if (new Set([...catalog.releases, ...catalog.rollbackReleases].flatMap((release) => release.targetCohorts)).size > 512) return null;
|
|
771
762
|
return catalog;
|
|
772
763
|
} catch {
|
|
773
764
|
return null;
|
|
@@ -777,4 +768,4 @@ const parseReleaseCatalog = (body, expectedScope) => {
|
|
|
777
768
|
//#region src/types.ts
|
|
778
769
|
const ARTIFACT_PROTOCOL_VERSION = 1;
|
|
779
770
|
//#endregion
|
|
780
|
-
export { ARTIFACT_PROTOCOL_VERSION, DEFAULT_ROLLOUT_COHORT_COUNT, INVALID_COHORT_ERROR_MESSAGE, MAX_COHORT_LENGTH, MAX_COMPILED_CATALOG_BYTES, MAX_CRASHED_BUNDLES, MAX_DISTINCT_TARGET_COHORTS_PER_SCOPE, MAX_RELEASE_CATALOG_WIRE_BYTES, MAX_TARGET_COHORTS_PER_RELEASE, NIL_UUID, NUMERIC_COHORT_SIZE, RELEASE_CATALOG_FALLBACK_POLICY, RELEASE_CATALOG_SCHEMA_VERSION, assertCanonicalChannelName, assessCatalogAcceptance, authorizeReleaseTransition, canonicalizeAppVersion, createPluginHost, createReleaseCatalogScopeKey, createReleaseSelectionContextHash, decodeChannelKey, defineClientPlugin, encodeChannelKey, getAssetBaseStorageUri, getBundlePatch, getBundlePatches, getDefaultNumericCohort, getManifestFileHash, getManifestStorageUri, getNumericCohortRolloutPosition, getNumericCohortValue, getPatchBaseBundleId, getPatchBaseFileHash, getPatchFileHash, getPatchStorageUri, getRolledOutNumericCohorts, getUtf8ByteLength, hasExpectedReleaseCatalogScope, isCohortEligibleForUpdate, isCustomCohort, isNumericCohort, isReleaseEligibleForCohort, isUUIDv7, isValidCohort, normalizeChannelName, normalizeCohortValue, normalizeRolloutCohortCount, parseReleaseCatalog, parseReleaseCatalogScopeKey, pluginStorageKey, resolveBaseURL, selectDesiredRelease
|
|
771
|
+
export { ARTIFACT_PROTOCOL_VERSION, DEFAULT_ROLLOUT_COHORT_COUNT, INVALID_COHORT_ERROR_MESSAGE, MAX_COHORT_LENGTH, MAX_COMPILED_CATALOG_BYTES, MAX_CRASHED_BUNDLES, MAX_DISTINCT_TARGET_COHORTS_PER_SCOPE, MAX_RELEASE_CATALOG_WIRE_BYTES, MAX_TARGET_COHORTS_PER_RELEASE, NIL_UUID, NUMERIC_COHORT_SIZE, RELEASE_CATALOG_FALLBACK_POLICY, RELEASE_CATALOG_SCHEMA_VERSION, assertCanonicalChannelName, assessCatalogAcceptance, authorizeReleaseTransition, canonicalizeAppVersion, createPluginHost, createReleaseCatalogScopeKey, createReleaseSelectionContextHash, decodeChannelKey, defineClientPlugin, encodeChannelKey, getAssetBaseStorageUri, getBundlePatch, getBundlePatches, getDefaultNumericCohort, getManifestFileHash, getManifestStorageUri, getNumericCohortRolloutPosition, getNumericCohortValue, getPatchBaseBundleId, getPatchBaseFileHash, getPatchFileHash, getPatchStorageUri, getRolledOutNumericCohorts, getUtf8ByteLength, hasExpectedReleaseCatalogScope, isCohortEligibleForUpdate, isCustomCohort, isNumericCohort, isReleaseEligibleForCohort, isUUIDv7, isValidCohort, normalizeChannelName, normalizeCohortValue, normalizeRolloutCohortCount, parseReleaseCatalog, parseReleaseCatalogScopeKey, pluginStorageKey, resolveBaseURL, selectDesiredRelease };
|