@hot-updater/aws 1.0.0-rc.33 → 1.0.0-rc.35

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
@@ -86,8 +86,6 @@ type BundleEventFailure = DatabaseJsonObject & {
86
86
  readonly origin_code?: string;
87
87
  readonly error_message?: string;
88
88
  readonly error_stack?: string;
89
- /** Android's `ApplicationExitInfo` reason for the process before this one. */
90
- readonly previous_process_exit?: string;
91
89
  };
92
90
  type DatabaseHttpResponse = DatabaseJsonObject & {
93
91
  readonly resource: "catalog" | "artifact";
@@ -110,8 +108,6 @@ type DatabaseBundleEventMetadata = DatabaseJsonObject & {
110
108
  readonly delivery?: "patch" | "manifest" | "archive" | "unknown";
111
109
  /** `UPDATE_DOWNLOADED`: a patch failed and the full files came instead. */
112
110
  readonly patch_fallback?: boolean;
113
- /** `RECOVERED`: Android's `ApplicationExitInfo` reason for the crashed process. */
114
- readonly previous_process_exit?: string;
115
111
  };
116
112
  type BundleEventRowBase = {
117
113
  readonly id: string;
@@ -340,17 +336,6 @@ interface InsightsUpdateFailures {
340
336
  };
341
337
  /** Over a time range: failures by stage and reason, most first. */
342
338
  readonly breakdown?: readonly InsightsFailureBreakdown[];
343
- /**
344
- * Over a time range: failed launches, and the recoveries whose crashed
345
- * process exited for a reason Android 11+ reported, by reason, most first.
346
- */
347
- readonly recoveries?: {
348
- readonly failedLaunches: number;
349
- readonly byExitReason: readonly {
350
- readonly exitReason: string;
351
- readonly events: number;
352
- }[];
353
- };
354
339
  }
355
340
  //#endregion
356
341
  //#region ../api-keys/dist/server/model.d.mts
package/dist/index.d.mts CHANGED
@@ -86,8 +86,6 @@ type BundleEventFailure = DatabaseJsonObject & {
86
86
  readonly origin_code?: string;
87
87
  readonly error_message?: string;
88
88
  readonly error_stack?: string;
89
- /** Android's `ApplicationExitInfo` reason for the process before this one. */
90
- readonly previous_process_exit?: string;
91
89
  };
92
90
  type DatabaseHttpResponse = DatabaseJsonObject & {
93
91
  readonly resource: "catalog" | "artifact";
@@ -110,8 +108,6 @@ type DatabaseBundleEventMetadata = DatabaseJsonObject & {
110
108
  readonly delivery?: "patch" | "manifest" | "archive" | "unknown";
111
109
  /** `UPDATE_DOWNLOADED`: a patch failed and the full files came instead. */
112
110
  readonly patch_fallback?: boolean;
113
- /** `RECOVERED`: Android's `ApplicationExitInfo` reason for the crashed process. */
114
- readonly previous_process_exit?: string;
115
111
  };
116
112
  type BundleEventRowBase = {
117
113
  readonly id: string;
@@ -340,17 +336,6 @@ interface InsightsUpdateFailures {
340
336
  };
341
337
  /** Over a time range: failures by stage and reason, most first. */
342
338
  readonly breakdown?: readonly InsightsFailureBreakdown[];
343
- /**
344
- * Over a time range: failed launches, and the recoveries whose crashed
345
- * process exited for a reason Android 11+ reported, by reason, most first.
346
- */
347
- readonly recoveries?: {
348
- readonly failedLaunches: number;
349
- readonly byExitReason: readonly {
350
- readonly exitReason: string;
351
- readonly events: number;
352
- }[];
353
- };
354
339
  }
355
340
  //#endregion
356
341
  //#region ../api-keys/dist/server/model.d.mts
@@ -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.33";
4573
+ const HOT_UPDATER_SERVER_VERSION = "1.0.0-rc.35";
4574
4574
  //#endregion
4575
4575
  //#region ../../packages/server/dist/handlerVersionRoutes.mjs
4576
4576
  /**
@@ -9792,8 +9792,8 @@ const isOptional = (value, key, valid) => !Object.hasOwn(value, key) || valid(va
9792
9792
  const isString = (value) => typeof value === "string";
9793
9793
  const isDatabaseHttpResponse = (value) => isDatabaseJsonObject(value) && (value.resource === "catalog" || value.resource === "artifact") && isString(value.path) && Number.isSafeInteger(value.status) && (value.body === null || isString(value.body)) && typeof value.body_truncated === "boolean" && Number.isSafeInteger(value.received_at_ms);
9794
9794
  /** An `UPDATE_FAILED` report's stored failure: a stage and a reason, and what else the client knew. */
9795
- const isDatabaseBundleEventFailure = (value) => isDatabaseJsonObject(value) && isString(value.stage) && isString(value.reason) && isOptional(value, "resource", isString) && isOptional(value, "http_status", (status) => Number.isSafeInteger(status)) && isOptional(value, "transport", isString) && isOptional(value, "origin_code", isString) && isOptional(value, "error_message", isString) && isOptional(value, "error_stack", isString) && isOptional(value, "previous_process_exit", isString);
9796
- const isDatabaseBundleEventMetadata = (value) => isDatabaseJsonObject(value) && typeof value.cohort === "string" && (value.update_strategy === null || value.update_strategy === "fingerprint" || value.update_strategy === "appVersion") && (value.fingerprint_hash === null || typeof value.fingerprint_hash === "string") && (value.sdk_version === null || typeof value.sdk_version === "string") && isOptional(value, "failure", isDatabaseBundleEventFailure) && isOptional(value, "http_response", isDatabaseHttpResponse) && isOptional(value, "delivery", isString) && isOptional(value, "patch_fallback", (flag) => typeof flag === "boolean") && isOptional(value, "previous_process_exit", isString);
9795
+ const isDatabaseBundleEventFailure = (value) => isDatabaseJsonObject(value) && isString(value.stage) && isString(value.reason) && isOptional(value, "resource", isString) && isOptional(value, "http_status", (status) => Number.isSafeInteger(status)) && isOptional(value, "transport", isString) && isOptional(value, "origin_code", isString) && isOptional(value, "error_message", isString) && isOptional(value, "error_stack", isString);
9796
+ const isDatabaseBundleEventMetadata = (value) => isDatabaseJsonObject(value) && typeof value.cohort === "string" && (value.update_strategy === null || value.update_strategy === "fingerprint" || value.update_strategy === "appVersion") && (value.fingerprint_hash === null || typeof value.fingerprint_hash === "string") && (value.sdk_version === null || typeof value.sdk_version === "string") && isOptional(value, "failure", isDatabaseBundleEventFailure) && isOptional(value, "http_response", isDatabaseHttpResponse) && isOptional(value, "delivery", isString) && isOptional(value, "patch_fallback", (flag) => typeof flag === "boolean");
9797
9797
  const isRecord$2 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
9798
9798
  const isIdentity$1 = (value) => typeof value === "string" && value.length > 0 && value.length <= 255;
9799
9799
  const isTextOrNull = (value) => value === null || typeof value === "string";
@@ -10133,7 +10133,7 @@ const DELIVERIES = [
10133
10133
  "manifest",
10134
10134
  "archive"
10135
10135
  ];
10136
- /** A storage error code or an Android exit reason: letters, digits, and `._-`. */
10136
+ /** A storage error code: letters, digits, and `._-`. */
10137
10137
  const CODE = /^[A-Za-z0-9._-]{1,64}$/;
10138
10138
  const readCode = (value) => typeof value === "string" && CODE.test(value) ? value : void 0;
10139
10139
  const readMetadata = (payload) => isRecord$1(payload.metadata) ? payload.metadata : {};
@@ -10149,7 +10149,6 @@ function readFailure(value) {
10149
10149
  const originCode = readCode(failure.originCode);
10150
10150
  const errorMessage = typeof failure.errorMessage === "string" && failure.errorMessage.length <= 2048 ? failure.errorMessage : void 0;
10151
10151
  const errorStack = typeof failure.errorStack === "string" && failure.errorStack.length <= 4096 ? failure.errorStack : void 0;
10152
- const previousProcessExit = readCode(failure.previousProcessExit);
10153
10152
  return {
10154
10153
  stage: oneOf(STAGES, failure.stage),
10155
10154
  reason: oneOf(REASONS, failure.reason),
@@ -10158,8 +10157,7 @@ function readFailure(value) {
10158
10157
  ...failure.transport == null ? {} : { transport: oneOf(TRANSPORTS, failure.transport) },
10159
10158
  ...originCode === void 0 ? {} : { originCode },
10160
10159
  ...errorMessage === void 0 ? {} : { errorMessage },
10161
- ...errorStack === void 0 ? {} : { errorStack },
10162
- ...previousProcessExit === void 0 ? {} : { previousProcessExit }
10160
+ ...errorStack === void 0 ? {} : { errorStack }
10163
10161
  };
10164
10162
  }
10165
10163
  function readHttpResponse(value) {
@@ -10249,21 +10247,11 @@ function requireEvent(payload) {
10249
10247
  ...Object.keys(read).length === 0 ? {} : { metadata: read }
10250
10248
  };
10251
10249
  }
10252
- case "UPDATE_APPLIED": return {
10250
+ case "UPDATE_APPLIED":
10251
+ case "RECOVERED": return {
10253
10252
  ...movement(),
10254
10253
  type
10255
10254
  };
10256
- case "RECOVERED": {
10257
- const previousProcessExit = readCode(metadata.previousProcessExit);
10258
- return {
10259
- ...movement(),
10260
- type,
10261
- ...previousProcessExit === void 0 ? {} : { metadata: {
10262
- ...httpMetadata,
10263
- previousProcessExit
10264
- } }
10265
- };
10266
- }
10267
10255
  case "UPDATE_FAILED": return {
10268
10256
  ...movement(),
10269
10257
  type,
@@ -10329,24 +10317,13 @@ function createBundleEventRow(input) {
10329
10317
  }
10330
10318
  };
10331
10319
  }
10332
- case "UPDATE_APPLIED": return {
10320
+ case "UPDATE_APPLIED":
10321
+ case "RECOVERED": return {
10333
10322
  ...base,
10334
10323
  from_bundle_id: input.fromBundleId,
10335
10324
  type: input.type,
10336
10325
  metadata
10337
10326
  };
10338
- case "RECOVERED": {
10339
- const exit = input.metadata?.previousProcessExit;
10340
- return {
10341
- ...base,
10342
- from_bundle_id: input.fromBundleId,
10343
- type: input.type,
10344
- metadata: {
10345
- ...metadata,
10346
- ...exit === void 0 ? {} : { previous_process_exit: exit }
10347
- }
10348
- };
10349
- }
10350
10327
  case "UPDATE_FAILED": {
10351
10328
  const { failure } = input.metadata;
10352
10329
  return {
@@ -10363,8 +10340,7 @@ function createBundleEventRow(input) {
10363
10340
  ...failure.resource === void 0 ? {} : { resource: failure.resource },
10364
10341
  ...failure.httpStatus === void 0 ? {} : { http_status: failure.httpStatus },
10365
10342
  ...failure.transport === void 0 ? {} : { transport: failure.transport },
10366
- ...failure.originCode === void 0 ? {} : { origin_code: failure.originCode },
10367
- ...failure.previousProcessExit === void 0 ? {} : { previous_process_exit: failure.previousProcessExit }
10343
+ ...failure.originCode === void 0 ? {} : { origin_code: failure.originCode }
10368
10344
  }
10369
10345
  }
10370
10346
  };
@@ -10528,10 +10504,9 @@ const toFailure = (failure) => ({
10528
10504
  ...failure.resource === void 0 ? {} : { resource: failure.resource },
10529
10505
  ...failure.http_status === void 0 ? {} : { httpStatus: failure.http_status },
10530
10506
  ...failure.transport === void 0 ? {} : { transport: failure.transport },
10531
- ...failure.origin_code === void 0 ? {} : { originCode: failure.origin_code },
10532
- ...failure.previous_process_exit === void 0 ? {} : { previousProcessExit: failure.previous_process_exit }
10507
+ ...failure.origin_code === void 0 ? {} : { originCode: failure.origin_code }
10533
10508
  });
10534
- /** What a row's metadata adds for its type: a failure, a delivery, an exit reason. */
10509
+ /** What a row's metadata adds for its type: a failure or a delivery. */
10535
10510
  const eventDetails = ({ type, metadata }) => ({
10536
10511
  ...metadata.http_response !== void 0 ? { httpResponse: {
10537
10512
  resource: metadata.http_response.resource,
@@ -10543,8 +10518,7 @@ const eventDetails = ({ type, metadata }) => ({
10543
10518
  } } : {},
10544
10519
  ...type === "UPDATE_FAILED" && metadata.failure !== void 0 ? { failure: toFailure(metadata.failure) } : {},
10545
10520
  ...type === "UPDATE_DOWNLOADED" && metadata.delivery !== void 0 ? { delivery: metadata.delivery } : {},
10546
- ...type === "UPDATE_DOWNLOADED" && metadata.patch_fallback === true ? { patchFallback: true } : {},
10547
- ...type === "RECOVERED" && metadata.previous_process_exit !== void 0 ? { previousProcessExit: metadata.previous_process_exit } : {}
10521
+ ...type === "UPDATE_DOWNLOADED" && metadata.patch_fallback === true ? { patchFallback: true } : {}
10548
10522
  });
10549
10523
  const toEventHistoryRow = (row) => ({
10550
10524
  ...row.to_release_id == null ? {} : { toReleaseId: row.to_release_id },
@@ -11026,14 +11000,12 @@ const lifetimeSketches = () => defineAggregate(identityFields, {
11026
11000
  indexes: { window }
11027
11001
  });
11028
11002
  /**
11029
- * Update failures by what failed, and recoveries by why the crashed process
11030
- * exited, a row an hour. `release_id` is the failed update's target release,
11031
- * or empty for a failed check or an unknown target, and the recovered
11032
- * release for a recovery. A failure's `stage` and `reason` say where and why
11033
- * it failed, and `detail` what else the client knew, as the JSON array
11034
- * `[resource, httpStatus, originCode, transport]`. A recovery's stage is
11035
- * `launch` and its reason the exit reason, with an empty detail. Every index
11036
- * is in key order, so its counters stay blind increments.
11003
+ * Update failures by what failed, a row an hour. `release_id` is the failed
11004
+ * update's target release, or empty for a failed check or an unknown target.
11005
+ * `stage` and `reason` say where and why it failed, and `detail` what else
11006
+ * the client knew, as the JSON array `[resource, httpStatus, originCode,
11007
+ * transport]`. Every index is in key order, so its counters stay blind
11008
+ * increments.
11037
11009
  */
11038
11010
  const insightsFailures = (retention) => defineAggregate({
11039
11011
  platform: {
@@ -11576,23 +11548,6 @@ const countFailure = (tx, event) => {
11576
11548
  detail: failureDetail(failure)
11577
11549
  }, { events: 1 }, { shardBy });
11578
11550
  };
11579
- /**
11580
- * A recovery's exit reason, which Android 11+ reports, in the breakdown of
11581
- * the release whose launch failed: stage `launch`, the reason as its reason.
11582
- */
11583
- const countExit = (tx, event) => {
11584
- const exit = event.metadata.previous_process_exit;
11585
- if (event.type !== "RECOVERED" || exit === void 0) return;
11586
- tx.aggregate("insights_failures", {
11587
- platform: event.platform,
11588
- channel: event.channel,
11589
- bucket_start_ms: hourOf(event.received_at_ms),
11590
- release_id: event.from_release_id ?? "",
11591
- stage: "launch",
11592
- reason: exit,
11593
- detail: ""
11594
- }, { events: 1 }, { shardBy: event.install_id });
11595
- };
11596
11551
  const isNewer = (event, head) => event.received_at_ms !== head.received_at_ms ? event.received_at_ms > head.received_at_ms : compareUtf8(event.id, head.id) > 0;
11597
11552
  /** What an UNCHANGED report must share with its installation's head to repeat it. */
11598
11553
  const REPEATED_FIELDS = [
@@ -11637,7 +11592,6 @@ const recordEvent = (db, event) => {
11637
11592
  return;
11638
11593
  }
11639
11594
  countEvent(tx, event);
11640
- countExit(tx, event);
11641
11595
  if (previous !== null && !isNewer(event, previous)) return;
11642
11596
  if (previous === null) tx.create("bundle_event_heads", event);
11643
11597
  else {
@@ -12121,21 +12075,18 @@ const isText = (value, maxLength) => typeof value === "string" && value.length >
12121
12075
  const failed = (...rows) => countDistinct(mergeDistinct(rows.flat().map((row) => row.failed_users)));
12122
12076
  /** Entries of a count map, most first, then in key order. */
12123
12077
  const mostFirst = (counts) => [...counts].sort(([leftKey, left], [rightKey, right]) => right.events - left.events || compareUtf8(leftKey, rightKey)).map(([, entry]) => entry);
12124
- /** Failure rows as their breakdown, and recovery rows as exit reasons. */
12078
+ /** The stages a failure row records: where an update failed. */
12079
+ const FAILURE_STAGES = /* @__PURE__ */ new Set([
12080
+ "check",
12081
+ "download",
12082
+ "install",
12083
+ "unknown"
12084
+ ]);
12085
+ /** Failure rows as their breakdown by stage, reason, and detail. */
12125
12086
  const breakdownOf = (rows) => {
12126
12087
  const failures = /* @__PURE__ */ new Map();
12127
- const exits = /* @__PURE__ */ new Map();
12128
12088
  for (const { stage, reason, detail, events } of rows) {
12129
12089
  if (events <= 0) continue;
12130
- if (stage === "launch") {
12131
- const exit = exits.get(reason) ?? {
12132
- value: reason,
12133
- events: 0
12134
- };
12135
- exit.events += events;
12136
- exits.set(reason, exit);
12137
- continue;
12138
- }
12139
12090
  const key = JSON.stringify([stage, reason]);
12140
12091
  const entry = failures.get(key) ?? {
12141
12092
  value: {
@@ -12154,37 +12105,30 @@ const breakdownOf = (rows) => {
12154
12105
  entry.details.set(detail, known);
12155
12106
  failures.set(key, entry);
12156
12107
  }
12157
- return {
12158
- breakdown: mostFirst(failures).map(({ value, events }) => {
12159
- const { details } = failures.get(JSON.stringify([value.stage, value.reason]));
12160
- return {
12161
- ...value,
12162
- events,
12163
- details: mostFirst(details).map(({ value: detail, events }) => {
12164
- const [resource, httpStatus, originCode, transport] = JSON.parse(detail);
12165
- return {
12166
- resource,
12167
- httpStatus,
12168
- originCode,
12169
- transport,
12170
- events
12171
- };
12172
- })
12173
- };
12174
- }),
12175
- byExitReason: mostFirst(exits).map(({ value, events }) => ({
12176
- exitReason: value,
12177
- events
12178
- }))
12179
- };
12108
+ return mostFirst(failures).map(({ value, events }) => {
12109
+ const { details } = failures.get(JSON.stringify([value.stage, value.reason]));
12110
+ return {
12111
+ ...value,
12112
+ events,
12113
+ details: mostFirst(details).map(({ value: detail, events }) => {
12114
+ const [resource, httpStatus, originCode, transport] = JSON.parse(detail);
12115
+ return {
12116
+ resource,
12117
+ httpStatus,
12118
+ originCode,
12119
+ transport,
12120
+ events
12121
+ };
12122
+ })
12123
+ };
12124
+ });
12180
12125
  };
12181
12126
  /**
12182
12127
  * A release's or a channel's update failures. Since a release's first
12183
12128
  * report: its lifetime counters and failed installations. Over a time range
12184
- * of at most 30 days: failures, failed checks, the breakdown by stage,
12185
- * reason, and detail, and recoveries by exit reason, all summed from the
12186
- * breakdown's hourly rows; downloads and failed launches from the counters;
12187
- * failed installations from their sketches. A release reads hourly rows, a
12129
+ * of at most 30 days: failures, failed checks, and the breakdown by stage,
12130
+ * reason, and detail, all summed from the breakdown's hourly rows; downloads
12131
+ * from the counters; failed installations from their sketches. A release reads hourly rows, a
12188
12132
  * channel daily rows past 48 hours like its activity; the breakdown's rows
12189
12133
  * are hourly, so its coverage is the raw period's.
12190
12134
  */
@@ -12271,13 +12215,12 @@ const getUpdateFailures = async (db, input, now, retention) => {
12271
12215
  }))
12272
12216
  ]);
12273
12217
  const total = (field) => counters.reduce((sum, row) => sum + row[field], 0);
12274
- const scoped = releaseId === void 0 ? rows : rows.filter((row) => row.release_id === releaseId);
12218
+ const scoped = rows.filter((row) => FAILURE_STAGES.has(row.stage) && (releaseId === void 0 || row.release_id === releaseId));
12275
12219
  const failuresAt = (counted) => scoped.reduce((sum, row) => sum + (counted(row.stage) ? Math.max(0, row.events) : 0), 0);
12276
- const { breakdown, byExitReason } = breakdownOf(scoped);
12277
12220
  return {
12278
12221
  coverage: coverageOf(timeRange.start, kept.hour),
12279
12222
  measuredAtMs: at,
12280
- failedUpdates: failuresAt((stage) => stage !== "check" && stage !== "launch"),
12223
+ failedUpdates: failuresAt((stage) => stage !== "check"),
12281
12224
  failedInstallations: failed(failures),
12282
12225
  downloads: total("downloads"),
12283
12226
  patchDownloads: total("patch_downloads"),
@@ -12287,11 +12230,7 @@ const getUpdateFailures = async (db, input, now, retention) => {
12287
12230
  failedInstallations: failed(checks),
12288
12231
  activeInstallations: countDistinct(mergeDistinct(active.map((row) => row.activity_users)))
12289
12232
  } } : {},
12290
- breakdown,
12291
- recoveries: {
12292
- failedLaunches: total("failed_launches"),
12293
- byExitReason
12294
- }
12233
+ breakdown: breakdownOf(scoped)
12295
12234
  };
12296
12235
  };
12297
12236
  //#endregion
@@ -12554,7 +12493,7 @@ const insights = (options = {}) => {
12554
12493
  const plugin = definePlugin({
12555
12494
  id: "insights",
12556
12495
  namespace: false,
12557
- schemaVersion: "1.4.0",
12496
+ schemaVersion: "1.0.0",
12558
12497
  schema: createInsightsSchema(retention),
12559
12498
  init: ({ db, now }) => {
12560
12499
  const api = createInsightsApi(db, now, retention);
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.33",
4
+ "version": "1.0.0-rc.35",
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.29",
49
- "@hot-updater/mock": "1.0.0-rc.29",
50
- "@hot-updater/test-utils": "1.0.0-rc.31"
48
+ "@hot-updater/protocol": "1.0.0-rc.35",
49
+ "@hot-updater/mock": "1.0.0-rc.35",
50
+ "@hot-updater/test-utils": "1.0.0-rc.35"
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/plugin-core": "1.0.0-rc.29",
66
- "@hot-updater/server": "1.0.0-rc.33",
67
- "@hot-updater/cli-tools": "1.0.0-rc.33"
65
+ "@hot-updater/cli-tools": "1.0.0-rc.35",
66
+ "@hot-updater/plugin-core": "1.0.0-rc.35",
67
+ "@hot-updater/server": "1.0.0-rc.35"
68
68
  },
69
69
  "scripts": {
70
70
  "build": "tsdown",