Skip to content

Commit 1c97710

Browse files
committed
feat: support process plugins in latest info
1 parent e0ed0d4 commit 1c97710

File tree

3 files changed

+82
-21
lines changed

3 files changed

+82
-21
lines changed

plugins.test.ts

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { assertEquals } from "./deps.test.ts";
22
import { pluginResolvers, tryResolveLatestJson, tryResolvePluginUrl, tryResolveSchemaUrl } from "./plugins.ts";
3-
import { getLatestReleaseTagName } from "./utils/mod.ts";
3+
import { getLatestReleaseInfo } from "./utils/mod.ts";
44

55
Deno.test("should get correct info for typescript resolver", () => {
66
const resolver = getResolverByName("typescript");
@@ -226,39 +226,59 @@ Deno.test("tryResolveUserLatestJson", async () => {
226226
// dprint repo
227227
{
228228
const result = await getValidResultForUrl("https://plugins.dprint.dev/dprint/typescript/latest.json");
229-
const tagName = await getLatestReleaseTagName("dprint", "dprint-plugin-typescript");
229+
const releaseInfo = await getLatestReleaseInfo("dprint", "dprint-plugin-typescript");
230230
assertEquals(result, {
231231
schemaVersion: 1,
232-
url: `https://plugins.dprint.dev/typescript-${tagName!}.wasm`,
232+
url: `https://plugins.dprint.dev/typescript-${releaseInfo!.tagName}.wasm`,
233+
version: releaseInfo!.tagName,
234+
checksum: undefined,
233235
});
234236
}
235237
// dprint repo full name
236238
{
237239
const result = await getValidResultForUrl(
238240
"https://plugins.dprint.dev/dprint/dprint-plugin-typescript/latest.json",
239241
);
240-
const tagName = await getLatestReleaseTagName("dprint", "dprint-plugin-typescript");
242+
const releaseInfo = await getLatestReleaseInfo("dprint", "dprint-plugin-typescript");
241243
assertEquals(result, {
242244
schemaVersion: 1,
243-
url: `https://plugins.dprint.dev/typescript-${tagName!}.wasm`,
245+
url: `https://plugins.dprint.dev/typescript-${releaseInfo!.tagName}.wasm`,
246+
version: releaseInfo!.tagName,
247+
checksum: undefined,
244248
});
245249
}
246250
// non-dprint repo
247251
{
248252
const result = await getValidResultForUrl("https://plugins.dprint.dev/malobre/vue/latest.json");
249-
const tagName = await getLatestReleaseTagName("malobre", "dprint-plugin-vue");
253+
const releaseInfo = await getLatestReleaseInfo("malobre", "dprint-plugin-vue");
250254
assertEquals(result, {
251255
schemaVersion: 1,
252-
url: `https://plugins.dprint.dev/malobre/vue-${tagName!}.wasm`,
256+
url: `https://plugins.dprint.dev/malobre/vue-${releaseInfo!.tagName}.wasm`,
257+
version: releaseInfo!.tagName.replace(/^v/, ""),
258+
checksum: undefined,
253259
});
254260
}
255261
// non-dprint repo full name
256262
{
257263
const result = await getValidResultForUrl("https://plugins.dprint.dev/malobre/dprint-plugin-vue/latest.json");
258-
const tagName = await getLatestReleaseTagName("malobre", "dprint-plugin-vue");
264+
const releaseInfo = await getLatestReleaseInfo("malobre", "dprint-plugin-vue");
259265
assertEquals(result, {
260266
schemaVersion: 1,
261-
url: `https://plugins.dprint.dev/malobre/vue-${tagName!}.wasm`,
267+
url: `https://plugins.dprint.dev/malobre/vue-${releaseInfo!.tagName}.wasm`,
268+
version: releaseInfo!.tagName.replace(/^v/, ""),
269+
checksum: undefined,
270+
});
271+
}
272+
// process plugin repo
273+
{
274+
const result = await getValidResultForUrl("https://plugins.dprint.dev/dprint/prettier/latest.json");
275+
const releaseInfo = await getLatestReleaseInfo("dprint", "dprint-plugin-prettier");
276+
assertEquals(releaseInfo?.checksum?.length, 64);
277+
assertEquals(result, {
278+
schemaVersion: 1,
279+
url: `https://plugins.dprint.dev/prettier-${releaseInfo!.tagName}.exe-plugin`,
280+
version: releaseInfo!.tagName,
281+
checksum: releaseInfo!.checksum,
262282
});
263283
}
264284

plugins.ts

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { checkGithubRepoExists, getLatestReleaseTagName } from "./utils/mod.ts";
1+
import { checkGithubRepoExists, getLatestReleaseInfo } from "./utils/mod.ts";
22
import { parseVersion } from "./version.ts";
33

44
export interface PluginResolver {
@@ -156,19 +156,22 @@ export async function tryResolveLatestJson(url: URL) {
156156
const username = result.pathname.groups[0];
157157
const shortRepoName = result.pathname.groups[1];
158158
const repoName = await getFullRepoName(username, shortRepoName);
159-
const tagName = await getLatestReleaseTagName(username, repoName);
160-
if (tagName == null) {
159+
const releaseInfo = await getLatestReleaseInfo(username, repoName);
160+
if (releaseInfo == null) {
161161
return 404;
162162
}
163163
const displayRepoName = shortRepoName.replace(/^dprint-plugin-/, "");
164+
const extension = releaseInfo.kind === "wasm" ? "wasm" : "exe-plugin";
164165

165166
// include the bare minimum in case someone else wants to implement
166167
// this behaviour on their server
167168
return {
168169
schemaVersion: 1,
169170
url: username === "dprint"
170-
? `https://plugins.dprint.dev/${displayRepoName}-${tagName}.wasm`
171-
: `https://plugins.dprint.dev/${username}/${displayRepoName}-${tagName}.wasm`,
171+
? `https://plugins.dprint.dev/${displayRepoName}-${releaseInfo.tagName}.${extension}`
172+
: `https://plugins.dprint.dev/${username}/${displayRepoName}-${releaseInfo.tagName}.${extension}`,
173+
version: releaseInfo.tagName.replace(/^v/, ""),
174+
checksum: releaseInfo.checksum,
172175
};
173176
}
174177

utils/github.ts

Lines changed: 45 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,18 @@ export async function checkGithubRepoExists(username: string, repoName: string)
3030
return result;
3131
}
3232

33-
const latestReleaseTagNameCache = new LruCacheWithExpiry<string, string | undefined>({
33+
interface ReleaseInfo {
34+
tagName: string;
35+
checksum: string | undefined;
36+
kind: "wasm" | "process";
37+
}
38+
39+
const latestReleaseTagNameCache = new LruCacheWithExpiry<string, ReleaseInfo | undefined>({
3440
size: 1000,
3541
expiryMs: 5 * 60 * 1_000, // keep entries for 5 minutes
3642
});
3743

38-
export async function getLatestReleaseTagName(username: string, repoName: string) {
44+
export async function getLatestReleaseInfo(username: string, repoName: string) {
3945
if (!validateName(username) || !validateName(repoName)) {
4046
return undefined;
4147
}
@@ -51,16 +57,48 @@ export async function getLatestReleaseTagName(username: string, repoName: string
5157
const text = await response.text();
5258
throw new Error(`Invalid response status: ${response.status}\n\n${text}`);
5359
}
54-
const data = await response.json();
55-
result = data.tag_name;
56-
if (typeof result !== "string") {
57-
throw new Error("The tag name was not a string.");
58-
}
60+
result = getReleaseInfo(await response.json());
5961
latestReleaseTagNameCache.set(url, result);
6062
}
6163
return result;
6264
}
6365

66+
function getReleaseInfo(data: { tag_name: string; body: string; assets: { name: string }[] }): ReleaseInfo {
67+
if (typeof data.tag_name !== "string") {
68+
throw new Error("The tag name was not a string.");
69+
}
70+
return {
71+
tagName: data.tag_name,
72+
checksum: getChecksum(),
73+
kind: getPluginKind(),
74+
};
75+
76+
function getChecksum() {
77+
if (typeof data.body !== "string") {
78+
return undefined;
79+
}
80+
// search the body text for a dprint style checksum
81+
const checksum = /\@([a-z0-9]{64})\b/i.exec(data.body);
82+
return checksum?.[1];
83+
}
84+
85+
function getPluginKind(): ReleaseInfo["kind"] {
86+
if (!(data.assets instanceof Array)) {
87+
return "wasm";
88+
}
89+
90+
for (const asset of data.assets) {
91+
if (typeof asset === "object" && typeof asset.name === "string") {
92+
if (asset.name.endsWith(".exe-plugin")) {
93+
return "process";
94+
}
95+
}
96+
}
97+
98+
return "wasm";
99+
}
100+
}
101+
64102
function validateName(name: string) {
65103
// usernames may only contain alphanumeric and hypens
66104
// repos may only contain alphanumeric, underscores, hyphens, and period

0 commit comments

Comments
 (0)