Skip to content

Commit 2e2a65b

Browse files
committed
Initial implementation.
1 parent 242ce05 commit 2e2a65b

File tree

12 files changed

+2211
-0
lines changed

12 files changed

+2211
-0
lines changed

.github/workflows/ci.yml

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
name: Node.js test and Build
2+
3+
on:
4+
push:
5+
branches: [ main ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
build:
11+
strategy:
12+
matrix:
13+
os: [ubuntu-latest, windows-latest]
14+
node-version: ['16']
15+
java: ['8']
16+
17+
runs-on: ${{ matrix.os }}
18+
19+
steps:
20+
- uses: actions/checkout@v3
21+
- name: Use Node.js ${{ matrix.node-version }}
22+
uses: actions/setup-node@v3
23+
with:
24+
node-version: ${{ matrix.node-version }}
25+
- name: Set up JDK ${{ matrix.java }}
26+
uses: actions/setup-java@v3
27+
with:
28+
distribution: 'adopt'
29+
java-version: ${{ matrix.java }}
30+
cache: 'sbt'
31+
32+
- name: Cache dependencies
33+
uses: actions/cache@v3
34+
with:
35+
path: |
36+
**/node_modules
37+
key: ${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
38+
39+
- name: Install dependencies
40+
run: npm install
41+
- name: Run sbt once in the test project to make sure sbt is downloaded
42+
run: sbt projects
43+
working-directory: ./test/testproject
44+
- name: Perform unit test
45+
run: npm test
46+
- name: Build
47+
run: npm run build

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
/node_modules/
2+
/dist/
3+
target/

index.ts

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import { spawn, SpawnOptions } from "child_process";
2+
import type { Plugin as VitePlugin } from "vite";
3+
4+
// Utility to invoke a given sbt task and fetch its output
5+
function printSbtTask(task: string, cwd?: string): Promise<string> {
6+
const args = ["--batch", "-no-colors", "-Dsbt.supershell=false", `print ${task}`];
7+
const options: SpawnOptions = {
8+
cwd: cwd,
9+
stdio: ['ignore', 'pipe', 'inherit'],
10+
};
11+
const child = process.platform === 'win32'
12+
? spawn("sbt.bat", args.map(x => `"${x}"`), {shell: true, ...options})
13+
: spawn("sbt", args, options);
14+
15+
let fullOutput: string = '';
16+
17+
child.stdout!.setEncoding('utf-8');
18+
child.stdout!.on('data', data => {
19+
fullOutput += data;
20+
process.stdout.write(data); // tee on my own stdout
21+
});
22+
23+
return new Promise((resolve, reject) => {
24+
child.on('error', err => {
25+
reject(new Error(`sbt invocation for Scala.js compilation could not start. Is it installed?\n${err}`));
26+
});
27+
child.on('close', code => {
28+
if (code !== 0)
29+
reject(new Error(`sbt invocation for Scala.js compilation failed with exit code ${code}.`));
30+
else
31+
resolve(fullOutput.trimEnd().split('\n').at(-1)!);
32+
});
33+
});
34+
}
35+
36+
export interface ScalaJSPluginOptions {
37+
projectID?: string,
38+
cwd?: string,
39+
}
40+
41+
export default function scalaJSPlugin(options: ScalaJSPluginOptions = {}): VitePlugin {
42+
const { projectID, cwd } = options;
43+
44+
let isDev: boolean | undefined = undefined;
45+
let scalaJSOutputDir: string | undefined = undefined;
46+
47+
return {
48+
name: "scalajs:sbt-scalajs-plugin",
49+
50+
// Vite-specific
51+
configResolved(resolvedConfig) {
52+
isDev = resolvedConfig.mode === 'development';
53+
},
54+
55+
// standard Rollup
56+
async buildStart(options) {
57+
if (isDev === undefined)
58+
throw new Error("configResolved must be called before buildStart");
59+
60+
const task = isDev ? "fastLinkJSOutput" : "fullLinkJSOutput";
61+
const projectTask = projectID ? `${projectID}/${task}` : task;
62+
scalaJSOutputDir = await printSbtTask(projectTask, cwd);
63+
},
64+
65+
// standard Rollup
66+
resolveId(source, importer, options) {
67+
if (scalaJSOutputDir === undefined)
68+
throw new Error("buildStart must be called before resolveId");
69+
70+
const parts = /^scalajs:(.*)$/g.exec(source);
71+
if (!parts)
72+
return null;
73+
74+
return `${scalaJSOutputDir}/${parts[1]}`;
75+
},
76+
};
77+
}

0 commit comments

Comments
 (0)