@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 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.kind === "BUNDLE" && release.bundleId !== null && !crashedBundleIds.has(release.bundleId) && release.bundleId >= input.minimumReleaseId;
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.rollbackReleases ?? catalog.releases;
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) && (descriptor.kind === "BUNDLE" || descriptor.kind === "EMBEDDED") && (descriptor.kind === "BUNDLE" && typeof descriptor.bundleId === "string" || descriptor.kind === "EMBEDDED" && descriptor.bundleId === null) && 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");
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) || catalog.rollbackReleases !== void 0 && (!Array.isArray(catalog.rollbackReleases) || !catalog.rollbackReleases.every(isValidReleaseDescriptor))) return null;
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 ?? []].flatMap((release) => release.targetCohorts)).size > 512) return null;
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" | "USE_EMBEDDED" | "USE_BUILTIN";
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" | "EMBEDDED";
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
- /** Enabled compatible Releases ordered newest first for v0-style rollback. */
450
- readonly rollbackReleases?: readonly ReleaseCatalogDescriptor[];
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, stripBundleArtifactMetadata };
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" | "USE_EMBEDDED" | "USE_BUILTIN";
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" | "EMBEDDED";
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
- /** Enabled compatible Releases ordered newest first for v0-style rollback. */
450
- readonly rollbackReleases?: readonly ReleaseCatalogDescriptor[];
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, stripBundleArtifactMetadata };
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.kind === "BUNDLE" && release.bundleId !== null && !crashedBundleIds.has(release.bundleId) && release.bundleId >= input.minimumReleaseId;
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.rollbackReleases ?? catalog.releases;
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) && (descriptor.kind === "BUNDLE" || descriptor.kind === "EMBEDDED") && (descriptor.kind === "BUNDLE" && typeof descriptor.bundleId === "string" || descriptor.kind === "EMBEDDED" && descriptor.bundleId === null) && 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");
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) || catalog.rollbackReleases !== void 0 && (!Array.isArray(catalog.rollbackReleases) || !catalog.rollbackReleases.every(isValidReleaseDescriptor))) return null;
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 ?? []].flatMap((release) => release.targetCohorts)).size > 512) return null;
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, stripBundleArtifactMetadata };
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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hot-updater/protocol",
3
- "version": "1.0.0-rc.45",
3
+ "version": "1.0.0-rc.47",
4
4
  "type": "module",
5
5
  "description": "The data formats and pure computations that Hot Updater's app and server share",
6
6
  "sideEffects": false,