@hot-updater/aws 1.0.0-rc.30 → 1.0.0-rc.32

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.d.cts CHANGED
@@ -200,6 +200,19 @@ interface InsightsCountEventsInput {
200
200
  readonly sinceMs: number;
201
201
  readonly beforeReceivedAtMs: number;
202
202
  }
203
+ /** One bundle filter's stored events in each interval of a time range. */
204
+ interface InsightsCountEventSeriesInput {
205
+ readonly filter: InsightsBundleEventFilter;
206
+ /** Whole UTC hours, at most 90 days, that a whole number of intervals fill. */
207
+ readonly timeRange: InsightsTimeRange;
208
+ /** Whole hours each point spans, from `timeRange.start`. */
209
+ readonly intervalMs: number;
210
+ }
211
+ /** Stored events in [startMs, startMs + intervalMs). */
212
+ interface InsightsEventSeriesPoint {
213
+ readonly startMs: number;
214
+ readonly events: number;
215
+ }
203
216
  interface ReleaseReference {
204
217
  readonly releaseId: string;
205
218
  readonly platform: "ios" | "android";
@@ -218,44 +231,22 @@ type InsightsCoverage = {
218
231
  readonly kind: "partial";
219
232
  readonly sinceMs: number | null;
220
233
  };
234
+ /**
235
+ * A release's counts since its first report, from its lifetime counters,
236
+ * which are kept.
237
+ */
221
238
  interface ReleaseActivityMetrics {
222
239
  readonly downloads: number;
223
240
  readonly launches: number;
224
241
  readonly failedLaunches: number;
225
- /** Omitted for lifetime-only bundle-row reads. */
226
- readonly uniqueUsers?: number;
227
- /**
228
- * Points of each UTC day, or of each `intervalMs` from the period's start
229
- * on a release read that asks for one; present only for period reads.
230
- */
231
- readonly series?: readonly {
232
- readonly startMs: number;
233
- readonly downloads: number;
234
- readonly launches: number;
235
- readonly failedLaunches: number;
236
- }[];
237
242
  }
238
- type InsightsGetReleaseActivityInput = {
243
+ interface InsightsGetReleaseActivityInput {
244
+ /** 1 to 100 releases. */
239
245
  readonly releases: readonly ReleaseReference[];
240
- readonly timeRange?: InsightsTimeRange;
241
- /**
242
- * Whole hours each series point spans, from `timeRange.start`, with
243
- * every point present; omitted, the series has a point per UTC day
244
- * with reports. Only with a `timeRange`.
245
- */
246
- readonly intervalMs?: number;
247
- readonly scope?: never;
248
- } | {
249
- readonly scope: InsightsScope;
250
- readonly timeRange: InsightsTimeRange;
251
- readonly intervalMs?: never;
252
- readonly releases?: never;
253
- };
246
+ }
254
247
  interface InsightsGetReleaseActivityResult {
255
- readonly coverage: InsightsCoverage;
256
248
  readonly data: readonly {
257
- readonly release?: ReleaseReference;
258
- readonly scope?: InsightsScope;
249
+ readonly release: ReleaseReference;
259
250
  readonly metrics: ReleaseActivityMetrics;
260
251
  }[];
261
252
  readonly measuredAtMs: number;
@@ -291,23 +282,6 @@ interface InsightsGetAppUsageResult {
291
282
  }[];
292
283
  readonly measuredAtMs: number;
293
284
  }
294
- /** Whole UTC days, at most 31, including the current unfinished day. */
295
- interface InsightsGetDistributionHistoryInput extends InsightsScope {
296
- readonly timeRange: InsightsTimeRange;
297
- }
298
- interface InsightsGetDistributionHistoryResult {
299
- readonly coverage: InsightsCoverage;
300
- readonly measuredAtMs: number;
301
- readonly points: readonly {
302
- readonly startMs: number;
303
- readonly bundles: readonly {
304
- readonly appVersion: string;
305
- readonly releaseId: string | null;
306
- readonly bundleKind: "release" | "builtin" | "unknown";
307
- readonly installations: number;
308
- }[];
309
- }[];
310
- }
311
285
  //#endregion
312
286
  //#region ../insights/dist/server/schema.d.mts
313
287
  //#region src/server/schema.d.ts
@@ -461,10 +435,6 @@ declare const plugins: readonly [import("@hot-updater/plugin-core").HotUpdaterPl
461
435
  movement_install_id: "string";
462
436
  bundle_ref: "string";
463
437
  }, {
464
- readonly recent: {
465
- readonly eq: readonly ["channel", "platform", "day"];
466
- readonly sort: readonly ["received_at_ms"];
467
- };
468
438
  readonly movementsByInstall: {
469
439
  readonly eq: readonly ["movement_install_id"];
470
440
  readonly sort: readonly ["received_at_ms"];
@@ -564,7 +534,7 @@ declare const plugins: readonly [import("@hot-updater/plugin-core").HotUpdaterPl
564
534
  readonly eq: readonly ["identity"];
565
535
  readonly sort: readonly ["bucket_start_ms"];
566
536
  };
567
- }, "launch_users" | "activity_users" | "failed_users", readonly ["identity", "bucket_start_ms"]>;
537
+ }, "activity_users" | "failed_users", readonly ["identity", "bucket_start_ms"]>;
568
538
  readonly insights_overview_daily: import("@hot-updater/plugin-core").AggregateDefinition<{
569
539
  readonly identity: {
570
540
  readonly type: "string";
@@ -592,7 +562,7 @@ declare const plugins: readonly [import("@hot-updater/plugin-core").HotUpdaterPl
592
562
  readonly eq: readonly ["identity"];
593
563
  readonly sort: readonly ["bucket_start_ms"];
594
564
  };
595
- }, "launch_users" | "activity_users" | "failed_users", readonly ["identity", "bucket_start_ms"]>;
565
+ }, "activity_users" | "failed_users", readonly ["identity", "bucket_start_ms"]>;
596
566
  readonly insights_overview_lifetime: import("@hot-updater/plugin-core").AggregateDefinition<{
597
567
  readonly identity: {
598
568
  readonly type: "string";
@@ -649,68 +619,6 @@ declare const plugins: readonly [import("@hot-updater/plugin-core").HotUpdaterPl
649
619
  readonly sort: readonly ["bucket_start_ms"];
650
620
  };
651
621
  }, never, readonly ["channel", "platform", "app_version", "release_id", "bucket_start_ms"]>;
652
- readonly bundle_daily_heads: import("@hot-updater/plugin-core").TableDefinition<{
653
- readonly install_id: {
654
- readonly type: "string";
655
- readonly maxLength: 255;
656
- };
657
- readonly bucket_start_ms: {
658
- readonly type: "integer";
659
- };
660
- readonly id: {
661
- readonly type: "string";
662
- readonly maxLength: 36;
663
- };
664
- readonly received_at_ms: {
665
- readonly type: "integer";
666
- };
667
- readonly channel: {
668
- readonly type: "string";
669
- };
670
- readonly platform: {
671
- readonly type: "string";
672
- readonly maxLength: 16;
673
- };
674
- readonly app_version: {
675
- readonly type: "string";
676
- };
677
- readonly release_id: {
678
- readonly type: "string";
679
- readonly maxLength: 36;
680
- };
681
- readonly bundle_kind: {
682
- readonly type: "string";
683
- readonly maxLength: 16;
684
- };
685
- }, Readonly<Record<string, import("@hot-updater/plugin-core").FieldType>>, {}, readonly ["install_id", "bucket_start_ms"]>;
686
- readonly insights_distribution_history: import("@hot-updater/plugin-core").AggregateDefinition<{
687
- readonly channel: {
688
- readonly type: "string";
689
- };
690
- readonly platform: {
691
- readonly type: "string";
692
- readonly maxLength: 16;
693
- };
694
- readonly app_version: {
695
- readonly type: "string";
696
- };
697
- readonly release_id: {
698
- readonly type: "string";
699
- readonly maxLength: 36;
700
- };
701
- readonly bundle_kind: {
702
- readonly type: "string";
703
- readonly maxLength: 16;
704
- };
705
- readonly bucket_start_ms: {
706
- readonly type: "integer";
707
- };
708
- }, "installations", {
709
- readonly byScope: {
710
- readonly eq: readonly ["channel", "platform"];
711
- readonly sort: readonly ["bucket_start_ms"];
712
- };
713
- }, never, readonly ["channel", "platform", "app_version", "release_id", "bundle_kind", "bucket_start_ms"]>;
714
622
  readonly insights_latest_by_bundle: import("@hot-updater/plugin-core").AggregateDefinition<{
715
623
  readonly platform: {
716
624
  readonly type: "string";
@@ -806,8 +714,8 @@ declare const plugins: readonly [import("@hot-updater/plugin-core").HotUpdaterPl
806
714
  findLatestEvents: (input: InsightsFindLatestEventsInput) => Promise<readonly BundleEventRow[]>;
807
715
  countLatestEvents: (input: InsightsCountLatestEventsInput) => Promise<number>;
808
716
  countEvents: (input: InsightsCountEventsInput) => Promise<number>;
717
+ countEventSeries: (input: InsightsCountEventSeriesInput) => Promise<readonly InsightsEventSeriesPoint[]>;
809
718
  getReleaseActivity: (input: InsightsGetReleaseActivityInput) => Promise<InsightsGetReleaseActivityResult>;
810
- getDistributionHistory: (input: InsightsGetDistributionHistoryInput) => Promise<InsightsGetDistributionHistoryResult>;
811
719
  getAppUsage: (input: InsightsGetAppUsageInput) => Promise<InsightsGetAppUsageResult>;
812
720
  getUpdateFailures: (input: InsightsUpdateFailuresInput) => Promise<InsightsUpdateFailures>;
813
721
  };
package/dist/index.d.mts CHANGED
@@ -200,6 +200,19 @@ interface InsightsCountEventsInput {
200
200
  readonly sinceMs: number;
201
201
  readonly beforeReceivedAtMs: number;
202
202
  }
203
+ /** One bundle filter's stored events in each interval of a time range. */
204
+ interface InsightsCountEventSeriesInput {
205
+ readonly filter: InsightsBundleEventFilter;
206
+ /** Whole UTC hours, at most 90 days, that a whole number of intervals fill. */
207
+ readonly timeRange: InsightsTimeRange;
208
+ /** Whole hours each point spans, from `timeRange.start`. */
209
+ readonly intervalMs: number;
210
+ }
211
+ /** Stored events in [startMs, startMs + intervalMs). */
212
+ interface InsightsEventSeriesPoint {
213
+ readonly startMs: number;
214
+ readonly events: number;
215
+ }
203
216
  interface ReleaseReference {
204
217
  readonly releaseId: string;
205
218
  readonly platform: "ios" | "android";
@@ -218,44 +231,22 @@ type InsightsCoverage = {
218
231
  readonly kind: "partial";
219
232
  readonly sinceMs: number | null;
220
233
  };
234
+ /**
235
+ * A release's counts since its first report, from its lifetime counters,
236
+ * which are kept.
237
+ */
221
238
  interface ReleaseActivityMetrics {
222
239
  readonly downloads: number;
223
240
  readonly launches: number;
224
241
  readonly failedLaunches: number;
225
- /** Omitted for lifetime-only bundle-row reads. */
226
- readonly uniqueUsers?: number;
227
- /**
228
- * Points of each UTC day, or of each `intervalMs` from the period's start
229
- * on a release read that asks for one; present only for period reads.
230
- */
231
- readonly series?: readonly {
232
- readonly startMs: number;
233
- readonly downloads: number;
234
- readonly launches: number;
235
- readonly failedLaunches: number;
236
- }[];
237
242
  }
238
- type InsightsGetReleaseActivityInput = {
243
+ interface InsightsGetReleaseActivityInput {
244
+ /** 1 to 100 releases. */
239
245
  readonly releases: readonly ReleaseReference[];
240
- readonly timeRange?: InsightsTimeRange;
241
- /**
242
- * Whole hours each series point spans, from `timeRange.start`, with
243
- * every point present; omitted, the series has a point per UTC day
244
- * with reports. Only with a `timeRange`.
245
- */
246
- readonly intervalMs?: number;
247
- readonly scope?: never;
248
- } | {
249
- readonly scope: InsightsScope;
250
- readonly timeRange: InsightsTimeRange;
251
- readonly intervalMs?: never;
252
- readonly releases?: never;
253
- };
246
+ }
254
247
  interface InsightsGetReleaseActivityResult {
255
- readonly coverage: InsightsCoverage;
256
248
  readonly data: readonly {
257
- readonly release?: ReleaseReference;
258
- readonly scope?: InsightsScope;
249
+ readonly release: ReleaseReference;
259
250
  readonly metrics: ReleaseActivityMetrics;
260
251
  }[];
261
252
  readonly measuredAtMs: number;
@@ -291,23 +282,6 @@ interface InsightsGetAppUsageResult {
291
282
  }[];
292
283
  readonly measuredAtMs: number;
293
284
  }
294
- /** Whole UTC days, at most 31, including the current unfinished day. */
295
- interface InsightsGetDistributionHistoryInput extends InsightsScope {
296
- readonly timeRange: InsightsTimeRange;
297
- }
298
- interface InsightsGetDistributionHistoryResult {
299
- readonly coverage: InsightsCoverage;
300
- readonly measuredAtMs: number;
301
- readonly points: readonly {
302
- readonly startMs: number;
303
- readonly bundles: readonly {
304
- readonly appVersion: string;
305
- readonly releaseId: string | null;
306
- readonly bundleKind: "release" | "builtin" | "unknown";
307
- readonly installations: number;
308
- }[];
309
- }[];
310
- }
311
285
  //#endregion
312
286
  //#region ../insights/dist/server/schema.d.mts
313
287
  //#region src/server/schema.d.ts
@@ -461,10 +435,6 @@ declare const plugins: readonly [import("@hot-updater/plugin-core").HotUpdaterPl
461
435
  movement_install_id: "string";
462
436
  bundle_ref: "string";
463
437
  }, {
464
- readonly recent: {
465
- readonly eq: readonly ["channel", "platform", "day"];
466
- readonly sort: readonly ["received_at_ms"];
467
- };
468
438
  readonly movementsByInstall: {
469
439
  readonly eq: readonly ["movement_install_id"];
470
440
  readonly sort: readonly ["received_at_ms"];
@@ -564,7 +534,7 @@ declare const plugins: readonly [import("@hot-updater/plugin-core").HotUpdaterPl
564
534
  readonly eq: readonly ["identity"];
565
535
  readonly sort: readonly ["bucket_start_ms"];
566
536
  };
567
- }, "launch_users" | "activity_users" | "failed_users", readonly ["identity", "bucket_start_ms"]>;
537
+ }, "activity_users" | "failed_users", readonly ["identity", "bucket_start_ms"]>;
568
538
  readonly insights_overview_daily: import("@hot-updater/plugin-core").AggregateDefinition<{
569
539
  readonly identity: {
570
540
  readonly type: "string";
@@ -592,7 +562,7 @@ declare const plugins: readonly [import("@hot-updater/plugin-core").HotUpdaterPl
592
562
  readonly eq: readonly ["identity"];
593
563
  readonly sort: readonly ["bucket_start_ms"];
594
564
  };
595
- }, "launch_users" | "activity_users" | "failed_users", readonly ["identity", "bucket_start_ms"]>;
565
+ }, "activity_users" | "failed_users", readonly ["identity", "bucket_start_ms"]>;
596
566
  readonly insights_overview_lifetime: import("@hot-updater/plugin-core").AggregateDefinition<{
597
567
  readonly identity: {
598
568
  readonly type: "string";
@@ -649,68 +619,6 @@ declare const plugins: readonly [import("@hot-updater/plugin-core").HotUpdaterPl
649
619
  readonly sort: readonly ["bucket_start_ms"];
650
620
  };
651
621
  }, never, readonly ["channel", "platform", "app_version", "release_id", "bucket_start_ms"]>;
652
- readonly bundle_daily_heads: import("@hot-updater/plugin-core").TableDefinition<{
653
- readonly install_id: {
654
- readonly type: "string";
655
- readonly maxLength: 255;
656
- };
657
- readonly bucket_start_ms: {
658
- readonly type: "integer";
659
- };
660
- readonly id: {
661
- readonly type: "string";
662
- readonly maxLength: 36;
663
- };
664
- readonly received_at_ms: {
665
- readonly type: "integer";
666
- };
667
- readonly channel: {
668
- readonly type: "string";
669
- };
670
- readonly platform: {
671
- readonly type: "string";
672
- readonly maxLength: 16;
673
- };
674
- readonly app_version: {
675
- readonly type: "string";
676
- };
677
- readonly release_id: {
678
- readonly type: "string";
679
- readonly maxLength: 36;
680
- };
681
- readonly bundle_kind: {
682
- readonly type: "string";
683
- readonly maxLength: 16;
684
- };
685
- }, Readonly<Record<string, import("@hot-updater/plugin-core").FieldType>>, {}, readonly ["install_id", "bucket_start_ms"]>;
686
- readonly insights_distribution_history: import("@hot-updater/plugin-core").AggregateDefinition<{
687
- readonly channel: {
688
- readonly type: "string";
689
- };
690
- readonly platform: {
691
- readonly type: "string";
692
- readonly maxLength: 16;
693
- };
694
- readonly app_version: {
695
- readonly type: "string";
696
- };
697
- readonly release_id: {
698
- readonly type: "string";
699
- readonly maxLength: 36;
700
- };
701
- readonly bundle_kind: {
702
- readonly type: "string";
703
- readonly maxLength: 16;
704
- };
705
- readonly bucket_start_ms: {
706
- readonly type: "integer";
707
- };
708
- }, "installations", {
709
- readonly byScope: {
710
- readonly eq: readonly ["channel", "platform"];
711
- readonly sort: readonly ["bucket_start_ms"];
712
- };
713
- }, never, readonly ["channel", "platform", "app_version", "release_id", "bundle_kind", "bucket_start_ms"]>;
714
622
  readonly insights_latest_by_bundle: import("@hot-updater/plugin-core").AggregateDefinition<{
715
623
  readonly platform: {
716
624
  readonly type: "string";
@@ -806,8 +714,8 @@ declare const plugins: readonly [import("@hot-updater/plugin-core").HotUpdaterPl
806
714
  findLatestEvents: (input: InsightsFindLatestEventsInput) => Promise<readonly BundleEventRow[]>;
807
715
  countLatestEvents: (input: InsightsCountLatestEventsInput) => Promise<number>;
808
716
  countEvents: (input: InsightsCountEventsInput) => Promise<number>;
717
+ countEventSeries: (input: InsightsCountEventSeriesInput) => Promise<readonly InsightsEventSeriesPoint[]>;
809
718
  getReleaseActivity: (input: InsightsGetReleaseActivityInput) => Promise<InsightsGetReleaseActivityResult>;
810
- getDistributionHistory: (input: InsightsGetDistributionHistoryInput) => Promise<InsightsGetDistributionHistoryResult>;
811
719
  getAppUsage: (input: InsightsGetAppUsageInput) => Promise<InsightsGetAppUsageResult>;
812
720
  getUpdateFailures: (input: InsightsUpdateFailuresInput) => Promise<InsightsUpdateFailures>;
813
721
  };
@@ -4570,7 +4570,7 @@ const createKvAdapter = ({ store, tablePrefix = "" }) => {
4570
4570
  };
4571
4571
  //#endregion
4572
4572
  //#region ../../packages/server/dist/version.mjs
4573
- const HOT_UPDATER_SERVER_VERSION = "1.0.0-rc.30";
4573
+ const HOT_UPDATER_SERVER_VERSION = "1.0.0-rc.32";
4574
4574
  //#endregion
4575
4575
  //#region ../../packages/server/dist/handlerVersionRoutes.mjs
4576
4576
  /**
@@ -9982,42 +9982,23 @@ const createValidatedInsightsModel = (model) => ({
9982
9982
  ]) || !isBundleFilter(input.filter) || !isTimestamp(input.sinceMs) || !isTimestamp(input.beforeReceivedAtMs) || input.sinceMs > input.beforeReceivedAtMs) invalidQuery();
9983
9983
  return validateCount(await model.countEvents(input));
9984
9984
  },
9985
- async getReleaseActivity(input) {
9985
+ async countEventSeries(input) {
9986
9986
  if (!isRecord$2(input) || !hasOnlyKeys(input, [
9987
- "releases",
9988
- "scope",
9987
+ "filter",
9989
9988
  "timeRange",
9990
9989
  "intervalMs"
9991
- ])) invalidQuery();
9992
- const releases = input.releases;
9993
- const scope = input.scope;
9994
- const timeRange = input.timeRange;
9995
- const intervalMs = input.intervalMs;
9996
- const releaseQuery = Array.isArray(releases) && releases.length > 0 && releases.length <= 100 && releases.every(isReleaseReference) && scope === void 0 && (timeRange === void 0 ? intervalMs === void 0 : isTimeRange(timeRange) && (intervalMs === void 0 || isTimestamp(intervalMs) && intervalMs > 0 && intervalMs % 36e5 === 0 && (timeRange.end - timeRange.start) / intervalMs <= 8784));
9997
- const scopeQuery = releases === void 0 && intervalMs === void 0 && isRecord$2(scope) && hasOnlyKeys(scope, ["platform", "channel"]) && hasScope(scope) && isTimeRange(timeRange);
9998
- if (!releaseQuery && !scopeQuery) invalidQuery();
9999
- const result = await model.getReleaseActivity(input);
10000
- validateAggregateResult(result);
10001
- if (!Array.isArray(result.data)) invalidResult();
10002
- return result;
9990
+ ]) || !isBundleFilter(input.filter) || !isTimeRange(input.timeRange) || !isTimestamp(input.intervalMs)) invalidQuery();
9991
+ const { start, end } = input.timeRange;
9992
+ const { intervalMs } = input;
9993
+ if (intervalMs === 0 || intervalMs % 36e5 !== 0 || start % 36e5 !== 0 || (end - start) % intervalMs !== 0 || end - start > 7776e6) invalidQuery();
9994
+ const points = await model.countEventSeries(input);
9995
+ if (!Array.isArray(points) || points.length !== (end - start) / intervalMs || points.some((point, index) => !isRecord$2(point) || !hasOnlyKeys(point, ["startMs", "events"]) || point.startMs !== start + index * intervalMs || !isTimestamp(point.events))) invalidResult();
9996
+ return points;
10003
9997
  },
10004
- async getDistributionHistory(input) {
10005
- if (!isRecord$2(input) || !hasOnlyKeys(input, [
10006
- "channel",
10007
- "platform",
10008
- "timeRange"
10009
- ]) || !hasScope(input) || !isTimeRange(input.timeRange) || input.timeRange.start % 864e5 !== 0 || input.timeRange.end % 864e5 !== 0 || input.timeRange.end - input.timeRange.start > 26784e5) invalidQuery();
10010
- const result = await model.getDistributionHistory(input);
10011
- validateAggregateResult(result);
10012
- if (!Array.isArray(result.points)) invalidResult();
10013
- for (const point of result.points) {
10014
- if (!isTimestamp(point.startMs) || !Array.isArray(point.bundles)) invalidResult();
10015
- for (const bundle of point.bundles) if (!isText$1(bundle.appVersion) || bundle.releaseId !== null && !isText$1(bundle.releaseId) || ![
10016
- "release",
10017
- "builtin",
10018
- "unknown"
10019
- ].includes(bundle.bundleKind) || !isTimestamp(bundle.installations)) invalidResult();
10020
- }
9998
+ async getReleaseActivity(input) {
9999
+ if (!isRecord$2(input) || !hasOnlyKeys(input, ["releases"]) || !Array.isArray(input.releases) || input.releases.length < 1 || input.releases.length > 100 || !input.releases.every(isReleaseReference)) invalidQuery();
10000
+ const result = await model.getReleaseActivity(input);
10001
+ if (!isRecord$2(result) || !isTimestamp(result.measuredAtMs) || !Array.isArray(result.data) || result.data.some((item) => !isRecord$2(item) || !isReleaseReference(item.release) || !isRecord$2(item.metrics) || !isTimestamp(item.metrics.downloads) || !isTimestamp(item.metrics.launches) || !isTimestamp(item.metrics.failedLaunches))) invalidResult();
10021
10002
  return result;
10022
10003
  },
10023
10004
  async getAppUsage(input) {
@@ -10050,9 +10031,9 @@ const createInsightsModel = (api) => createValidatedInsightsModel({
10050
10031
  findLatestEvents: api.findLatestEvents,
10051
10032
  countLatestEvents: api.countLatestEvents,
10052
10033
  countEvents: api.countEvents,
10034
+ countEventSeries: api.countEventSeries,
10053
10035
  getReleaseActivity: api.getReleaseActivity,
10054
- getAppUsage: api.getAppUsage,
10055
- getDistributionHistory: api.getDistributionHistory
10036
+ getAppUsage: api.getAppUsage
10056
10037
  });
10057
10038
  //#endregion
10058
10039
  //#region ../insights/dist/server/official.mjs
@@ -10872,14 +10853,6 @@ const bundleEvents = (days) => defineTable({
10872
10853
  }
10873
10854
  },
10874
10855
  indexes: {
10875
- recent: {
10876
- eq: [
10877
- "channel",
10878
- "platform",
10879
- "day"
10880
- ],
10881
- sort: ["received_at_ms"]
10882
- },
10883
10856
  movementsByInstall: {
10884
10857
  eq: ["movement_install_id"],
10885
10858
  sort: ["received_at_ms"]
@@ -10996,10 +10969,11 @@ const window = {
10996
10969
  };
10997
10970
  /**
10998
10971
  * Counters of one period kind: hourly, daily, or lifetime at bucket 0. A
10999
- * release or channel row counts downloads, launches, and failed launches,
11000
- * and downloads a patch delivered and those that fell back from one. A
11001
- * release's lifetime row counts its failed updates (`failed_updates`), since
11002
- * no breakdown row outlives the raw period; windowed reads sum
10972
+ * release or channel row counts downloads and failed launches, and downloads
10973
+ * a patch delivered and those that fell back from one. Only a release's
10974
+ * lifetime row counts launches, which the bundle list reads and no windowed
10975
+ * read sums. It also counts the release's failed updates (`failed_updates`),
10976
+ * since no breakdown row outlives the raw period; windowed reads sum
11003
10977
  * `insights_failures` instead.
11004
10978
  */
11005
10979
  const counters = (retention) => defineAggregate(identityFields, {
@@ -11018,17 +10992,13 @@ const counters = (retention) => defineAggregate(identityFields, {
11018
10992
  ...retention === void 0 ? {} : { retention }
11019
10993
  });
11020
10994
  /**
11021
- * Unique-installation sketches of one period kind. Rows of a failure
11022
- * identity (`failure` and `check` scopes) keep only `failed_users`, so a
11023
- * release's launch rows never grow by a failure's registers.
10995
+ * Unique-installation sketches of one period kind: a usage row's active
10996
+ * installations (`activity_users`), and a `failure` or `check` row's
10997
+ * installations whose update or update check failed (`failed_users`).
11024
10998
  */
11025
10999
  const sketches = (retention) => defineAggregate(identityFields, {
11026
11000
  key: ["identity", "bucket_start_ms"],
11027
- distinct: [
11028
- "launch_users",
11029
- "activity_users",
11030
- "failed_users"
11031
- ],
11001
+ distinct: ["activity_users", "failed_users"],
11032
11002
  shards: SKETCH_SHARDS,
11033
11003
  batched: true,
11034
11004
  indexes: { window },
@@ -11134,71 +11104,6 @@ const insightsDistribution = (retention) => defineAggregate({
11134
11104
  },
11135
11105
  retention
11136
11106
  });
11137
- /** The last running bundle observed per installation and UTC day. */
11138
- const bundleDailyHeads = (retention) => defineTable({
11139
- install_id: {
11140
- type: "string",
11141
- maxLength: 255
11142
- },
11143
- bucket_start_ms: { type: "integer" },
11144
- id: {
11145
- type: "string",
11146
- maxLength: 36
11147
- },
11148
- received_at_ms: { type: "integer" },
11149
- channel: { type: "string" },
11150
- platform: {
11151
- type: "string",
11152
- maxLength: 16
11153
- },
11154
- app_version: { type: "string" },
11155
- release_id: {
11156
- type: "string",
11157
- maxLength: 36
11158
- },
11159
- bundle_kind: {
11160
- type: "string",
11161
- maxLength: 16
11162
- }
11163
- }, {
11164
- key: ["install_id", "bucket_start_ms"],
11165
- retention
11166
- });
11167
- /** Daily observations stay in their day when an installation reports again. */
11168
- const insightsDistributionHistory = (retention) => defineAggregate({
11169
- channel: { type: "string" },
11170
- platform: {
11171
- type: "string",
11172
- maxLength: 16
11173
- },
11174
- app_version: { type: "string" },
11175
- release_id: {
11176
- type: "string",
11177
- maxLength: 36
11178
- },
11179
- bundle_kind: {
11180
- type: "string",
11181
- maxLength: 16
11182
- },
11183
- bucket_start_ms: { type: "integer" }
11184
- }, {
11185
- key: [
11186
- "channel",
11187
- "platform",
11188
- "app_version",
11189
- "release_id",
11190
- "bundle_kind",
11191
- "bucket_start_ms"
11192
- ],
11193
- gauges: ["installations"],
11194
- shards: GAUGE_SHARDS,
11195
- batched: true,
11196
- indexes: { byScope: {
11197
- eq: ["channel", "platform"],
11198
- sort: ["bucket_start_ms"]
11199
- } },
11200
- retention
11201
- });
11202
11107
  /** Latest events by the bundle they came from or went to, bucketed like the distribution. */
11203
11108
  const insightsLatestByBundle = (retention) => defineAggregate({
11204
11109
  platform: {
@@ -11318,8 +11223,6 @@ const createInsightsSchema = ({ rawDays, dailyDays } = DEFAULT_INSIGHTS_RETENTIO
11318
11223
  insights_overview_lifetime: counters(),
11319
11224
  insights_sketches_lifetime: lifetimeSketches(),
11320
11225
  insights_distribution: insightsDistribution(daily),
11321
- bundle_daily_heads: bundleDailyHeads(daily),
11322
- insights_distribution_history: insightsDistributionHistory(daily),
11323
11226
  insights_latest_by_bundle: insightsLatestByBundle(daily),
11324
11227
  insights_outcomes: insightsOutcomes(hourly),
11325
11228
  insights_failures: insightsFailures(hourly)
@@ -11362,12 +11265,14 @@ const insightsOverviewDeltas = (event) => {
11362
11265
  downloads: (previous?.downloads ?? 0) + values.downloads,
11363
11266
  launches: (previous?.launches ?? 0) + values.launches,
11364
11267
  failedLaunches: (previous?.failedLaunches ?? 0) + values.failedLaunches,
11365
- launchIdentity: previous?.launchIdentity ?? values.launchIdentity,
11366
11268
  activityIdentity: previous?.activityIdentity ?? values.activityIdentity
11367
11269
  });
11368
11270
  };
11369
11271
  const metric = (releaseId, values) => {
11370
- const launchIdentity = values.launches > 0 ? event.install_id : void 0;
11272
+ const windowed = {
11273
+ ...values,
11274
+ launches: 0
11275
+ };
11371
11276
  if (releaseId !== null) for (const [periodKind, start] of [["lifetime", 0], ["hour", bucketStartMs]]) append({
11372
11277
  scopeKind: "release",
11373
11278
  releaseKind: "specific",
@@ -11378,10 +11283,7 @@ const insightsOverviewDeltas = (event) => {
11378
11283
  appVersion: "",
11379
11284
  periodKind,
11380
11285
  bucketStartMs: start
11381
- }, {
11382
- ...values,
11383
- ...periodKind === "hour" ? { launchIdentity } : {}
11384
- });
11286
+ }, periodKind === "lifetime" ? values : windowed);
11385
11287
  append({
11386
11288
  scopeKind: "channel",
11387
11289
  releaseKind: "all",
@@ -11392,10 +11294,7 @@ const insightsOverviewDeltas = (event) => {
11392
11294
  appVersion: "",
11393
11295
  periodKind: "hour",
11394
11296
  bucketStartMs
11395
- }, {
11396
- ...values,
11397
- launchIdentity
11398
- });
11297
+ }, windowed);
11399
11298
  };
11400
11299
  if (event.type === "UPDATE_DOWNLOADED") metric(event.to_release_id, {
11401
11300
  downloads: 1,
@@ -11520,11 +11419,10 @@ const patchCounters = (event) => event.type !== "UPDATE_DOWNLOADED" ? {} : {
11520
11419
  };
11521
11420
  /**
11522
11421
  * Counters and sketches for one event: release, channel, and usage rows, with
11523
- * day rollups for channel and usage. Usage rows are written for the event's
11524
- * platform only, since a read for every platform merges the ios and android
11525
- * sketches; a channel's active installations come from its usage rows, so
11526
- * channel rows keep no sketch of their own. A download's patch counters go
11527
- * in the rows that count it.
11422
+ * day rollups for channel and usage. Only usage rows keep a sketch, of active
11423
+ * installations, and only for the event's platform, since a read for every
11424
+ * platform merges the ios and android sketches. A download's patch counters
11425
+ * go in the rows that count it.
11528
11426
  */
11529
11427
  const countEvent = (tx, event) => {
11530
11428
  const shardBy = event.install_id;
@@ -11550,11 +11448,7 @@ const countEvent = (tx, event) => {
11550
11448
  ...delta.downloads === 0 ? {} : patchCounters(event)
11551
11449
  };
11552
11450
  if (Object.keys(counters).length > 0) tx.aggregate(models.counters, key, counters, { shardBy });
11553
- const sketches = {
11554
- ...delta.launchIdentity === void 0 || parts.scopeKind === "channel" ? {} : { launch_users: addDistinct(null, delta.launchIdentity) },
11555
- ...delta.activityIdentity === void 0 ? {} : { activity_users: addDistinct(null, delta.activityIdentity) }
11556
- };
11557
- if (models.sketches !== void 0 && Object.keys(sketches).length > 0) tx.aggregate(models.sketches, key, sketches, { shardBy });
11451
+ if (models.sketches !== void 0 && delta.activityIdentity !== void 0) tx.aggregate(models.sketches, key, { activity_users: addDistinct(null, delta.activityIdentity) }, { shardBy });
11558
11452
  }
11559
11453
  }
11560
11454
  };
@@ -11707,66 +11601,21 @@ const REPEATED_FIELDS = [
11707
11601
  const repeatsHead = (event, head) => event.type === "UNCHANGED" && head.type !== "UPDATE_DOWNLOADED" && dayOf(event.received_at_ms) === dayOf(head.received_at_ms) && REPEATED_FIELDS.every((field) => event[field] === head[field]);
11708
11602
  /**
11709
11603
  * Records one event in one transaction: one batch read of the event and its
11710
- * installation's latest and daily heads, then the gauge and sketch rows it
11711
- * changes and one
11604
+ * installation's head, one of the gauge and sketch rows it changes, then one
11712
11605
  * write. On a database that batches aggregates (DynamoDB, Firestore), the
11713
11606
  * write holds the event's rows and one log row instead, and a compaction
11714
11607
  * reads and writes the aggregate rows. A stored event's id changes nothing
11715
11608
  * when repeated, whichever installation sends it, and neither does the id
11716
11609
  * of the installation's head. An UNCHANGED report that repeats its head on
11717
- * the same UTC day only advances its daily observation. An older event counts in its
11610
+ * the same UTC day writes nothing at all. An older event still counts in its
11718
11611
  * own hour but never replaces the head. An update failure is stored and
11719
11612
  * counted, but changes what no installation runs, so it moves no head.
11720
11613
  */
11721
11614
  const recordEvent = (db, event) => {
11722
11615
  assertBundleEventRow(event);
11723
11616
  return db.transaction(async (tx) => {
11724
- const dailyKey = {
11725
- install_id: event.install_id,
11726
- bucket_start_ms: dayOf(event.received_at_ms)
11727
- };
11728
- const [existing, previous, daily] = await Promise.all([
11729
- tx.findOne("bundle_events", { id: event.id }),
11730
- tx.findOne("bundle_event_heads", { install_id: event.install_id }),
11731
- event.type === "UPDATE_FAILED" ? null : tx.findOne("bundle_daily_heads", dailyKey)
11732
- ]);
11733
- if (existing !== null || previous?.id === event.id || daily?.id === event.id) return;
11734
- if (event.type !== "UPDATE_FAILED" && (daily === null || isNewer(event, daily))) {
11735
- const downloaded = event.type === "UPDATE_DOWNLOADED";
11736
- const releaseId = downloaded ? event.from_release_id : event.to_release_id;
11737
- const bundleId = downloaded ? event.from_bundle_id : event.to_bundle_id;
11738
- const next = {
11739
- ...dailyKey,
11740
- id: event.id,
11741
- received_at_ms: event.received_at_ms,
11742
- channel: event.channel,
11743
- platform: event.platform,
11744
- app_version: event.app_version,
11745
- release_id: releaseId ?? "",
11746
- bundle_kind: bundleId === "00000000-0000-0000-0000-000000000000" ? "builtin" : releaseId === null ? "unknown" : "release"
11747
- };
11748
- const count = (head, delta) => {
11749
- tx.aggregate("insights_distribution_history", {
11750
- channel: head.channel,
11751
- platform: head.platform,
11752
- app_version: head.app_version,
11753
- release_id: head.release_id,
11754
- bundle_kind: head.bundle_kind,
11755
- bucket_start_ms: head.bucket_start_ms
11756
- }, { installations: delta }, { shardBy: head.install_id });
11757
- };
11758
- if (daily !== null) {
11759
- if (daily.channel !== next.channel || daily.platform !== next.platform || daily.app_version !== next.app_version || daily.release_id !== next.release_id || daily.bundle_kind !== next.bundle_kind) {
11760
- count(daily, -1);
11761
- count(next, 1);
11762
- }
11763
- const { install_id: _, bucket_start_ms: __, ...fields } = next;
11764
- tx.update("bundle_daily_heads", daily, fields);
11765
- } else {
11766
- tx.create("bundle_daily_heads", next);
11767
- count(next, 1);
11768
- }
11769
- }
11617
+ const [existing, previous] = await Promise.all([tx.findOne("bundle_events", { id: event.id }), tx.findOne("bundle_event_heads", { install_id: event.install_id })]);
11618
+ if (existing !== null || previous?.id === event.id) return;
11770
11619
  if (previous !== null && repeatsHead(event, previous)) return;
11771
11620
  if (event.type !== "UNCHANGED") {
11772
11621
  tx.create("bundle_events", event);
@@ -11958,6 +11807,30 @@ const countEvents = async (db, input) => {
11958
11807
  }));
11959
11808
  return await countRaw(db, filter, sinceMs, start) + hours.reduce((sum, row) => sum + row.events, 0) + await countRaw(db, filter, end, beforeReceivedAtMs);
11960
11809
  };
11810
+ /**
11811
+ * A bundle filter's stored events in each interval of whole hours: one read
11812
+ * of its hourly counts, every interval present.
11813
+ */
11814
+ const countEventSeries = async (db, input) => {
11815
+ const { filter, intervalMs } = input;
11816
+ const { start, end } = input.timeRange;
11817
+ const events = Array.from({ length: (end - start) / intervalMs }, () => 0);
11818
+ const hours = await drain((page) => db.findAggregates("insights_outcomes", {
11819
+ index: "byRef",
11820
+ where: scopeOf(filter),
11821
+ range: {
11822
+ gte: start,
11823
+ lt: end
11824
+ },
11825
+ limit: PAGE,
11826
+ ...page
11827
+ }));
11828
+ for (const row of hours) events[Math.floor((row.bucket_start_ms - start) / intervalMs)] += row.events;
11829
+ return events.map((count, index) => ({
11830
+ startMs: start + index * intervalMs,
11831
+ events: count
11832
+ }));
11833
+ };
11961
11834
  /** A bundle filter's distinct (field, value, type) predicates. */
11962
11835
  const latestPredicates = (bundle) => {
11963
11836
  if (bundle === void 0) return void 0;
@@ -12029,7 +11902,7 @@ const retained = (now, { rawDays, dailyDays }) => ({
12029
11902
  * Whether the rows a window reads still hold all of it; an older start is
12030
11903
  * partial from `oldest`, the first bucket its rows keep.
12031
11904
  */
12032
- const coverageOf = (start, oldest) => start === void 0 || start >= oldest ? {
11905
+ const coverageOf = (start, oldest) => start >= oldest ? {
12033
11906
  kind: "complete",
12034
11907
  sinceMs: 0
12035
11908
  } : {
@@ -12132,43 +12005,6 @@ const lifetimeMetrics = async (db, release) => {
12132
12005
  failedLaunches: lifetime?.failed_launches ?? 0
12133
12006
  };
12134
12007
  };
12135
- /**
12136
- * Counters, unique users, and a series over a window: a point per UTC day
12137
- * with rows, or, with `intervalMs`, every point of that span from the
12138
- * window's start.
12139
- */
12140
- const rangedMetrics = async (db, parts, users, range, days, hour, intervalMs) => {
12141
- const [counters, sketches] = await Promise.all([counterRows(db, parts, range, days, hour), sketchRows(db, users.parts, range, days, hour)]);
12142
- const series = /* @__PURE__ */ new Map();
12143
- if (intervalMs !== void 0) for (let start = range.start; start < range.end; start += intervalMs) series.set(start, {
12144
- downloads: 0,
12145
- launches: 0,
12146
- failedLaunches: 0
12147
- });
12148
- for (const row of counters) {
12149
- const start = intervalMs === void 0 ? dayFloor(row.bucket_start_ms) : row.bucket_start_ms - (row.bucket_start_ms - range.start) % intervalMs;
12150
- const point = series.get(start) ?? {
12151
- downloads: 0,
12152
- launches: 0,
12153
- failedLaunches: 0
12154
- };
12155
- point.downloads += row.downloads;
12156
- point.launches += row.launches;
12157
- point.failedLaunches += row.failed_launches;
12158
- series.set(start, point);
12159
- }
12160
- const total = (field) => counters.reduce((sum, row) => sum + row[field], 0);
12161
- return {
12162
- downloads: total("downloads"),
12163
- launches: total("launches"),
12164
- failedLaunches: total("failed_launches"),
12165
- uniqueUsers: countDistinct(mergeDistinct(sketches.map((row) => row[users.field]))),
12166
- series: [...series].sort(([left], [right]) => left - right).map(([startMs, point]) => ({
12167
- startMs,
12168
- ...point
12169
- }))
12170
- };
12171
- };
12172
12008
  /** A channel and platform's usage rows, of every app version or of one. */
12173
12009
  const usageParts = (channel, platform, appVersion) => ({
12174
12010
  scopeKind: "usage",
@@ -12179,35 +12015,15 @@ const usageParts = (channel, platform, appVersion) => ({
12179
12015
  appVersionKind: appVersion === void 0 ? "all" : "specific",
12180
12016
  appVersion: appVersion ?? ""
12181
12017
  });
12182
- const getReleaseActivity = async (db, input, now, retention) => {
12183
- const at = now();
12184
- const kept = retained(at, retention);
12185
- const data = input.scope !== void 0 ? [{
12186
- scope: input.scope,
12187
- metrics: await rangedMetrics(db, {
12188
- scopeKind: "channel",
12189
- releaseKind: "all",
12190
- releaseId: "",
12191
- channel: input.scope.channel,
12192
- platform: input.scope.platform,
12193
- appVersionKind: "all",
12194
- appVersion: ""
12195
- }, {
12196
- parts: usageParts(input.scope.channel, input.scope.platform),
12197
- field: "activity_users"
12198
- }, input.timeRange, true, kept.hour)
12199
- }] : await Promise.all(input.releases.map(async (release) => ({
12200
- release,
12201
- metrics: input.timeRange === void 0 ? await lifetimeMetrics(db, release) : await rangedMetrics(db, releaseParts(release), {
12202
- parts: releaseParts(release),
12203
- field: "launch_users"
12204
- }, input.timeRange, false, kept.hour, input.intervalMs)
12205
- })));
12206
- const oldest = kept[input.scope === void 0 ? "hour" : "day"];
12018
+ /** Each release's lifetime counters, which are kept: one logical row apiece. */
12019
+ const getReleaseActivity = async (db, input, now) => {
12020
+ const measuredAtMs = now();
12207
12021
  return {
12208
- coverage: coverageOf(input.timeRange?.start, oldest),
12209
- data,
12210
- measuredAtMs: at
12022
+ data: await Promise.all(input.releases.map(async (release) => ({
12023
+ release,
12024
+ metrics: await lifetimeMetrics(db, release)
12025
+ }))),
12026
+ measuredAtMs
12211
12027
  };
12212
12028
  };
12213
12029
  /**
@@ -12467,43 +12283,6 @@ const getUpdateFailures = async (db, input, now, retention) => {
12467
12283
  }
12468
12284
  };
12469
12285
  };
12470
- /** Reads daily gauges, never raw events or mutable latest-state distribution. */
12471
- const getDistributionHistory = async (db, input, now, retention) => {
12472
- const at = now();
12473
- const { start, end } = input.timeRange;
12474
- const points = /* @__PURE__ */ new Map();
12475
- for (let day = start; day < end; day += DAY_MS) points.set(day, []);
12476
- const rows = await drain((page) => db.findAggregates("insights_distribution_history", {
12477
- index: "byScope",
12478
- where: {
12479
- channel: input.channel,
12480
- platform: input.platform
12481
- },
12482
- range: {
12483
- gte: start,
12484
- lt: end
12485
- },
12486
- limit: PAGE,
12487
- ...page
12488
- }));
12489
- for (const row of rows) {
12490
- if (row.installations <= 0) continue;
12491
- points.get(row.bucket_start_ms).push({
12492
- appVersion: row.app_version,
12493
- releaseId: row.release_id || null,
12494
- bundleKind: row.bundle_kind,
12495
- installations: row.installations
12496
- });
12497
- }
12498
- return {
12499
- coverage: coverageOf(start, retained(at, retention).day),
12500
- measuredAtMs: at,
12501
- points: [...points].map(([startMs, bundles]) => ({
12502
- startMs,
12503
- bundles
12504
- }))
12505
- };
12506
- };
12507
12286
  //#endregion
12508
12287
  //#region ../insights/dist/server/queryInput.mjs
12509
12288
  const MAX_PAGE_LIMIT = 100;
@@ -12694,8 +12473,8 @@ const createInsightsApi = (db, now, retention) => ({
12694
12473
  findLatestEvents: (input) => findLatestEvents(db, input),
12695
12474
  countLatestEvents: (input) => countLatestEvents(db, input),
12696
12475
  countEvents: (input) => countEvents(db, input),
12697
- getReleaseActivity: (input) => getReleaseActivity(db, input, now, retention),
12698
- getDistributionHistory: (input) => getDistributionHistory(db, input, now, retention),
12476
+ countEventSeries: (input) => countEventSeries(db, input),
12477
+ getReleaseActivity: (input) => getReleaseActivity(db, input, now),
12699
12478
  getAppUsage: (input) => getAppUsage(db, input, now, retention),
12700
12479
  /** A release's or a channel's update failures, and their breakdown over a time range. */
12701
12480
  getUpdateFailures: (input) => getUpdateFailures(db, input, now, retention)
@@ -12764,7 +12543,7 @@ const insights = (options = {}) => {
12764
12543
  const plugin = definePlugin({
12765
12544
  id: "insights",
12766
12545
  namespace: false,
12767
- schemaVersion: "1.3.0",
12546
+ schemaVersion: "1.2.0",
12768
12547
  schema: createInsightsSchema(retention),
12769
12548
  init: ({ db, now }) => {
12770
12549
  const api = createInsightsApi(db, now, retention);
@@ -12779,32 +12558,6 @@ const insights = (options = {}) => {
12779
12558
  handler: (request, params) => routes[handler](params, request)
12780
12559
  })),
12781
12560
  failuresEndpoint(api),
12782
- {
12783
- access: "admin",
12784
- method: "GET",
12785
- path: "/distribution-history",
12786
- handler: async (request) => {
12787
- const query = new URL(request.url).searchParams;
12788
- try {
12789
- const result = await createInsightsModel(api).getDistributionHistory({
12790
- platform: query.get("platform"),
12791
- channel: query.get("channel") ?? "",
12792
- timeRange: {
12793
- start: Number(query.get("start") ?? NaN),
12794
- end: Number(query.get("end") ?? NaN)
12795
- }
12796
- });
12797
- return Response.json(result, { headers: { "cache-control": "private, no-store" } });
12798
- } catch (error) {
12799
- if (error instanceof DatabaseAdapterInputError) return Response.json({ error: "Choose a platform, channel, and up to 31 whole UTC days." }, { status: 400 });
12800
- if (!isDatabaseBusyError(error)) throw error;
12801
- return Response.json({ error: "Service unavailable" }, {
12802
- status: 503,
12803
- headers: { "retry-after": "5" }
12804
- });
12805
- }
12806
- }
12807
- },
12808
12561
  {
12809
12562
  access: "admin",
12810
12563
  method: "GET",
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.30",
4
+ "version": "1.0.0-rc.32",
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.28",
49
- "@hot-updater/mock": "1.0.0-rc.28",
50
- "@hot-updater/test-utils": "1.0.0-rc.29"
48
+ "@hot-updater/protocol": "1.0.0-rc.29",
49
+ "@hot-updater/mock": "1.0.0-rc.29",
50
+ "@hot-updater/test-utils": "1.0.0-rc.30"
51
51
  },
52
52
  "dependencies": {
53
53
  "@aws-sdk/client-cloudfront": "3.1066.0",
@@ -62,9 +62,9 @@
62
62
  "@aws-sdk/lib-storage": "3.1066.0",
63
63
  "@aws-sdk/lib-dynamodb": "3.1066.0",
64
64
  "hono": "4.12.34",
65
- "@hot-updater/cli-tools": "1.0.0-rc.30",
66
- "@hot-updater/plugin-core": "1.0.0-rc.28",
67
- "@hot-updater/server": "1.0.0-rc.30"
65
+ "@hot-updater/cli-tools": "1.0.0-rc.32",
66
+ "@hot-updater/plugin-core": "1.0.0-rc.29",
67
+ "@hot-updater/server": "1.0.0-rc.32"
68
68
  },
69
69
  "scripts": {
70
70
  "build": "tsdown",