@decohere/flux 0.0.1-dev.130 → 0.0.1-dev.131

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
@@ -240,7 +240,7 @@ Only source files (`.ts`) that a served entry imports trigger a reboot.
240
240
 
241
241
  **Memory grows over a long session.** Each reboot imports changed modules under a new `?version=` URL, and Node's ES module cache never releases the old versions. That's fine for a working day; if a session runs for days with thousands of reboots, restart it.
242
242
 
243
- Flux uses **Forge’s compiler**, with one SWC config per project built once per run. SWC leaves imports as written; Flux's resolve hook maps each one to its TypeScript source: `@scope/pkg` and `@scope/pkg/sub` through the the workspace package aliases (and tsconfig `paths`), `./file.js` and `./file` to `file.ts` or `file.tsx`, `./file.mjs` to `file.mts`, `./file.cjs` to `file.cts` (which runs as CommonJS), and `./dir` to `dir/index.ts`. Doing it in one place, instead of in SWC (`jsc.paths`, `resolveFully`) and again in the hook, made loading about 20% faster once Node and SWC are warm (`pnpm bench flux-load`). Before Node imports an entry, Flux compiles it and the files it imports, following their imports out from the entry, in parallel on SWC's thread pool. The load hook is synchronous and would otherwise compile one file at a time; files the app never imports, such as tests, are not compiled. A file that fails to compile there is compiled again when Node loads it, and that load fails with the file's name, as before. That is a debug rule so you can edit a library and hit HMR without a pre-build or `node_modules` workspace symlink. Release still resolves through real `node_modules` (published `exports` / `main`).
243
+ Flux uses **Forge’s compiler** (`@decohere/forge/transpile`), with one SWC config per project built once per run. It never loads the TypeScript compiler: SWC strips types without checking them, so type errors are `forge typecheck`'s job. SWC leaves imports as written; Flux's resolve hook maps each one to its TypeScript source: `@scope/pkg` and `@scope/pkg/sub` through the the workspace package aliases (and tsconfig `paths`), `./file.js` and `./file` to `file.ts` or `file.tsx`, `./file.mjs` to `file.mts`, `./file.cjs` to `file.cts` (which runs as CommonJS), and `./dir` to `dir/index.ts`. Doing it in one place, instead of in SWC (`jsc.paths`, `resolveFully`) and again in the hook, made loading about 20% faster once Node and SWC are warm (`pnpm bench flux-load`). Before Node imports an entry, Flux compiles it and the files it imports, following their imports out from the entry, in parallel on SWC's thread pool. The load hook is synchronous and would otherwise compile one file at a time; files the app never imports, such as tests, are not compiled. A file that fails to compile there is compiled again when Node loads it, and that load fails with the file's name, as before. That is a debug rule so you can edit a library and hit HMR without a pre-build or `node_modules` workspace symlink. Release still resolves through real `node_modules` (published `exports` / `main`).
244
244
 
245
245
  Why aliases, and a tree of where a symlink misses `src/index.ts`: [Forge — debug path aliases](../forge/README.md#debug-path-aliases-not-node_modules-links).
246
246
 
@@ -8,7 +8,7 @@ Object.defineProperty(exports, "FluxModule", {
8
8
  return FluxModule;
9
9
  }
10
10
  });
11
- const _forge = require("@decohere/forge");
11
+ const _transpile = require("@decohere/forge/transpile");
12
12
  const _cli = require("@decohere/devkit/cli");
13
13
  const _deferredscriptrunner = require("./deferred-script-runner.js");
14
14
  const _fluxcommand = require("./flux.command.js");
@@ -28,6 +28,6 @@ class FluxModule extends _cli.ModuleManifest {
28
28
  }
29
29
  createWorkspace(options) {
30
30
  // Same workspace as `flux.run` / `flux.serve` and forge.
31
- return (0, _forge.createWorkspace)(options);
31
+ return (0, _transpile.createWorkspace)(options);
32
32
  }
33
33
  }
@@ -13,7 +13,7 @@ const _nodemodule = require("node:module");
13
13
  const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
14
14
  const _nodeurl = require("node:url");
15
15
  const _decorators = require("@decohere/crucible/decorators");
