@jesscss/plugin-js 2.0.0-alpha.6 → 2.0.0-alpha.8

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/README.md CHANGED
@@ -1,6 +1,51 @@
1
1
  # @jesscss/plugin-js
2
2
 
3
- Jess plugin that enables JavaScript/TypeScript module imports.
3
+ **Import bridge for JavaScript/TypeScript modules in stylesheets — a seed of the
4
+ JavaScript-execution / CSS-in-JS story.**
4
5
 
5
- This package checks for a usable Deno runtime before executing non-`@jesscss/fns`
6
- modules. It is intended to be auto-loaded by `jess` when installed.
6
+ This plugin lets a stylesheet pull in JavaScript/TypeScript modules
7
+ (`.js`, `.mjs`, `.cjs`, `.ts`, `.mts`, `.cts`) the mechanism behind `@use` /
8
+ `@-from` script imports and legacy Less `@plugin` loading. When installed, it is
9
+ auto-loaded by `jess`.
10
+
11
+ ## Sandboxed execution
12
+
13
+ `plugin-js` does **not** run untrusted module code in your Node process. Before
14
+ executing anything, it checks for a usable **Deno** runtime (`deno --version`)
15
+ and runs the module in a Deno subprocess behind a permission broker:
16
+
17
+ - **read** is limited to `node_modules` (and an optional `jsReadRoot`),
18
+ - **net** is denied unless you opt in (`allowHttp`, optionally scoped to
19
+ `allowNetHosts`),
20
+ - **env / write / run / ffi / sys** are denied outright.
21
+
22
+ Values cross the boundary through a small typed bridge (dimensions, colors,
23
+ quoted strings, lists, detached rules, …). Built-in `@jesscss/fns` modules are
24
+ trusted and imported directly, without the worker. If no Deno binary is found,
25
+ the plugin fails with a clear message instead of falling back to unsandboxed
26
+ execution.
27
+
28
+ ## Why it exists — the convergence angle
29
+
30
+ One of the four tools [Jess](https://github.com/jesscss/jess) aims to converge is
31
+ **CSS-in-JS**: running real JavaScript inside stylesheets so styles can be
32
+ dynamic without leaving CSS files. This plugin — together with
33
+ [`@jesscss/plugin-node-modules`](../jess-plugin-node-modules), which resolves the
34
+ packages — is a seed of that story.
35
+
36
+ That convergence is **roadmap — being proven through the alpha, not claimed as
37
+ done.** Legacy Less `@plugin` is supported for compatibility but deprecated in
38
+ favor of `@-from` / `@-use`.
39
+
40
+ ## Status
41
+
42
+ **Alpha.** Part of Jess, the ground-up rewrite of Less.js (Jess *is* Less.js
43
+ v5). Requires a Deno runtime for script execution. The programmatic
44
+ plugin/compiler API is **not yet stabilized** — the `jess` / `lessc` CLIs are the
45
+ public surface for the alpha. Watch the [docs site](https://jesscss.github.io/)
46
+ for the API once it settles.
47
+
48
+ - Project overview & positioning: <https://github.com/jesscss/jess#readme>
49
+ - Docs: <https://jesscss.github.io/> (currently pre-alpha content)
50
+ - Issues: <https://github.com/jesscss/jess/issues>
51
+ - License: MIT
@@ -0,0 +1,51 @@
1
+ export type JsBridgeDeclaration = {
2
+ name: string;
3
+ value: JsBridgeValue;
4
+ };
5
+ export type JsBridgeValue = {
6
+ __jessBridge: true;
7
+ kind: 'scalar';
8
+ value: string | number | boolean;
9
+ } | {
10
+ __jessBridge: true;
11
+ kind: 'dimension';
12
+ value: number;
13
+ unit?: string;
14
+ } | {
15
+ __jessBridge: true;
16
+ kind: 'color';
17
+ rgb: [number, number, number];
18
+ alpha?: number;
19
+ format?: string;
20
+ } | {
21
+ __jessBridge: true;
22
+ kind: 'quoted';
23
+ value: string;
24
+ quote?: '"' | '\'';
25
+ escaped?: boolean;
26
+ } | {
27
+ __jessBridge: true;
28
+ kind: 'keyword';
29
+ value: string;
30
+ } | {
31
+ __jessBridge: true;
32
+ kind: 'anonymous';
33
+ value: string;
34
+ } | {
35
+ __jessBridge: true;
36
+ kind: 'list';
37
+ items: JsBridgeValue[];
38
+ separator?: ',' | ';' | '/';
39
+ } | {
40
+ __jessBridge: true;
41
+ kind: 'sequence';
42
+ items: JsBridgeValue[];
43
+ } | {
44
+ __jessBridge: true;
45
+ kind: 'detached';
46
+ rules: JsBridgeDeclaration[];
47
+ };
48
+ export declare function encodeBridgeValue(value: unknown): unknown;
49
+ export declare function decodeBridgeValue(value: unknown): unknown;
50
+ export declare function encodeBridgeArgs(args: unknown[]): unknown[];
51
+ //# sourceMappingURL=bridge.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAcA,MAAM,MAAM,mBAAmB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,aAAa,CAAA;CAAE,CAAC;AAEzE,MAAM,MAAM,aAAa,GACrB;IAAE,YAAY,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,CAAA;CAAE,GACxE;IAAE,YAAY,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,GACvE;IAAE,YAAY,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACrG;IAAE,YAAY,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,GAC5F;IAAE,YAAY,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACtD;IAAE,YAAY,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,WAAW,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACxD;IAAE,YAAY,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,aAAa,EAAE,CAAC;IAAC,SAAS,CAAC,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,CAAA;CAAE,GACzF;IAAE,YAAY,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,aAAa,EAAE,CAAA;CAAE,GAChE;IAAE,YAAY,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,UAAU,CAAC;IAAC,KAAK,EAAE,mBAAmB,EAAE,CAAA;CAAE,CAAC;AAqC3E,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAmEzD;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CA+BzD;AAED,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,EAAE,GAAG,OAAO,EAAE,CAE3D"}
package/lib/index.cjs CHANGED
@@ -33,6 +33,99 @@ let node_path = require("node:path");
33
33
  node_path = __toESM(node_path);
34
34
  let node_url = require("node:url");
35
35
  let node_child_process = require("node:child_process");
36
+ //#region src/bridge.ts
37
+ const isBridgeValue = (value) => typeof value === "object" && value !== null && value.__jessBridge === true && typeof value.kind === "string";
38
+ const colorFormatFromString = (value) => {
39
+ if (!value) return;
40
+ if (value in _jesscss_core.ColorFormat) return _jesscss_core.ColorFormat[value];
41
+ if (Object.values(_jesscss_core.ColorFormat).includes(value)) return value;
42
+ };
43
+ function encodeBridgeChildValue(value) {
44
+ const encoded = encodeBridgeValue(value);
45
+ if (isBridgeValue(encoded)) return encoded;
46
+ return {
47
+ __jessBridge: true,
48
+ kind: "scalar",
49
+ value: typeof encoded === "string" || typeof encoded === "number" || typeof encoded === "boolean" ? encoded : String(encoded)
50
+ };
51
+ }
52
+ function encodeBridgeValue(value) {
53
+ if (value instanceof _jesscss_core.Dimension) return {
54
+ __jessBridge: true,
55
+ kind: "dimension",
56
+ value: value.number,
57
+ unit: value.unit
58
+ };
59
+ if (value instanceof _jesscss_core.Color) return {
60
+ __jessBridge: true,
61
+ kind: "color",
62
+ rgb: value.rgb,
63
+ alpha: value.alpha,
64
+ format: value.options.format === void 0 ? void 0 : _jesscss_core.ColorFormat[value.options.format]
65
+ };
66
+ if (value instanceof _jesscss_core.Quoted) return {
67
+ __jessBridge: true,
68
+ kind: "quoted",
69
+ value: String(value.value),
70
+ quote: value.quote,
71
+ escaped: value.escaped
72
+ };
73
+ if (value instanceof _jesscss_core.Any) return {
74
+ __jessBridge: true,
75
+ kind: value.role === "keyword" ? "keyword" : "anonymous",
76
+ value: value.value
77
+ };
78
+ if (value instanceof _jesscss_core.List) return {
79
+ __jessBridge: true,
80
+ kind: "list",
81
+ items: value.value.map(encodeBridgeChildValue),
82
+ separator: value.options.sep
83
+ };
84
+ if (value instanceof _jesscss_core.Sequence) return {
85
+ __jessBridge: true,
86
+ kind: "sequence",
87
+ items: value.value.map(encodeBridgeChildValue)
88
+ };
89
+ if (value instanceof _jesscss_core.Rules) {
90
+ const rules = [];
91
+ for (const rule of value.rules ?? []) if (rule instanceof _jesscss_core.Declaration && typeof rule.name === "string") rules.push({
92
+ name: rule.name,
93
+ value: encodeBridgeChildValue(rule.value)
94
+ });
95
+ return {
96
+ __jessBridge: true,
97
+ kind: "detached",
98
+ rules
99
+ };
100
+ }
101
+ return value;
102
+ }
103
+ function decodeBridgeValue(value) {
104
+ if (!isBridgeValue(value)) return value;
105
+ switch (value.kind) {
106
+ case "scalar": return new _jesscss_core.Any(String(value.value));
107
+ case "dimension": return new _jesscss_core.Dimension({
108
+ number: value.value,
109
+ unit: value.unit
110
+ });
111
+ case "color": return new _jesscss_core.Color({
112
+ rgb: value.rgb,
113
+ alpha: value.alpha
114
+ }, { format: colorFormatFromString(value.format) });
115
+ case "quoted": return new _jesscss_core.Quoted(value.value, {
116
+ quote: value.quote,
117
+ escaped: value.escaped
118
+ });
119
+ case "keyword": return new _jesscss_core.Any(value.value, { role: "keyword" });
120
+ case "anonymous": return new _jesscss_core.Any(value.value);
121
+ case "list": return new _jesscss_core.List(value.items.map((item) => decodeBridgeValue(item)), { sep: value.separator });
122
+ case "sequence": return new _jesscss_core.Sequence(value.items.map((item) => decodeBridgeValue(item)));
123
+ }
124
+ }
125
+ function encodeBridgeArgs(args) {
126
+ return args.map(encodeBridgeValue);
127
+ }
128
+ //#endregion
36
129
  //#region src/index.ts
37
130
  const SCRIPT_EXTENSIONS = new Set([
38
131
  ".js",
@@ -51,6 +144,33 @@ const RUNTIME_MISSING_MESSAGE = [
51
144
  const BOOT_TIMEOUT_MS = 8e3;
52
145
  const REQUEST_TIMEOUT_MS = 1e4;
53
146
  const IDLE_SHUTDOWN_MS = 5e3;
147
+ /**
148
+ * Environment variables that inject a Node.js debugger/inspector bootloader
149
+ * into child processes (VS Code / Cursor "Auto Attach", `node --inspect`, etc.).
150
+ *
151
+ * These must never leak into the sandboxed Deno worker: the injected bootloader
152
+ * tries to read the environment, the Jess Deno sandbox denies `env` permission,
153
+ * and the worker never signals ready — producing a spurious
154
+ * "Timed out waiting for Deno worker startup" failure. Deno does not use any of
155
+ * these vars, so stripping them is safe.
156
+ */
157
+ const DEBUG_ENV_KEY_RE = /^(NODE_OPTIONS|NODE_INSPECT|VSCODE_INSPECTOR_OPTIONS)/i;
158
+ const DEBUG_ENV_VALUE_RE = /js-debug|bootloader/i;
159
+ /**
160
+ * Returns a copy of `env` with Node debugger/inspector-attach variables removed,
161
+ * so a spawned Deno subprocess starts regardless of the parent's debug env.
162
+ * The Deno permission sandbox is untouched; this only stops leaking the debugger
163
+ * into it.
164
+ */
165
+ const sanitizeSpawnEnv = (env = process.env) => {
166
+ const clean = {};
167
+ for (const [key, value] of Object.entries(env)) {
168
+ if (DEBUG_ENV_KEY_RE.test(key)) continue;
169
+ if (typeof value === "string" && DEBUG_ENV_VALUE_RE.test(value)) continue;
170
+ clean[key] = value;
171
+ }
172
+ return clean;
173
+ };
54
174
  const isPathInside = (candidatePath, rootPath) => {
55
175
  const rel = node_path.relative(rootPath, candidatePath);
56
176
  return rel === "" || !rel.startsWith("..") && !node_path.isAbsolute(rel);
@@ -90,6 +210,7 @@ var JsPlugin = class JsPlugin extends _jesscss_core.AbstractPlugin {
90
210
  name = "js";
91
211
  supportedExtensions = Array.from(SCRIPT_EXTENSIONS);
92
212
  runtimeState = { status: "idle" };
213
+ shuttingDown = false;
93
214
  brokerServer;
94
215
  brokerSocketPath;
95
216
  worker;
@@ -133,7 +254,10 @@ var JsPlugin = class JsPlugin extends _jesscss_core.AbstractPlugin {
133
254
  this.idleTimer.unref?.();
134
255
  }
135
256
  ensureRuntimeAvailable() {
136
- if ((0, node_child_process.spawnSync)(this.opts.denoCommand ?? "deno", ["--version"], { stdio: "ignore" }).status !== 0) throw new Error(RUNTIME_MISSING_MESSAGE);
257
+ if ((0, node_child_process.spawnSync)(this.opts.denoCommand ?? "deno", ["--version"], {
258
+ stdio: "ignore",
259
+ env: sanitizeSpawnEnv(process.env)
260
+ }).status !== 0) throw new Error(RUNTIME_MISSING_MESSAGE);
137
261
  }
138
262
  ensureRuntime() {
139
263
  if (this.runtimeState.status === "ready") {
@@ -142,6 +266,7 @@ var JsPlugin = class JsPlugin extends _jesscss_core.AbstractPlugin {
142
266
  }
143
267
  if (this.runtimeState.status === "initializing") return this.runtimeState.promise;
144
268
  if (this.runtimeState.status === "failed") return Promise.reject(this.runtimeState.error);
269
+ if (this.runtimeState.status === "disposed") return Promise.reject(/* @__PURE__ */ new Error("Deno worker has been disposed."));
145
270
  const promise = this.startRuntime().then(() => {
146
271
  this.runtimeState = { status: "ready" };
147
272
  this.scheduleIdleShutdown();
@@ -206,6 +331,7 @@ var JsPlugin = class JsPlugin extends _jesscss_core.AbstractPlugin {
206
331
  const socketPath = this.createBrokerPath();
207
332
  if (process.platform !== "win32" && node_fs.existsSync(socketPath)) node_fs.unlinkSync(socketPath);
208
333
  const server = node_net.createServer((socket) => {
334
+ socket.unref();
209
335
  let buf = "";
210
336
  socket.setEncoding("utf8");
211
337
  socket.on("data", (chunk) => {
@@ -236,6 +362,7 @@ var JsPlugin = class JsPlugin extends _jesscss_core.AbstractPlugin {
236
362
  server.once("error", reject);
237
363
  server.listen(socketPath, () => resolve());
238
364
  });
365
+ server.unref();
239
366
  this.brokerServer = server;
240
367
  this.brokerSocketPath = socketPath;
241
368
  return socketPath;
@@ -248,7 +375,8 @@ var JsPlugin = class JsPlugin extends _jesscss_core.AbstractPlugin {
248
375
  const child = (0, node_child_process.spawn)(denoCommand, [
249
376
  "run",
250
377
  "--no-prompt",
251
- node_fs.existsSync(compiledWorkerPath) ? compiledWorkerPath : sourceWorkerPath
378
+ node_fs.existsSync(compiledWorkerPath) ? compiledWorkerPath : sourceWorkerPath,
379
+ `--runtime-api=${this.opts.runtimeApi ?? "module"}`
252
380
  ], {
253
381
  stdio: [
254
382
  "pipe",
@@ -256,15 +384,24 @@ var JsPlugin = class JsPlugin extends _jesscss_core.AbstractPlugin {
256
384
  "pipe"
257
385
  ],
258
386
  env: {
259
- ...process.env,
387
+ ...sanitizeSpawnEnv(process.env),
260
388
  DENO_PERMISSION_BROKER_PATH: socketPath
261
389
  }
262
390
  });
263
391
  this.worker = child;
392
+ child.unref();
393
+ child.stdin.unref?.();
394
+ child.stdout.unref?.();
395
+ child.stderr.unref?.();
264
396
  child.stdout.setEncoding("utf8");
265
397
  child.stderr.setEncoding("utf8");
266
398
  child.stdout.on("data", (chunk) => this.onWorkerStdout(chunk));
267
399
  child.on("exit", () => {
400
+ this.worker = void 0;
401
+ if (this.shuttingDown) {
402
+ this.shuttingDown = false;
403
+ return;
404
+ }
268
405
  const err = /* @__PURE__ */ new Error("Deno worker exited unexpectedly.");
269
406
  this.rejectAllPending(err);
270
407
  if (this.runtimeState.status !== "failed") this.runtimeState = {
@@ -273,9 +410,13 @@ var JsPlugin = class JsPlugin extends _jesscss_core.AbstractPlugin {
273
410
  };
274
411
  });
275
412
  return new Promise((resolve, reject) => {
413
+ let stderrText = "";
276
414
  const timer = setTimeout(() => {
277
- reject(/* @__PURE__ */ new Error("Timed out waiting for Deno worker startup."));
415
+ reject(/* @__PURE__ */ new Error(stderrText.trim() ? `Timed out waiting for Deno worker startup.\n${stderrText.trim()}` : "Timed out waiting for Deno worker startup."));
278
416
  }, BOOT_TIMEOUT_MS);
417
+ const onStderr = (chunk) => {
418
+ stderrText += chunk;
419
+ };
279
420
  const onData = (chunk) => {
280
421
  this.workerBuffer += chunk;
281
422
  let idx = this.workerBuffer.indexOf("\n");
@@ -288,6 +429,7 @@ var JsPlugin = class JsPlugin extends _jesscss_core.AbstractPlugin {
288
429
  if (JSON.parse(line).type === "ready") {
289
430
  clearTimeout(timer);
290
431
  child.stdout.off("data", onData);
432
+ child.stderr.off("data", onStderr);
291
433
  resolve();
292
434
  return;
293
435
  }
@@ -295,9 +437,11 @@ var JsPlugin = class JsPlugin extends _jesscss_core.AbstractPlugin {
295
437
  }
296
438
  };
297
439
  child.stdout.on("data", onData);
440
+ child.stderr.on("data", onStderr);
298
441
  child.once("error", (err) => {
299
442
  clearTimeout(timer);
300
443
  child.stdout.off("data", onData);
444
+ child.stderr.off("data", onStderr);
301
445
  reject(err);
302
446
  });
303
447
  });
@@ -366,7 +510,13 @@ var JsPlugin = class JsPlugin extends _jesscss_core.AbstractPlugin {
366
510
  }
367
511
  shutdown() {
368
512
  this.clearIdleTimer();
369
- if (this.worker && !this.worker.killed) this.worker.kill();
513
+ if (this.worker && !this.worker.killed) {
514
+ this.shuttingDown = true;
515
+ this.worker.stdin.destroy();
516
+ this.worker.stdout.destroy();
517
+ this.worker.stderr.destroy();
518
+ this.worker.kill();
519
+ }
370
520
  this.worker = void 0;
371
521
  if (this.brokerServer) {
372
522
  this.brokerServer.close();
@@ -379,7 +529,8 @@ var JsPlugin = class JsPlugin extends _jesscss_core.AbstractPlugin {
379
529
  }
380
530
  dispose() {
381
531
  this.shutdown();
382
- this.runtimeState = { status: "idle" };
532
+ JsPlugin.liveInstances.delete(this);
533
+ this.runtimeState = { status: "disposed" };
383
534
  }
384
535
  assertAllowedPath(absoluteFilePath) {
385
536
  const resolvedPath = node_path.resolve(absoluteFilePath);
@@ -408,10 +559,10 @@ var JsPlugin = class JsPlugin extends _jesscss_core.AbstractPlugin {
408
559
  type: "invoke",
409
560
  modulePath,
410
561
  exportName: item.name,
411
- args
562
+ args: encodeBridgeArgs(args)
412
563
  });
413
564
  if (!invokeResult.ok) throw new Error(invokeResult.error);
414
- return invokeResult.value;
565
+ return decodeBridgeValue(invokeResult.value);
415
566
  };
416
567
  else moduleObject[item.name] = item.value;
417
568
  return moduleObject;
@@ -421,6 +572,36 @@ var JsPlugin = class JsPlugin extends _jesscss_core.AbstractPlugin {
421
572
  for (const [key, value] of Object.entries(module)) if (typeof value === "function" || isJsonValue(value)) safeModule[key] = value;
422
573
  return safeModule;
423
574
  }
575
+ /**
576
+ * Loads a legacy Less `@plugin` wrapper file in Deno Less-compat mode.
577
+ *
578
+ * @deprecated Less `@plugin` is deprecated. Prefer `@-from` for
579
+ * ESM-style script imports or `@-use` for Sass-module-style namespace imports.
580
+ */
581
+ async importLessPlugin(absoluteFilePath) {
582
+ const ext = node_path.extname(absoluteFilePath);
583
+ if (!SCRIPT_EXTENSIONS.has(ext)) throw new Error(`Plugin "${this.name}" cannot import Less plugin "${absoluteFilePath}"`);
584
+ this.assertAllowedPath(absoluteFilePath);
585
+ await this.ensureRuntime();
586
+ const modulePath = node_path.resolve(absoluteFilePath);
587
+ const loadResult = await this.callWorker({
588
+ type: "loadLessPlugin",
589
+ modulePath
590
+ });
591
+ if (!loadResult.ok) throw new Error(loadResult.error);
592
+ const functions = {};
593
+ for (const functionName of loadResult.functions ?? []) functions[functionName] = async (...args) => {
594
+ const invokeResult = await this.callWorker({
595
+ type: "invokeLessPluginFunction",
596
+ modulePath,
597
+ functionName,
598
+ args: encodeBridgeArgs(args)
599
+ });
600
+ if (!invokeResult.ok) throw new Error(invokeResult.error);
601
+ return decodeBridgeValue(invokeResult.value);
602
+ };
603
+ return { functions };
604
+ }
424
605
  };
425
606
  /**
426
607
  * Global flag set when @jesscss/plugin-js is loaded.
@@ -434,4 +615,6 @@ const jsPlugin = ((opts) => {
434
615
  //#endregion
435
616
  exports.JESS_PLUGIN_JS_GLOBAL = JESS_PLUGIN_JS_GLOBAL;
436
617
  exports.JsPlugin = JsPlugin;
618
+ exports.__toESM = __toESM;
437
619
  exports.default = jsPlugin;
620
+ exports.sanitizeSpawnEnv = sanitizeSpawnEnv;
package/lib/index.d.ts CHANGED
@@ -6,7 +6,21 @@ export type JavaScriptSandboxConfig = {
6
6
  };
7
7
  export interface JsPluginOptions extends JavaScriptSandboxConfig {
8
8
  denoCommand?: string;
9
+ /**
10
+ * Runtime API exposed inside the Deno worker.
11
+ *
12
+ * Jess `@-use`/script imports run as plain ESM modules. Legacy Less
13
+ * `@plugin` loading can opt into the Less-compatible global shape.
14
+ */
15
+ runtimeApi?: 'module' | 'less';
9
16
  }
17
+ /**
18
+ * Returns a copy of `env` with Node debugger/inspector-attach variables removed,
19
+ * so a spawned Deno subprocess starts regardless of the parent's debug env.
20
+ * The Deno permission sandbox is untouched; this only stops leaking the debugger
21
+ * into it.
22
+ */
23
+ export declare const sanitizeSpawnEnv: (env?: NodeJS.ProcessEnv) => NodeJS.ProcessEnv;
10
24
  export declare class JsPlugin extends AbstractPlugin {
11
25
  opts: JsPluginOptions;
12
26
  private static cleanupRegistered;
@@ -14,6 +28,7 @@ export declare class JsPlugin extends AbstractPlugin {
14
28
  name: string;
15
29
  supportedExtensions: string[];
16
30
  private runtimeState;
31
+ private shuttingDown;
17
32
  private brokerServer;
18
33
  private brokerSocketPath;
19
34
  private worker;
@@ -42,6 +57,15 @@ export declare class JsPlugin extends AbstractPlugin {
42
57
  dispose(): void;
43
58
  private assertAllowedPath;
44
59
  import(absoluteFilePath: string): Promise<Record<string, any>>;
60
+ /**
61
+ * Loads a legacy Less `@plugin` wrapper file in Deno Less-compat mode.
62
+ *
63
+ * @deprecated Less `@plugin` is deprecated. Prefer `@-from` for
64
+ * ESM-style script imports or `@-use` for Sass-module-style namespace imports.
65
+ */
66
+ importLessPlugin(absoluteFilePath: string): Promise<{
67
+ functions: Record<string, (...args: unknown[]) => Promise<unknown>>;
68
+ }>;
45
69
  }
46
70
  /**
47
71
  * Global flag set when @jesscss/plugin-js is loaded.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,cAAc,EACf,MAAM,eAAe,CAAC;AAOvB,MAAM,MAAM,uBAAuB,GAAG;IACpC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,WAAW,eAAgB,SAAQ,uBAAuB;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAqGD,qBAAa,QAAS,SAAQ,cAAc;IAmBvB,IAAI,EAAE,eAAe;IAlBxC,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAS;IACzC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAuB;IACnD,IAAI,SAAQ;IACZ,mBAAmB,WAAiC;IACpD,OAAO,CAAC,YAAY,CAAoC;IACxD,OAAO,CAAC,YAAY,CAAyB;IAC7C,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,MAAM,CAA6C;IAC3D,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,OAAO,CAIV;IAEL,OAAO,CAAC,SAAS,CAA6B;gBAE3B,IAAI,GAAE,eAAoB;IAM7C,OAAO;IAIP,OAAO,CAAC,MAAM,CAAC,sBAAsB;IAkBrC,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,oBAAoB;IAY5B,OAAO,CAAC,sBAAsB;IAU9B,OAAO,CAAC,aAAa;IAyBrB,OAAO,CAAC,gBAAgB;IAUxB,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,mBAAmB;YA0Bb,WAAW;IA4CzB,OAAO,CAAC,WAAW;YAmEL,YAAY;IAW1B,OAAO,CAAC,cAAc;IAiCtB,OAAO,CAAC,gBAAgB;YAQV,UAAU;IAsBxB,OAAO,CAAC,QAAQ;IAsBhB,OAAO;IAKP,OAAO,CAAC,iBAAiB;IAgBnB,MAAM,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CA8CrE;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,iCAAiC,CAAC;AAOpE,QAAA,MAAM,QAAQ,UAAY,eAAe,aAEtB,CAAC;AAEpB,eAAe,QAAQ,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,cAAc,EACf,MAAM,eAAe,CAAC;AAQvB,MAAM,MAAM,uBAAuB,GAAG;IACpC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,EAAE,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,WAAW,eAAgB,SAAQ,uBAAuB;IAC9D,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB;;;;;OAKG;IACH,UAAU,CAAC,EAAE,QAAQ,GAAG,MAAM,CAAC;CAChC;AAmCD;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,GAC3B,MAAK,MAAM,CAAC,UAAwB,KACnC,MAAM,CAAC,UAYT,CAAC;AA0FF,qBAAa,QAAS,SAAQ,cAAc;IAoBvB,IAAI,EAAE,eAAe;IAnBxC,OAAO,CAAC,MAAM,CAAC,iBAAiB,CAAS;IACzC,OAAO,CAAC,MAAM,CAAC,aAAa,CAAuB;IACnD,IAAI,SAAQ;IACZ,mBAAmB,WAAiC;IACpD,OAAO,CAAC,YAAY,CAAoC;IACxD,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,YAAY,CAAyB;IAC7C,OAAO,CAAC,gBAAgB,CAAqB;IAC7C,OAAO,CAAC,MAAM,CAA6C;IAC3D,OAAO,CAAC,YAAY,CAAM;IAC1B,OAAO,CAAC,aAAa,CAAK;IAC1B,OAAO,CAAC,OAAO,CAIV;IAEL,OAAO,CAAC,SAAS,CAA6B;gBAE3B,IAAI,GAAE,eAAoB;IAM7C,OAAO;IAIP,OAAO,CAAC,MAAM,CAAC,sBAAsB;IAkBrC,OAAO,CAAC,cAAc;IAOtB,OAAO,CAAC,oBAAoB;IAY5B,OAAO,CAAC,sBAAsB;IAW9B,OAAO,CAAC,aAAa;IA4BrB,OAAO,CAAC,gBAAgB;IAUxB,OAAO,CAAC,aAAa;IAarB,OAAO,CAAC,YAAY;IAepB,OAAO,CAAC,mBAAmB;YA0Bb,WAAW;IA8CzB,OAAO,CAAC,WAAW;YAwFL,YAAY;IAW1B,OAAO,CAAC,cAAc;IAiCtB,OAAO,CAAC,gBAAgB;YAQV,UAAU;IAwBxB,OAAO,CAAC,QAAQ;IA0BhB,OAAO;IAMP,OAAO,CAAC,iBAAiB;IAgBnB,MAAM,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IA+CpE;;;;;OAKG;IACG,gBAAgB,CAAC,gBAAgB,EAAE,MAAM,GAAG,OAAO,CAAC;QAAE,SAAS,EAAE,MAAM,CAAC,MAAM,EAAE,CAAC,GAAG,IAAI,EAAE,OAAO,EAAE,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC,CAAA;KAAE,CAAC;CA6BnI;AAED;;;GAGG;AACH,eAAO,MAAM,qBAAqB,iCAAiC,CAAC;AAOpE,QAAA,MAAM,QAAQ,UAAY,eAAe,aAEtB,CAAC;AAEpB,eAAe,QAAQ,CAAC"}