Skip to content

Commit 5e53b6a

Browse files
authored
feat(hex): Add protobuf definitions for registry v2 support (#32222)
1 parent 9faae86 commit 5e53b6a

File tree

7 files changed

+742
-1
lines changed

7 files changed

+742
-1
lines changed
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
import protobuf from 'protobufjs';
2+
import upath from 'upath';
3+
import { Package } from './package';
4+
import { Signed } from './signed';
5+
6+
function protobufLoad(file: string): Promise<protobuf.Root> {
7+
const resolvedFile = upath.join(__dirname, file);
8+
return new Promise((resolve, reject) => {
9+
protobuf.load(resolvedFile, (err, root) => {
10+
if (err) {
11+
reject(err);
12+
return;
13+
}
14+
15+
if (!root) {
16+
reject(new Error('Root is empty'));
17+
return;
18+
}
19+
20+
resolve(root);
21+
});
22+
});
23+
}
24+
25+
describe('modules/datasource/hex/v2/index', () => {
26+
describe('Signed', () => {
27+
async function encodeSigned(input: unknown): Promise<Buffer> {
28+
const message = Signed.fromJSON(input);
29+
const root = await protobufLoad('signed.proto');
30+
const x = root.lookupType('Signed').encode(message).finish();
31+
return Buffer.from(x);
32+
}
33+
34+
it('roundtrip', async () => {
35+
const input = {
36+
payload: Buffer.from('foo'),
37+
signature: Buffer.from('bar'),
38+
};
39+
const encodedBuf = await encodeSigned(input);
40+
41+
const output = Signed.decode(encodedBuf);
42+
43+
expect(output).toEqual(input);
44+
});
45+
});
46+
47+
describe('Package', () => {
48+
async function encodePackage(input: unknown): Promise<Buffer> {
49+
const message = Package.fromJSON(input);
50+
const root = await protobufLoad('package.proto');
51+
const x = root.lookupType('Package').encode(message).finish();
52+
return Buffer.from(x);
53+
}
54+
55+
it('roundtrip', async () => {
56+
const input: Package = {
57+
name: 'foo',
58+
repository: 'hexpm',
59+
releases: [
60+
{
61+
version: '1.0.0',
62+
innerChecksum: new Uint8Array(),
63+
dependencies: [],
64+
},
65+
{
66+
version: '2.0.0',
67+
innerChecksum: new Uint8Array(),
68+
dependencies: [],
69+
},
70+
{
71+
version: '3.0.0',
72+
innerChecksum: new Uint8Array(),
73+
dependencies: [],
74+
},
75+
],
76+
};
77+
const encodedBuf = await encodePackage(input);
78+
79+
const output = Package.decode(encodedBuf);
80+
81+
expect(output).toMatchObject({
82+
name: 'foo',
83+
repository: 'hexpm',
84+
releases: [
85+
{ version: '1.0.0' },
86+
{ version: '2.0.0' },
87+
{ version: '3.0.0' },
88+
],
89+
});
90+
});
91+
});
92+
});
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
// https://github.com/hexpm/specifications/blob/9c411dbe96c87ccee438d40838d02b5fa6abb60b/registry/package.proto
2+
3+
syntax = "proto2";
4+
5+
message Package {
6+
// All releases of the package
7+
repeated Release releases = 1;
8+
// Name of package
9+
required string name = 2;
10+
// Name of repository
11+
required string repository = 3;
12+
}
13+
14+
message Release {
15+
// Release version
16+
required string version = 1;
17+
// sha256 checksum of "inner" package tarball
18+
// deprecated in favor of outer_checksum
19+
required bytes inner_checksum = 2;
20+
// All dependencies of the release
21+
repeated Dependency dependencies = 3;
22+
// If set the release is retired, a retired release should only be
23+
// resolved if it has already been locked in a project
24+
optional RetirementStatus retired = 4;
25+
// sha256 checksum of outer package tarball
26+
// required when encoding but optional when decoding
27+
optional bytes outer_checksum = 5;
28+
}
29+
30+
message RetirementStatus {
31+
required RetirementReason reason = 1;
32+
optional string message = 2;
33+
}
34+
35+
enum RetirementReason {
36+
RETIRED_OTHER = 0;
37+
RETIRED_INVALID = 1;
38+
RETIRED_SECURITY = 2;
39+
RETIRED_DEPRECATED = 3;
40+
RETIRED_RENAMED = 4;
41+
}
42+
43+
message Dependency {
44+
// Package name of dependency
45+
required string package = 1;
46+
// Version requirement of dependency
47+
required string requirement = 2;
48+
// If set and true the package is optional (see dependency resolution)
49+
optional bool optional = 3;
50+
// If set is the OTP application name of the dependency, if not set the
51+
// application name is the same as the package name
52+
optional string app = 4;
53+
// If set, the repository where the dependency is located
54+
optional string repository = 5;
55+
}

0 commit comments

Comments
 (0)