-
Notifications
You must be signed in to change notification settings - Fork 6
/
upgrade.ts
154 lines (145 loc) · 4.48 KB
/
upgrade.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
#!/usr/bin/env -S deno run --allow-read --allow-write --allow-net
/**
* Installation script for kview.
*
* @module
*/
import $, { type Path } from "jsr:@david/[email protected]";
import { assert } from "jsr:/@std/assert@~1/assert";
import { parseArgs } from "jsr:@std/cli@~1/parse-args";
import * as JSONC from "jsr:@std/jsonc@~1";
import { ZipReader } from "jsr:@zip-js/[email protected]";
interface DenoConfig {
version?: string;
exclude?: string[];
imports: Record<string, string>;
lock?: boolean;
tasks?: Record<string, string>;
}
interface Manifest {
tasks: Record<string, string>;
mappings: [string, string][];
dirs: string[];
files: string[];
}
const LATEST_DENO_JSON = "https://deno.land/x/kview/deno.json";
const PREVIEW_DENO_JSON =
"https://raw.githubusercontent.com/kitsonk/kview/main/deno.json";
const EXTRACT_PATH = "./_fresh";
async function extract(installPath: Path) {
$.logStep("Extracting build files...");
const zipFilePath = installPath.join("_fresh.zip");
const zipFile = await zipFilePath.open({ read: true });
const reader = new ZipReader(zipFile);
const extractPath = installPath.join(EXTRACT_PATH);
if (await extractPath.exists()) {
await extractPath.emptyDir();
}
const entries = await reader.getEntries();
const progress = $.progress({
message: "Extracting build files...",
length: entries.length,
});
await progress.with(async () => {
for (const entry of entries) {
if (entry.getData) {
const file = extractPath.join(entry.filename);
await file.parent()?.mkdir({ recursive: true });
try {
const outFile = await file.open({ create: true, write: true });
await entry.getData(outFile.writable);
} catch (error) {
assert(error instanceof Error);
console.error(
` error: ${error.message}, file: ${await file.realPath()}`,
);
}
}
progress.increment();
}
});
await reader.close();
await zipFilePath.remove();
$.logLight(" complete.");
}
async function getLatestDenoConfig(preview: boolean): Promise<
[url: string, config: DenoConfig]
> {
const res = await fetch(preview ? PREVIEW_DENO_JSON : LATEST_DENO_JSON);
if (!res.ok) {
throw new Error(
`Error fetching latest deno.json: ${res.status} ${res.statusText}`,
);
}
return [res.url, JSONC.parse(await res.text()) as unknown as DenoConfig];
}
async function main() {
$.logStep(`Upgrading kview...`);
const args = parseArgs(Deno.args, {
boolean: ["dry-run", "preview"],
});
const dryRun = args["dry-run"];
const preview = args["preview"];
if ($.path(new URL("./dev.ts", import.meta.url)).isFileSync() && !dryRun) {
$.logError("Development environment detected. Aborting!");
Deno.exit(1);
}
$.logStep("Fetching latest configuration...");
const [url, config] = await getLatestDenoConfig(preview);
$.logLight(
` upgrading to version: ${config.version} ${preview ? "(preview)" : ""}`,
);
$.logStep("Updating config file...");
const cwd = $.path(new URL(".", import.meta.url));
const localConfig = JSONC.parse(
await cwd.join("deno.json").readText(),
) as unknown as DenoConfig;
for (const [key, value] of Object.entries(config.imports)) {
localConfig.imports[key] = value;
}
const manifest: Manifest = await $.request(
new URL("./install.manifest.json", url),
)
.json();
for (const [key, value] of manifest.mappings) {
localConfig.imports[key] = new URL(value, url).toString();
}
localConfig.tasks = manifest.tasks;
if (dryRun) {
console.log(localConfig);
} else {
await cwd.join("deno.json").writeJsonPretty(localConfig);
}
$.logLight(" complete.");
$.logStep("Updating local application files...");
const progress = $.progress({
message: "Updating application files...",
length: manifest.dirs.length + manifest.files.length,
});
await progress.with(async () => {
for (const dir of manifest.dirs) {
await cwd.join(dir).mkdir({ recursive: true });
progress.increment();
}
for (const item of manifest.files) {
const req = $.request(new URL(item, url));
if (dryRun) {
if (!(await req).ok) {
$.logError(`Unable to fetch: ${item}`);
}
} else {
await req.pipeToPath(cwd.join(item));
}
progress.increment();
}
});
$.logLight(" complete.");
await extract(cwd);
$.logStep("Done.");
console.log(
`\n\nUpgrade of %ckview%c is complete.`,
"color:green",
"color:none",
);
}
main();