@hot-updater/test-utils 1.0.0-rc.43 → 1.0.0-rc.45

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/README.md CHANGED
@@ -37,12 +37,10 @@ Connect your database's lifecycle and the real server:
37
37
 
38
38
  ```ts
39
39
  import { createHotUpdater } from "@hot-updater/server";
40
- import {
41
- createInsightsModel,
42
- insights,
43
- } from "@hot-updater/server/plugins/insights";
40
+ import { createInsightsModel, insights } from "@hot-updater/server/plugins";
44
41
 
45
42
  import {
43
+ createReleaseCatalogTestStorage,
46
44
  insightsTestSuite,
47
45
  setupDatabaseTestSuite,
48
46
  startHttpTestServer,
@@ -77,6 +75,7 @@ setupDatabaseTestSuite({
77
75
  createInsightsModel(
78
76
  createHotUpdater({
79
77
  database,
78
+ storage: createReleaseCatalogTestStorage(),
80
79
  plugins: [insights()],
81
80
  clientAccess: "public",
82
81
  }).api.insights,
package/dist/index.d.mts CHANGED
@@ -128,7 +128,7 @@ type DatabaseTestSuiteOptions<TDatabase extends EngineDatabase = EngineDatabase>
128
128
  */
129
129
  readonly createHttpClient: (options: {
130
130
  readonly database: TDatabase;
131
- readonly storage: readonly StorageAdapter[];
131
+ readonly storage: StorageAdapter;
132
132
  }) => HttpTestServer | Promise<HttpTestServer>;
133
133
  /** The suites of the server plugins the provider opts in to test. */
134
134
  readonly plugins?: readonly DatabasePluginTestSuite<TDatabase>[];
@@ -464,8 +464,9 @@ declare const setupInsightsHttpTestSuite: (options: {
464
464
  //#region src/insights/setupInsightsModelTestSuite.d.ts
465
465
  /**
466
466
  * The Insights report contract on one database: pass the Insights plugin's
467
- * model over it, `createInsightsModel(createHotUpdater({ database, plugins:
468
- * [insights()], clientAccess: "public" }).api.insights)`, as `createDatabase`.
467
+ * model over it, `createInsightsModel(createHotUpdater({ database, storage,
468
+ * plugins: [insights()], clientAccess: "public" }).api.insights)`, as
469
+ * `createDatabase`.
469
470
  */
470
471
  declare const setupInsightsModelTestSuite: (lifecycle: DatabaseTestLifecycle<InsightsModel>) => void;
471
472
  //#endregion
@@ -474,8 +475,8 @@ declare const setupInsightsModelTestSuite: (lifecycle: DatabaseTestLifecycle<Ins
474
475
  * The Insights plugin's tests, for `setupDatabaseTestSuite`'s `plugins`: its
475
476
  * HTTP routes on the provider's server, which must run `insights()`, and
476
477
  * with `createModel` its report contract on the provider's database, such as
477
- * `(database) => createInsightsModel(createHotUpdater({ database, plugins:
478
- * [insights()], clientAccess: "public" }).api.insights)`.
478
+ * `(database) => createInsightsModel(createHotUpdater({ database, storage,
479
+ * plugins: [insights()], clientAccess: "public" }).api.insights)`.
479
480
  */
480
481
  declare const insightsTestSuite: <TDatabase = EngineDatabase>(options?: {
481
482
  readonly createModel?: (database: TDatabase) => InsightsModel;
package/dist/index.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import { afterAll, afterEach, beforeAll, beforeEach, describe, expect, it } from "vitest";
2
2
  import { NIL_UUID, createReleaseCatalogScopeKey, encodeChannelKey, selectDesiredRelease } from "@hot-updater/protocol";
3
- import { DATABASE_VERSION_COLUMN, DatabaseAdapterContractError, SETTINGS_TABLE, addDistinct, aggregateBatchingTables, assertStorageOperations, bundleToPatchRows, bundleToRow, compareUtf8, coreSchema, countDistinct, createBundleStorageKey, createEngine, createMemoryAdapter, createStorageKeyBuilder, createStorageRootUriWithPath, createStorageUri, createStorageUriWithRelativePath, findPhysicalIndex, getBundleArchiveStorageUri, getContentAddressedAssetStoragePath, indexOrderColumns, meterReads, parseStorageDownloadPath, parseStorageUri, targetBaseCandidateKey, toolingTargetOf, verifyAdapter } from "@hot-updater/plugin-core";
3
+ import { DATABASE_VERSION_COLUMN, DatabaseAdapterContractError, SETTINGS_TABLE, addDistinct, aggregateBatchingTables, assertStorageOperations, bundleToPatchRows, bundleToRow, compareUtf8, coreSchema, countDistinct, createBundleStorageKey, createEngine, createMemoryAdapter, createStorageKeyBuilder, createStorageRootUriWithPath, createStorageUri, createStorageUriWithRelativePath, findPhysicalIndex, getBundleArchiveStorageUri, getContentAddressedAssetStoragePath, indexOrderColumns, meterReads, parseStorageUri, targetBaseCandidateKey, toolingTargetOf, verifyAdapter } from "@hot-updater/plugin-core";
4
4
  import { createServer } from "node:http";
5
5
  //#region src/adminApiTestClient.ts
6
6
  const jsonRequest = (method, body) => ({
@@ -1357,7 +1357,7 @@ const setupDatabaseTestSuite = (options) => {
1357
1357
  beforeEach(async () => {
1358
1358
  client = await options.createHttpClient({
1359
1359
  database: getDatabase(),
1360
- storage: [createReleaseCatalogTestStorage()]
1360
+ storage: createReleaseCatalogTestStorage()
1361
1361
  });
1362
1362
  });
1363
1363
  afterEach(async () => {
@@ -2469,7 +2469,7 @@ const storageCase = (title, operations, run) => ({
2469
2469
  /**
2470
2470
  * The storage adapter contract, from what its consumers rely on: deploy and
2471
2471
  * patch (`put`, `get`, `exists`, `delete`), the Console, the server's update
2472
- * responses and signed downloads (`get`, `getDownloadUrl`), and
2472
+ * responses and the URLs devices download from (`get`, `getDownloadUrl`), and
2473
2473
  * `storage prune` (`listObjects`, `deleteObjects`).
2474
2474
  */
2475
2475
  const storageAdapterTestCases = [
@@ -2639,17 +2639,13 @@ const storageAdapterTestCases = [
2639
2639
  const { url } = await storage.getDownloadUrl({ storageUri });
2640
2640
  const label = `getDownloadUrl("${storageUri}") returned "${url}"`;
2641
2641
  expect(typeof url, label).toBe("string");
2642
- if (/^[a-z][a-z\d+.-]*:/i.test(url)) {
2643
- expect(["http:", "https:"], `${label}; a URL must use http(s)`).toContain(new URL(url).protocol);
2644
- if (fetchDownloadUrls) {
2645
- const response = await fetch(url);
2646
- expect(response.status, `${label}, which answered`).toBe(200);
2647
- expectBytes(new Uint8Array(await response.arrayBuffer()), bytes, `${label}, whose download`);
2648
- }
2649
- continue;
2642
+ expect(/^https?:\/\//i.test(url), `${label}; a download URL must be an absolute http(s) URL`).toBe(true);
2643
+ expect(() => new URL(url), label).not.toThrow();
2644
+ if (fetchDownloadUrls) {
2645
+ const response = await fetch(url);
2646
+ expect(response.status, `${label}, which answered`).toBe(200);
2647
+ expectBytes(new Uint8Array(await response.arrayBuffer()), bytes, `${label}, whose download`);
2650
2648
  }
2651
- expect(parseStorageDownloadPath(url)?.storageUri, `${label}; a path must be the /storage/ path of the same URI`).toBe(storageUri);
2652
- expect((await storage.getDownloadUrl({ storageUri })).url, `${label}, then another path`).toBe(url);
2653
2649
  }
2654
2650
  }),
2655
2651
  storageCase("lists every object with its key relative to the base path", ["listObjects"], async ({ storage, basePath }) => {
@@ -2786,7 +2782,10 @@ const createMeasuredDatabase = async (adapter, plugins, options = {}) => {
2786
2782
  });
2787
2783
  const hotUpdater = createHotUpdater({
2788
2784
  database,
2789
- storage: options.storage === void 0 ? [] : [storageOf(options.storage)],
2785
+ storage: options.storage === void 0 ? {
2786
+ name: "measuredStorage",
2787
+ protocol: "none"
2788
+ } : storageOf(options.storage),
2790
2789
  plugins: observed,
2791
2790
  ...plugins.some((plugin) => plugin.provides?.clientAuth === true) ? {} : { clientAccess: "public" }
2792
2791
  });
@@ -3481,11 +3480,7 @@ const setupReadBudgetTestSuite = (options) => {
3481
3480
  let seeded;
3482
3481
  let writes = 0;
3483
3482
  beforeAll(async () => {
3484
- const [{ insights }, { apiKeys }, { remoteConfig }] = await Promise.all([
3485
- import("@hot-updater/server/plugins/insights"),
3486
- import("@hot-updater/server/plugins/api-keys"),
3487
- import("@hot-updater/server/plugins/remote-config")
3488
- ]);
3483
+ const { insights, apiKeys, remoteConfig } = await import("@hot-updater/server/plugins");
3489
3484
  const plugins = [
3490
3485
  insights(),
3491
3486
  apiKeys(),
@@ -5206,8 +5201,9 @@ const setupInsightsHttpTestSuite = (options) => {
5206
5201
  //#region src/insights/setupInsightsModelTestSuite.ts
5207
5202
  /**
5208
5203
  * The Insights report contract on one database: pass the Insights plugin's
5209
- * model over it, `createInsightsModel(createHotUpdater({ database, plugins:
5210
- * [insights()], clientAccess: "public" }).api.insights)`, as `createDatabase`.
5204
+ * model over it, `createInsightsModel(createHotUpdater({ database, storage,
5205
+ * plugins: [insights()], clientAccess: "public" }).api.insights)`, as
5206
+ * `createDatabase`.
5211
5207
  */
5212
5208
  const setupInsightsModelTestSuite = (lifecycle) => {
5213
5209
  describe(lifecycle.name, () => {
@@ -5236,8 +5232,8 @@ const setupInsightsModelTestSuite = (lifecycle) => {
5236
5232
  * The Insights plugin's tests, for `setupDatabaseTestSuite`'s `plugins`: its
5237
5233
  * HTTP routes on the provider's server, which must run `insights()`, and
5238
5234
  * with `createModel` its report contract on the provider's database, such as
5239
- * `(database) => createInsightsModel(createHotUpdater({ database, plugins:
5240
- * [insights()], clientAccess: "public" }).api.insights)`.
5235
+ * `(database) => createInsightsModel(createHotUpdater({ database, storage,
5236
+ * plugins: [insights()], clientAccess: "public" }).api.insights)`.
5241
5237
  */
5242
5238
  const insightsTestSuite = (options = {}) => ({
5243
5239
  name: "Insights plugin",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hot-updater/test-utils",
3
- "version": "1.0.0-rc.43",
3
+ "version": "1.0.0-rc.45",
4
4
  "type": "module",
5
5
  "description": "Test utilities for Hot Updater packages",
6
6
  "sideEffects": false,
@@ -50,10 +50,10 @@
50
50
  "mysql2": "*",
51
51
  "pg": "*",
52
52
  "vitest": "^4.0.0",
53
- "@hot-updater/plugin-insights": "^1.0.0-rc.43",
54
- "@hot-updater/protocol": "^1.0.0-rc.43",
55
- "@hot-updater/plugin-core": "^1.0.0-rc.43",
56
- "@hot-updater/server": "^1.0.0-rc.43"
53
+ "@hot-updater/plugin-insights": "^1.0.0-rc.45",
54
+ "@hot-updater/protocol": "^1.0.0-rc.45",
55
+ "@hot-updater/plugin-core": "^1.0.0-rc.45",
56
+ "@hot-updater/server": "^1.0.0-rc.45"
57
57
  },
58
58
  "peerDependenciesMeta": {
59
59
  "@electric-sql/pglite": {
@@ -83,11 +83,11 @@
83
83
  "typescript": "npm:@typescript/typescript6@6.0.2",
84
84
  "vitest": "4.1.4",
85
85
  "workspace-tools": "^0.41.7",
86
- "@hot-updater/plugin-insights": "1.0.0-rc.43",
87
- "@hot-updater/protocol": "1.0.0-rc.43",
88
- "@hot-updater/server": "1.0.0-rc.43",
89
- "@hot-updater/plugin-core": "1.0.0-rc.43",
90
- "@hot-updater/js": "1.0.0-rc.43"
86
+ "@hot-updater/plugin-insights": "1.0.0-rc.45",
87
+ "@hot-updater/protocol": "1.0.0-rc.45",
88
+ "@hot-updater/js": "1.0.0-rc.45",
89
+ "@hot-updater/plugin-core": "1.0.0-rc.45",
90
+ "@hot-updater/server": "1.0.0-rc.45"
91
91
  },
92
92
  "inlinedDependencies": {
93
93
  "@nodelib/fs.scandir": "2.1.5",