Skip to content

Commit ede2b62

Browse files
authored
Ws (#20)
* [CHANGE] websocket transport is part of core * [CI] changed module version generation/validation to be a ts file * [TEST] added WS default connection test, added fixme for sanitizers.
1 parent 970427e commit ede2b62

27 files changed

+681
-184
lines changed

Diff for: bin/check-bundle-version.ts

+208-71
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,148 @@
11
#!/usr/bin/env -S deno run -A
2-
/*
3-
* Copyright 2021-2024 The NATS Authors
4-
* Licensed under the Apache License, Version 2.0 (the "License");
5-
* you may not use this file except in compliance with the License.
6-
* You may obtain a copy of the License at
7-
*
8-
* http://www.apache.org/licenses/LICENSE-2.0
9-
*
10-
* Unless required by applicable law or agreed to in writing, software
11-
* distributed under the License is distributed on an "AS IS" BASIS,
12-
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13-
* See the License for the specific language governing permissions and
14-
* limitations under the License.
15-
*/
16-
172
import { parseArgs } from "jsr:@std/cli/parse-args";
183
import { join } from "jsr:@std/path";
194

20-
async function load(fp: string): Promise<{ version: string }> {
21-
const src = await Deno.readTextFile(fp);
5+
class ModuleVersions {
6+
file?: SemVer;
7+
deno?: SemVer;
8+
node?: SemVer;
9+
10+
constructor() {
11+
}
12+
13+
max(): SemVer | null {
14+
const vers = this.versions();
15+
let vv: SemVer | null = null;
16+
vers.forEach((v) => {
17+
vv = vv == null ? v : vv.max(v);
18+
});
19+
return vv;
20+
}
21+
22+
versions(): SemVer[] {
23+
const vers = [];
24+
if (this.file) {
25+
vers.push(this.file);
26+
}
27+
if (this.deno) {
28+
vers.push(this.deno);
29+
}
30+
if (this.node) {
31+
vers.push(this.node);
32+
}
33+
return vers;
34+
}
35+
36+
check() {
37+
const m = this.max();
38+
if (m !== null) {
39+
this.versions().forEach((v) => {
40+
if (m.compare(v) !== 0) {
41+
throw new Error("different versions found");
42+
}
43+
});
44+
}
45+
}
46+
}
47+
48+
class SemVer {
49+
major: number;
50+
minor: number;
51+
micro: number;
52+
qualifier: string;
53+
54+
constructor(v: string) {
55+
const m = v.match(/(\d+).(\d+).(\d+)(-{1}(.+))?/);
56+
if (m) {
57+
this.major = parseInt(m[1]);
58+
this.minor = parseInt(m[2]);
59+
this.micro = parseInt(m[3]);
60+
this.qualifier = m[5] ? m[5] : "";
61+
} else {
62+
throw new Error(`'${v}' is not a semver value`);
63+
}
64+
}
65+
66+
compare(b: SemVer): number {
67+
if (this.major < b.major) return -1;
68+
if (this.major > b.major) return 1;
69+
if (this.minor < b.minor) return -1;
70+
if (this.minor > b.minor) return 1;
71+
if (this.micro < b.micro) return -1;
72+
if (this.micro > b.micro) return 1;
73+
if (this.qualifier === "") return 1;
74+
if (b.qualifier === "") return -1;
75+
return this.qualifier.localeCompare(b.qualifier);
76+
}
77+
78+
max(b: SemVer): SemVer {
79+
return this.compare(b) > 0 ? this : b;
80+
}
81+
82+
string(): string {
83+
return `${this.major}.${this.minor}.${this.micro}` +
84+
(this.qualifier ? `-${this.qualifier}` : "");
85+
}
86+
}
87+
88+
async function loadVersionFile(module: string): Promise<string> {
89+
const { version } = await import(
90+
join(Deno.cwd(), module, "src", "version.ts")
91+
).catch(() => {
92+
return "";
93+
});
94+
return version;
95+
}
96+
97+
async function loadPackageFile(fp: string): Promise<{ version: string }> {
98+
const src = await Deno.readTextFile(fp)
99+
.catch(() => {
100+
return JSON.stringify({ version: "" });
101+
});
22102
return JSON.parse(src);
23103
}
24104

105+
async function loadVersions(module: string): Promise<ModuleVersions> {
106+
const v = new ModuleVersions();
107+
const file = await loadVersionFile(module);
108+
if (file) {
109+
v.file = new SemVer(file);
110+
}
111+
112+
const { version: deno } = await loadPackageFile(
113+
join(Deno.cwd(), module, "deno.json"),
114+
);
115+
if (deno) {
116+
v.deno = new SemVer(deno);
117+
}
118+
119+
const { version: node } = await loadPackageFile(
120+
join(Deno.cwd(), module, "package.json"),
121+
);
122+
if (node) {
123+
v.node = new SemVer(node);
124+
}
125+
return v;
126+
}
127+
128+
async function fixPackageVersion(fp: string, version: SemVer): Promise<void> {
129+
const d = JSON.parse(await Deno.readTextFile(fp));
130+
d.version = version.string();
131+
return Deno.writeTextFile(
132+
fp,
133+
JSON.stringify(d, null, 2),
134+
);
135+
}
136+
137+
async function fixVersionFile(module: string, version: SemVer): Promise<void> {
138+
await Deno.writeTextFile(
139+
join(module, "src", "version.ts"),
140+
`// This file is generated - do not edit
141+
export const version = "${version.string()}";
142+
`,
143+
);
144+
}
145+
25146
const argv = parseArgs(
26147
Deno.args,
27148
{
@@ -44,70 +165,86 @@ if (module === null) {
44165
Deno.exit(1);
45166
}
46167

47-
let version: string;
48-
49-
if (module.startsWith("transport-")) {
50-
let packageVersion: { version: string } | undefined;
51-
const versionFilePath = join(module, "src", "version.json");
52-
let versionFile = await load(versionFilePath);
53-
switch (module) {
54-
case "transport-node":
55-
packageVersion = await load(join(module, "package.json"));
56-
break;
57-
default:
58-
packageVersion = await load(join(module, "deno.json"));
59-
break;
60-
}
61-
if (!packageVersion) {
62-
console.error(
63-
`[ERROR] package version for module ${module} is missing a version`,
64-
);
65-
Deno.exit(1);
66-
}
67-
if (!versionFile) {
68-
console.error(
69-
`[ERROR] src/version.json file for module ${module} is missing a version`,
70-
);
71-
Deno.exit(1);
72-
}
73-
if (packageVersion.version !== versionFile.version) {
168+
const versions = await loadVersions(module);
169+
console.log(versions);
170+
171+
switch (module) {
172+
case "transport-deno":
173+
// no node
174+
if (!versions.deno) {
175+
console.error(`[ERROR] deno.json for ${module} is missing`);
176+
Deno.exit(1);
177+
}
178+
break;
179+
case "transport-node":
180+
if (!versions.node) {
181+
console.error(`[ERROR] package.json for ${module} is missing`);
182+
Deno.exit(1);
183+
}
184+
break;
185+
case "core":
186+
if (!versions.deno) {
187+
console.error(`[ERROR] deno.json for ${module} is missing`);
188+
Deno.exit(1);
189+
}
190+
if (!versions.node) {
191+
console.error(`[ERROR] package.json for ${module} is missing`);
192+
Deno.exit(1);
193+
}
194+
if (!versions.file) {
195+
console.error(`[ERROR] version.json for ${module} is missing`);
196+
Deno.exit(1);
197+
}
198+
break;
199+
default:
200+
if (!versions.deno) {
201+
console.error(`[ERROR] deno.json for ${module} is missing`);
202+
Deno.exit(1);
203+
}
204+
if (!versions.node) {
205+
console.error(`[ERROR] package.json for ${module} is missing`);
206+
Deno.exit(1);
207+
}
208+
}
209+
210+
const version = versions.max()!;
211+
212+
try {
213+
versions.check();
214+
} catch (_) {
215+
if (versions.file && version.compare(versions.file) !== 0) {
74216
if (argv.fix) {
75-
versionFile = { version: packageVersion.version };
76-
await Deno.writeTextFile(
77-
versionFilePath,
78-
JSON.stringify(versionFile, null, 2),
217+
await fixVersionFile(module, versions.max()!);
218+
console.error(
219+
`[OK] fixed src/version.ts file for module ${module}.`,
79220
);
80-
console.log(
81-
`[OK] updated ${versionFilePath} to ${packageVersion.version}`,
221+
} else {
222+
console.error(
223+
`[ERROR] src/version.ts file for module ${module} has an inconsistent version.`,
82224
);
83-
Deno.exit(0);
225+
Deno.exit(1);
84226
}
85-
console.error(
86-
`[ERROR] expected versions to match - package: ${packageVersion.version} src/version.json: ${versionFile.version}`,
87-
);
88-
Deno.exit(1);
89227
}
90-
version = versionFile.version;
91-
} else {
92-
const deno = await load(join(module, "deno.json"));
93-
version = deno.version;
94-
const nodePackagePath = join(module, "package.json");
95-
const node = await load(nodePackagePath);
96-
97-
if (deno.version !== node.version) {
228+
if (versions.node && version.compare(versions.node) !== 0) {
229+
if (argv.fix) {
230+
await fixPackageVersion(join(module, "package.json"), versions.max()!);
231+
} else {
232+
console.error(
233+
`[ERROR] package.json file for module ${module} has an inconsistent version.`,
234+
);
235+
Deno.exit(1);
236+
}
237+
}
238+
if (versions.deno && version.compare(versions.deno) !== 0) {
98239
if (argv.fix) {
99-
node.version = deno.version;
100-
await Deno.writeTextFile(nodePackagePath, JSON.stringify(node, null, 2));
101-
console.log(`[OK] updated ${nodePackagePath} to ${deno.version}`);
102-
Deno.exit(0);
240+
await fixPackageVersion(join(module, "deno.json"), versions.max()!);
103241
} else {
104242
console.error(
105-
`[ERROR] expected versions to match - deno.json: ${deno.version} package.json: ${node.version}`,
243+
`[ERROR] deno.json file for module ${module} has an inconsistent version.`,
106244
);
107245
Deno.exit(1);
108246
}
109247
}
110-
node.version = deno.version;
111248
}
112249

113250
if (argv.tag) {
@@ -116,12 +253,12 @@ if (argv.tag) {
116253
if (tag.startsWith(prefix)) {
117254
tag = tag.substring(prefix.length);
118255
}
119-
if (tag !== version!) {
256+
if (tag !== version.string()) {
120257
console.error(
121258
`[ERROR] expected tag version to match - bundle: ${version!} tag: ${argv.tag}}`,
122259
);
123260
Deno.exit(1);
124261
}
125262
}
126-
console.log(`[OK] ${module} version ${version!}`);
263+
console.log(`[OK] ${module} version ${version.string()}`);
127264
Deno.exit(0);

Diff for: core/deno.json

+12-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@nats-io/nats-core",
3-
"version": "3.0.0-17",
3+
"version": "3.0.0-18",
44
"exports": {
55
".": "./src/mod.ts",
66
"./internal": "./src/internal_mod.ts"
@@ -11,9 +11,19 @@
1111
"./unsafe_tests/**/*"
1212
]
1313
},
14+
"lint": {
15+
"exclude": [
16+
"lib/"
17+
]
18+
},
19+
"fmt": {
20+
"exclude": [
21+
"lib/"
22+
]
23+
},
1424
"tasks": {
1525
"clean": "rm -rf ./lib ./cjs ./esm",
16-
"test": "deno test -A --parallel --reload --quiet tests/ --import-map=./import_map.json"
26+
"test": "deno test -A --parallel --reload tests/ --import-map=./import_map.json"
1727
},
1828
"imports": {
1929
"@nats-io/nkeys": "jsr:@nats-io/[email protected]",

Diff for: core/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@nats-io/nats-core",
3-
"version": "3.0.0-17",
3+
"version": "3.0.0-18",
44
"files": [
55
"lib/",
66
"build/src/"

Diff for: core/src/internal_mod.ts

+17
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,18 @@
1+
/*
2+
* Copyright 2024 The NATS Authors
3+
* Licensed under the Apache License, Version 2.0 (the "License");
4+
* you may not use this file except in compliance with the License.
5+
* You may obtain a copy of the License at
6+
*
7+
* http://www.apache.org/licenses/LICENSE-2.0
8+
*
9+
* Unless required by applicable law or agreed to in writing, software
10+
* distributed under the License is distributed on an "AS IS" BASIS,
11+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
* See the License for the specific language governing permissions and
13+
* limitations under the License.
14+
*/
15+
116
export { NatsConnectionImpl } from "./nats.ts";
217
export { Nuid, nuid } from "./nuid.ts";
318

@@ -127,3 +142,5 @@ export { isIPV4OrHostname, Servers } from "./servers.ts";
127142
export { Base64Codec, Base64UrlCodec, Base64UrlPaddedCodec } from "./base64.ts";
128143

129144
export { SHA256 } from "./sha256.ts";
145+
146+
export { wsconnect, wsUrlParseFn } from "./ws_transport.ts";

0 commit comments

Comments
 (0)