@hot-updater/cloudflare 1.0.0-rc.17 → 1.0.0-rc.18

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.
@@ -109,10 +109,10 @@ const createD1Database = (runner) => {
109
109
  //#region src/d1Schema.ts
110
110
  /**
111
111
  * D1's schema: the guard table batch writes need, then the shared SQL
112
- * schema, settings last. Every statement can run again, so a migration for a
113
- * server's plugin tables repeats the built-in ones.
112
+ * schema of core and the target's plugins, settings last. Every statement can
113
+ * run again, so a migration for a server's plugin tables repeats core's.
114
114
  */
115
- const d1SchemaStatements = ({ schema, settings } = _hot_updater_server_database.builtInTarget) => [...(0, _hot_updater_server_database.createTableStatements)("sqlite", [_hot_updater_server_database.WRITE_GUARD_TABLE]), ...(0, _hot_updater_server_db.generateEngineSql)("sqlite", schema, settings)];
115
+ const d1SchemaStatements = ({ schema, settings } = _hot_updater_server_database.coreTarget) => [...(0, _hot_updater_server_database.createTableStatements)("sqlite", [_hot_updater_server_database.WRITE_GUARD_TABLE]), ...(0, _hot_updater_server_db.generateEngineSql)("sqlite", schema, settings)];
116
116
  /** The schema as a D1 migration, which `wrangler d1 migrations apply` runs. */
117
117
  const d1SchemaSql = (target) => `-- HotUpdater.schema\n\n${d1SchemaStatements(target).map((statement) => `${statement};`).join("\n\n")}\n`;
118
118
  //#endregion
@@ -151,8 +151,8 @@ const d1Database = (config) => {
151
151
  query: async (statement) => (await execute([statement]))[0],
152
152
  batch: execute
153
153
  }),
