@hot-updater/test-utils 1.0.0-rc.42 → 1.0.0-rc.44
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 +3 -4
- package/dist/index.d.mts +6 -5
- package/dist/index.mjs +21 -23
- package/package.json +10 -10
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:
|
|
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,
|
|
468
|
-
* [insights()], clientAccess: "public" }).api.insights)`, as
|
|
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,
|
|
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,
|
|
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) => ({
|
|
@@ -883,6 +883,7 @@ const setupReleaseCatalogTestSuite = (options) => {
|
|
|
883
883
|
expect(response.status).toBe(200);
|
|
884
884
|
expect(response.headers.get("content-type")).toBe("application/vnd.hot-updater.release-catalog+json; version=1");
|
|
885
885
|
expect(response.headers.get("cache-control")).toBe("public, max-age=0, s-maxage=5");
|
|
886
|
+
expect(response.headers.get("cdn-cache-control")).toBe("public, max-age=5, stale-while-revalidate=5, stale-if-error=0");
|
|
886
887
|
const catalog = await response.json();
|
|
887
888
|
expect(catalog).toMatchObject({
|
|
888
889
|
schemaVersion: 1,
|
|
@@ -1034,6 +1035,7 @@ const setupReleaseCatalogTestSuite = (options) => {
|
|
|
1034
1035
|
const response = await request(catalogPath());
|
|
1035
1036
|
expect(response.status).toBe(404);
|
|
1036
1037
|
expect(response.headers.get("cache-control")).toBe("public, max-age=0, s-maxage=5");
|
|
1038
|
+
expect(response.headers.get("cdn-cache-control")).toBe("public, max-age=5, stale-while-revalidate=5, stale-if-error=0");
|
|
1037
1039
|
expect(response.headers.get("x-hot-updater-catalog")).toBe("none");
|
|
1038
1040
|
await publish("121");
|
|
1039
1041
|
expect((await readCatalog()).releases).toHaveLength(1);
|
|
@@ -1355,7 +1357,7 @@ const setupDatabaseTestSuite = (options) => {
|
|
|
1355
1357
|
beforeEach(async () => {
|
|
1356
1358
|
client = await options.createHttpClient({
|
|
1357
1359
|
database: getDatabase(),
|
|
1358
|
-
storage:
|
|
1360
|
+
storage: createReleaseCatalogTestStorage()
|
|
1359
1361
|
});
|
|
1360
1362
|
});
|
|
1361
1363
|
afterEach(async () => {
|
|
@@ -2467,7 +2469,7 @@ const storageCase = (title, operations, run) => ({
|
|
|
2467
2469
|
/**
|
|
2468
2470
|
* The storage adapter contract, from what its consumers rely on: deploy and
|
|
2469
2471
|
* patch (`put`, `get`, `exists`, `delete`), the Console, the server's update
|
|
2470
|
-
* responses and
|
|
2472
|
+
* responses and the URLs devices download from (`get`, `getDownloadUrl`), and
|
|
2471
2473
|
* `storage prune` (`listObjects`, `deleteObjects`).
|
|
2472
2474
|
*/
|
|
2473
2475
|
const storageAdapterTestCases = [
|
|
@@ -2637,17 +2639,13 @@ const storageAdapterTestCases = [
|
|
|
2637
2639
|
const { url } = await storage.getDownloadUrl({ storageUri });
|
|
2638
2640
|
const label = `getDownloadUrl("${storageUri}") returned "${url}"`;
|
|
2639
2641
|
expect(typeof url, label).toBe("string");
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
}
|
|
2647
|
-
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`);
|
|
2648
2648
|
}
|
|
2649
|
-
expect(parseStorageDownloadPath(url)?.storageUri, `${label}; a path must be the /storage/ path of the same URI`).toBe(storageUri);
|
|
2650
|
-
expect((await storage.getDownloadUrl({ storageUri })).url, `${label}, then another path`).toBe(url);
|
|
2651
2649
|
}
|
|
2652
2650
|
}),
|
|
2653
2651
|
storageCase("lists every object with its key relative to the base path", ["listObjects"], async ({ storage, basePath }) => {
|
|
@@ -2784,7 +2782,10 @@ const createMeasuredDatabase = async (adapter, plugins, options = {}) => {
|
|
|
2784
2782
|
});
|
|
2785
2783
|
const hotUpdater = createHotUpdater({
|
|
2786
2784
|
database,
|
|
2787
|
-
storage: options.storage === void 0 ?
|
|
2785
|
+
storage: options.storage === void 0 ? {
|
|
2786
|
+
name: "measuredStorage",
|
|
2787
|
+
protocol: "none"
|
|
2788
|
+
} : storageOf(options.storage),
|
|
2788
2789
|
plugins: observed,
|
|
2789
2790
|
...plugins.some((plugin) => plugin.provides?.clientAuth === true) ? {} : { clientAccess: "public" }
|
|
2790
2791
|
});
|
|
@@ -3479,11 +3480,7 @@ const setupReadBudgetTestSuite = (options) => {
|
|
|
3479
3480
|
let seeded;
|
|
3480
3481
|
let writes = 0;
|
|
3481
3482
|
beforeAll(async () => {
|
|
3482
|
-
const
|
|
3483
|
-
import("@hot-updater/server/plugins/insights"),
|
|
3484
|
-
import("@hot-updater/server/plugins/api-keys"),
|
|
3485
|
-
import("@hot-updater/server/plugins/remote-config")
|
|
3486
|
-
]);
|
|
3483
|
+
const { insights, apiKeys, remoteConfig } = await import("@hot-updater/server/plugins");
|
|
3487
3484
|
const plugins = [
|
|
3488
3485
|
insights(),
|
|
3489
3486
|
apiKeys(),
|
|
@@ -5204,8 +5201,9 @@ const setupInsightsHttpTestSuite = (options) => {
|
|
|
5204
5201
|
//#region src/insights/setupInsightsModelTestSuite.ts
|
|
5205
5202
|
/**
|
|
5206
5203
|
* The Insights report contract on one database: pass the Insights plugin's
|
|
5207
|
-
* model over it, `createInsightsModel(createHotUpdater({ database,
|
|
5208
|
-
* [insights()], clientAccess: "public" }).api.insights)`, as
|
|
5204
|
+
* model over it, `createInsightsModel(createHotUpdater({ database, storage,
|
|
5205
|
+
* plugins: [insights()], clientAccess: "public" }).api.insights)`, as
|
|
5206
|
+
* `createDatabase`.
|
|
5209
5207
|
*/
|
|
5210
5208
|
const setupInsightsModelTestSuite = (lifecycle) => {
|
|
5211
5209
|
describe(lifecycle.name, () => {
|
|
@@ -5234,8 +5232,8 @@ const setupInsightsModelTestSuite = (lifecycle) => {
|
|
|
5234
5232
|
* The Insights plugin's tests, for `setupDatabaseTestSuite`'s `plugins`: its
|
|
5235
5233
|
* HTTP routes on the provider's server, which must run `insights()`, and
|
|
5236
5234
|
* with `createModel` its report contract on the provider's database, such as
|
|
5237
|
-
* `(database) => createInsightsModel(createHotUpdater({ database,
|
|
5238
|
-
* [insights()], clientAccess: "public" }).api.insights)`.
|
|
5235
|
+
* `(database) => createInsightsModel(createHotUpdater({ database, storage,
|
|
5236
|
+
* plugins: [insights()], clientAccess: "public" }).api.insights)`.
|
|
5239
5237
|
*/
|
|
5240
5238
|
const insightsTestSuite = (options = {}) => ({
|
|
5241
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.
|
|
3
|
+
"version": "1.0.0-rc.44",
|
|
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-
|
|
54
|
-
"@hot-updater/protocol": "^1.0.0-rc.
|
|
55
|
-
"@hot-updater/
|
|
56
|
-
"@hot-updater/
|
|
53
|
+
"@hot-updater/plugin-core": "^1.0.0-rc.44",
|
|
54
|
+
"@hot-updater/protocol": "^1.0.0-rc.44",
|
|
55
|
+
"@hot-updater/server": "^1.0.0-rc.44",
|
|
56
|
+
"@hot-updater/plugin-insights": "^1.0.0-rc.44"
|
|
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.
|
|
87
|
-
"@hot-updater/protocol": "1.0.0-rc.
|
|
88
|
-
"@hot-updater/js": "1.0.0-rc.
|
|
89
|
-
"@hot-updater/server": "1.0.0-rc.
|
|
90
|
-
"@hot-updater/plugin-core": "1.0.0-rc.
|
|
86
|
+
"@hot-updater/plugin-insights": "1.0.0-rc.44",
|
|
87
|
+
"@hot-updater/protocol": "1.0.0-rc.44",
|
|
88
|
+
"@hot-updater/js": "1.0.0-rc.44",
|
|
89
|
+
"@hot-updater/server": "1.0.0-rc.44",
|
|
90
|
+
"@hot-updater/plugin-core": "1.0.0-rc.44"
|
|
91
91
|
},
|
|
92
92
|
"inlinedDependencies": {
|
|
93
93
|
"@nodelib/fs.scandir": "2.1.5",
|