@decohere/forge 0.0.1-dev.125 → 0.0.1-dev.126

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
@@ -8,9 +8,9 @@ Build system (SWC). `forge build --configuration debug` rewrites workspace impor
8
8
 
9
9
  ## Debug path aliases (not `node_modules` links)
10
10
 
11
- Forge debug (`aliasPaths: true`) asks the workspace package for a map of `package.json` `name` → source `main` (`Workspace.getPackageAliases`) and feeds it to SWC as `jsc.paths`. Flux uses the same map in its resolve hook only, and compiles without `jsc.paths` or `resolveFully`, so imports are resolved once (#513).
11
+ Forge debug (`aliasPaths: true`) asks the workspace package for a map of `package.json` `name` → source `main` (`Workspace.getPackageAliases`) and feeds it to SWC as `jsc.paths`. Flux uses the same map in its resolve hook only, and compiles without `jsc.paths` or `resolveFully`, so imports are resolved once.
12
12
 
13
- `tsc` can't read the workspace alias map, and without `node_modules` links it finds workspace packages only through tsconfig `paths`. `forge paths` writes the map to `tsconfig.paths.json` for the root tsconfig to extend, and `forge paths --check` fails when the file is out of date (#518).
13
+ `tsc` can't read the workspace alias map, and without `node_modules` links it finds workspace packages only through tsconfig `paths`. `forge paths` writes the map to `tsconfig.paths.json` for the root tsconfig to extend, and `forge paths --check` fails when the file is out of date.
14
14
 
15
15
  That is a **debug** rule. Release does not rewrite aliases: production must resolve like any other Node app (installed packages, `exports` / `main` pointing at emitted JS).
16
16
 
@@ -98,7 +98,7 @@ projects/shop.api/.package/
98
98
  ```
99
99
 
100
100
  - **Which libraries.** Forge walks the compiled import graph from the deployable's `main`, following relative imports and bare imports that the workspace package resolves to a workspace project (including subpath `exports` such as `@app/kernel/testing`, and transitively through copied libraries). Only those libraries are copied. A library nothing reaches, and its dependencies, stay out.
101
- - **Which third-party packages.** What is **declared** ships: the union of `dependencies` (never `devDependencies`) of the deployable, every copied library and the workspace root `package.json`. They do not have to be imported, so a module loaded by name at run time (a pino transport `target: "pino-roll"`) ships as long as it is declared. Removing dependencies nothing uses is the author's job; a warning-only unused-dependency analysis is planned in [#635](https://github.com/typesmiths/decohere/issues/635).
101
+ - **Which third-party packages.** What is **declared** ships: the union of `dependencies` (never `devDependencies`) of the deployable, every copied library and the workspace root `package.json`. They do not have to be imported, so a module loaded by name at run time (a pino transport `target: "pino-roll"`) ships as long as it is declared. Removing dependencies nothing uses is the author's job; a warning-only unused-dependency analysis is planned.
102
102
  - **Versions.** Each shipped package is pinned to the exact version installed in the workspace (so the image runs what the tests ran). A declared package that is not installed fails the command.
103
103
  - **Imports that would crash.** If packaged code imports a third-party package that is only a `devDependency`, or declared nowhere, the command fails and names the package and who imports it.
104
104
  - **Install first, copy second.** `npm` removes folders it does not know, so the libraries are copied in after it runs. `npm` (not pnpm) is used because it writes real folders. The command fails if the output holds any symlink.
@@ -132,7 +132,7 @@ export default {
132
132
  };
133
133
  ```
134
134
 
135
- `forge package @app/shop.api` then copies `projects/shop.web/dist/` to `projects/shop.api/.package/ui/` (real files, never links). The API calls `.withStatic("/ui/", "ui")` and the Dockerfile stays `COPY .package/ ./`. `forge package` does **not** build the UI: if the folder is missing it fails and tells you to build the UI first. `to` must be a new folder inside `.package/` (not `es6`, `node_modules` or `config`). Running the UI's own toolchain from `forge build` is [#381](https://github.com/typesmiths/decohere/issues/381); see [ADR 0007](../../docs/adr/0007-serving-a-built-ui-from-http.md).
135
+ `forge package @app/shop.api` then copies `projects/shop.web/dist/` to `projects/shop.api/.package/ui/` (real files, never links). The API calls `.withStatic("/ui/", "ui")` and the Dockerfile stays `COPY .package/ ./`. `forge package` does **not** build the UI: if the folder is missing it fails and tells you to build the UI first. `to` must be a new folder inside `.package/` (not `es6`, `node_modules` or `config`). Running the UI's own toolchain from `forge build` is not done yet; see [ADR 0007](../../docs/adr/0007-serving-a-built-ui-from-http.md).
136
136
 
137
137
  Design record: [ADR 0006](../../docs/adr/0006-forge-package-deployables.md).
138
138
 
@@ -73,7 +73,7 @@ class SwcConfigFactory {
73
73
  mergeArrays: false
74
74
  }, defaultOptions, options, userConfig ?? {});
