@peers-app/peers-sdk 0.27.3 → 0.27.4
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/contracts/contract-proxy.d.ts +7 -0
- package/dist/contracts/contract-proxy.js +19 -2
- package/dist/contracts/create-local-consumer.js +16 -1
- package/dist/contracts/index.d.ts +2 -0
- package/dist/contracts/index.js +2 -0
- package/dist/contracts/system/index.d.ts +2 -0
- package/dist/contracts/system/index.js +2 -0
- package/dist/contracts/system/invites-contract.js +2 -1
- package/dist/contracts/system/sync-check-contract.d.ts +97 -0
- package/dist/contracts/system/sync-check-contract.js +115 -0
- package/dist/contracts/tool-arguments.d.ts +15 -0
- package/dist/contracts/tool-arguments.js +41 -0
- package/dist/contracts/tool-catalog-service.js +2 -12
- package/dist/data/change-tracking.d.ts +40 -0
- package/dist/data/change-tracking.js +89 -0
- package/dist/data/orm/types.d.ts +24 -7
- package/dist/data/orm/types.js +97 -24
- package/dist/define/manifest.js +6 -34
- package/dist/package-loader/package-loader.js +27 -22
- package/dist/system-ids.d.ts +5 -0
- package/dist/system-ids.js +6 -1
- package/package.json +4 -2
- package/dist/context/user-context-identity.test.d.ts +0 -1
- package/dist/context/user-context-identity.test.js +0 -220
- package/dist/contracts/__tests__/action-dispatch.test.d.ts +0 -1
- package/dist/contracts/__tests__/action-dispatch.test.js +0 -319
- package/dist/contracts/__tests__/also-implements.test.d.ts +0 -1
- package/dist/contracts/__tests__/also-implements.test.js +0 -110
- package/dist/contracts/__tests__/builder.test.d.ts +0 -1
- package/dist/contracts/__tests__/builder.test.js +0 -669
- package/dist/contracts/__tests__/contract-events.test.d.ts +0 -1
- package/dist/contracts/__tests__/contract-events.test.js +0 -199
- package/dist/contracts/__tests__/contract-observables.test.d.ts +0 -1
- package/dist/contracts/__tests__/contract-observables.test.js +0 -290
- package/dist/contracts/__tests__/contract-provider-router.test.d.ts +0 -1
- package/dist/contracts/__tests__/contract-provider-router.test.js +0 -315
- package/dist/contracts/__tests__/contract-proxy.test.d.ts +0 -1
- package/dist/contracts/__tests__/contract-proxy.test.js +0 -657
- package/dist/contracts/__tests__/contract-resolvers.test.d.ts +0 -1
- package/dist/contracts/__tests__/contract-resolvers.test.js +0 -758
- package/dist/contracts/__tests__/contract-subscription-lifecycle.test.d.ts +0 -1
- package/dist/contracts/__tests__/contract-subscription-lifecycle.test.js +0 -353
- package/dist/contracts/__tests__/contract-table-events.test.d.ts +0 -1
- package/dist/contracts/__tests__/contract-table-events.test.js +0 -209
- package/dist/contracts/__tests__/contract-transport.test.d.ts +0 -1
- package/dist/contracts/__tests__/contract-transport.test.js +0 -163
- package/dist/contracts/__tests__/extract.test.d.ts +0 -1
- package/dist/contracts/__tests__/extract.test.js +0 -145
- package/dist/contracts/__tests__/frozen-contracts.test.d.ts +0 -1
- package/dist/contracts/__tests__/frozen-contracts.test.js +0 -191
- package/dist/contracts/__tests__/generic-tool-dispatch.test.d.ts +0 -1
- package/dist/contracts/__tests__/generic-tool-dispatch.test.js +0 -130
- package/dist/contracts/__tests__/host-contract-client.test.d.ts +0 -1
- package/dist/contracts/__tests__/host-contract-client.test.js +0 -793
- package/dist/contracts/__tests__/host-contract-consumer.test.d.ts +0 -1
- package/dist/contracts/__tests__/host-contract-consumer.test.js +0 -163
- package/dist/contracts/__tests__/host-contract-transport.test.d.ts +0 -1
- package/dist/contracts/__tests__/host-contract-transport.test.js +0 -66
- package/dist/contracts/__tests__/integration.test.d.ts +0 -1
- package/dist/contracts/__tests__/integration.test.js +0 -348
- package/dist/contracts/__tests__/legacy-removal.test.d.ts +0 -1
- package/dist/contracts/__tests__/legacy-removal.test.js +0 -128
- package/dist/contracts/__tests__/persistent-registry.test.d.ts +0 -1
- package/dist/contracts/__tests__/persistent-registry.test.js +0 -109
- package/dist/contracts/__tests__/playground.test.d.ts +0 -1
- package/dist/contracts/__tests__/playground.test.js +0 -216
- package/dist/contracts/__tests__/registry.test.d.ts +0 -1
- package/dist/contracts/__tests__/registry.test.js +0 -238
- package/dist/contracts/__tests__/remote-contract-transport.test.d.ts +0 -1
- package/dist/contracts/__tests__/remote-contract-transport.test.js +0 -119
- package/dist/contracts/__tests__/system-contracts.test.d.ts +0 -1
- package/dist/contracts/__tests__/system-contracts.test.js +0 -247
- package/dist/contracts/__tests__/target-dispatch.d.ts +0 -11
- package/dist/contracts/__tests__/target-dispatch.js +0 -24
- package/dist/contracts/__tests__/tool-catalog-inventory.test.d.ts +0 -1
- package/dist/contracts/__tests__/tool-catalog-inventory.test.js +0 -44
- package/dist/contracts/__tests__/tool-catalog-service.test.d.ts +0 -1
- package/dist/contracts/__tests__/tool-catalog-service.test.js +0 -482
- package/dist/contracts/__tests__/tool-catalog.test.d.ts +0 -1
- package/dist/contracts/__tests__/tool-catalog.test.js +0 -1199
- package/dist/contracts/__tests__/validate.test.d.ts +0 -1
- package/dist/contracts/__tests__/validate.test.js +0 -991
- package/dist/contracts/__tests__/workflow-context.test.d.ts +0 -1
- package/dist/contracts/__tests__/workflow-context.test.js +0 -50
- package/dist/data/access-level.test.d.ts +0 -1
- package/dist/data/access-level.test.js +0 -53
- package/dist/data/change-tracking.test.d.ts +0 -1
- package/dist/data/change-tracking.test.js +0 -62
- package/dist/data/files/files.test.d.ts +0 -1
- package/dist/data/files/files.test.js +0 -770
- package/dist/data/group-members.test.d.ts +0 -1
- package/dist/data/group-members.test.js +0 -336
- package/dist/data/group-share.test.d.ts +0 -1
- package/dist/data/group-share.test.js +0 -110
- package/dist/data/groups.test.d.ts +0 -1
- package/dist/data/groups.test.js +0 -153
- package/dist/data/orm/cursor.test.d.ts +0 -1
- package/dist/data/orm/cursor.test.js +0 -314
- package/dist/data/orm/data-query.mongo.test.d.ts +0 -1
- package/dist/data/orm/data-query.mongo.test.js +0 -367
- package/dist/data/orm/data-query.sqlite.test.d.ts +0 -1
- package/dist/data/orm/data-query.sqlite.test.js +0 -365
- package/dist/data/orm/data-query.test.d.ts +0 -1
- package/dist/data/orm/data-query.test.js +0 -545
- package/dist/data/orm/dependency-injection.test.d.ts +0 -1
- package/dist/data/orm/dependency-injection.test.js +0 -171
- package/dist/data/orm/event-registry.test.d.ts +0 -1
- package/dist/data/orm/event-registry.test.js +0 -44
- package/dist/data/orm/multi-cursors.test.d.ts +0 -1
- package/dist/data/orm/multi-cursors.test.js +0 -463
- package/dist/data/orm/sql.data-source.test.d.ts +0 -1
- package/dist/data/orm/sql.data-source.test.js +0 -731
- package/dist/data/orm/table-container-events.test.d.ts +0 -1
- package/dist/data/orm/table-container-events.test.js +0 -101
- package/dist/data/orm/table-container.test.d.ts +0 -1
- package/dist/data/orm/table-container.test.js +0 -273
- package/dist/data/orm/table.event-source.test.d.ts +0 -1
- package/dist/data/orm/table.event-source.test.js +0 -331
- package/dist/data/orm/types.test.d.ts +0 -1
- package/dist/data/orm/types.test.js +0 -409
- package/dist/data/package-table-identity.test.d.ts +0 -1
- package/dist/data/package-table-identity.test.js +0 -46
- package/dist/data/package-version-permissions.test.d.ts +0 -1
- package/dist/data/package-version-permissions.test.js +0 -107
- package/dist/data/package-version-resolver.test.d.ts +0 -4
- package/dist/data/package-version-resolver.test.js +0 -543
- package/dist/data/package-versions.test.d.ts +0 -1
- package/dist/data/package-versions.test.js +0 -227
- package/dist/data/persistent-vars.conflict.test.d.ts +0 -1
- package/dist/data/persistent-vars.conflict.test.js +0 -126
- package/dist/data/persistent-vars.migration.test.d.ts +0 -1
- package/dist/data/persistent-vars.migration.test.js +0 -133
- package/dist/data/persistent-vars.package-scope.test.d.ts +0 -1
- package/dist/data/persistent-vars.package-scope.test.js +0 -27
- package/dist/data/sync-recovery-queue.test.d.ts +0 -1
- package/dist/data/sync-recovery-queue.test.js +0 -215
- package/dist/data/table-signing.test.d.ts +0 -1
- package/dist/data/table-signing.test.js +0 -118
- package/dist/data/tool-access.test.d.ts +0 -1
- package/dist/data/tool-access.test.js +0 -166
- package/dist/data/user-permissions.test.d.ts +0 -1
- package/dist/data/user-permissions.test.js +0 -305
- package/dist/data/user-trust-levels.test.d.ts +0 -1
- package/dist/data/user-trust-levels.test.js +0 -37
- package/dist/define/also-implements.test.d.ts +0 -1
- package/dist/define/also-implements.test.js +0 -123
- package/dist/define/declare-contract.test.d.ts +0 -1
- package/dist/define/declare-contract.test.js +0 -573
- package/dist/define/define.test.d.ts +0 -1
- package/dist/define/define.test.js +0 -1010
- package/dist/define/empty-fields.test.d.ts +0 -1
- package/dist/define/empty-fields.test.js +0 -55
- package/dist/define/events-observables.test.d.ts +0 -1
- package/dist/define/events-observables.test.js +0 -1013
- package/dist/define/serve-members.test.d.ts +0 -1
- package/dist/define/serve-members.test.js +0 -630
- package/dist/define/vars.test.d.ts +0 -1
- package/dist/define/vars.test.js +0 -39
- package/dist/device/binary-peer-connection-v2.test.d.ts +0 -1
- package/dist/device/binary-peer-connection-v2.test.js +0 -730
- package/dist/device/binary-peer-connection.test.d.ts +0 -1
- package/dist/device/binary-peer-connection.test.js +0 -184
- package/dist/device/connection.test.d.ts +0 -1
- package/dist/device/connection.test.js +0 -613
- package/dist/device/device-election.test.d.ts +0 -1
- package/dist/device/device-election.test.js +0 -516
- package/dist/device/device.test.d.ts +0 -1
- package/dist/device/device.test.js +0 -243
- package/dist/device/frame-cipher.test.d.ts +0 -1
- package/dist/device/frame-cipher.test.js +0 -219
- package/dist/device/get-trust-level-fn.test.d.ts +0 -1
- package/dist/device/get-trust-level-fn.test.js +0 -685
- package/dist/device/streamed-socket.test.d.ts +0 -1
- package/dist/device/streamed-socket.test.js +0 -216
- package/dist/device/tx-encoding.test.d.ts +0 -1
- package/dist/device/tx-encoding.test.js +0 -295
- package/dist/device-pairing/cpace.test.d.ts +0 -1
- package/dist/device-pairing/cpace.test.js +0 -116
- package/dist/device-pairing/device-pairing.test.d.ts +0 -1
- package/dist/device-pairing/device-pairing.test.js +0 -211
- package/dist/hlc.test.d.ts +0 -1
- package/dist/hlc.test.js +0 -45
- package/dist/host-credentials.test.d.ts +0 -1
- package/dist/host-credentials.test.js +0 -88
- package/dist/identity/account-email.test.d.ts +0 -1
- package/dist/identity/account-email.test.js +0 -59
- package/dist/identity/anchor-document.test.d.ts +0 -1
- package/dist/identity/anchor-document.test.js +0 -16
- package/dist/identity/anchor-resolution.test.d.ts +0 -1
- package/dist/identity/anchor-resolution.test.js +0 -130
- package/dist/identity/key-change.test.d.ts +0 -1
- package/dist/identity/key-change.test.js +0 -811
- package/dist/invites/group-approval.test.d.ts +0 -1
- package/dist/invites/group-approval.test.js +0 -223
- package/dist/invites/invite-token.test.d.ts +0 -1
- package/dist/invites/invite-token.test.js +0 -123
- package/dist/keys.test.d.ts +0 -1
- package/dist/keys.test.js +0 -336
- package/dist/logging/console-logger.test.d.ts +0 -1
- package/dist/logging/console-logger.test.js +0 -300
- package/dist/logging/console-logs.table.test.d.ts +0 -1
- package/dist/logging/console-logs.table.test.js +0 -156
- package/dist/observable.test.d.ts +0 -1
- package/dist/observable.test.js +0 -309
- package/dist/package-build/build-package.test.d.ts +0 -1
- package/dist/package-build/build-package.test.js +0 -204
- package/dist/package-build/contract-add.test.d.ts +0 -1
- package/dist/package-build/contract-add.test.js +0 -467
- package/dist/package-build/freeze-contracts.test.d.ts +0 -1
- package/dist/package-build/freeze-contracts.test.js +0 -355
- package/dist/package-installer/package-author-signing.test.d.ts +0 -1
- package/dist/package-installer/package-author-signing.test.js +0 -200
- package/dist/package-installer/package-cloner.test.d.ts +0 -1
- package/dist/package-installer/package-cloner.test.js +0 -278
- package/dist/package-installer/package-creator.test.d.ts +0 -1
- package/dist/package-installer/package-creator.test.js +0 -908
- package/dist/package-installer/package-dev-tools.test.d.ts +0 -1
- package/dist/package-installer/package-dev-tools.test.js +0 -64
- package/dist/package-installer/package-installer.test.d.ts +0 -1
- package/dist/package-installer/package-installer.test.js +0 -882
- package/dist/package-installer/package-propagation.test.d.ts +0 -1
- package/dist/package-installer/package-propagation.test.js +0 -1269
- package/dist/package-installer/package-publisher.test.d.ts +0 -1
- package/dist/package-installer/package-publisher.test.js +0 -153
- package/dist/package-installer/package-remote-checker.test.d.ts +0 -1
- package/dist/package-installer/package-remote-checker.test.js +0 -334
- package/dist/package-installer/package-seed-installer.test.d.ts +0 -1
- package/dist/package-installer/package-seed-installer.test.js +0 -123
- package/dist/package-installer/package-tarball.test.d.ts +0 -1
- package/dist/package-installer/package-tarball.test.js +0 -75
- package/dist/package-installer/peers-core-installer.test.d.ts +0 -1
- package/dist/package-installer/peers-core-installer.test.js +0 -49
- package/dist/package-installer/peers-core-trust-anchor.test.d.ts +0 -1
- package/dist/package-installer/peers-core-trust-anchor.test.js +0 -155
- package/dist/package-loader/contract-package-loader.test.d.ts +0 -1
- package/dist/package-loader/contract-package-loader.test.js +0 -274
- package/dist/package-loader/host-authority-loading.test.d.ts +0 -1
- package/dist/package-loader/host-authority-loading.test.js +0 -104
- package/dist/package-loader/host-dispatch-policy.test.d.ts +0 -1
- package/dist/package-loader/host-dispatch-policy.test.js +0 -56
- package/dist/package-loader/isolated-artifact.test.d.ts +0 -1
- package/dist/package-loader/isolated-artifact.test.js +0 -688
- package/dist/package-loader/isolated-persistent-var-gateway.test.d.ts +0 -1
- package/dist/package-loader/isolated-persistent-var-gateway.test.js +0 -56
- package/dist/package-loader/isolated-table-gateway.test.d.ts +0 -1
- package/dist/package-loader/isolated-table-gateway.test.js +0 -633
- package/dist/package-loader/package-loader.test.d.ts +0 -1
- package/dist/package-loader/package-loader.test.js +0 -1764
- package/dist/package-loader/resolve-consumed-contracts.test.d.ts +0 -1
- package/dist/package-loader/resolve-consumed-contracts.test.js +0 -166
- package/dist/serial-json.compat.test.d.ts +0 -1
- package/dist/serial-json.compat.test.js +0 -369
- package/dist/serial-json.test.d.ts +0 -1
- package/dist/serial-json.test.js +0 -401
- package/dist/testing/mock-host-contract.test.d.ts +0 -1
- package/dist/testing/mock-host-contract.test.js +0 -782
- package/dist/utils.test.d.ts +0 -1
- package/dist/utils.test.js +0 -232
|
@@ -1,355 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const promises_1 = require("node:fs/promises");
|
|
4
|
-
const node_os_1 = require("node:os");
|
|
5
|
-
const path = require("node:path");
|
|
6
|
-
const peer_id_1 = require("../peer-id");
|
|
7
|
-
const build_package_1 = require("./build-package");
|
|
8
|
-
const cli_1 = require("./cli");
|
|
9
|
-
const freeze_contracts_1 = require("./freeze-contracts");
|
|
10
|
-
const sdkRoot = path.resolve(__dirname, "../..");
|
|
11
|
-
const packageId = (0, peer_id_1.newid)();
|
|
12
|
-
const contractId = (0, peer_id_1.newid)();
|
|
13
|
-
let root;
|
|
14
|
-
/** A `/define` package providing Probe v1 (and v2 when asked), its tool shaped by `input`. */
|
|
15
|
-
function declaration(version, input, description = "Probe.", withV2 = false) {
|
|
16
|
-
const contract = (contractVersion) => `defineContract({
|
|
17
|
-
contractId: ${JSON.stringify(contractId)}, version: ${contractVersion}, name: "Probe",
|
|
18
|
-
tools: [defineTool({
|
|
19
|
-
name: "probe", usageDescription: ${JSON.stringify(description)}, accessLevel: 0,
|
|
20
|
-
inputSchema: z.object(${input}), outputSchema: z.object({}),
|
|
21
|
-
handler: () => ({}),
|
|
22
|
-
})],
|
|
23
|
-
})`;
|
|
24
|
-
return `
|
|
25
|
-
import { defineContract, definePackage, defineTool, z } from "@peers-app/peers-sdk/define";
|
|
26
|
-
export default definePackage((pkg) => {
|
|
27
|
-
pkg.packageId = ${JSON.stringify(packageId)};
|
|
28
|
-
pkg.version = ${JSON.stringify(version)};
|
|
29
|
-
pkg.provides(${contract(1)});
|
|
30
|
-
${withV2 ? `pkg.provides(${contract(2)});` : ""}
|
|
31
|
-
});
|
|
32
|
-
`;
|
|
33
|
-
}
|
|
34
|
-
const frozen = async () => JSON.parse(await (0, promises_1.readFile)(path.join(root, "frozen-contracts.json"), "utf8"));
|
|
35
|
-
beforeEach(async () => {
|
|
36
|
-
root = await (0, promises_1.mkdtemp)(path.join((0, node_os_1.tmpdir)(), "peers-package-freeze-"));
|
|
37
|
-
await (0, promises_1.mkdir)(path.join(root, "src"));
|
|
38
|
-
await (0, promises_1.mkdir)(path.join(root, "node_modules/@peers-app"), { recursive: true });
|
|
39
|
-
await (0, promises_1.symlink)(sdkRoot, path.join(root, "node_modules/@peers-app/peers-sdk"), "dir");
|
|
40
|
-
await (0, promises_1.symlink)(path.dirname(require.resolve("esbuild/package.json")), path.join(root, "node_modules/esbuild"), "dir");
|
|
41
|
-
await (0, promises_1.writeFile)(path.join(root, "package.json"), '{"name":"freeze-probe","version":"1.0.0"}');
|
|
42
|
-
await (0, promises_1.writeFile)(path.join(root, "src/package.ts"), declaration("1.0.0", "{ name: z.string() }"));
|
|
43
|
-
});
|
|
44
|
-
afterEach(async () => {
|
|
45
|
-
await (0, promises_1.rm)(root, { recursive: true, force: true });
|
|
46
|
-
});
|
|
47
|
-
test("freezes a release's contracts, then the build refuses a shape change but not a new description", async () => {
|
|
48
|
-
const log = jest.spyOn(console, "log").mockImplementation(() => undefined);
|
|
49
|
-
const error = jest.spyOn(console, "error").mockImplementation(() => undefined);
|
|
50
|
-
try {
|
|
51
|
-
// Nothing frozen yet: the check passes, saying so, and the build runs.
|
|
52
|
-
await expect((0, cli_1.main)(["contract", "freeze", "--check", "--root", root])).resolves.toBe(0);
|
|
53
|
-
expect(log).toHaveBeenCalledWith(expect.stringContaining("nothing is frozen yet"));
|
|
54
|
-
await expect((0, freeze_contracts_1.freezePackageContracts)({ root })).resolves.toMatchObject({
|
|
55
|
-
packageVersion: "1.0.0",
|
|
56
|
-
added: [expect.objectContaining({ contractId, version: 1, frozenBy: "1.0.0" })],
|
|
57
|
-
written: true,
|
|
58
|
-
});
|
|
59
|
-
expect((await frozen()).contracts.map(({ version, frozenBy }) => [version, frozenBy])).toEqual([
|
|
60
|
-
[1, "1.0.0"],
|
|
61
|
-
]);
|
|
62
|
-
await expect((0, freeze_contracts_1.freezePackageContracts)({ root })).resolves.toMatchObject({
|
|
63
|
-
added: [],
|
|
64
|
-
written: false,
|
|
65
|
-
});
|
|
66
|
-
// A new description is allowed; a changed input isn't, in the build or the check.
|
|
67
|
-
await (0, promises_1.writeFile)(path.join(root, "src/package.ts"), declaration("1.1.0", "{ name: z.string() }", "Probe, described again."));
|
|
68
|
-
await expect((0, build_package_1.buildPackage)({ root })).resolves.toMatchObject({});
|
|
69
|
-
await (0, promises_1.writeFile)(path.join(root, "src/package.ts"), declaration("1.1.0", "{ name: z.string(), count: z.number() }"));
|
|
70
|
-
await expect((0, build_package_1.buildPackage)({ root })).rejects.toThrow(`This build changes a frozen contract:\nProbe (${contractId}@1), frozen by 1.0.0: tool probe changed.`);
|
|
71
|
-
await expect((0, build_package_1.generatePackageManifest)({ root })).rejects.toThrow("tool probe changed");
|
|
72
|
-
const beforeFailure = await (0, promises_1.readFile)(path.join(root, "frozen-contracts.json"), "utf8");
|
|
73
|
-
await expect((0, cli_1.main)(["contract", "freeze", "--check", "--root", root])).resolves.toBe(1);
|
|
74
|
-
await expect((0, cli_1.main)(["contract", "freeze", "--root", root])).resolves.toBe(1);
|
|
75
|
-
expect(error).toHaveBeenCalledWith(expect.stringContaining("tool probe changed"));
|
|
76
|
-
expect((await frozen()).contracts).toHaveLength(1);
|
|
77
|
-
expect(await (0, promises_1.readFile)(path.join(root, "frozen-contracts.json"), "utf8")).toBe(beforeFailure);
|
|
78
|
-
// The change goes in a new version, which the next stable release freezes.
|
|
79
|
-
await (0, promises_1.writeFile)(path.join(root, "src/package.ts"), declaration("2.0.0", "{ name: z.string() }", "Probe.", true));
|
|
80
|
-
await expect((0, cli_1.main)(["contract", "freeze", "--root", root])).resolves.toBe(0);
|
|
81
|
-
expect((await frozen()).contracts.map(({ version, frozenBy }) => [version, frozenBy])).toEqual([
|
|
82
|
-
[1, "1.0.0"],
|
|
83
|
-
[2, "2.0.0"],
|
|
84
|
-
]);
|
|
85
|
-
}
|
|
86
|
-
finally {
|
|
87
|
-
log.mockRestore();
|
|
88
|
-
error.mockRestore();
|
|
89
|
-
}
|
|
90
|
-
});
|
|
91
|
-
test("doesn't note a frozen version the package still serves through alsoImplements", async () => {
|
|
92
|
-
const log = jest.spyOn(console, "log").mockImplementation(() => undefined);
|
|
93
|
-
const v2 = (alsoImplements) => `
|
|
94
|
-
import { defineContract, definePackage, defineTool, z } from "@peers-app/peers-sdk/define";
|
|
95
|
-
export default definePackage((pkg) => {
|
|
96
|
-
pkg.packageId = ${JSON.stringify(packageId)};
|
|
97
|
-
pkg.version = "2.0.0";
|
|
98
|
-
pkg.provides(defineContract({
|
|
99
|
-
contractId: ${JSON.stringify(contractId)}, version: 2, name: "Probe",
|
|
100
|
-
tools: [defineTool({
|
|
101
|
-
name: "probe", usageDescription: "Probe.", accessLevel: 0,
|
|
102
|
-
inputSchema: z.object({ name: z.string(), tag: z.string().optional() }),
|
|
103
|
-
outputSchema: z.object({}), handler: () => ({}),
|
|
104
|
-
})],
|
|
105
|
-
${alsoImplements}
|
|
106
|
-
}));
|
|
107
|
-
});
|
|
108
|
-
`;
|
|
109
|
-
try {
|
|
110
|
-
await (0, freeze_contracts_1.freezePackageContracts)({ root });
|
|
111
|
-
await (0, promises_1.writeFile)(path.join(root, "src/package.ts"), v2("alsoImplements: [1],"));
|
|
112
|
-
await expect((0, freeze_contracts_1.freezePackageContracts)({ root, check: true })).resolves.toMatchObject({
|
|
113
|
-
check: { changed: [], notProvided: [] },
|
|
114
|
-
});
|
|
115
|
-
await expect((0, cli_1.main)(["contract", "freeze", "--root", root])).resolves.toBe(0);
|
|
116
|
-
expect(log).not.toHaveBeenCalledWith(expect.stringContaining("is no longer provided"));
|
|
117
|
-
expect((await frozen()).contracts.map(({ version, frozenBy }) => [version, frozenBy])).toEqual([
|
|
118
|
-
[1, "1.0.0"],
|
|
119
|
-
[2, "2.0.0"],
|
|
120
|
-
]);
|
|
121
|
-
// Without the alias, v1's consumers lose this provider, and the check says so.
|
|
122
|
-
await (0, promises_1.writeFile)(path.join(root, "src/package.ts"), v2(""));
|
|
123
|
-
const checked = await (0, freeze_contracts_1.freezePackageContracts)({ root, check: true });
|
|
124
|
-
expect(checked.check.notProvided.map(({ version }) => version)).toEqual([1]);
|
|
125
|
-
}
|
|
126
|
-
finally {
|
|
127
|
-
log.mockRestore();
|
|
128
|
-
}
|
|
129
|
-
});
|
|
130
|
-
test("reads an isolated artifact with a cwd-relative bundle and a separate root", async () => {
|
|
131
|
-
const built = await (0, build_package_1.buildPackage)({ root });
|
|
132
|
-
await expect((0, freeze_contracts_1.freezePackageContracts)({
|
|
133
|
-
root,
|
|
134
|
-
bundle: path.relative(process.cwd(), built.artifactPath),
|
|
135
|
-
})).resolves.toMatchObject({ written: true, packageVersion: "1.0.0" });
|
|
136
|
-
await expect((0, freeze_contracts_1.freezePackageContracts)({ root, bundle: built.artifactPath, check: true })).resolves.toMatchObject({ written: false, check: { changed: [] } });
|
|
137
|
-
});
|
|
138
|
-
test("checks a bundle's carried shapes against frozen versions before writing", async () => {
|
|
139
|
-
await (0, freeze_contracts_1.freezePackageContracts)({ root });
|
|
140
|
-
const file = path.join(root, "frozen-contracts.json");
|
|
141
|
-
const before = await (0, promises_1.readFile)(file, "utf8");
|
|
142
|
-
const built = await (0, build_package_1.buildPackage)({ root });
|
|
143
|
-
const { frozenBy: _frozenBy, ...original } = (await frozen()).contracts[0];
|
|
144
|
-
const carried = {
|
|
145
|
-
...original,
|
|
146
|
-
tools: [{ ...original.tools[0], inputFields: [] }],
|
|
147
|
-
};
|
|
148
|
-
const manifest = structuredClone(built.manifest);
|
|
149
|
-
manifest.provides[0].version = 2;
|
|
150
|
-
manifest.provides[0].tools[0].inputFields = [];
|
|
151
|
-
manifest.provides[0].alsoImplements = [{ contractId, version: 1, definition: carried }];
|
|
152
|
-
await (0, promises_1.writeFile)(built.artifactPath, `PEERS_ISOLATED_PACKAGE_V1\n${JSON.stringify({ manifest, providerSource: "void 0;" })}\n`);
|
|
153
|
-
for (const check of [true, false]) {
|
|
154
|
-
await expect((0, freeze_contracts_1.freezePackageContracts)({ root, bundle: built.artifactPath, check })).resolves.toMatchObject({
|
|
155
|
-
added: [],
|
|
156
|
-
written: false,
|
|
157
|
-
check: {
|
|
158
|
-
changed: [{ contract: { contractId, version: 1 }, changes: ["tool probe changed"] }],
|
|
159
|
-
},
|
|
160
|
-
});
|
|
161
|
-
expect(await (0, promises_1.readFile)(file, "utf8")).toBe(before);
|
|
162
|
-
}
|
|
163
|
-
await expect((0, freeze_contracts_1.assertFrozenContracts)(root, manifest)).rejects.toThrow("tool probe changed");
|
|
164
|
-
});
|
|
165
|
-
test("only a provided host contract's aliases quiet retirement notes, with inclusive ranges", async () => {
|
|
166
|
-
await (0, freeze_contracts_1.freezePackageContracts)({ root });
|
|
167
|
-
const { frozenBy: _frozenBy, ...original } = (await frozen()).contracts[0];
|
|
168
|
-
const otherId = (0, peer_id_1.newid)();
|
|
169
|
-
const provided = { ...original, contractId: otherId, version: 3 };
|
|
170
|
-
const bundle = path.join(root, "aliases.bundle.js");
|
|
171
|
-
const target = { contractId, version: { from: 1, to: 2 } };
|
|
172
|
-
const cases = [
|
|
173
|
-
{ key: `${otherId}@3`, target, notProvided: [] },
|
|
174
|
-
{ key: `${otherId}@2`, target, notProvided: [expect.objectContaining({ contractId })] },
|
|
175
|
-
{
|
|
176
|
-
key: `${otherId}@3`,
|
|
177
|
-
target: { contractId: otherId, version: { from: 1, to: 2 } },
|
|
178
|
-
notProvided: [expect.objectContaining({ contractId })],
|
|
179
|
-
},
|
|
180
|
-
];
|
|
181
|
-
for (const { key, target, notProvided } of cases) {
|
|
182
|
-
await (0, promises_1.writeFile)(bundle, `exports.packageDefinition = {
|
|
183
|
-
version: "2.0.0", contracts: [${JSON.stringify(provided)}],
|
|
184
|
-
alsoImplements: new Map([[${JSON.stringify(key)}, [${JSON.stringify(target)}]]]),
|
|
185
|
-
};`);
|
|
186
|
-
for (const check of [true, false]) {
|
|
187
|
-
await expect((0, freeze_contracts_1.freezePackageContracts)({ root, bundle, check })).resolves.toMatchObject({
|
|
188
|
-
check: { changed: [], notProvided },
|
|
189
|
-
});
|
|
190
|
-
}
|
|
191
|
-
}
|
|
192
|
-
});
|
|
193
|
-
test.each([
|
|
194
|
-
"{}",
|
|
195
|
-
`new Map([[${JSON.stringify(`${contractId}@2`)}, {}]])`,
|
|
196
|
-
`new Map([[${JSON.stringify(`${contractId}@2`)}, [null]]])`,
|
|
197
|
-
`new Map([[${JSON.stringify(`${contractId}@2`)}, [{ contractId: ${JSON.stringify(contractId)}, version: 1.5 }]]])`,
|
|
198
|
-
`new Map([[${JSON.stringify(`${contractId}@2`)}, [{ contractId: ${JSON.stringify(contractId)}, version: { from: 2, to: 1 } }]]])`,
|
|
199
|
-
])("rejects malformed host alsoImplements without changing the snapshot: %s", async (aliases) => {
|
|
200
|
-
await (0, freeze_contracts_1.freezePackageContracts)({ root });
|
|
201
|
-
const file = path.join(root, "frozen-contracts.json");
|
|
202
|
-
const before = await (0, promises_1.readFile)(file, "utf8");
|
|
203
|
-
const { frozenBy: _frozenBy, ...original } = (await frozen()).contracts[0];
|
|
204
|
-
const bundle = path.join(root, "invalid-alias.bundle.js");
|
|
205
|
-
await (0, promises_1.writeFile)(bundle, `exports.packageDefinition = {
|
|
206
|
-
version: "2.0.0", contracts: [${JSON.stringify({ ...original, version: 2 })}],
|
|
207
|
-
alsoImplements: ${aliases},
|
|
208
|
-
};`);
|
|
209
|
-
for (const check of [true, false]) {
|
|
210
|
-
await expect((0, freeze_contracts_1.freezePackageContracts)({ root, bundle, check })).rejects.toThrow("Invalid alsoImplements");
|
|
211
|
-
expect(await (0, promises_1.readFile)(file, "utf8")).toBe(before);
|
|
212
|
-
}
|
|
213
|
-
});
|
|
214
|
-
test.each([
|
|
215
|
-
"",
|
|
216
|
-
"{",
|
|
217
|
-
"null",
|
|
218
|
-
"{}",
|
|
219
|
-
'{"contracts":[{}]}',
|
|
220
|
-
'{"contracts":null}',
|
|
221
|
-
])("rejects a malformed snapshot without overwriting it: %s", async (content) => {
|
|
222
|
-
const file = path.join(root, "frozen-contracts.json");
|
|
223
|
-
await (0, promises_1.writeFile)(file, content);
|
|
224
|
-
await expect((0, freeze_contracts_1.freezePackageContracts)({ root })).rejects.toThrow();
|
|
225
|
-
await expect((0, freeze_contracts_1.freezePackageContracts)({ root, check: true })).rejects.toThrow();
|
|
226
|
-
await expect((0, build_package_1.buildPackage)({ root })).rejects.toThrow();
|
|
227
|
-
expect(await (0, promises_1.readFile)(file, "utf8")).toBe(content);
|
|
228
|
-
});
|
|
229
|
-
test("rejects incomplete shapes and duplicate frozen identities", async () => {
|
|
230
|
-
await (0, freeze_contracts_1.freezePackageContracts)({ root });
|
|
231
|
-
const snapshot = await frozen();
|
|
232
|
-
const invalid = [
|
|
233
|
-
{ contracts: snapshot.contracts.map(({ version: _version, ...entry }) => entry) },
|
|
234
|
-
{ contracts: snapshot.contracts.map(({ tools: _tools, ...entry }) => entry) },
|
|
235
|
-
{ contracts: snapshot.contracts.map((entry) => ({ ...entry, tools: [{ name: "broken" }] })) },
|
|
236
|
-
{ contracts: [...snapshot.contracts, ...snapshot.contracts] },
|
|
237
|
-
];
|
|
238
|
-
for (const content of invalid) {
|
|
239
|
-
await (0, promises_1.writeFile)(path.join(root, "frozen-contracts.json"), JSON.stringify(content));
|
|
240
|
-
await expect((0, freeze_contracts_1.freezePackageContracts)({ root, check: true })).rejects.toThrow("Invalid");
|
|
241
|
-
}
|
|
242
|
-
});
|
|
243
|
-
test("accepts an empty contracts list and refuses to freeze a missing package version", async () => {
|
|
244
|
-
await (0, promises_1.writeFile)(path.join(root, "frozen-contracts.json"), '{"contracts":[]}');
|
|
245
|
-
await expect((0, freeze_contracts_1.freezePackageContracts)({ root })).resolves.toMatchObject({ written: true });
|
|
246
|
-
const snapshot = await (0, promises_1.readFile)(path.join(root, "frozen-contracts.json"), "utf8");
|
|
247
|
-
const bundle = path.join(root, "missing-version.js");
|
|
248
|
-
await (0, promises_1.writeFile)(bundle, "exports.packageDefinition = { contracts: [] };");
|
|
249
|
-
await expect((0, freeze_contracts_1.freezePackageContracts)({ root, bundle })).rejects.toThrow("no version");
|
|
250
|
-
expect(await (0, promises_1.readFile)(path.join(root, "frozen-contracts.json"), "utf8")).toBe(snapshot);
|
|
251
|
-
});
|
|
252
|
-
test("reports a newly written empty snapshot", async () => {
|
|
253
|
-
const bundle = path.join(root, "empty.js");
|
|
254
|
-
await (0, promises_1.writeFile)(bundle, 'exports.packageDefinition = { version: "1.0.0", contracts: [] };');
|
|
255
|
-
const log = jest.spyOn(console, "log").mockImplementation(() => undefined);
|
|
256
|
-
try {
|
|
257
|
-
await expect((0, cli_1.main)(["contract", "freeze", "--root", root, "--bundle", bundle])).resolves.toBe(0);
|
|
258
|
-
expect(log).toHaveBeenCalledWith(expect.stringContaining("Wrote "));
|
|
259
|
-
expect((await frozen()).contracts).toEqual([]);
|
|
260
|
-
}
|
|
261
|
-
finally {
|
|
262
|
-
log.mockRestore();
|
|
263
|
-
}
|
|
264
|
-
});
|
|
265
|
-
test("rejects malformed host definitions without creating or replacing a snapshot", async () => {
|
|
266
|
-
const bundle = path.join(root, "malformed.bundle.js");
|
|
267
|
-
await (0, promises_1.writeFile)(bundle, 'exports.packageDefinition = { version: "1.0.0", contracts: [{}] };');
|
|
268
|
-
for (const check of [true, false]) {
|
|
269
|
-
await expect((0, freeze_contracts_1.freezePackageContracts)({ root, bundle, check })).rejects.toThrow("Invalid contracts");
|
|
270
|
-
}
|
|
271
|
-
await expect((0, promises_1.readFile)(path.join(root, "frozen-contracts.json"))).rejects.toMatchObject({
|
|
272
|
-
code: "ENOENT",
|
|
273
|
-
});
|
|
274
|
-
await (0, freeze_contracts_1.freezePackageContracts)({ root });
|
|
275
|
-
const before = await (0, promises_1.readFile)(path.join(root, "frozen-contracts.json"), "utf8");
|
|
276
|
-
for (const check of [true, false]) {
|
|
277
|
-
await expect((0, freeze_contracts_1.freezePackageContracts)({ root, bundle, check })).rejects.toThrow("Invalid contracts");
|
|
278
|
-
}
|
|
279
|
-
expect(await (0, promises_1.readFile)(path.join(root, "frozen-contracts.json"), "utf8")).toBe(before);
|
|
280
|
-
});
|
|
281
|
-
test("rejects duplicate host contracts without writing and preserves unknown shape keys", async () => {
|
|
282
|
-
await (0, freeze_contracts_1.freezePackageContracts)({ root });
|
|
283
|
-
const file = path.join(root, "frozen-contracts.json");
|
|
284
|
-
const before = await (0, promises_1.readFile)(file, "utf8");
|
|
285
|
-
const { frozenBy: _frozenBy, ...original } = (await frozen()).contracts[0];
|
|
286
|
-
const changed = { ...original, tools: [] };
|
|
287
|
-
const bundle = path.join(root, "duplicate.bundle.js");
|
|
288
|
-
const writeBundle = (contracts) => (0, promises_1.writeFile)(bundle, `exports.packageDefinition = ${JSON.stringify({ version: "1.1.0", contracts })};`);
|
|
289
|
-
await writeBundle([changed, original]);
|
|
290
|
-
for (const check of [true, false]) {
|
|
291
|
-
await expect((0, freeze_contracts_1.freezePackageContracts)({ root, bundle, check })).rejects.toThrow("Duplicate provided contract");
|
|
292
|
-
}
|
|
293
|
-
expect(await (0, promises_1.readFile)(file, "utf8")).toBe(before);
|
|
294
|
-
await (0, promises_1.rm)(file);
|
|
295
|
-
await expect((0, freeze_contracts_1.freezePackageContracts)({ root, bundle })).rejects.toThrow("Duplicate provided contract");
|
|
296
|
-
await expect((0, promises_1.readFile)(file)).rejects.toMatchObject({ code: "ENOENT" });
|
|
297
|
-
const extended = {
|
|
298
|
-
...original,
|
|
299
|
-
tools: [{ ...original.tools[0], futureShape: { enabled: true } }],
|
|
300
|
-
};
|
|
301
|
-
await writeBundle([extended]);
|
|
302
|
-
await (0, freeze_contracts_1.freezePackageContracts)({ root, bundle });
|
|
303
|
-
expect((await frozen()).contracts[0].tools[0]).toMatchObject({ futureShape: { enabled: true } });
|
|
304
|
-
await writeBundle([
|
|
305
|
-
{ ...extended, tools: [{ ...extended.tools[0], futureShape: { enabled: false } }] },
|
|
306
|
-
]);
|
|
307
|
-
expect((await (0, freeze_contracts_1.freezePackageContracts)({ root, bundle, check: true })).check.changed).toHaveLength(1);
|
|
308
|
-
});
|
|
309
|
-
test("reads a host-backed package's CommonJS bundle, with the SDK and zod as externals", async () => {
|
|
310
|
-
const bundle = path.join(root, "legacy.bundle.js");
|
|
311
|
-
const tool = (fields) => `{
|
|
312
|
-
tool: {
|
|
313
|
-
toolId: ${JSON.stringify((0, peer_id_1.newid)())}, name: "act", code: "", usageDescription: "Act.",
|
|
314
|
-
inputSchema: { type: "complex", fields: ${fields} },
|
|
315
|
-
outputSchema: { type: "complex", fields: [] },
|
|
316
|
-
},
|
|
317
|
-
}`;
|
|
318
|
-
const legacy = (version, fields) => `
|
|
319
|
-
const { definePackage } = require("PeersSDK");
|
|
320
|
-
require("zod");
|
|
321
|
-
exports.packageDefinition = definePackage((pkg) => {
|
|
322
|
-
pkg.packageId = ${JSON.stringify(packageId)};
|
|
323
|
-
pkg.version = ${JSON.stringify(version)};
|
|
324
|
-
const contract = pkg.contract(${JSON.stringify(contractId)}, 1, "Legacy", "A legacy contract.");
|
|
325
|
-
contract.tools = [${tool(fields)}];
|
|
326
|
-
});
|
|
327
|
-
`;
|
|
328
|
-
await (0, promises_1.writeFile)(bundle, legacy("0.5.0", '[{ name: "value", type: "string" }]'));
|
|
329
|
-
await expect((0, freeze_contracts_1.freezePackageContracts)({ root, bundle })).resolves.toMatchObject({
|
|
330
|
-
packageVersion: "0.5.0",
|
|
331
|
-
added: [expect.objectContaining({ name: "Legacy", version: 1, frozenBy: "0.5.0" })],
|
|
332
|
-
});
|
|
333
|
-
expect((await frozen()).contracts[0]).not.toHaveProperty("devTag");
|
|
334
|
-
await (0, promises_1.writeFile)(bundle, legacy("0.6.0", '[{ name: "value", type: "number" }]'));
|
|
335
|
-
const checked = await (0, freeze_contracts_1.freezePackageContracts)({ root, bundle, check: true });
|
|
336
|
-
expect(checked.check.changed.map(({ changes }) => changes)).toEqual([["tool act changed"]]);
|
|
337
|
-
// v2 also implementing v1 still serves it; without that, v1 is no longer provided.
|
|
338
|
-
const upgraded = (alsoImplements) => `
|
|
339
|
-
const { definePackage } = require("PeersSDK");
|
|
340
|
-
exports.packageDefinition = definePackage((pkg) => {
|
|
341
|
-
pkg.packageId = ${JSON.stringify(packageId)};
|
|
342
|
-
pkg.version = "1.0.0";
|
|
343
|
-
const contract = pkg.contract(${JSON.stringify(contractId)}, 2, "Legacy", "A legacy contract.");
|
|
344
|
-
contract.tools = [${tool('[{ name: "value", type: "string" }]')}];
|
|
345
|
-
${alsoImplements}
|
|
346
|
-
});
|
|
347
|
-
`;
|
|
348
|
-
await (0, promises_1.writeFile)(bundle, upgraded(`contract.alsoImplements(${JSON.stringify(contractId)}, 1);`));
|
|
349
|
-
await expect((0, freeze_contracts_1.freezePackageContracts)({ root, bundle, check: true })).resolves.toMatchObject({
|
|
350
|
-
check: { changed: [], notProvided: [] },
|
|
351
|
-
});
|
|
352
|
-
await (0, promises_1.writeFile)(bundle, upgraded(""));
|
|
353
|
-
const dropped = await (0, freeze_contracts_1.freezePackageContracts)({ root, bundle, check: true });
|
|
354
|
-
expect(dropped.check.notProvided.map(({ version }) => version)).toEqual([1]);
|
|
355
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1,200 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const keys_1 = require("../keys");
|
|
4
|
-
const utils_1 = require("../utils");
|
|
5
|
-
const package_author_signing_1 = require("./package-author-signing");
|
|
6
|
-
function makePV(overrides) {
|
|
7
|
-
return {
|
|
8
|
-
packageId: (0, utils_1.newid)(),
|
|
9
|
-
packageVersionId: (0, utils_1.newid)(),
|
|
10
|
-
version: "1.2.3",
|
|
11
|
-
versionTag: "stable",
|
|
12
|
-
packageBundleFileHash: "abc123hash",
|
|
13
|
-
routesBundleFileHash: "routes456hash",
|
|
14
|
-
uiBundleFileHash: "ui789hash",
|
|
15
|
-
...overrides,
|
|
16
|
-
};
|
|
17
|
-
}
|
|
18
|
-
describe("package-author-signing", () => {
|
|
19
|
-
const keys = (0, keys_1.newKeys)();
|
|
20
|
-
describe("PACKAGE_SIGNING_KEY_PREFIX", () => {
|
|
21
|
-
it("has the expected value", () => {
|
|
22
|
-
expect(package_author_signing_1.PACKAGE_SIGNING_KEY_PREFIX).toBe("packageSigningKey_");
|
|
23
|
-
});
|
|
24
|
-
});
|
|
25
|
-
describe("buildAuthorSignedPayload", () => {
|
|
26
|
-
it("extracts the correct fields from a PV", () => {
|
|
27
|
-
const pv = makePV();
|
|
28
|
-
const payload = (0, package_author_signing_1.buildAuthorSignedPayload)(pv, keys.publicKey);
|
|
29
|
-
expect(payload).toEqual({
|
|
30
|
-
packageId: pv.packageId,
|
|
31
|
-
packageVersionId: pv.packageVersionId,
|
|
32
|
-
version: "1.2.3",
|
|
33
|
-
versionTag: "stable",
|
|
34
|
-
packageBundleFileHash: "abc123hash",
|
|
35
|
-
routesBundleFileHash: "routes456hash",
|
|
36
|
-
uiBundleFileHash: "ui789hash",
|
|
37
|
-
publicKey: keys.publicKey,
|
|
38
|
-
});
|
|
39
|
-
});
|
|
40
|
-
it("omits optional hash fields when undefined", () => {
|
|
41
|
-
const pv = makePV({ routesBundleFileHash: undefined, uiBundleFileHash: undefined });
|
|
42
|
-
const payload = (0, package_author_signing_1.buildAuthorSignedPayload)(pv, keys.publicKey);
|
|
43
|
-
expect(payload).not.toHaveProperty("routesBundleFileHash");
|
|
44
|
-
expect(payload).not.toHaveProperty("uiBundleFileHash");
|
|
45
|
-
expect(payload.packageBundleFileHash).toBe("abc123hash");
|
|
46
|
-
});
|
|
47
|
-
it("omits uiBundleFileHash but includes routesBundleFileHash when only ui is undefined", () => {
|
|
48
|
-
const pv = makePV({ uiBundleFileHash: undefined });
|
|
49
|
-
const payload = (0, package_author_signing_1.buildAuthorSignedPayload)(pv, keys.publicKey);
|
|
50
|
-
expect(payload.routesBundleFileHash).toBe("routes456hash");
|
|
51
|
-
expect(payload).not.toHaveProperty("uiBundleFileHash");
|
|
52
|
-
});
|
|
53
|
-
it("treats empty string versionTag the same as undefined", () => {
|
|
54
|
-
const pv = makePV({ versionTag: undefined });
|
|
55
|
-
const payload = (0, package_author_signing_1.buildAuthorSignedPayload)(pv, keys.publicKey);
|
|
56
|
-
expect(payload.versionTag).toBe("");
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
describe("signPackageAuthor + verifyPackageAuthorSignature round-trip", () => {
|
|
60
|
-
it("produces a valid signature that verifies", () => {
|
|
61
|
-
const pv = makePV();
|
|
62
|
-
const signature = (0, package_author_signing_1.signPackageAuthor)(pv, keys.secretKey);
|
|
63
|
-
expect(typeof signature).toBe("string");
|
|
64
|
-
expect(signature.length).toBeGreaterThan(0);
|
|
65
|
-
const result = (0, package_author_signing_1.verifyPackageAuthorSignature)({ ...pv, packageAuthorSignature: signature }, keys.publicKey);
|
|
66
|
-
expect(result.valid).toBe(true);
|
|
67
|
-
expect(result.publicKey).toBe(keys.publicKey);
|
|
68
|
-
});
|
|
69
|
-
it("works with only the required bundle hash (no routes or ui)", () => {
|
|
70
|
-
const pv = makePV({ routesBundleFileHash: undefined, uiBundleFileHash: undefined });
|
|
71
|
-
const signature = (0, package_author_signing_1.signPackageAuthor)(pv, keys.secretKey);
|
|
72
|
-
const result = (0, package_author_signing_1.verifyPackageAuthorSignature)({ ...pv, packageAuthorSignature: signature }, keys.publicKey);
|
|
73
|
-
expect(result.valid).toBe(true);
|
|
74
|
-
});
|
|
75
|
-
it("works with undefined versionTag", () => {
|
|
76
|
-
const pv = makePV({ versionTag: undefined });
|
|
77
|
-
const signature = (0, package_author_signing_1.signPackageAuthor)(pv, keys.secretKey);
|
|
78
|
-
const result = (0, package_author_signing_1.verifyPackageAuthorSignature)({ ...pv, packageAuthorSignature: signature }, keys.publicKey);
|
|
79
|
-
expect(result.valid).toBe(true);
|
|
80
|
-
});
|
|
81
|
-
});
|
|
82
|
-
describe("verification fails on tampered fields", () => {
|
|
83
|
-
const pv = makePV();
|
|
84
|
-
let signature;
|
|
85
|
-
beforeAll(() => {
|
|
86
|
-
signature = (0, package_author_signing_1.signPackageAuthor)(pv, keys.secretKey);
|
|
87
|
-
});
|
|
88
|
-
it("fails when packageBundleFileHash is changed", () => {
|
|
89
|
-
const tampered = {
|
|
90
|
-
...pv,
|
|
91
|
-
packageBundleFileHash: "tampered",
|
|
92
|
-
packageAuthorSignature: signature,
|
|
93
|
-
};
|
|
94
|
-
const result = (0, package_author_signing_1.verifyPackageAuthorSignature)(tampered, keys.publicKey);
|
|
95
|
-
expect(result.valid).toBe(false);
|
|
96
|
-
});
|
|
97
|
-
it("fails when version is changed", () => {
|
|
98
|
-
const tampered = { ...pv, version: "9.9.9", packageAuthorSignature: signature };
|
|
99
|
-
const result = (0, package_author_signing_1.verifyPackageAuthorSignature)(tampered, keys.publicKey);
|
|
100
|
-
expect(result.valid).toBe(false);
|
|
101
|
-
});
|
|
102
|
-
it("fails when versionTag is changed", () => {
|
|
103
|
-
const tampered = { ...pv, versionTag: "beta", packageAuthorSignature: signature };
|
|
104
|
-
const result = (0, package_author_signing_1.verifyPackageAuthorSignature)(tampered, keys.publicKey);
|
|
105
|
-
expect(result.valid).toBe(false);
|
|
106
|
-
});
|
|
107
|
-
it("fails when packageId is changed", () => {
|
|
108
|
-
const tampered = { ...pv, packageId: (0, utils_1.newid)(), packageAuthorSignature: signature };
|
|
109
|
-
const result = (0, package_author_signing_1.verifyPackageAuthorSignature)(tampered, keys.publicKey);
|
|
110
|
-
expect(result.valid).toBe(false);
|
|
111
|
-
});
|
|
112
|
-
it("fails when packageVersionId is changed", () => {
|
|
113
|
-
const tampered = { ...pv, packageVersionId: (0, utils_1.newid)(), packageAuthorSignature: signature };
|
|
114
|
-
const result = (0, package_author_signing_1.verifyPackageAuthorSignature)(tampered, keys.publicKey);
|
|
115
|
-
expect(result.valid).toBe(false);
|
|
116
|
-
});
|
|
117
|
-
it("fails when routesBundleFileHash is changed", () => {
|
|
118
|
-
const tampered = {
|
|
119
|
-
...pv,
|
|
120
|
-
routesBundleFileHash: "tampered",
|
|
121
|
-
packageAuthorSignature: signature,
|
|
122
|
-
};
|
|
123
|
-
const result = (0, package_author_signing_1.verifyPackageAuthorSignature)(tampered, keys.publicKey);
|
|
124
|
-
expect(result.valid).toBe(false);
|
|
125
|
-
});
|
|
126
|
-
it("fails when uiBundleFileHash is changed", () => {
|
|
127
|
-
const tampered = { ...pv, uiBundleFileHash: "tampered", packageAuthorSignature: signature };
|
|
128
|
-
const result = (0, package_author_signing_1.verifyPackageAuthorSignature)(tampered, keys.publicKey);
|
|
129
|
-
expect(result.valid).toBe(false);
|
|
130
|
-
});
|
|
131
|
-
it("fails when a signed createdBy is changed", () => {
|
|
132
|
-
const signed = makePV({ createdBy: "00author0000000000000000a" });
|
|
133
|
-
const signedSignature = (0, package_author_signing_1.signPackageAuthor)(signed, keys.secretKey);
|
|
134
|
-
const tampered = {
|
|
135
|
-
...signed,
|
|
136
|
-
createdBy: "00attacker000000000000000a",
|
|
137
|
-
packageAuthorSignature: signedSignature,
|
|
138
|
-
};
|
|
139
|
-
const result = (0, package_author_signing_1.verifyPackageAuthorSignature)(tampered, keys.publicKey);
|
|
140
|
-
expect(result.valid).toBe(false);
|
|
141
|
-
});
|
|
142
|
-
});
|
|
143
|
-
describe("verification fails with wrong key", () => {
|
|
144
|
-
it("rejects when verified against a different key", () => {
|
|
145
|
-
const pv = makePV();
|
|
146
|
-
const signature = (0, package_author_signing_1.signPackageAuthor)(pv, keys.secretKey);
|
|
147
|
-
const otherKeys = (0, keys_1.newKeys)();
|
|
148
|
-
const result = (0, package_author_signing_1.verifyPackageAuthorSignature)({ ...pv, packageAuthorSignature: signature }, otherKeys.publicKey);
|
|
149
|
-
expect(result.valid).toBe(false);
|
|
150
|
-
});
|
|
151
|
-
});
|
|
152
|
-
describe("TOFU enforcement via expectedPublicKey", () => {
|
|
153
|
-
it("succeeds when expectedPublicKey matches the signer", () => {
|
|
154
|
-
const pv = makePV();
|
|
155
|
-
const signature = (0, package_author_signing_1.signPackageAuthor)(pv, keys.secretKey);
|
|
156
|
-
const result = (0, package_author_signing_1.verifyPackageAuthorSignature)({ ...pv, packageAuthorSignature: signature }, keys.publicKey);
|
|
157
|
-
expect(result.valid).toBe(true);
|
|
158
|
-
expect(result.publicKey).toBe(keys.publicKey);
|
|
159
|
-
});
|
|
160
|
-
it("fails when expectedPublicKey does not match the signer", () => {
|
|
161
|
-
const pv = makePV();
|
|
162
|
-
const signature = (0, package_author_signing_1.signPackageAuthor)(pv, keys.secretKey);
|
|
163
|
-
const differentKey = (0, keys_1.newKeys)().publicKey;
|
|
164
|
-
const result = (0, package_author_signing_1.verifyPackageAuthorSignature)({ ...pv, packageAuthorSignature: signature }, differentKey);
|
|
165
|
-
expect(result.valid).toBe(false);
|
|
166
|
-
});
|
|
167
|
-
});
|
|
168
|
-
describe("edge cases", () => {
|
|
169
|
-
it("returns invalid when packageAuthorSignature is undefined", () => {
|
|
170
|
-
const pv = makePV();
|
|
171
|
-
const result = (0, package_author_signing_1.verifyPackageAuthorSignature)({ ...pv, packageAuthorSignature: undefined }, keys.publicKey);
|
|
172
|
-
expect(result.valid).toBe(false);
|
|
173
|
-
});
|
|
174
|
-
it("returns invalid when packageAuthorSignature is malformed", () => {
|
|
175
|
-
const pv = makePV();
|
|
176
|
-
const result = (0, package_author_signing_1.verifyPackageAuthorSignature)({ ...pv, packageAuthorSignature: "not-a-valid-signature!!!" }, keys.publicKey);
|
|
177
|
-
expect(result.valid).toBe(false);
|
|
178
|
-
});
|
|
179
|
-
it("returns invalid when expectedPublicKey is malformed", () => {
|
|
180
|
-
const pv = makePV();
|
|
181
|
-
const signature = (0, package_author_signing_1.signPackageAuthor)(pv, keys.secretKey);
|
|
182
|
-
const result = (0, package_author_signing_1.verifyPackageAuthorSignature)({ ...pv, packageAuthorSignature: signature }, "not-a-valid-key");
|
|
183
|
-
expect(result.valid).toBe(false);
|
|
184
|
-
});
|
|
185
|
-
it("signature is deterministic for same inputs", () => {
|
|
186
|
-
const pv = makePV();
|
|
187
|
-
const sig1 = (0, package_author_signing_1.signPackageAuthor)(pv, keys.secretKey);
|
|
188
|
-
const sig2 = (0, package_author_signing_1.signPackageAuthor)(pv, keys.secretKey);
|
|
189
|
-
expect(sig1).toBe(sig2);
|
|
190
|
-
});
|
|
191
|
-
it("derives the correct public key from the secret key", () => {
|
|
192
|
-
const pv = makePV();
|
|
193
|
-
const signature = (0, package_author_signing_1.signPackageAuthor)(pv, keys.secretKey);
|
|
194
|
-
const derived = (0, keys_1.hydrateKeys)(keys.secretKey);
|
|
195
|
-
expect(derived.publicKey).toBe(keys.publicKey);
|
|
196
|
-
const result = (0, package_author_signing_1.verifyPackageAuthorSignature)({ ...pv, packageAuthorSignature: signature }, derived.publicKey);
|
|
197
|
-
expect(result.valid).toBe(true);
|
|
198
|
-
});
|
|
199
|
-
});
|
|
200
|
-
});
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|