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

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
@@ -49,7 +49,7 @@ Scaffolded apps already depend on `@decohere/cli` — use those scripts (`pnpm d
49
49
 
50
50
  ## CLI
51
51
 
52
- Host options (`--config-file`, `--log-level`) are parsed before the subcommand. `--config-file` (default `.decohere.js` if present) is optional workspace config for package discovery. Omit it to use [workspace defaults](../workspace/README.md#workspace-layout).
52
+ Host options (`--root-dir`, `--config-file`, `--log-level`) are parsed before the subcommand. `--root-dir` (default: the current folder) is the workspace root. `--config-file` (default `.decohere.js` in the root, if present) is optional workspace config for package discovery. Omit it to use [workspace defaults](../workspace/README.md#workspace-layout).
53
53
 
54
54
  ### `flux run` — one-shot script
55
55
 
@@ -137,7 +137,7 @@ class SourceModuleLoader {
137
137
  const rewritten = (0, _rewriteservespecifier.rewriteServeSpecifier)({
138
138
  specifier,
139
139
  parentUrl,
140
- isWatchedTs: (filePath)=>this.fileInfoMap.has(filePath),
140
+ isWatchedTs: (filePath)=>this.sourceInfo(filePath) != null,
141
141
  resolveBare: (bare)=>_workspace.packageAliases.resolvePath(bare, this.aliasPaths, this.aliasBaseUrl),
142
142
  versionFileUrl: this.versionFileUrl
143
143
  }) ?? specifier;
@@ -180,6 +180,16 @@ class SourceModuleLoader {
180
180
  this.workspace?.[Symbol.dispose]();
181
181
  this.workspace = undefined;
182
182
  }
183
+ /**
184
+ * The file as a source flux compiles: a workspace package's file, or any other TypeScript
185
+ * source on disk outside `node_modules`, which Node would otherwise only strip of types, failing
186
+ * on enums, decorators and parameter properties. Null for everything else.
187
+ */ sourceInfo(fullPath) {
188
+ const fileInfo = this.fileInfoMap.get(fullPath);
189
+ if (fileInfo != null) return fileInfo;
190
+ const outsidePackages = _workspace.sourceExtensions.isSource(fullPath) && !fullPath.split(/[/\\]/).includes("node_modules") && (0, _nodefs.existsSync)(fullPath);
191
+ return outsidePackages ? {} : null;
192
+ }
183
193
  async buildFileInfoMap(buildConfig) {
184
194
  const projects = this.workspace?.getProjects(buildConfig) ?? [];
185
195
  const entries = await Promise.all(projects.map(async (project)=>{
@@ -228,7 +238,7 @@ class SourceModuleLoader {
228
238
  this.reachedFrom.set(entryPath, seen);
229
239
  }
230
240
  /** The file's compiled code, from the cache or compiled now; undefined if it isn't a source. */ compiledAhead(fullPath) {
231
- const fileInfo = this.fileInfoMap.get(fullPath);
241
+ const fileInfo = this.sourceInfo(fullPath);
232
242
  if (fileInfo == null) return Promise.resolve(undefined);
233
243
  const cached = this.transpileCache.get(fullPath);
234
244
  if (cached != null) return Promise.resolve(cached);
@@ -250,7 +260,7 @@ class SourceModuleLoader {
250
260
  const url = (0, _rewriteservespecifier.rewriteServeSpecifier)({
251
261
  specifier,
252
262
  parentUrl,
253
- isWatchedTs: (filePath)=>this.fileInfoMap.has(filePath),
263
+ isWatchedTs: (filePath)=>this.sourceInfo(filePath) != null,
254
264
  resolveBare: (bare)=>_workspace.packageAliases.resolvePath(bare, this.aliasPaths, this.aliasBaseUrl),
255
265
  versionFileUrl: (fileUrl)=>fileUrl
256
266
  });
@@ -261,7 +271,7 @@ class SourceModuleLoader {
261
271
  // fileURLToPath, not URL.pathname: decodes %20 and gives Windows paths, so files
262
272
  // whose path has a space still match the workspace's package list.
263
273
  const cleanPath = (0, _nodeurl.fileURLToPath)(url);
264
- const fileInfo = this.fileInfoMap.get(cleanPath);
274
+ const fileInfo = this.sourceInfo(cleanPath);
265
275
  if (fileInfo == null) return null;
266
276
  const format = _workspace.sourceExtensions.isCommonJs(cleanPath) ? "commonjs" : "module";
267
277
  const cached = this.transpileCache.get(cleanPath);
@@ -351,12 +361,12 @@ class SourceModuleLoader {
351
361
  this.commonJsConfigs.set(project, commonJs);
352
362
  return commonJs;
353
363
  }
354
- esModuleConfigFor(project) {
364
+ /** Forge's defaults when there is no project: decorators and their metadata on. */ esModuleConfigFor(project) {
355
365
  const cached = this.swcConfigs.get(project);
356
366
  if (cached != null) return cached;
357
367
  const base = this.transpiler.createBaseConfig(_forge.BuildTargets.es6, {
358
- tsConfig: project.getTsConfigSync(),
359
- userConfig: project.getSwcConfigSync(),
368
+ tsConfig: project?.getTsConfigSync(),
369
+ userConfig: project?.getSwcConfigSync(),
360
370
  aliasPaths: false,
361
371
  workspace: this.workspace
362
372
  });
@@ -4,7 +4,7 @@ function _ts_decorate(decorators, target, key, desc) {
4
4
  else for(var i = decorators.length - 1; i >= 0; i--)if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  }
7
- import { readFileSync } from "node:fs";
7
+ import { existsSync, readFileSync } from "node:fs";
8
8
  import { registerHooks } from "node:module";
9
9
  import path from "node:path";
10
10
  import { fileURLToPath, pathToFileURL } from "node:url";
@@ -81,7 +81,7 @@ export class SourceModuleLoader {
81
81
  const rewritten = rewriteServeSpecifier({
82
82
  specifier,
83
83
  parentUrl,
84
- isWatchedTs: (filePath)=>this.fileInfoMap.has(filePath),
84
+ isWatchedTs: (filePath)=>this.sourceInfo(filePath) != null,
85
85
  resolveBare: (bare)=>packageAliases.resolvePath(bare, this.aliasPaths, this.aliasBaseUrl),
86
86
  versionFileUrl: this.versionFileUrl
87
87
  }) ?? specifier;
@@ -124,6 +124,16 @@ export class SourceModuleLoader {
124
124
  this.workspace?.[Symbol.dispose]();
125
125
  this.workspace = undefined;
126
126
  }
127
+ /**
128
+ * The file as a source flux compiles: a workspace package's file, or any other TypeScript
129
+ * source on disk outside `node_modules`, which Node would otherwise only strip of types, failing
130
+ * on enums, decorators and parameter properties. Null for everything else.
131
+ */ sourceInfo(fullPath) {
132
+ const fileInfo = this.fileInfoMap.get(fullPath);
133
+ if (fileInfo != null) return fileInfo;
134
+ const outsidePackages = sourceExtensions.isSource(fullPath) && !fullPath.split(/[/\\]/).includes("node_modules") && existsSync(fullPath);
135
+ return outsidePackages ? {} : null;
136
+ }
127
137
  async buildFileInfoMap(buildConfig) {
128
138
  const projects = this.workspace?.getProjects(buildConfig) ?? [];
129
139
  const entries = await Promise.all(projects.map(async (project)=>{
@@ -172,7 +182,7 @@ export class SourceModuleLoader {
172
182
  this.reachedFrom.set(entryPath, seen);
173
183
  }
174
184
  /** The file's compiled code, from the cache or compiled now; undefined if it isn't a source. */ compiledAhead(fullPath) {
175
- const fileInfo = this.fileInfoMap.get(fullPath);
185
+ const fileInfo = this.sourceInfo(fullPath);
176
186
  if (fileInfo == null) return Promise.resolve(undefined);
177
187
  const cached = this.transpileCache.get(fullPath);
178
188
  if (cached != null) return Promise.resolve(cached);
@@ -194,7 +204,7 @@ export class SourceModuleLoader {
194
204
  const url = rewriteServeSpecifier({
195
205
  specifier,
196
206
  parentUrl,
197
- isWatchedTs: (filePath)=>this.fileInfoMap.has(filePath),
207
+ isWatchedTs: (filePath)=>this.sourceInfo(filePath) != null,
198
208
  resolveBare: (bare)=>packageAliases.resolvePath(bare, this.aliasPaths, this.aliasBaseUrl),
199
209
  versionFileUrl: (fileUrl)=>fileUrl
200
210
  });
@@ -205,7 +215,7 @@ export class SourceModuleLoader {
205
215
  // fileURLToPath, not URL.pathname: decodes %20 and gives Windows paths, so files
206
216
  // whose path has a space still match the workspace's package list.
207
217
  const cleanPath = fileURLToPath(url);
208
- const fileInfo = this.fileInfoMap.get(cleanPath);
218
+ const fileInfo = this.sourceInfo(cleanPath);
209
219
  if (fileInfo == null) return null;
210
220
  const format = sourceExtensions.isCommonJs(cleanPath) ? "commonjs" : "module";
211
221
  const cached = this.transpileCache.get(cleanPath);
@@ -295,12 +305,12 @@ export class SourceModuleLoader {
295
305
  this.commonJsConfigs.set(project, commonJs);
296
306
  return commonJs;
297
307
  }
298
- esModuleConfigFor(project) {
308
+ /** Forge's defaults when there is no project: decorators and their metadata on. */ esModuleConfigFor(project) {
299
309
  const cached = this.swcConfigs.get(project);
300
310
  if (cached != null) return cached;
301
311
  const base = this.transpiler.createBaseConfig(BuildTargets.es6, {
302
- tsConfig: project.getTsConfigSync(),
303
- userConfig: project.getSwcConfigSync(),
312
+ tsConfig: project?.getTsConfigSync(),
313
+ userConfig: project?.getSwcConfigSync(),
304
314
  aliasPaths: false,
305
315
  workspace: this.workspace
306
316
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decohere/flux",
3
- "version": "0.0.1-dev.129",
3
+ "version": "0.0.1-dev.130",
4
4
  "description": "Hot module reload server for Node.js ESM applications",
5
5
  "keywords": [
6
6
  "typescript",
@@ -34,12 +34,12 @@
34
34
  "test": "echo \"Error: no test specified\" && exit 1"
35
35
  },
36
36
  "dependencies": {
37
- "@decohere/core": "0.0.1-dev.129",
38
- "@decohere/crucible": "0.0.1-dev.129",
39
- "@decohere/devkit": "0.0.1-dev.129",
40
- "@decohere/forge": "0.0.1-dev.129",
41
- "@decohere/scribe": "0.0.1-dev.129",
42
- "@decohere/workspace": "0.0.1-dev.129",
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
43
  "commander": "^13.1.0",
44
44
  "rxjs": "^7.8.2"
45
45
  },
@@ -17,8 +17,9 @@ export interface SourceModuleLoaderOptions {
17
17
  onResolved?: (result: ResolveFnOutput, parentUrl: string) => void;
18
18
  }
19
19
  /**
20
- * Registers Node ESM resolve/load hooks and SWC-transpiles workspace `.ts`
21
- * on the fly. No file watching and no entry reboot — that belongs to
20
+ * Registers Node ESM resolve/load hooks and SWC-transpiles TypeScript on the fly: workspace
21
+ * packages' files with their package's options, and any other source outside `node_modules`
22
+ * (a script in a plain folder) with Forge's defaults. No file watching and no entry reboot — that belongs to
22
23
  * {@link HotReloadServer}.
23
24
  */
24
25
  export declare class SourceModuleLoader {
@@ -54,6 +55,12 @@ export declare class SourceModuleLoader {
54
55
  importEntry(absolutePath: string): Promise<unknown>;
55
56
  invalidateTranspile(...absolutePaths: string[]): void;
56
57
  dispose(): void;
58
+ /**
59
+ * The file as a source flux compiles: a workspace package's file, or any other TypeScript
60
+ * source on disk outside `node_modules`, which Node would otherwise only strip of types, failing
61
+ * on enums, decorators and parameter properties. Null for everything else.
62
+ */
63
+ private sourceInfo;
57
64
  private buildFileInfoMap;
58
65
  /**
59
66
  * Compiles the entry and the source files it imports, before Node imports it. The load
@@ -92,5 +99,6 @@ export declare class SourceModuleLoader {
92
99
  * directory indexes), so SWC does not resolve them a second time against the disk.
93
100
  */
94
101
  private swcConfigFor;
102
+ /** Forge's defaults when there is no project: decorators and their metadata on. */
95
103
  private esModuleConfigFor;
96
104
  }