Skip to content

Commit 80a1835

Browse files
committed
Migrate to Deno 2
- Use deno.jsonc instead of import map - Replace deprecated functions Deno.emit() with the original typescript compiler - Replace deprecated Deno.run() with Deno.Command()
1 parent 6b26546 commit 80a1835

31 files changed

+4601
-4729
lines changed

.src/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ moment.
1111
## Building
1212

1313
```sh
14-
deno run -A --import-map=import_map.json --unstable ./.src/build.ts
14+
deno run -A .src/build.ts
1515
```
1616

1717
By default, the build script will skip building drafts that have no
1818
modifications to their `definition.ts` file. If you need to force a rebuild, add
1919
`--force` onto the end of the build command:
2020

2121
```sh
22-
deno run -A --import-map=import_map.json --unstable ./.src/build.ts --force
22+
deno run -A .src/build.ts --force
2323
```
2424

2525
## Adding a new draft

.src/build.ts

Lines changed: 29 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,14 @@
1-
import * as fs from "std/fs/mod.ts";
2-
import * as path from "std/path/mod.ts";
1+
import * as fs from "@std/fs";
2+
import * as path from "@std/path";
33
import type * as types from "./types.ts";
44
import { expandSourcePlaceholders } from "./utils/source_code.ts";
55
import { formatMarkdown } from "./utils/format_markdown.ts";
66
import { formatDefinitionDescriptions } from "./utils/format_definition_descriptions.ts";
77
import { fileChecksum } from "./utils/checksum.ts";
8-
import checksums from "./checksums.json" assert { type: "json" };
8+
import { compileTypeScript } from "./tsc.ts";
9+
import checksums from "./checksums.json" with { type: "json" };
910
import { VERSION } from "./version.ts";
10-
import packageJson from "../dist/node/package.json" assert { type: "json" };
11+
import packageJson from "../dist/node/package.json" with { type: "json" };
1112

1213
// -----------------------------------------------------------------------------
1314

@@ -50,7 +51,6 @@ drafts.sort((a, b) => a.localeCompare(b));
5051
// Process each draft
5152