154
- generateSchema: ((version, _name, target = _hot_updater_server_database.builtInTarget) => {
155
- if (version !== "latest" && version !== _hot_updater_server_database.builtInSettings["schema.core"]) throw new Error(`Invalid version ${version}`);
154
+ generateSchema: ((version, _name, target = _hot_updater_server_database.coreTarget) => {
155
+ if (version !== "latest" && version !== _hot_updater_server_database.coreSettings["schema.core"]) throw new Error(`Invalid version ${version}`);
156
156
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/\D/g, "").slice(0, 14);
157
157
  return {
158
158
  code: d1SchemaSql(target),
@@ -11427,23 +11427,6 @@ const getConfigScaffold = (build) => {
11427
11427
  };
11428
11428
  //#endregion
11429
11429
  //#region iac/index.ts
11430
- const SOURCE_TEMPLATE = `// add this to your App.tsx
11431
- import { HotUpdater } from "@hot-updater/react-native";
11432
-
11433
- function App() {
11434
- return null; // Replace with your app root
11435
- }
11436
-
11437
- HotUpdater.init({
11438
- baseURL: "%%source%%",
11439
- requestHeaders: {
11440
- "x-api-key": %%apiKey%%,
11441
- },
11442
- });
11443
-
11444
- // Call HotUpdater.checkForUpdate({ updateStrategy: "appVersion" })
11445
- // when your app is ready to check.
11446
- export default App;`;
11447
11430
  const deployWorker = async (apiToken, accountId, { credentialSource, d1DatabaseId, d1DatabaseName, nonInteractive, r2BucketName, workerName }) => {
11448
11431
  const cwd = (0, _hot_updater_cli_tools.getCwd)();
11449
11432
  const cloudflarePackagePath = require.resolve("@hot-updater/cloudflare/package.json", { paths: [cwd] });
@@ -11827,13 +11810,13 @@ const runInit = async ({ build, envFile }) => {
11827
11810
  cloudflareApiToken: apiToken,
11828
11811
  databaseId: selectedD1DatabaseId
11829
11812
  });
11830
- let apiKey;
11813
+ let credential;
11831
11814
  try {
11832
- apiKey = (await (0, _hot_updater_server_db.createDatabasePluginApis)(database, plugins).apiKeys.provision({
11833
- existingApiKey: initInputEnv.HOT_UPDATER_API_KEY,
11815
+ credential = await (0, _hot_updater_server_db.provisionClientCredential)(database, plugins, {
11816
+ env: initInputEnv,
11834
11817
  name: "Cloudflare init"
11835
- })).apiKey;
11836
- await (0, _hot_updater_cli_tools.makeEnv)({ HOT_UPDATER_API_KEY: apiKey });
11818
+ });
11819
+ if (credential !== void 0) await (0, _hot_updater_cli_tools.makeEnv)({ [credential.env]: credential.value });
11837
11820
  } finally {
11838
11821
  await database.dispose?.();
11839
11822
  }
@@ -11843,12 +11826,11 @@ const runInit = async ({ build, envFile }) => {
11843
11826
  else if (configWriteResult.status === "merged") _hot_updater_cli_tools.p.log.success("Updated 'hot-updater.config.ts' file with Cloudflare settings.");
11844
11827
  else _hot_updater_cli_tools.p.log.warn(`Kept existing 'hot-updater.config.ts' unchanged: ${configWriteResult.reason}`);
11845
11828
  await (0, _hot_updater_cli_tools.generateHotUpdaterPlugins)("@hot-updater/cloudflare");
11846
- if (subdomains.subdomain) _hot_updater_cli_tools.p.note((0, _hot_updater_cli_tools.transformTemplate)(SOURCE_TEMPLATE, {
11847
- apiKey: JSON.stringify(apiKey),
11848
- source: `https://${workerName}.${subdomains.subdomain}.workers.dev`
11849
- }));
11850
- _hot_updater_cli_tools.p.note((0, _hot_updater_cli_tools.formatApiKeyNote)(apiKey), "API Key");
11851
- _hot_updater_cli_tools.p.log.message("Store this API key separately in a secure place.");
11829
+ (0, _hot_updater_cli_tools.printAppSetup)({
11830
+ ...subdomains.subdomain ? { baseURL: `https://${workerName}.${subdomains.subdomain}.workers.dev` } : {},
11831
+ ...credential === void 0 ? {} : { credential },
11832
+ clientPlugins: (0, _hot_updater_server_db.clientPluginsOf)(plugins)
11833
+ });
11852
11834
  _hot_updater_cli_tools.p.log.message(`Next step: ${(0, _hot_updater_cli_tools.link)("https://hot-updater.dev/docs/managed/cloudflare#step-4-add-hotupdater-to-your-project")}`);
11853
11835
  _hot_updater_cli_tools.p.log.success("Done! 🎉");
11854
11836
  };
@@ -2,10 +2,10 @@ import { createRequire } from "node:module";
2
2
  import crypto from "crypto";
3
3
  import fs from "fs/promises";
4
4
  import path from "path";
5
- import { ConfigBuilder, InitError, LegacyInfrastructureError, assertInfrastructureGenerationAtUrl, assertInitInputs, assertInitProviderInputs, confirmInitInputPersistence, copyDirToTmp, createHotUpdaterConfigScaffoldFromBuilder, formatApiKeyNote, generateHotUpdaterPlugins, getCwd, getHotUpdaterInitInputEnv, getInitProviderEnvVars, getInitProviderTextPromptValues, link, makeEnv, p, readHotUpdaterInitEnv, resolveInitProviderInput, transformTemplate, writeHotUpdaterConfig } from "@hot-updater/cli-tools";
6
- import { createDatabasePluginApis, generateEngineSql } from "@hot-updater/server/db";
5
+ import { ConfigBuilder, InitError, LegacyInfrastructureError, assertInfrastructureGenerationAtUrl, assertInitInputs, assertInitProviderInputs, confirmInitInputPersistence, copyDirToTmp, createHotUpdaterConfigScaffoldFromBuilder, generateHotUpdaterPlugins, getCwd, getHotUpdaterInitInputEnv, getInitProviderEnvVars, getInitProviderTextPromptValues, link, makeEnv, p, printAppSetup, readHotUpdaterInitEnv, resolveInitProviderInput, transformTemplate, writeHotUpdaterConfig } from "@hot-updater/cli-tools";
6
+ import { clientPluginsOf, generateEngineSql, provisionClientCredential } from "@hot-updater/server/db";
7
7
  import Cloudflare$1, { Cloudflare } from "cloudflare";
8
- import { WRITE_GUARD_TABLE, builtInSettings, builtInTarget, createEngineDatabase, createSqlAdapter, createTableStatements } from "@hot-updater/server/database";
8
+ import { WRITE_GUARD_TABLE, coreSettings, coreTarget, createEngineDatabase, createSqlAdapter, createTableStatements } from "@hot-updater/server/database";
9
9
  import { apiKeys } from "@hot-updater/server/plugins/api-keys";
10
10
  import { insights } from "@hot-updater/server/plugins/insights";
11
11
  import { fileURLToPath } from "node:url";
@@ -101,10 +101,10 @@ const createD1Database = (runner) => {
101
101
  //#region src/d1Schema.ts
102
102
  /**
103
103
  * D1's schema: the guard table batch writes need, then the shared SQL
104
- * schema, settings last. Every statement can run again, so a migration for a
105
- * server's plugin tables repeats the built-in ones.
104
+ * schema of core and the target's plugins, settings last. Every statement can
105
+ * run again, so a migration for a server's plugin tables repeats core's.
106
106
  */
107
- const d1SchemaStatements = ({ schema, settings } = builtInTarget) => [...createTableStatements("sqlite", [WRITE_GUARD_TABLE]), ...generateEngineSql("sqlite", schema, settings)];
107
+ const d1SchemaStatements = ({ schema, settings } = coreTarget) => [...createTableStatements("sqlite", [WRITE_GUARD_TABLE]), ...generateEngineSql("sqlite", schema, settings)];
108
108
  /** The schema as a D1 migration, which `wrangler d1 migrations apply` runs. */
109
109
  const d1SchemaSql = (target) => `-- HotUpdater.schema\n\n${d1SchemaStatements(target).map((statement) => `${statement};`).join("\n\n")}\n`;
110
110
  //#endregion
@@ -143,8 +143,8 @@ const d1Database = (config) => {
143
143
  query: async (statement) => (await execute([statement]))[0],
144
144
  batch: execute
145
145
  }),
146
- generateSchema: ((version, _name, target = builtInTarget) => {
147
- if (version !== "latest" && version !== builtInSettings["schema.core"]) throw new Error(`Invalid version ${version}`);
146
+ generateSchema: ((version, _name, target = coreTarget) => {
147
+ if (version !== "latest" && version !== coreSettings["schema.core"]) throw new Error(`Invalid version ${version}`);
148
148
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/\D/g, "").slice(0, 14);
149
149
  return {
150
150
  code: d1SchemaSql(target),
@@ -11419,23 +11419,6 @@ const getConfigScaffold = (build) => {
11419
11419
  };
11420
11420
  //#endregion
11421
11421
  //#region iac/index.ts
11422
- const SOURCE_TEMPLATE = `// add this to your App.tsx
11423
- import { HotUpdater } from "@hot-updater/react-native";
11424
-
11425
- function App() {
11426
- return null; // Replace with your app root
11427
- }
11428
-
11429
- HotUpdater.init({
11430
- baseURL: "%%source%%",
11431
- requestHeaders: {
11432
- "x-api-key": %%apiKey%%,
11433
- },
11434
- });
11435
-
11436
- // Call HotUpdater.checkForUpdate({ updateStrategy: "appVersion" })
11437
- // when your app is ready to check.
11438
- export default App;`;
11439
11422
  const deployWorker = async (apiToken, accountId, { credentialSource, d1DatabaseId, d1DatabaseName, nonInteractive, r2BucketName, workerName }) => {
11440
11423
  const cwd = getCwd();
11441
11424
  const cloudflarePackagePath = __require.resolve("@hot-updater/cloudflare/package.json", { paths: [cwd] });
@@ -11819,13 +11802,13 @@ const runInit = async ({ build, envFile }) => {
11819
11802
  cloudflareApiToken: apiToken,
11820
11803
  databaseId: selectedD1DatabaseId
11821
11804
  });
11822
- let apiKey;
11805
+ let credential;
11823
11806
  try {
11824
- apiKey = (await createDatabasePluginApis(database, plugins).apiKeys.provision({
11825
- existingApiKey: initInputEnv.HOT_UPDATER_API_KEY,
11807
+ credential = await provisionClientCredential(database, plugins, {
11808
+ env: initInputEnv,
11826
11809
  name: "Cloudflare init"
11827
- })).apiKey;
11828
- await makeEnv({ HOT_UPDATER_API_KEY: apiKey });
11810
+ });
11811
+ if (credential !== void 0) await makeEnv({ [credential.env]: credential.value });
11829
11812
  } finally {
11830
11813
  await database.dispose?.();
11831
11814
  }
@@ -11835,12 +11818,11 @@ const runInit = async ({ build, envFile }) => {
11835
11818
  else if (configWriteResult.status === "merged") p.log.success("Updated 'hot-updater.config.ts' file with Cloudflare settings.");
11836
11819
  else p.log.warn(`Kept existing 'hot-updater.config.ts' unchanged: ${configWriteResult.reason}`);
11837
11820
  await generateHotUpdaterPlugins("@hot-updater/cloudflare");
11838
- if (subdomains.subdomain) p.note(transformTemplate(SOURCE_TEMPLATE, {
11839
- apiKey: JSON.stringify(apiKey),
11840
- source: `https://${workerName}.${subdomains.subdomain}.workers.dev`
11841
- }));
11842
- p.note(formatApiKeyNote(apiKey), "API Key");
11843
- p.log.message("Store this API key separately in a secure place.");
11821
+ printAppSetup({
11822
+ ...subdomains.subdomain ? { baseURL: `https://${workerName}.${subdomains.subdomain}.workers.dev` } : {},
11823
+ ...credential === void 0 ? {} : { credential },
11824
+ clientPlugins: clientPluginsOf(plugins)
11825
+ });
11844
11826
  p.log.message(`Next step: ${link("https://hot-updater.dev/docs/managed/cloudflare#step-4-add-hotupdater-to-your-project")}`);
11845
11827
  p.log.success("Done! 🎉");
11846
11828
  };
package/dist/index.cjs CHANGED
@@ -81,10 +81,10 @@ const createD1Database = (runner) => {
81
81
  //#region src/d1Schema.ts
82
82
  /**
83
83
  * D1's schema: the guard table batch writes need, then the shared SQL
84
- * schema, settings last. Every statement can run again, so a migration for a
85
- * server's plugin tables repeats the built-in ones.
84
+ * schema of core and the target's plugins, settings last. Every statement can
85
+ * run again, so a migration for a server's plugin tables repeats core's.
86
86
  */
87
- const d1SchemaStatements = ({ schema, settings } = _hot_updater_server_database.builtInTarget) => [...(0, _hot_updater_server_database.createTableStatements)("sqlite", [_hot_updater_server_database.WRITE_GUARD_TABLE]), ...(0, _hot_updater_server_db.generateEngineSql)("sqlite", schema, settings)];
87
+ const d1SchemaStatements = ({ schema, settings } = _hot_updater_server_database.coreTarget) => [...(0, _hot_updater_server_database.createTableStatements)("sqlite", [_hot_updater_server_database.WRITE_GUARD_TABLE]), ...(0, _hot_updater_server_db.generateEngineSql)("sqlite", schema, settings)];
88
88
  /** The schema as a D1 migration, which `wrangler d1 migrations apply` runs. */
89
89
  const d1SchemaSql = (target) => `-- HotUpdater.schema\n\n${d1SchemaStatements(target).map((statement) => `${statement};`).join("\n\n")}\n`;
90
90
  //#endregion
@@ -123,8 +123,8 @@ const d1Database = (config) => {
123
123
  query: async (statement) => (await execute([statement]))[0],
124
124
  batch: execute
125
125
  }),
126
- generateSchema: ((version, _name, target = _hot_updater_server_database.builtInTarget) => {
127
- if (version !== "latest" && version !== _hot_updater_server_database.builtInSettings["schema.core"]) throw new Error(`Invalid version ${version}`);
126
+ generateSchema: ((version, _name, target = _hot_updater_server_database.coreTarget) => {
127
+ if (version !== "latest" && version !== _hot_updater_server_database.coreSettings["schema.core"]) throw new Error(`Invalid version ${version}`);
128
128
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/\D/g, "").slice(0, 14);
129
129
  return {
130
130
  code: d1SchemaSql(target),
package/dist/index.d.cts CHANGED
@@ -171,12 +171,7 @@ declare const plugins: readonly [import("@hot-updater/server/plugins").HotUpdate
171
171
  readonly received_at_ms: {
172
172
  readonly type: "integer";
173
173
  };
174
- readonly current_release_id: {
175
- readonly type: "string";
176
- readonly maxLength: 36;
177
- readonly required: false;
178
- };
179
- }, {}, {
174
+ }, Readonly<Record<string, import("@hot-updater/server/database").FieldType>>, {
180
175
  readonly byUser: {
181
176
  readonly eq: readonly ["user_id"];
182
177
  readonly sort: readonly ["install_id"];
@@ -190,7 +185,7 @@ declare const plugins: readonly [import("@hot-updater/server/plugins").HotUpdate
190
185
  readonly bucket_start_ms: {
191
186
  readonly type: "integer";
192
187
  };
193
- }, "downloads" | "launches" | "failed_launches", {
188
+ }, "downloads" | "launches" | "failed_launches" | "failed_updates" | "patch_downloads" | "patch_fallbacks", {
194
189
  readonly window: {
195
190
  readonly eq: readonly ["identity"];
196
191
  readonly sort: readonly ["bucket_start_ms"];
@@ -209,7 +204,63 @@ declare const plugins: readonly [import("@hot-updater/server/plugins").HotUpdate
209
204
  readonly eq: readonly ["identity"];
210
205
  readonly sort: readonly ["bucket_start_ms"];
211
206
  };
212
- }, "launch_users" | "activity_users", readonly ["identity", "bucket_start_ms"]>;
207
+ }, "launch_users" | "activity_users" | "failed_users", readonly ["identity", "bucket_start_ms"]>;
208
+ readonly insights_overview_daily: import("@hot-updater/server/database").AggregateDefinition<{
209
+ readonly identity: {
210
+ readonly type: "string";
211
+ readonly maxLength: 32;
212
+ };
213
+ readonly bucket_start_ms: {
214
+ readonly type: "integer";
215
+ };
216
+ }, "downloads" | "launches" | "failed_launches" | "failed_updates" | "patch_downloads" | "patch_fallbacks", {
217
+ readonly window: {
218
+ readonly eq: readonly ["identity"];
219
+ readonly sort: readonly ["bucket_start_ms"];
220
+ };
221
+ }, never, readonly ["identity", "bucket_start_ms"]>;
222
+ readonly insights_sketches_daily: import("@hot-updater/server/database").AggregateDefinition<{
223
+ readonly identity: {
224
+ readonly type: "string";
225
+ readonly maxLength: 32;
226
+ };
227
+ readonly bucket_start_ms: {
228
+ readonly type: "integer";
229
+ };
230
+ }, never, {
231
+ readonly window: {
232
+ readonly eq: readonly ["identity"];
233
+ readonly sort: readonly ["bucket_start_ms"];
234
+ };
235
+ }, "launch_users" | "activity_users" | "failed_users", readonly ["identity", "bucket_start_ms"]>;
236
+ readonly insights_overview_lifetime: import("@hot-updater/server/database").AggregateDefinition<{
237
+ readonly identity: {
238
+ readonly type: "string";
239
+ readonly maxLength: 32;
240
+ };
241
+ readonly bucket_start_ms: {
242
+ readonly type: "integer";
243
+ };
244
+ }, "downloads" | "launches" | "failed_launches" | "failed_updates" | "patch_downloads" | "patch_fallbacks", {
245
+ readonly window: {
246
+ readonly eq: readonly ["identity"];
247
+ readonly sort: readonly ["bucket_start_ms"];
248
+ };
249
+ }, never, readonly ["identity", "bucket_start_ms"]>;
250
+ readonly insights_sketches_lifetime: import("@hot-updater/server/database").AggregateDefinition<{
251
+ readonly identity: {
252
+ readonly type: "string";
253
+ readonly maxLength: 32;
254
+ };
255
+ readonly bucket_start_ms: {
256
+ readonly type: "integer";
257
+ };
258
+ }, never, {
259
+ readonly window: {
260
+ readonly eq: readonly ["identity"];
261
+ readonly sort: readonly ["bucket_start_ms"];
262
+ };
263
+ }, "failed_users", readonly ["identity", "bucket_start_ms"]>;
213
264
  readonly insights_distribution: import("@hot-updater/server/database").AggregateDefinition<{
214
265
  readonly channel: {
215
266
  readonly type: "string";
@@ -292,22 +343,52 @@ declare const plugins: readonly [import("@hot-updater/server/plugins").HotUpdate
292
343
  readonly sort: readonly ["bucket_start_ms"];
293
344
  };
294
345
  }, never, readonly ["platform", "channel", "type", "bundle_ref", "bucket_start_ms"]>;
346
+ readonly insights_failures: import("@hot-updater/server/database").AggregateDefinition<{
347
+ readonly platform: {
348
+ readonly type: "string";
349
+ readonly maxLength: 16;
350
+ };
351
+ readonly channel: {
352
+ readonly type: "string";
353
+ };
354
+ readonly bucket_start_ms: {
355
+ readonly type: "integer";
356
+ };
357
+ readonly release_id: {
358
+ readonly type: "string";
359
+ readonly maxLength: 36;
360
+ };
361
+ readonly stage: {
362
+ readonly type: "string";
363
+ readonly maxLength: 16;
364
+ };
365
+ readonly reason: {
366
+ readonly type: "string";
367
+ readonly maxLength: 64;
368
+ };
369
+ readonly detail: {
370
+ readonly type: "string";
371
+ readonly maxLength: 160;
372
+ };
373
+ }, "events", {
374
+ readonly byScope: {
375
+ readonly eq: readonly ["platform", "channel"];
376
+ readonly sort: readonly ["bucket_start_ms"];
377
+ };
378
+ }, never, readonly ["platform", "channel", "bucket_start_ms", "release_id", "stage", "reason", "detail"]>;
295
379
  }, {
296
380
  api: {
297
- recordEvent: (event: import("@hot-updater/plugin-core").BundleEventRow) => Promise<void>;
298
- listEvents: (input: import("@hot-updater/plugin-core").InsightsListEventsInput) => Promise<readonly import("@hot-updater/plugin-core").BundleEventRow[]>;
299
- findLatestEvents: (input: import("@hot-updater/plugin-core").InsightsFindLatestEventsInput) => Promise<readonly import("@hot-updater/plugin-core").BundleEventRow[]>;
300
- countLatestEvents: (input: import("@hot-updater/plugin-core").InsightsCountLatestEventsInput) => Promise<number>;
301
- countEvents: (input: import("@hot-updater/plugin-core").InsightsCountEventsInput) => Promise<number>;
302
- getReleaseActivity: (input: import("@hot-updater/plugin-core").InsightsGetReleaseActivityInput) => Promise<import("@hot-updater/plugin-core").InsightsGetReleaseActivityResult>;
303
- getAppUsage: (input: import("@hot-updater/plugin-core").InsightsGetAppUsageInput) => Promise<import("@hot-updater/plugin-core").InsightsGetAppUsageResult>;
381
+ retention: import("@hot-updater/server/plugins/insights").InsightsRetention;
382
+ recordEvent: (event: import("@hot-updater/server/plugins/insights").BundleEventRow) => Promise<void>;
383
+ listEvents: (input: import("@hot-updater/server/plugins/insights").InsightsListEventsInput) => Promise<readonly import("@hot-updater/server/plugins/insights").BundleEventRow[]>;
384
+ findLatestEvents: (input: import("@hot-updater/server/plugins/insights").InsightsFindLatestEventsInput) => Promise<readonly import("@hot-updater/server/plugins/insights").BundleEventRow[]>;
385
+ countLatestEvents: (input: import("@hot-updater/server/plugins/insights").InsightsCountLatestEventsInput) => Promise<number>;
386
+ countEvents: (input: import("@hot-updater/server/plugins/insights").InsightsCountEventsInput) => Promise<number>;
387
+ getReleaseActivity: (input: import("@hot-updater/server/plugins/insights").InsightsGetReleaseActivityInput) => Promise<import("@hot-updater/server/plugins/insights").InsightsGetReleaseActivityResult>;
388
+ getAppUsage: (input: import("@hot-updater/server/plugins/insights").InsightsGetAppUsageInput) => Promise<import("@hot-updater/server/plugins/insights").InsightsGetAppUsageResult>;
389
+ getUpdateFailures: (input: import("@hot-updater/server/plugins/insights").InsightsUpdateFailuresInput) => Promise<import("@hot-updater/server/plugins/insights").InsightsUpdateFailures>;
304
390
  };
305
- endpoints: {
306
- access: "client" | "admin";
307
- method: "POST" | "GET";
308
- path: "/events" | "/overview" | "/installations" | "/installations/:installId/events" | "/installations/:installId";
309
- handler: (request: Request, params: Readonly<Record<string, string>>) => Promise<Response>;
310
- }[];
391
+ endpoints: import("@hot-updater/server/plugins").PluginEndpoint[];
311
392
  }, {}>, import("@hot-updater/server/plugins").HotUpdaterPlugin<"apiKeys", {
312
393
  readonly api_keys: import("@hot-updater/server/database").TableDefinition<{
313
394
  readonly id: {
@@ -350,21 +431,21 @@ declare const plugins: readonly [import("@hot-updater/server/plugins").HotUpdate
350
431
  readonly apiKey: string;
351
432
  readonly name: string;
352
433
  readonly createdAtMs?: number;
353
- }) => Promise<import("@hot-updater/server").CreatedApiKey>;
434
+ }) => Promise<import("@hot-updater/server/plugins/api-keys").CreatedApiKey>;
354
435
  provision: (input: {
355
436
  readonly existingApiKey?: string;
356
437
  readonly name: string;
357
- }) => Promise<import("@hot-updater/server").CreatedApiKey>;
438
+ }) => Promise<import("@hot-updater/server/plugins/api-keys").CreatedApiKey>;
358
439
  create(input: {
359
440
  readonly name: string;
360
441
  }): Promise<{
361
442
  readonly apiKey: string;
362
- readonly record: import("@hot-updater/server").ApiKeyMetadata;
443
+ readonly record: import("@hot-updater/server/plugins/api-keys").ApiKeyMetadata;
363
444
  }>;
364
- list(): Promise<readonly import("@hot-updater/server").ApiKeyMetadata[]>;
445
+ list(): Promise<readonly import("@hot-updater/server/plugins/api-keys").ApiKeyMetadata[]>;
365
446
  revoke(input: {
366
447
  readonly id: string;
367
- }): Promise<import("@hot-updater/server").ApiKeyMetadata | null>;
448
+ }): Promise<import("@hot-updater/server/plugins/api-keys").ApiKeyMetadata | null>;
368
449
  };
369
450
  clientAuth: {
370
451
  varyHeaders: string[];
package/dist/index.d.mts CHANGED
@@ -171,12 +171,7 @@ declare const plugins: readonly [import("@hot-updater/server/plugins").HotUpdate
171
171
  readonly received_at_ms: {
172
172
  readonly type: "integer";
173
173
  };
174
- readonly current_release_id: {
175
- readonly type: "string";
176
- readonly maxLength: 36;
177
- readonly required: false;
178
- };
179
- }, {}, {
174
+ }, Readonly<Record<string, import("@hot-updater/server/database").FieldType>>, {
180
175
  readonly byUser: {
181
176
  readonly eq: readonly ["user_id"];
182
177
  readonly sort: readonly ["install_id"];
@@ -190,7 +185,7 @@ declare const plugins: readonly [import("@hot-updater/server/plugins").HotUpdate
190
185
  readonly bucket_start_ms: {
191
186
  readonly type: "integer";
192
187
  };
193
- }, "downloads" | "launches" | "failed_launches", {
188
+ }, "downloads" | "launches" | "failed_launches" | "failed_updates" | "patch_downloads" | "patch_fallbacks", {
194
189
  readonly window: {
195
190
  readonly eq: readonly ["identity"];
196
191
  readonly sort: readonly ["bucket_start_ms"];
@@ -209,7 +204,63 @@ declare const plugins: readonly [import("@hot-updater/server/plugins").HotUpdate
209
204
  readonly eq: readonly ["identity"];
210
205
  readonly sort: readonly ["bucket_start_ms"];
211
206
  };
212
- }, "launch_users" | "activity_users", readonly ["identity", "bucket_start_ms"]>;
207
+ }, "launch_users" | "activity_users" | "failed_users", readonly ["identity", "bucket_start_ms"]>;
208
+ readonly insights_overview_daily: import("@hot-updater/server/database").AggregateDefinition<{
209
+ readonly identity: {
210
+ readonly type: "string";
211
+ readonly maxLength: 32;
212
+ };
213
+ readonly bucket_start_ms: {
214
+ readonly type: "integer";
215
+ };
216
+ }, "downloads" | "launches" | "failed_launches" | "failed_updates" | "patch_downloads" | "patch_fallbacks", {
217
+ readonly window: {
218
+ readonly eq: readonly ["identity"];
219
+ readonly sort: readonly ["bucket_start_ms"];
220
+ };
221
+ }, never, readonly ["identity", "bucket_start_ms"]>;
222
+ readonly insights_sketches_daily: import("@hot-updater/server/database").AggregateDefinition<{
223
+ readonly identity: {
224
+ readonly type: "string";
225
+ readonly maxLength: 32;
226
+ };
227
+ readonly bucket_start_ms: {
228
+ readonly type: "integer";
229
+ };
230
+ }, never, {
231
+ readonly window: {
232
+ readonly eq: readonly ["identity"];
233
+ readonly sort: readonly ["bucket_start_ms"];
234
+ };
235
+ }, "launch_users" | "activity_users" | "failed_users", readonly ["identity", "bucket_start_ms"]>;
236
+ readonly insights_overview_lifetime: import("@hot-updater/server/database").AggregateDefinition<{
237
+ readonly identity: {
238
+ readonly type: "string";
239
+ readonly maxLength: 32;
240
+ };
241
+ readonly bucket_start_ms: {
242
+ readonly type: "integer";
243
+ };
244
+ }, "downloads" | "launches" | "failed_launches" | "failed_updates" | "patch_downloads" | "patch_fallbacks", {
245
+ readonly window: {
246
+ readonly eq: readonly ["identity"];
247
+ readonly sort: readonly ["bucket_start_ms"];
248
+ };
249
+ }, never, readonly ["identity", "bucket_start_ms"]>;
250
+ readonly insights_sketches_lifetime: import("@hot-updater/server/database").AggregateDefinition<{
251
+ readonly identity: {
252
+ readonly type: "string";
253
+ readonly maxLength: 32;
254
+ };
255
+ readonly bucket_start_ms: {
256
+ readonly type: "integer";
257
+ };
258
+ }, never, {
259
+ readonly window: {
260
+ readonly eq: readonly ["identity"];
261
+ readonly sort: readonly ["bucket_start_ms"];
262
+ };
263
+ }, "failed_users", readonly ["identity", "bucket_start_ms"]>;
213
264
  readonly insights_distribution: import("@hot-updater/server/database").AggregateDefinition<{
214
265
  readonly channel: {
215
266
  readonly type: "string";
@@ -292,22 +343,52 @@ declare const plugins: readonly [import("@hot-updater/server/plugins").HotUpdate
292
343
  readonly sort: readonly ["bucket_start_ms"];
293
344
  };
294
345
  }, never, readonly ["platform", "channel", "type", "bundle_ref", "bucket_start_ms"]>;
346
+ readonly insights_failures: import("@hot-updater/server/database").AggregateDefinition<{
347
+ readonly platform: {
348
+ readonly type: "string";
349
+ readonly maxLength: 16;
350
+ };
351
+ readonly channel: {
352
+ readonly type: "string";
353
+ };
354
+ readonly bucket_start_ms: {
355
+ readonly type: "integer";
356
+ };
357
+ readonly release_id: {
358
+ readonly type: "string";
359
+ readonly maxLength: 36;
360
+ };
361
+ readonly stage: {
362
+ readonly type: "string";
363
+ readonly maxLength: 16;
364
+ };
365
+ readonly reason: {
366
+ readonly type: "string";
367
+ readonly maxLength: 64;
368
+ };
369
+ readonly detail: {
370
+ readonly type: "string";
371
+ readonly maxLength: 160;
372
+ };
373
+ }, "events", {
374
+ readonly byScope: {
375
+ readonly eq: readonly ["platform", "channel"];
376
+ readonly sort: readonly ["bucket_start_ms"];
377
+ };
378
+ }, never, readonly ["platform", "channel", "bucket_start_ms", "release_id", "stage", "reason", "detail"]>;
295
379
  }, {
296
380
  api: {
297
- recordEvent: (event: import("@hot-updater/plugin-core").BundleEventRow) => Promise<void>;
298
- listEvents: (input: import("@hot-updater/plugin-core").InsightsListEventsInput) => Promise<readonly import("@hot-updater/plugin-core").BundleEventRow[]>;
299
- findLatestEvents: (input: import("@hot-updater/plugin-core").InsightsFindLatestEventsInput) => Promise<readonly import("@hot-updater/plugin-core").BundleEventRow[]>;
300
- countLatestEvents: (input: import("@hot-updater/plugin-core").InsightsCountLatestEventsInput) => Promise<number>;
301
- countEvents: (input: import("@hot-updater/plugin-core").InsightsCountEventsInput) => Promise<number>;
302
- getReleaseActivity: (input: import("@hot-updater/plugin-core").InsightsGetReleaseActivityInput) => Promise<import("@hot-updater/plugin-core").InsightsGetReleaseActivityResult>;
303
- getAppUsage: (input: import("@hot-updater/plugin-core").InsightsGetAppUsageInput) => Promise<import("@hot-updater/plugin-core").InsightsGetAppUsageResult>;
381
+ retention: import("@hot-updater/server/plugins/insights").InsightsRetention;
382
+ recordEvent: (event: import("@hot-updater/server/plugins/insights").BundleEventRow) => Promise<void>;
383
+ listEvents: (input: import("@hot-updater/server/plugins/insights").InsightsListEventsInput) => Promise<readonly import("@hot-updater/server/plugins/insights").BundleEventRow[]>;
384
+ findLatestEvents: (input: import("@hot-updater/server/plugins/insights").InsightsFindLatestEventsInput) => Promise<readonly import("@hot-updater/server/plugins/insights").BundleEventRow[]>;
385
+ countLatestEvents: (input: import("@hot-updater/server/plugins/insights").InsightsCountLatestEventsInput) => Promise<number>;
386
+ countEvents: (input: import("@hot-updater/server/plugins/insights").InsightsCountEventsInput) => Promise<number>;
387
+ getReleaseActivity: (input: import("@hot-updater/server/plugins/insights").InsightsGetReleaseActivityInput) => Promise<import("@hot-updater/server/plugins/insights").InsightsGetReleaseActivityResult>;
388
+ getAppUsage: (input: import("@hot-updater/server/plugins/insights").InsightsGetAppUsageInput) => Promise<import("@hot-updater/server/plugins/insights").InsightsGetAppUsageResult>;
389
+ getUpdateFailures: (input: import("@hot-updater/server/plugins/insights").InsightsUpdateFailuresInput) => Promise<import("@hot-updater/server/plugins/insights").InsightsUpdateFailures>;
304
390
  };
305
- endpoints: {
306
- access: "client" | "admin";
307
- method: "POST" | "GET";
308
- path: "/events" | "/overview" | "/installations" | "/installations/:installId/events" | "/installations/:installId";
309
- handler: (request: Request, params: Readonly<Record<string, string>>) => Promise<Response>;
310
- }[];
391
+ endpoints: import("@hot-updater/server/plugins").PluginEndpoint[];
311
392
  }, {}>, import("@hot-updater/server/plugins").HotUpdaterPlugin<"apiKeys", {
312
393
  readonly api_keys: import("@hot-updater/server/database").TableDefinition<{
313
394
  readonly id: {
@@ -350,21 +431,21 @@ declare const plugins: readonly [import("@hot-updater/server/plugins").HotUpdate
350
431
  readonly apiKey: string;
351
432
  readonly name: string;
352
433
  readonly createdAtMs?: number;
353
- }) => Promise<import("@hot-updater/server").CreatedApiKey>;
434
+ }) => Promise<import("@hot-updater/server/plugins/api-keys").CreatedApiKey>;
354
435
  provision: (input: {
355
436
  readonly existingApiKey?: string;
356
437
  readonly name: string;
357
- }) => Promise<import("@hot-updater/server").CreatedApiKey>;
438
+ }) => Promise<import("@hot-updater/server/plugins/api-keys").CreatedApiKey>;
358
439
  create(input: {
359
440
  readonly name: string;
360
441
  }): Promise<{
361
442
  readonly apiKey: string;
362
- readonly record: import("@hot-updater/server").ApiKeyMetadata;
443
+ readonly record: import("@hot-updater/server/plugins/api-keys").ApiKeyMetadata;
363
444
  }>;
364
- list(): Promise<readonly import("@hot-updater/server").ApiKeyMetadata[]>;
445
+ list(): Promise<readonly import("@hot-updater/server/plugins/api-keys").ApiKeyMetadata[]>;
365
446
  revoke(input: {
366
447
  readonly id: string;
367
- }): Promise<import("@hot-updater/server").ApiKeyMetadata | null>;
448
+ }): Promise<import("@hot-updater/server/plugins/api-keys").ApiKeyMetadata | null>;
368
449
  };
369
450
  clientAuth: {
370
451
  varyHeaders: string[];
package/dist/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- import { WRITE_GUARD_TABLE, builtInSettings, builtInTarget, createEngineDatabase, createSqlAdapter, createTableStatements } from "@hot-updater/server/database";
1
+ import { WRITE_GUARD_TABLE, coreSettings, coreTarget, createEngineDatabase, createSqlAdapter, createTableStatements } from "@hot-updater/server/database";
2
2
  import Cloudflare from "cloudflare";
3
3
  import { generateEngineSql } from "@hot-updater/server/db";
4
4
  import { DeleteObjectCommand, GetObjectCommand, HeadObjectCommand, S3Client } from "@aws-sdk/client-s3";
@@ -57,10 +57,10 @@ const createD1Database = (runner) => {
57
57
  //#region src/d1Schema.ts
58
58
  /**
59
59
  * D1's schema: the guard table batch writes need, then the shared SQL
60
- * schema, settings last. Every statement can run again, so a migration for a
61
- * server's plugin tables repeats the built-in ones.
60
+ * schema of core and the target's plugins, settings last. Every statement can
61
+ * run again, so a migration for a server's plugin tables repeats core's.
62
62
  */
63
- const d1SchemaStatements = ({ schema, settings } = builtInTarget) => [...createTableStatements("sqlite", [WRITE_GUARD_TABLE]), ...generateEngineSql("sqlite", schema, settings)];
63
+ const d1SchemaStatements = ({ schema, settings } = coreTarget) => [...createTableStatements("sqlite", [WRITE_GUARD_TABLE]), ...generateEngineSql("sqlite", schema, settings)];
64
64
  /** The schema as a D1 migration, which `wrangler d1 migrations apply` runs. */
65
65
  const d1SchemaSql = (target) => `-- HotUpdater.schema\n\n${d1SchemaStatements(target).map((statement) => `${statement};`).join("\n\n")}\n`;
66
66
  //#endregion
@@ -99,8 +99,8 @@ const d1Database = (config) => {
99
99
  query: async (statement) => (await execute([statement]))[0],
100
100
  batch: execute
101
101
  }),
102
- generateSchema: ((version, _name, target = builtInTarget) => {
103
- if (version !== "latest" && version !== builtInSettings["schema.core"]) throw new Error(`Invalid version ${version}`);
102
+ generateSchema: ((version, _name, target = coreTarget) => {
103
+ if (version !== "latest" && version !== coreSettings["schema.core"]) throw new Error(`Invalid version ${version}`);
104
104
  const timestamp = (/* @__PURE__ */ new Date()).toISOString().replace(/\D/g, "").slice(0, 14);
105
105
  return {
106
106
  code: d1SchemaSql(target),