Skip to content

Commit 6c2b43c

Browse files
authored
feat(swc-plugin): Add version data of swc_core and swc_plugin_runner (#53)
1 parent f16e38f commit 6c2b43c

File tree

9 files changed

+332
-42
lines changed

9 files changed

+332
-42
lines changed

apps/swc-plugins/.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,6 @@ yarn-error.log*
3434
# typescript
3535
*.tsbuildinfo
3636
next-env.d.ts
37+
38+
# scripts
39+
.cache/

apps/swc-plugins/app/api/versions/from-plugin-runner/[version]/page.tsx

-12
This file was deleted.

apps/swc-plugins/app/compat/core/[version]/page.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ export default function Page({
88
}: {
99
params: { version: string };
1010
}) {
11-
const [compatRange] = apiClient.compatRange.byVersion.useSuspenseQuery({
11+
const [compatRange] = apiClient.compatRange.byCoreVersion.useSuspenseQuery({
1212
version,
1313
});
1414

apps/swc-plugins/app/import/runtime/route.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ export async function POST(req: NextRequest) {
3535
const api = await createCaller();
3636

3737
for (const version of versions) {
38-
const compatRange = await api.compatRange.byVersion({
38+
const compatRange = await api.compatRange.byCoreVersion({
3939
version: version.swcCoreVersion,
4040
});
4141
if (!compatRange) {
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { createCaller } from "@/lib/server";
2+
import { NextRequest, NextResponse } from "next/server";
3+
import { z } from "zod";
4+
5+
const CoreVersionSchema = z.object({
6+
version: z.string(),
7+
pluginRunnerReq: z.string(),
8+
});
9+
10+
const BodySchema = z.object({
11+
coreVersions: z.array(CoreVersionSchema),
12+
pluginRunnerVersions: z.array(z.string()),
13+
});
14+
15+
export async function POST(req: NextRequest) {
16+
const api = await createCaller();
17+
const { coreVersions, pluginRunnerVersions } = BodySchema.parse(
18+
await req.json()
19+
);
20+
21+
await api.compatRange.addCacheForCrates({
22+
coreVersions,
23+
pluginRunnerVersions,
24+
});
25+
26+
return NextResponse.json({
27+
ok: true,
28+
});
29+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
import { createCaller } from "@/lib/server";
2+
import { redirect } from "next/navigation";
3+
4+
export default async function Page({
5+
params: { version },
6+
}: {
7+
params: { version: string };
8+
}) {
9+
const api = await createCaller();
10+
const compatRange = await api.compatRange.byPluginRunnerVersion({
11+
version,
12+
});
13+
14+
if (compatRange) {
15+
return redirect(`/compat/range/${compatRange.id}`);
16+
}
17+
18+
return <div>No compat range found for swc_plugin_runner@{version}</div>;
19+
}

apps/swc-plugins/lib/api/compatRange/router.ts

+194-21
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,20 @@
11
import { publicProcedure, router } from "@/lib/base";
22
import { db } from "@/lib/prisma";
3+
import { TRPCError } from "@trpc/server";
34
import semver from "semver";
45
import { z } from "zod";
56
import { VersionRange, VersionRangeSchema } from "./zod";
67

8+
export const CompatRangeSchema = z.object({
9+
id: z.bigint(),
10+
from: z.string(),
11+
to: z.string(),
12+
});
13+
714
export const compatRangeRouter = router({
815
list: publicProcedure
916
.input(z.void())
10-
.output(
11-
z.array(
12-
z.object({
13-
id: z.bigint(),
14-
from: z.string(),
15-
to: z.string(),
16-
})
17-
)
18-
)
17+
.output(z.array(CompatRangeSchema))
1918
.query(async ({ ctx }) => {
2019
const versions = await db.compatRange.findMany({
2120
orderBy: {
@@ -97,31 +96,72 @@ export const compatRangeRouter = router({
9796
};
9897
}),
9998

100-
byVersion: publicProcedure
99+
byPluginRunnerVersion: publicProcedure
101100
.input(
102101
z.object({
103-
version: z.string(),
102+
version: z.string().describe("The version of the swc_plugin_runner"),
104103
})
105104
)
106-
.output(
107-
z.nullable(
108-
z.object({
109-
id: z.bigint(),
110-
from: z.string(),
111-
to: z.string(),
112-
})
113-
)
105+
.output(z.nullable(CompatRangeSchema))
106+
.query(async ({ ctx, input: { version } }) => {
107+
const v = await db.swcPluginRunnerVersion.findUnique({
108+
where: {
109+
version,
110+
},
111+
select: {
112+
compatRange: {
113+
select: {
114+
id: true,
115+
from: true,
116+
to: true,
117+
},
118+
},
119+
},
120+
});
121+
122+
return v?.compatRange ?? null;
123+
}),
124+
125+
byCoreVersion: publicProcedure
126+
.input(
127+
z.object({
128+
version: z.string(),
129+
})
114130
)
131+
.output(z.nullable(CompatRangeSchema))
115132
.query(async ({ ctx, input: { version } }) => {
116-
const versions = await db.compatRange.findMany({
133+
// Try the cache first.
134+
{
135+
const v = await db.swcCoreVersion.findUnique({
136+
where: {
137+
version,
138+
},
139+
select: {
140+
compatRange: {
141+
select: {
142+
id: true,
143+
from: true,
144+
to: true,
145+
},
146+
},
147+
},
148+
});
149+
150+
if (v) {
151+
return v.compatRange;
152+
}
153+
}
154+
155+
console.warn("Fallback to full search");
156+
const compatRanges = await db.compatRange.findMany({
117157
select: {
118158
id: true,
119159
from: true,
120160
to: true,
121161
},
122162
});
123163

124-
for (const range of versions) {
164+
for (const range of compatRanges) {
125165
if (
126166
semver.gte(version, range.from) &&
127167
(range.to === "*" || semver.lte(version, range.to))
@@ -132,6 +172,115 @@ export const compatRangeRouter = router({
132172

133173
return null;
134174
}),
175+
176+
addCacheForCrates: publicProcedure
177+
.input(
178+
z.object({
179+
pluginRunnerVersions: z.array(z.string()),
180+
coreVersions: z.array(
181+
z.object({
182+
version: z.string().describe("The version of the swc_core"),
183+
pluginRunnerReq: z.string(),
184+
})
185+
),
186+
})
187+
)
188+
.output(z.void())
189+
.mutation(
190+
async ({ ctx, input: { coreVersions, pluginRunnerVersions } }) => {
191+
if (process.env.NODE_ENV === "production") {
192+
throw new TRPCError({
193+
code: "FORBIDDEN",
194+
});
195+
}
196+
197+
const previousMaxCoreVersion = await maxSwcCoreVersion();
198+
const previousMaxPluginRunnerVersion =
199+
await maxSwcPluginRunnerVersion();
200+
201+
const compatRanges = await db.compatRange.findMany({
202+
select: {
203+
id: true,
204+
from: true,
205+
to: true,
206+
},
207+
});
208+
209+
const done = new Set<string>();
210+
211+
function byVersion(swcCoreVersion: string) {
212+
for (const range of compatRanges) {
213+
if (
214+
semver.gte(swcCoreVersion, range.from) &&
215+
(range.to === "*" || semver.lte(swcCoreVersion, range.to))
216+
) {
217+
return range;
218+
}
219+
}
220+
}
221+
222+
for (const corePkg of coreVersions) {
223+
corePkg.version = corePkg.version.replace("v", "");
224+
225+
if (semver.lt(corePkg.version, previousMaxCoreVersion)) {
226+
console.log(
227+
`Skipping swc_core@${corePkg.version} as it's less than previous max (${previousMaxCoreVersion})`
228+
);
229+
continue;
230+
}
231+
232+
const compatRange = byVersion(corePkg.version);
233+
234+
if (!compatRange) {
235+
console.error(`Compat range not found for ${corePkg.version}`);
236+
continue;
237+
}
238+
239+
for (let rv of pluginRunnerVersions) {
240+
rv = rv.replace("v", "");
241+
242+
if (done.has(rv)) {
243+
continue;
244+
}
245+
if (semver.lt(rv, previousMaxPluginRunnerVersion)) {
246+
continue;
247+
}
248+
249+
if (semver.satisfies(rv, corePkg.pluginRunnerReq)) {
250+
await db.swcPluginRunnerVersion.upsert({
251+
where: {
252+
version: rv,
253+
},
254+
create: {
255+
version: rv,
256+
compatRangeId: compatRange.id,
257+
},
258+
update: {
259+
compatRangeId: compatRange.id,
260+
},
261+
});
262+
console.log(`Imported swc_plugin_runner@${rv}`);
263+
done.add(rv);
264+
}
265+
}
266+
267+
await db.swcCoreVersion.upsert({
268+
where: {
269+
version: corePkg.version,
270+
},
271+
create: {
272+
version: corePkg.version,
273+
pluginRunnerReq: corePkg.pluginRunnerReq,
274+
compatRangeId: compatRange.id,
275+
},
276+
update: {
277+
pluginRunnerReq: corePkg.pluginRunnerReq,
278+
},
279+
});
280+
console.log(`Imported swc_core@${corePkg.version}`);
281+
}
282+
}
283+
),
135284
});
136285

137286
function merge(ranges: { name: string; version: string }[]): VersionRange[] {
@@ -165,3 +314,27 @@ function mergeVersion(min: string, max: string, newValue: string) {
165314

166315
return { min: minVersion, max: maxVersion };
167316
}
317+
318+
async function maxSwcCoreVersion() {
319+
const coreVersions = await db.swcCoreVersion.findMany({
320+
select: {
321+
version: true,
322+
},
323+
});
324+
325+
return coreVersions.reduce((max, core) => {
326+
return semver.gt(max, core.version) ? max : core.version;
327+
}, "0.0.0");
328+
}
329+
330+
async function maxSwcPluginRunnerVersion() {
331+
const pluginRunnerVersions = await db.swcPluginRunnerVersion.findMany({
332+
select: {
333+
version: true,
334+
},
335+
});
336+
337+
return pluginRunnerVersions.reduce((max, pluginRunner) => {
338+
return semver.gt(max, pluginRunner.version) ? max : pluginRunner.version;
339+
}, "0.0.0");
340+
}

apps/swc-plugins/prisma/schema.prisma

+31-7
Original file line numberDiff line numberDiff line change
@@ -134,13 +134,15 @@ model TeamInvitation {
134134

135135
/// The range of versions of the `swc_core` that a plugin is compatible with.
136136
model CompatRange {
137-
id BigInt @id @default(autoincrement())
138-
from String
139-
to String
140-
createdAt DateTime @default(now())
141-
updatedAt DateTime @updatedAt
142-
runtimes SwcRuntimeVersion[]
143-
plugins SwcPluginVersion[]
137+
id BigInt @id @default(autoincrement())
138+
from String
139+
to String
140+
createdAt DateTime @default(now())
141+
updatedAt DateTime @updatedAt
142+
runtimes SwcRuntimeVersion[]
143+
plugins SwcPluginVersion[]
144+
coreVersions SwcCoreVersion[]
145+
SwcPluginRunnerVersion SwcPluginRunnerVersion[]
144146
145147
@@unique([from, to])
146148
}
@@ -194,3 +196,25 @@ model SwcPluginVersion {
194196
195197
@@unique([pluginId, version])
196198
}
199+
200+
model SwcCoreVersion {
201+
id BigInt @id @default(autoincrement())
202+
/// The version of the (exact) `swc_core` package.
203+
version String @unique
204+
/// Semver range of the `swc_plugin_runner` package that is compatible with this version of `swc_core`.
205+
pluginRunnerReq String?
206+
compatRange CompatRange @relation(fields: [compatRangeId], references: [id])
207+
compatRangeId BigInt
208+
createdAt DateTime @default(now())
209+
updatedAt DateTime @updatedAt
210+
}
211+
212+
model SwcPluginRunnerVersion {
213+
id BigInt @id @default(autoincrement())
214+
/// The version of the `swc_plugin_runner` package.
215+
version String @unique
216+
compatRange CompatRange @relation(fields: [compatRangeId], references: [id])
217+
compatRangeId BigInt
218+
createdAt DateTime @default(now())
219+
updatedAt DateTime @updatedAt
220+
}

0 commit comments

Comments
 (0)