5253
for (const draftId of drafts) {
53-
const nodeDraftId = draftId.replaceAll("_", "-");
5454
const draftDir = path.join(SRC_DIR, "draft", draftId);
5555
const draftDefFilename = path.join(draftDir, "definition.ts");
5656
const draftDefChecksum = await fileChecksum(draftDefFilename);
@@ -105,7 +105,7 @@ for (const draftId of drafts) {
105105
draftSpec as unknown as types.ValidationSpecDefinition,
106106
);
107107

108-
const outputFilename = path.join(NODE_DIR, `draft-${nodeDraftId}.ts`);
108+
const outputFilename = path.join(DENO_DIR, `draft_${draftId}.ts`);
109109
await Deno.writeTextFile(
110110
outputFilename,
111111
[
@@ -115,43 +115,17 @@ for (const draftId of drafts) {
115115
modCode,
116116
].join("\n"),
117117
);
118-
await Deno.run({ cmd: ["deno", "fmt", "--quiet", outputFilename] }).status();
119-
120-
// Copy to the deno directory
121-
await fs.copy(
122-
outputFilename,
123-
path.join(DENO_DIR, `draft_${draftId}.ts`),
124-
{ overwrite: true },
125-
);
118+
const fmtCommand = new Deno.Command("deno", {
119+
args: ["fmt", "--quiet", outputFilename],
120+
});
121+
await fmtCommand.output();
126122

127123
// -------------------------------------------------------------------------
128124
// Compile to JS
129125
// -------------------------------------------------------------------------
130-
const { files } = await Deno.emit(outputFilename, {
131-
bundle: "module",
132-
compilerOptions: { target: "es6" },
133-
});
134-
135-
const js = files["deno:///bundle.js"];
136-
const map = files["deno:///bundle.js.map"];
137-
138-
// Write to the node directory
139-
const mapJson = JSON.parse(map) as { sources: string[] };
140-
mapJson.sources = mapJson.sources.map((source) => path.basename(source));
141-
142-
await Deno.writeTextFile(
143-
path.join(NODE_DIR, `draft-${nodeDraftId}.js`),
144-
[
145-
`/// <reference types="./draft-${nodeDraftId}.ts" />`,
146-
"// @generated",
147-
js,
148-
`//# sourceMappingURL=draft-${nodeDraftId}.js.map`,
149-
].join("\n"),
150-
);
151-
152-
await Deno.writeTextFile(
153-
path.join(NODE_DIR, `draft-${nodeDraftId}.js.map`),
154-
JSON.stringify(mapJson),
126+
await compileTypeScript(
127+
outputFilename,
128+
NODE_DIR,
155129
);
156130

157131
console.log(`draft_${draftId}: complete`);
@@ -185,8 +159,6 @@ if (latestDraft === undefined) {
185159
throw new Error("TODO");
186160
}
187161

188-
const nodeLatestDraft = latestDraft.replaceAll("_", "-");
189-
190162
await Deno.writeTextFile(
191163
path.join(DENO_DIR, "draft_latest.ts"),
192164
`export * from "./draft_${latestDraft}.ts";`,
@@ -224,11 +196,10 @@ for (const readmeFilename of readmeFilenames) {
224196
})
225197
.replaceAll("{LATEST_DRAFT}", latestDraft),
226198
);
227-
const p = Deno.run({
228-
cmd: ["deno", "fmt", "--quiet", readmeFilename.output],
199+
const fmtCommand = new Deno.Command("deno", {
200+
args: ["fmt", "--quiet", readmeFilename.output],
229201
});
230-
await p.status();
231-
p.close();
202+
await fmtCommand.output();
232203
}
233204

234205
// -----------------------------------------------------------------------------
@@ -276,16 +247,26 @@ for (const dir of ALL_DIST_DIRS) {
276247
// -----------------------------------------------------------------------------
277248
{
278249
packageJson.version = VERSION;
279-
packageJson.main = `./draft-${nodeLatestDraft}.js`;
250+
packageJson.main = `./draft_${latestDraft}.js`;
251+
packageJson.types = `./draft_${latestDraft}.d.ts`;
280252
// @ts-expect-error this is valid
281253
packageJson.exports = {
282-
".": `./draft-${nodeLatestDraft}.js`,
254+
".": {
255+
types: `./draft_${latestDraft}.d.ts`,
256+
default: `./draft_${latestDraft}.js`,
257+
},
283258
...Object.fromEntries(
284259
drafts.map((
285260
draftId,
286261
) => {
287262
const nodeDraftId = draftId.replaceAll("_", "-");
288-
return [`./draft-${nodeDraftId}`, `./draft-${nodeDraftId}.js`];
263+
return [
264+
`./draft-${nodeDraftId}`,
265+
{
266+
types: `./draft_${draftId}.d.ts`,
267+
default: `./draft_${draftId}.js`,
268+
},
269+
];
289270
}),
290271
),
291272
};

.src/tsc.ts

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
import * as ts from "npm:typescript";
2+
3+
/**
4+
* Compiles a TypeScript file to JavaScript using the TypeScript compiler API.
5+
*
6+
* @param sourceFile - Path to the TypeScript source file
7+
* @param outputDir - Directory where the compiled files should be written
8+
*/
9+
export async function compileTypeScript(
10+
sourceFile: string,
11+
outputDir: string,
12+
): Promise<void> {
13+
// Use TypeScript compiler API programmatically
14+
const compilerOptions: ts.CompilerOptions = {
15+
target: ts.ScriptTarget.ES2015,
16+
module: ts.ModuleKind.ES2015,
17+
declaration: true,
18+
outDir: outputDir,
19+
};
20+
21+
const host = ts.createCompilerHost(compilerOptions);
22+
const program = ts.createProgram([sourceFile], compilerOptions, host);
23+
24+
// Emit the compiled code
25+
const emitResult = program.emit();
26+
27+
// Check for compilation errors
28+
const allDiagnostics = ts
29+
.getPreEmitDiagnostics(program)
30+
.concat(emitResult.diagnostics);
31+
32+
if (allDiagnostics.length > 0) {
33+
const errors = allDiagnostics.map((diagnostic) => {
34+
if (diagnostic.file) {
35+
const { line, character } = diagnostic.file.getLineAndCharacterOfPosition(
36+
diagnostic.start!,
37+
);
38+
const message = ts.flattenDiagnosticMessageText(
39+
diagnostic.messageText,
40+
"\n",
41+
);
42+
return `${diagnostic.file.fileName} (${line + 1},${character + 1}): ${message}`;
43+
} else {
44+
return ts.flattenDiagnosticMessageText(diagnostic.messageText, "\n");
45+
}
46+
});
47+
throw new Error(`TypeScript compilation failed:\n${errors.join("\n")}`);
48+
}
49+
50+
if (emitResult.emitSkipped) {
51+
throw new Error("TypeScript compilation was skipped");
52+
}
53+
}
54+

.src/utils/checksum.ts

Lines changed: 13 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
1-
import { crypto } from "std/crypto/mod.ts";
2-
import { iterateReader } from "std/streams/conversion.ts";
1+
import { crypto } from "@std/crypto";
32

43
export const algorithm = "MD5" as const;
54

65
export const fileChecksum = async (
76
file: URL | string | Deno.FsFile,
87
): Promise<string> => {
9-
const f = file instanceof Deno.FsFile ? file : await Deno.open(file);
10-
const arrayBuffer = await crypto.subtle.digest(algorithm, iterateReader(f));
11-
12-
f.close();
13-
return toHexString(arrayBuffer);
14-
};
15-
16-
const toHexString = (bytes: ArrayBuffer): string =>
17-
new Uint8Array(bytes).reduce(
18-
(str, byte) => str + byte.toString(16).padStart(2, "0"),
19-
"",
20-
);
8+
const fileContent = file instanceof Deno.FsFile
9+
? await Deno.readAll(file)
10+
: await Deno.readFile(file);
11+
12+
const hashBuffer = await crypto.subtle.digest(algorithm, fileContent);
13+
14+
// Convert to hex string
15+
const hashArray = Array.from(new Uint8Array(hashBuffer));
16+
const hashHex = hashArray.map(byte => byte.toString(16).padStart(2, '0')).join('');
17+
18+
return hashHex;
19+
};

LICENSE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
BSD 2-Clause License
22

3-
Original source code is copyright (c) 2019-2022 Jeremy Rylan
3+
Original source code is copyright (c) 2019-2025 Jeremy Rylan
44
<https://github.com/jrylan>
55

66
All JSON Schema documentation and descriptions are copyright (c):

deno.jsonc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,13 @@
33
"files": {
44
"exclude": ["dist/"]
55
}
6+
},
7+
"imports": {
8+
"@std/crypto": "jsr:@std/crypto@^1.0.5",
9+
"@std/fs": "jsr:@std/fs@^1.0.19",
10+
"@std/io": "jsr:@std/io@^0.225.2",
11+
"@std/path": "jsr:@std/path@^1.1.2",
12+
"@std/streams": "jsr:@std/streams@^1.0.13",
13+
"typescript": "npm:typescript@^5.9.3"
614
}
715
}

deno.lock

Lines changed: 69 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/deno/LICENSE.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
BSD 2-Clause License
22

3-
Original source code is copyright (c) 2019-2022 Jeremy Rylan
3+
Original source code is copyright (c) 2019-2025 Jeremy Rylan
44
<https://github.com/jrylan>
55

66
All JSON Schema documentation and descriptions are copyright (c):

dist/deno/draft_07.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -725,12 +725,11 @@ export type JSONSchema<
725725
// -----------------------------------------------------------------------------
726726

727727
export namespace JSONSchema {
728-
export type TypeValue = (
728+
export type TypeValue =
729729
| ValueOf<TypeName>
730730
| TypeName
731731
| Array<ValueOf<TypeName> | TypeName>
732-
| ReadonlyArray<ValueOf<TypeName> | TypeName>
733-
);
732+
| ReadonlyArray<ValueOf<TypeName> | TypeName>;
734733

735734
/**
736735
* JSON Schema interface

dist/deno/draft_2019_09.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1095,12 +1095,11 @@ export type JSONSchema<
10951095
// -----------------------------------------------------------------------------
10961096

10971097
export namespace JSONSchema {
1098-
export type TypeValue = (
1098+
export type TypeValue =
10991099
| ValueOf<TypeName>
11001100
| TypeName
11011101
| Array<ValueOf<TypeName> | TypeName>
1102-
| ReadonlyArray<ValueOf<TypeName> | TypeName>
1103-
);
1102+
| ReadonlyArray<ValueOf<TypeName> | TypeName>;
11041103

11051104
/**
11061105
* JSON Schema interface

0 commit comments

Comments
 (0)