16
- const _forge = require("@decohere/forge");
16
+ const _transpile = require("@decohere/forge/transpile");
17
17
  const _workspace = require("@decohere/workspace");
18
18
  const _io = require("@decohere/core/io");
19
19
  const _scribe = require("@decohere/scribe");
@@ -74,7 +74,7 @@ function _ts_decorate(decorators, target, key, desc) {
74
74
  }
75
75
  class SourceModuleLoader {
76
76
  logger = _scribe.scribe.logger(SourceModuleLoader.name);
77
- transpiler = new _forge.SwcTranspiler();
77
+ transpiler = new _transpile.SwcTranspiler();
78
78
  disposed = false;
79
79
  hooksRegistered = false;
80
80
  workspace;
@@ -113,7 +113,7 @@ class SourceModuleLoader {
113
113
  this.swcConfigs.clear();
114
114
  this.commonJsConfigs.clear();
115
115
  this.buildConfig = options.buildConfig;
116
- this.workspace = options.workspace ?? await (0, _forge.createWorkspace)();
116
+ this.workspace = options.workspace ?? await (0, _transpile.createWorkspace)();
117
117
  this.versionFileUrl = options.versionFileUrl ?? ((fileUrl)=>fileUrl);
118
118
  this.onResolved = options.onResolved;
119
119
  this.fileInfoMap = await this.buildFileInfoMap(this.buildConfig);
@@ -306,7 +306,7 @@ class SourceModuleLoader {
306
306
  const key = this.diskCache?.keyFor(fullPath, source, baseConfig);
307
307
  const hit = key == null ? undefined : this.diskCache?.readSync(key);
308
308
  if (hit != null) return hit;
309
- const response = this.transpiler.transformCodeSync(source, file, _forge.BuildTargets.es6, baseConfig);
309
+ const response = this.transpiler.transformCodeSync(source, file, _transpile.BuildTargets.es6, baseConfig);
310
310
  if (response.outcome !== "success") {
311
311
  this.logger.error(`Failed to transpile ${fullPath}`, response);
312
312
  throw new Error(`Failed to transpile ${fullPath}`);
@@ -335,7 +335,7 @@ class SourceModuleLoader {
335
335
  const key = this.diskCache?.keyFor(fullPath, source, baseConfig);
336
336
  const hit = key == null ? undefined : this.diskCache?.readSync(key);
337
337
  if (hit != null) return hit;
338
- const response = await this.transpiler.transformCode(source, file, _forge.BuildTargets.es6, baseConfig);
338
+ const response = await this.transpiler.transformCode(source, file, _transpile.BuildTargets.es6, baseConfig);
339
339
  if (response.outcome !== "success") return undefined;
340
340
  if (key != null) await this.diskCache?.write(key, response.code);
341
341
  return response.code;
@@ -364,7 +364,7 @@ class SourceModuleLoader {
364
364
  /** Forge's defaults when there is no project: decorators and their metadata on. */ esModuleConfigFor(project) {
365
365
  const cached = this.swcConfigs.get(project);
366
366
  if (cached != null) return cached;
367
- const base = this.transpiler.createBaseConfig(_forge.BuildTargets.es6, {
367
+ const base = this.transpiler.createBaseConfig(_transpile.BuildTargets.es6, {
368
368
  tsConfig: project?.getTsConfigSync(),
369
369
  userConfig: project?.getSwcConfigSync(),
370
370
  aliasPaths: false,
@@ -11,7 +11,7 @@ Object.defineProperty(exports, "TranspileDiskCache", {
11
11
  const _nodecrypto = require("node:crypto");
12
12
  const _nodefs = /*#__PURE__*/ _interop_require_default(require("node:fs"));
13
13
  const _nodepath = /*#__PURE__*/ _interop_require_default(require("node:path"));
14
- const _forge = require("@decohere/forge");
14
+ const _transpile = require("@decohere/forge/transpile");
15
15
  const _scribe = require("@decohere/scribe");
16
16
  function _interop_require_default(obj) {
17
17
  return obj && obj.__esModule ? obj : {
@@ -30,7 +30,7 @@ class TranspileDiskCache {
30
30
  this.dir = dir;
31
31
  }
32
32
  /** The cache for a workspace, or null when caching is off (`DECOHERE_CACHE=0`). */ static forWorkspace(rootDir) {
33
- const base = _forge.transpileCache.directory(rootDir);
33
+ const base = _transpile.transpileCache.directory(rootDir);
34
34
  return base == null ? null : new TranspileDiskCache(_nodepath.default.join(base, "flux"));
35
35
  }
36
36
  get directory() {
@@ -41,7 +41,7 @@ class TranspileDiskCache {
41
41
  * file's path (forge's `createFileConfig`), so hashing the base once per project and adding
42
42
  * the path covers them without serialising options for every file.
43
43
  */ keyFor(fullPath, source, baseOptions) {
44
- return (0, _nodecrypto.createHash)("sha256").update(`${FORMAT}\0${_forge.transpileCache.swcVersion}\0${this.optionsHash(baseOptions)}\0`).update(`${fullPath}\0`).update(source).digest("hex");
44
+ return (0, _nodecrypto.createHash)("sha256").update(`${FORMAT}\0${_transpile.transpileCache.swcVersion}\0${this.optionsHash(baseOptions)}\0`).update(`${fullPath}\0`).update(source).digest("hex");
45
45
  }
46
46
  optionsHashes = new WeakMap();
47
47
  optionsHash(options) {
@@ -1,4 +1,4 @@
1
- import { createWorkspace } from "@decohere/forge";
1
+ import { createWorkspace } from "@decohere/forge/transpile";
2
2
  import { ModuleManifest } from "@decohere/devkit/cli";
3
3
  import { DeferredScriptRunner } from "./deferred-script-runner.js";
4
4
  import { FluxCommand } from "./flux.command.js";
@@ -9,7 +9,7 @@ import { registerHooks } from "node:module";
9
9
  import path from "node:path";
10
10
  import { fileURLToPath, pathToFileURL } from "node:url";
11
11
  import { injectable } from "@decohere/crucible/decorators";
12
- import { BuildTargets, createWorkspace, SwcTranspiler } from "@decohere/forge";
12
+ import { BuildTargets, createWorkspace, SwcTranspiler } from "@decohere/forge/transpile";
13
13
  import { packageAliases, sourceExtensions } from "@decohere/workspace";
14
14
  import { FileEx, io } from "@decohere/core/io";
15
15
  import { scribe } from "@decohere/scribe";
@@ -1,7 +1,7 @@
1
1
  import { createHash, randomBytes } from "node:crypto";
2
2
  import fs from "node:fs";
3
3
  import path from "node:path";
4
- import { transpileCache } from "@decohere/forge";
4
+ import { transpileCache } from "@decohere/forge/transpile";
5
5
  import { scribe } from "@decohere/scribe";
6
6
  /** Bump when what flux stores changes, so older entries stop matching. */ const FORMAT = 1;
7
7
  /** Entries untouched for this long are pruned. */ const MAX_AGE_MS = 30 * 24 * 60 * 60 * 1000;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decohere/flux",
3
- "version": "0.0.1-dev.130",
3
+ "version": "0.0.1-dev.131",
4
4
  "description": "Hot module reload server for Node.js ESM applications",
5
5
  "keywords": [
6
6
  "typescript",
@@ -34,14 +34,13 @@
34
34
  "test": "echo \"Error: no test specified\" && exit 1"
35
35
  },
36
36
  "dependencies": {
37
- "@decohere/core": "0.0.1-dev.130",
38
- "@decohere/crucible": "0.0.1-dev.130",
39
- "@decohere/devkit": "0.0.1-dev.130",
40
- "@decohere/forge": "0.0.1-dev.130",
41
- "@decohere/scribe": "0.0.1-dev.130",
42
- "@decohere/workspace": "0.0.1-dev.130",
43
- "commander": "^13.1.0",
44
- "rxjs": "^7.8.2"
37
+ "@decohere/core": "0.0.1-dev.131",
38
+ "@decohere/crucible": "0.0.1-dev.131",
39
+ "@decohere/devkit": "0.0.1-dev.131",
40
+ "@decohere/forge": "0.0.1-dev.131",
41
+ "@decohere/scribe": "0.0.1-dev.131",
42
+ "@decohere/workspace": "0.0.1-dev.131",
43
+ "commander": "^13.1.0"
45
44
  },
46
45
  "devDependencies": {}
47
46
  }