clojurific 0.12.4 → 0.12.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/cljf/cli.js +3 -3
- package/cljf/launcher.js +2 -2
- package/cljf/repl.js +28 -10
- package/karma-esm/adapter.js +3 -3
- package/package.json +1 -1
- package/vite-plugin-cljs/index.js +5 -5
package/cljf/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
// cljf: builds and watches ClojureScript with the compiler (
|
|
2
|
+
// cljf: builds and watches ClojureScript with the compiler (cljf.esm), on the
|
|
3
3
|
// project's classpath resolved from its deps.edn. See usage below.
|
|
4
4
|
import { spawn } from 'node:child_process';
|
|
5
5
|
import path from 'node:path';
|
|
@@ -10,7 +10,7 @@ import { repl } from './repl.js';
|
|
|
10
10
|
const usage = `Usage: cljf [options] <command> [arguments]
|
|
11
11
|
|
|
12
12
|
Commands:
|
|
13
|
-
build [options...] compile once,
|
|
13
|
+
build [options...] compile once, cljf.esm's options: EDN maps, @file.edn
|
|
14
14
|
and :profile keywords (defaults to :release)
|
|
15
15
|
watch [options...] compile, then recompile on changes (defaults to :dev)
|
|
16
16
|
classpath print the project's classpath
|
|
@@ -69,7 +69,7 @@ async function main() {
|
|
|
69
69
|
case 'build':
|
|
70
70
|
case 'watch': {
|
|
71
71
|
const cmd = await compilerCommand({ ...opts, interactive, log });
|
|
72
|
-
run(cmd.command, [...cmd.args, '-m', '
|
|
72
|
+
run(cmd.command, [...cmd.args, '-m', 'cljf.esm', command, ...args]);
|
|
73
73
|
break;
|
|
74
74
|
}
|
|
75
75
|
case 'classpath': {
|
package/cljf/launcher.js
CHANGED
|
@@ -141,8 +141,8 @@ export async function classpath({ cwd = process.cwd(), aliases = [], force = fal
|
|
|
141
141
|
|
|
142
142
|
/**
|
|
143
143
|
* The command starting clojure.main with the compiler on the project's
|
|
144
|
-
* classpath: {command, args, java, classpath},
|
|
145
|
-
* args, i.e. [...args, '-m', '
|
|
144
|
+
* classpath: {command, args, java, classpath}, cljf.esm's arguments go after
|
|
145
|
+
* args, i.e. [...args, '-m', 'cljf.esm', 'build']. Options: cwd (the
|
|
146
146
|
* project, with its deps.edn), aliases, force (resolve the classpath again),
|
|
147
147
|
* interactive (offer to install Java), env and log.
|
|
148
148
|
*/
|
package/cljf/repl.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// cljf repl: a ClojureScript REPL in the terminal, evaluating in the pages
|
|
2
2
|
// running a watched build. It's an nREPL client of the watcher's nREPL server
|
|
3
|
-
// (:repl {:nrepl-port 0}, see
|
|
4
|
-
// switches to ClojureScript with (
|
|
3
|
+
// (:repl {:nrepl-port 0}, see cljf.esm.repl.nrepl), whose session it
|
|
4
|
+
// switches to ClojureScript with (cljf.esm.repl/repl).
|
|
5
5
|
import { existsSync } from 'node:fs';
|
|
6
6
|
import fs from 'node:fs/promises';
|
|
7
7
|
import net from 'node:net';
|
|
@@ -99,14 +99,27 @@ export function complete(code) {
|
|
|
99
99
|
return depth <= 0;
|
|
100
100
|
}
|
|
101
101
|
|
|
102
|
-
/**
|
|
102
|
+
/**
|
|
103
|
+
* An nREPL connection: requests whose responses end with status done. Once the
|
|
104
|
+
* socket closes, pending and later requests reject.
|
|
105
|
+
*/
|
|
103
106
|
export class Connection {
|
|
104
107
|
#socket;
|
|
105
108
|
#ids = 0;
|
|
106
109
|
#pending = new Map();
|
|
110
|
+
#closed = null;
|
|
107
111
|
|
|
108
112
|
constructor(socket) {
|
|
109
113
|
this.#socket = socket;
|
|
114
|
+
const fail = e => {
|
|
115
|
+
if (this.#closed) return;
|
|
116
|
+
this.#closed = new LauncherError(`cljf repl: the nREPL server closed the connection${e ? `: ${e.message}` : ''}`);
|
|
117
|
+
for (const { reject } of this.#pending.values()) reject(this.#closed);
|
|
118
|
+
this.#pending.clear();
|
|
119
|
+
};
|
|
120
|
+
// an error is followed by close
|
|
121
|
+
socket.on('error', fail);
|
|
122
|
+
socket.on('close', () => fail());
|
|
110
123
|
const decoder = new Decoder();
|
|
111
124
|
socket.on('data', chunk => {
|
|
112
125
|
for (const msg of decoder.push(chunk)) {
|
|
@@ -132,8 +145,12 @@ export class Connection {
|
|
|
132
145
|
*/
|
|
133
146
|
request(msg, onResponse = () => {}) {
|
|
134
147
|
const id = msg.id ?? this.newId();
|
|
135
|
-
return new Promise(resolve => {
|
|
136
|
-
this.#
|
|
148
|
+
return new Promise((resolve, reject) => {
|
|
149
|
+
if (this.#closed) {
|
|
150
|
+
reject(this.#closed);
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
153
|
+
this.#pending.set(id, { onResponse, resolve, reject });
|
|
137
154
|
this.#socket.write(bencode({ ...msg, id }));
|
|
138
155
|
});
|
|
139
156
|
}
|
|
@@ -211,14 +228,14 @@ export async function repl({
|
|
|
211
228
|
const write = (stream, text) => text && stream.write(text);
|
|
212
229
|
const { 'new-session': session } = await conn.request({ op: 'clone' });
|
|
213
230
|
let failed = false;
|
|
214
|
-
await conn.request({ op: 'eval', session, code: '(
|
|
231
|
+
await conn.request({ op: 'eval', session, code: '(cljf.esm.repl/repl)' }, msg => {
|
|
215
232
|
write(output, msg.out);
|
|
216
233
|
write(errorOutput, msg.err);
|
|
217
234
|
if (msg.ex) failed = true;
|
|
218
235
|
});
|
|
219
236
|
if (failed) {
|
|
220
237
|
conn.close();
|
|
221
|
-
throw new LauncherError('cljf repl: the nREPL server has no ClojureScript REPL (
|
|
238
|
+
throw new LauncherError('cljf repl: the nREPL server has no ClojureScript REPL (cljf.esm.repl), is it the dev server\'s?');
|
|
222
239
|
}
|
|
223
240
|
|
|
224
241
|
const history = terminal ? await readHistory(historyFile) : [];
|
|
@@ -247,7 +264,7 @@ export async function repl({
|
|
|
247
264
|
rl.close();
|
|
248
265
|
// the server forgets the session, unless it doesn't answer
|
|
249
266
|
const timeout = new Promise(r => setTimeout(r, 1000).unref());
|
|
250
|
-
Promise.race([conn.request({ op: 'close', session }), timeout]).finally(() => {
|
|
267
|
+
Promise.race([conn.request({ op: 'close', session }), timeout]).catch(() => {}).finally(() => {
|
|
251
268
|
conn.close();
|
|
252
269
|
resolve(code);
|
|
253
270
|
});
|
|
@@ -262,7 +279,7 @@ export async function repl({
|
|
|
262
279
|
|
|
263
280
|
rl.on('SIGINT', () => {
|
|
264
281
|
if (evaluating) {
|
|
265
|
-
conn.request({ op: 'interrupt', session, 'interrupt-id': evaluating });
|
|
282
|
+
conn.request({ op: 'interrupt', session, 'interrupt-id': evaluating }).catch(() => {});
|
|
266
283
|
} else if (pending || rl.line) {
|
|
267
284
|
pending = '';
|
|
268
285
|
interrupted = false;
|
|
@@ -307,12 +324,13 @@ export async function repl({
|
|
|
307
324
|
return;
|
|
308
325
|
}
|
|
309
326
|
evaluating = conn.newId();
|
|
327
|
+
// a lost connection rejects, closed (above) reports it
|
|
310
328
|
await conn.request({ op: 'eval', session, code, ns, id: evaluating }, msg => {
|
|
311
329
|
write(output, msg.out);
|
|
312
330
|
write(errorOutput, msg.err);
|
|
313
331
|
if (msg.value !== undefined) output.write(`${msg.value}\n`);
|
|
314
332
|
if (msg.ns) ns = msg.ns;
|
|
315
|
-
});
|
|
333
|
+
}).catch(() => {});
|
|
316
334
|
evaluating = null;
|
|
317
335
|
if (closing) return;
|
|
318
336
|
prompt();
|
package/karma-esm/adapter.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
// Karma adapter for a
|
|
2
|
-
//
|
|
1
|
+
// Karma adapter for a cljf.esm test bundle (an ES module) run by
|
|
2
|
+
// cljf.esm.karma/start. Add it to Karma's files, serve the bundle's directory
|
|
3
3
|
// (included: false), and name its entry module in client.args:
|
|
4
4
|
//
|
|
5
5
|
// files: ['<this file>', {pattern: 'build/ci-test/**/*', included: false}],
|
|
6
6
|
// client: {args: ['/base/build/ci-test/my.test-runner.js']},
|
|
7
7
|
//
|
|
8
8
|
// Karma calls start once the page has loaded, module scripts may not have run
|
|
9
|
-
// yet:
|
|
9
|
+
// yet: cljf.esm.karma/start runs the tests in whichever order the two happen.
|
|
10
10
|
window.__karma__.start = function () {
|
|
11
11
|
window.__karmaStarted = true;
|
|
12
12
|
if (window.__karmaRun) window.__karmaRun();
|
package/package.json
CHANGED
|
@@ -16,7 +16,7 @@ import { Worker } from 'node:worker_threads';
|
|
|
16
16
|
import { compilerCommand } from '../cljf/launcher.js';
|
|
17
17
|
import { pruneChunks, propertyRenames } from './prune.js';
|
|
18
18
|
|
|
19
|
-
const EVENT_PREFIX = '[
|
|
19
|
+
const EVENT_PREFIX = '[cljf.esm] ';
|
|
20
20
|
const NPM_AS = 'cljs-npm-as:';
|
|
21
21
|
// a ClojureScript source loaded by a page or imported from JavaScript, which
|
|
22
22
|
// the dev server serves as an import of its compiled module
|
|
@@ -227,11 +227,11 @@ export default module.exports;
|
|
|
227
227
|
* the compiler added and stock ClojureScript removed, see cljf/launcher.js.
|
|
228
228
|
* @param {string[]} [options.command] starts Clojure with the compiler on the
|
|
229
229
|
* classpath instead of the launcher, i.e. ["clojure", "-M:cljs"],
|
|
230
|
-
*
|
|
230
|
+
* cljf.esm's arguments follow
|
|
231
231
|
* @param {string} [options.cwd] the compiler's working directory, with the
|
|
232
232
|
* project's deps.edn, defaults to Vite's root (the project's directory)
|
|
233
233
|
* @param {string} [options.config] compiler options file (EDN, see
|
|
234
|
-
*
|
|
234
|
+
* cljf.esm/load-options), relative to cwd
|
|
235
235
|
* @param {string} [options.profile] profile of the config file, defaults to
|
|
236
236
|
* dev when serving and release when building
|
|
237
237
|
* @param {string} options.outputDir the compiler's output directory, relative
|
|
@@ -285,7 +285,7 @@ export default function cljs(options) {
|
|
|
285
285
|
|
|
286
286
|
function run(args, onEvent) {
|
|
287
287
|
const [cmd, ...cmdArgs] = compiler;
|
|
288
|
-
const child = spawn(cmd, [...cmdArgs, '-m', '
|
|
288
|
+
const child = spawn(cmd, [...cmdArgs, '-m', 'cljf.esm', ...args], {
|
|
289
289
|
cwd,
|
|
290
290
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
291
291
|
});
|
|
@@ -686,7 +686,7 @@ export default function cljs(options) {
|
|
|
686
686
|
server.ws.send(problem);
|
|
687
687
|
};
|
|
688
688
|
server.ws.on('connection', socket => problem && socket.send(JSON.stringify(problem)));
|
|
689
|
-
// The REPL (
|
|
689
|
+
// The REPL (cljf.esm.repl): pages running the build (cljf.esm.repl-runtime)
|
|
690
690
|
// say hello over Vite's websocket, each connection gets a runtime id. Their
|
|
691
691
|
// cljs:repl messages go to the compiler as `repl <json>` lines, the
|
|
692
692
|
// compiler's repl-send events to the page of their runtime id.
|