75
75
  }
76
- /** Stamps a per-file filename onto a pre-built base config; `.tsx` also turns on JSX (#518). */ createFileConfig(file, baseConfig) {
76
+ /** Stamps a per-file filename onto a pre-built base config; `.tsx` also turns on JSX. */ createFileConfig(file, baseConfig) {
77
77
  const tsx = file.fullPath.endsWith(".tsx");
78
78
  const jsc = tsx && baseConfig.jsc?.parser?.syntax === "typescript" ? {
79
79
  ...baseConfig.jsc,
@@ -92,7 +92,7 @@ class SwcTranspiler {
92
92
  */ createBaseConfig(buildTarget, options = {}) {
93
93
  return this.#swcConfigFactory.createBaseConfig(buildTarget, this.withAliasContext(options));
94
94
  }
95
- /** Sync variant of {@link transformCode}, for the load hook, which cannot await (#514). */ transformCodeSync(content, file, buildTarget, baseConfig) {
95
+ /** Sync variant of {@link transformCode}, for the load hook, which cannot await. */ transformCodeSync(content, file, buildTarget, baseConfig) {
96
96
  const swcOptions = this.#swcConfigFactory.createFileConfig(file, baseConfig);
97
97
  if (content === "") return SwcTranspiler.skippedEmpty(file, swcOptions);
98
98
  try {
@@ -114,8 +114,8 @@ class SwcTranspiler {
114
114
  /**
115
115
  * Compiles `content` as the source of `file`, without reading the file: for callers that
116
116
  * already hold the code, such as the Vitest plugin, which must compile what Vite passes it
117
- * rather than an earlier read of the disk (#517). Async SWC, on the thread pool, so many
118
- * calls in flight compile in parallel (#661). With a `project`, the response carries where
117
+ * rather than an earlier read of the disk. Async SWC, on the thread pool, so many
118
+ * calls in flight compile in parallel. With a `project`, the response carries where
119
119
  * the build writes the output.
120
120
  */ async transformCode(content, file, buildTarget, baseConfig, project) {
121
121
  const swcOptions = this.#swcConfigFactory.createFileConfig(file, baseConfig);
@@ -18,7 +18,7 @@ function _interop_require_default(obj) {
18
18
  };
19
19
  }
20
20
  /**
21
- * Where compiled code is cached on disk (#514), or null when caching is off:
21
+ * Where compiled code is cached on disk, or null when caching is off:
22
22
  *
23
23
  * - `DECOHERE_CACHE=0` turns it off.
24
24
  * - `DECOHERE_CACHE_DIR` puts it in that directory.
@@ -41,7 +41,7 @@ function forgeBuild(options) {
41
41
  const transpiler = new _swctranspiler.SwcTranspiler();
42
42
  /**
43
43
  * SWC options per project (tsconfig, `.swcrc`, path aliases), built once: rebuilding them for
44
- * every file was most of the plugin's per-file cost, as it was in flux (#513, #517).
44
+ * every file was most of the plugin's per-file cost, as it was in flux.
45
45
  */ const baseConfigs = new Map();
46
46
  const transformCache = new Map();
47
47
  let workspace = null;
@@ -72,7 +72,7 @@ function forgeBuild(options) {
72
72
  logger.debug("Plugin loaded");
73
73
  },
74
74
  resolveId (source, importer) {
75
- // `./a.js` is `a.ts` or `a.tsx`, `./a.mjs` is `a.mts`, `./a.cjs` is `a.cts` (#518).
75
+ // `./a.js` is `a.ts` or `a.tsx`, `./a.mjs` is `a.mts`, `./a.cjs` is `a.cts`.
76
76
  if (importer != null && /\.[mc]?jsx?$/.test(source) && source.startsWith(".")) {
77
77
  const written = _nodepath.default.resolve(_nodepath.default.dirname(importer), source);
78
78
  return _workspace.sourceExtensions.candidates(written).find((c)=>(0, _nodefs.existsSync)(c)) ?? null;
@@ -93,7 +93,7 @@ function forgeBuild(options) {
93
93
  await initWorkspace();
94
94
  const project = await workspace?.findProject(id, buildConfig);
95
95
  // The code Vite passes, not a read of the file: no content cache can serve an older
96
- // version, and there is no pre-warm compiling files ahead from disk (#517).
96
+ // version, and there is no pre-warm compiling files ahead from disk.
97
97
  const response = await transpiler.transformCode(code, new _io.FileEx({
98
98
  fullPath: id,
99
99
  content: code
@@ -58,7 +58,7 @@ export class SwcConfigFactory {
58
58
  mergeArrays: false
59
59
  }, defaultOptions, options, userConfig ?? {});
60
60
  }
61
- /** Stamps a per-file filename onto a pre-built base config; `.tsx` also turns on JSX (#518). */ createFileConfig(file, baseConfig) {
61
+ /** Stamps a per-file filename onto a pre-built base config; `.tsx` also turns on JSX. */ createFileConfig(file, baseConfig) {
62
62
  const tsx = file.fullPath.endsWith(".tsx");
63
63
  const jsc = tsx && baseConfig.jsc?.parser?.syntax === "typescript" ? {
64
64
  ...baseConfig.jsc,
@@ -77,7 +77,7 @@ export class SwcTranspiler {
77
77
  */ createBaseConfig(buildTarget, options = {}) {
78
78
  return this.#swcConfigFactory.createBaseConfig(buildTarget, this.withAliasContext(options));
79
79
  }
80
- /** Sync variant of {@link transformCode}, for the load hook, which cannot await (#514). */ transformCodeSync(content, file, buildTarget, baseConfig) {
80
+ /** Sync variant of {@link transformCode}, for the load hook, which cannot await. */ transformCodeSync(content, file, buildTarget, baseConfig) {
81
81
  const swcOptions = this.#swcConfigFactory.createFileConfig(file, baseConfig);
82
82
  if (content === "") return SwcTranspiler.skippedEmpty(file, swcOptions);
83
83
  try {
@@ -99,8 +99,8 @@ export class SwcTranspiler {
99
99
  /**
100
100
  * Compiles `content` as the source of `file`, without reading the file: for callers that
101
101
  * already hold the code, such as the Vitest plugin, which must compile what Vite passes it
102
- * rather than an earlier read of the disk (#517). Async SWC, on the thread pool, so many
103
- * calls in flight compile in parallel (#661). With a `project`, the response carries where
102
+ * rather than an earlier read of the disk. Async SWC, on the thread pool, so many
103
+ * calls in flight compile in parallel. With a `project`, the response carries where
104
104
  * the build writes the output.
105
105
  */ async transformCode(content, file, buildTarget, baseConfig, project) {
106
106
  const swcOptions = this.#swcConfigFactory.createFileConfig(file, baseConfig);
@@ -3,7 +3,7 @@ import os from "node:os";
3
3
  import path from "node:path";
4
4
  import { version as swcVersion } from "@swc/core";
5
5
  /**
6
- * Where compiled code is cached on disk (#514), or null when caching is off:
6
+ * Where compiled code is cached on disk, or null when caching is off:
7
7
  *
8
8
  * - `DECOHERE_CACHE=0` turns it off.
9
9
  * - `DECOHERE_CACHE_DIR` puts it in that directory.
@@ -26,7 +26,7 @@ export function forgeBuild(options) {
26
26
  const transpiler = new SwcTranspiler();
27
27
  /**
28
28
  * SWC options per project (tsconfig, `.swcrc`, path aliases), built once: rebuilding them for
29
- * every file was most of the plugin's per-file cost, as it was in flux (#513, #517).
29
+ * every file was most of the plugin's per-file cost, as it was in flux.
30
30
  */ const baseConfigs = new Map();
31
31
  const transformCache = new Map();
32
32
  let workspace = null;
@@ -57,7 +57,7 @@ export function forgeBuild(options) {
57
57
  logger.debug("Plugin loaded");
58
58
  },
59
59
  resolveId (source, importer) {
60
- // `./a.js` is `a.ts` or `a.tsx`, `./a.mjs` is `a.mts`, `./a.cjs` is `a.cts` (#518).
60
+ // `./a.js` is `a.ts` or `a.tsx`, `./a.mjs` is `a.mts`, `./a.cjs` is `a.cts`.
61
61
  if (importer != null && /\.[mc]?jsx?$/.test(source) && source.startsWith(".")) {
62
62
  const written = path.resolve(path.dirname(importer), source);
63
63
  return sourceExtensions.candidates(written).find((c)=>existsSync(c)) ?? null;
@@ -78,7 +78,7 @@ export function forgeBuild(options) {
78
78
  await initWorkspace();
79
79
  const project = await workspace?.findProject(id, buildConfig);
80
80
  // The code Vite passes, not a read of the file: no content cache can serve an older
81
- // version, and there is no pre-warm compiling files ahead from disk (#517).
81
+ // version, and there is no pre-warm compiling files ahead from disk.
82
82
  const response = await transpiler.transformCode(code, new FileEx({
83
83
  fullPath: id,
84
84
  content: code
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@decohere/forge",
3
- "version": "0.0.1-dev.125",
3
+ "version": "0.0.1-dev.126",
4
4
  "description": "TypeScript monorepo build system — zero config, fast compilation, streamlined developer workflow",
5
5
  "keywords": [
6
6
  "typescript",
@@ -38,11 +38,11 @@
38
38
  "test": "echo \"Error: no test specified\" && exit 1"
39
39
  },
40
40
  "dependencies": {
41
- "@decohere/core": "0.0.1-dev.125",
42
- "@decohere/crucible": "0.0.1-dev.125",
43
- "@decohere/devkit": "0.0.1-dev.125",
44
- "@decohere/scribe": "0.0.1-dev.125",
45
- "@decohere/workspace": "0.0.1-dev.125",
41
+ "@decohere/core": "0.0.1-dev.126",
42
+ "@decohere/crucible": "0.0.1-dev.126",
43
+ "@decohere/devkit": "0.0.1-dev.126",
44
+ "@decohere/scribe": "0.0.1-dev.126",
45
+ "@decohere/workspace": "0.0.1-dev.126",
46
46
  "@swc/core": "^1.11.11",
47
47
  "async": "^3.2.6",
48
48
  "parse-imports": "^2.2.1",
@@ -14,7 +14,7 @@ export type PathsResponse = {
14
14
  };
15
15
  /**
16
16
  * Writes `tsconfig.paths.json`: tsconfig `paths` for every workspace package and the subpaths it
17
- * exports, from the workspace aliases (#518). Without `node_modules` links, `tsc` finds workspace
17
+ * exports, from the workspace aliases. Without `node_modules` links, `tsc` finds workspace
18
18
  * packages only through `paths`; generating them keeps them in step with what Flux, the Vitest
19
19
  * plugin and builds resolve. The root tsconfig extends the file.
20
20
  */
@@ -8,7 +8,7 @@ export declare class SwcConfigFactory {
8
8
  * Call once per (project, target) and then use createFileConfig() per file.
9
9
  */
10
10
  createBaseConfig(buildTarget: TranspileTarget, configOptions: SwcConfigOptions): Options;
11
- /** Stamps a per-file filename onto a pre-built base config; `.tsx` also turns on JSX (#518). */
11
+ /** Stamps a per-file filename onto a pre-built base config; `.tsx` also turns on JSX. */
12
12
  createFileConfig(file: FileEx, baseConfig: Options): Options;
13
13
  private static nonemptyPaths;
14
14
  /**
@@ -28,13 +28,13 @@ export declare class SwcTranspiler implements Transformer {
28
28
  * once and passes them to {@link transformCode}.
29
29
  */
30
30
  createBaseConfig(buildTarget: TranspileTarget, options?: TranspileOptions): Options;
31
- /** Sync variant of {@link transformCode}, for the load hook, which cannot await (#514). */
31
+ /** Sync variant of {@link transformCode}, for the load hook, which cannot await. */
32
32
  transformCodeSync(content: string, file: FileEx, buildTarget: TranspileTarget, baseConfig: Options): TransformResponse;
33
33
  /**
34
34
  * Compiles `content` as the source of `file`, without reading the file: for callers that
35
35
  * already hold the code, such as the Vitest plugin, which must compile what Vite passes it
36
- * rather than an earlier read of the disk (#517). Async SWC, on the thread pool, so many
37
- * calls in flight compile in parallel (#661). With a `project`, the response carries where
36
+ * rather than an earlier read of the disk. Async SWC, on the thread pool, so many
37
+ * calls in flight compile in parallel. With a `project`, the response carries where
38
38
  * the build writes the output.
39
39
  */
40
40
  transformCode(content: string, file: FileEx, buildTarget: TranspileTarget, baseConfig: Options, project?: Project): Promise<TransformResponse>;
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Where compiled code is cached on disk (#514), or null when caching is off:
2
+ * Where compiled code is cached on disk, or null when caching is off:
3
3
  *
4
4
  * - `DECOHERE_CACHE=0` turns it off.
5
5
  * - `DECOHERE_CACHE_DIR` puts it in that directory.