plgg-bundle 0.0.1 → 0.0.3

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.
Files changed (208) hide show
  1. package/bin/hook.d.mts +20 -0
  2. package/bin/hook.mjs +11 -2
  3. package/bin/plgg-bundle.mjs +9 -0
  4. package/bin/relocate.mjs +108 -0
  5. package/package.json +2 -5
  6. package/src/Dev/fixtures/aliasDir/index.ts +6 -0
  7. package/src/Dev/node/devServer.ts +5 -5
  8. package/src/Dev/node/httpAdapter.ts +1 -1
  9. package/src/Dev/node/scanGraph.ts +2 -2
  10. package/src/Dev/node/watch.ts +1 -1
  11. package/src/Dev/usecase/selfAliasResolve.spec.ts +68 -0
  12. package/src/domain/usecase/build.ts +2 -2
  13. package/src/domain/usecase/collectModules.ts +2 -2
  14. package/src/domain/usecase/deriveExternal.ts +2 -2
  15. package/src/domain/usecase/discoverWorkspace.ts +2 -2
  16. package/src/domain/usecase/emitDts.ts +4 -4
  17. package/src/domain/usecase/resolveSpecifier.ts +2 -2
  18. package/src/domain/usecase/resolveWorkspaceSpecifier.ts +1 -1
  19. package/src/domain/usecase/rewriteDtsAliases.ts +2 -2
  20. package/src/vendors/nodeFs.ts +22 -0
  21. package/src/vendors/nodeHttp.ts +14 -0
  22. package/src/vendors/nodePath.ts +15 -0
  23. package/src/vendors/nodeProc.ts +12 -0
  24. package/src/vendors/nodeUrl.ts +6 -0
  25. package/dist/Dev/fixtures/devPoc.spec.d.ts +0 -2
  26. package/dist/Dev/fixtures/devPoc.spec.d.ts.map +0 -1
  27. package/dist/Dev/fixtures/devPoc.spec.js +0 -145
  28. package/dist/Dev/fixtures/devPoc.spec.js.map +0 -1
  29. package/dist/Dev/model/Fetch.d.ts +0 -20
  30. package/dist/Dev/model/Fetch.d.ts.map +0 -1
  31. package/dist/Dev/model/Fetch.js +0 -8
  32. package/dist/Dev/model/Fetch.js.map +0 -1
  33. package/dist/Dev/model/ModuleGraph.d.ts +0 -27
  34. package/dist/Dev/model/ModuleGraph.d.ts.map +0 -1
  35. package/dist/Dev/model/ModuleGraph.js +0 -2
  36. package/dist/Dev/model/ModuleGraph.js.map +0 -1
  37. package/dist/Dev/model/Protocol.d.ts +0 -22
  38. package/dist/Dev/model/Protocol.d.ts.map +0 -1
  39. package/dist/Dev/model/Protocol.js +0 -31
  40. package/dist/Dev/model/Protocol.js.map +0 -1
  41. package/dist/Dev/node/devServer.d.ts +0 -21
  42. package/dist/Dev/node/devServer.d.ts.map +0 -1
  43. package/dist/Dev/node/devServer.js +0 -298
  44. package/dist/Dev/node/devServer.js.map +0 -1
  45. package/dist/Dev/node/httpAdapter.d.ts +0 -19
  46. package/dist/Dev/node/httpAdapter.d.ts.map +0 -1
  47. package/dist/Dev/node/httpAdapter.js +0 -76
  48. package/dist/Dev/node/httpAdapter.js.map +0 -1
  49. package/dist/Dev/node/scanGraph.d.ts +0 -21
  50. package/dist/Dev/node/scanGraph.d.ts.map +0 -1
  51. package/dist/Dev/node/scanGraph.js +0 -145
  52. package/dist/Dev/node/scanGraph.js.map +0 -1
  53. package/dist/Dev/node/watch.d.ts +0 -10
  54. package/dist/Dev/node/watch.d.ts.map +0 -1
  55. package/dist/Dev/node/watch.js +0 -44
  56. package/dist/Dev/node/watch.js.map +0 -1
  57. package/dist/Dev/usecase/allowedHost.d.ts +0 -16
  58. package/dist/Dev/usecase/allowedHost.d.ts.map +0 -1
  59. package/dist/Dev/usecase/allowedHost.js +0 -33
  60. package/dist/Dev/usecase/allowedHost.js.map +0 -1
  61. package/dist/Dev/usecase/allowedHost.spec.d.ts +0 -2
  62. package/dist/Dev/usecase/allowedHost.spec.d.ts.map +0 -1
  63. package/dist/Dev/usecase/allowedHost.spec.js +0 -13
  64. package/dist/Dev/usecase/allowedHost.spec.js.map +0 -1
  65. package/dist/Dev/usecase/buildGraph.d.ts +0 -12
  66. package/dist/Dev/usecase/buildGraph.d.ts.map +0 -1
  67. package/dist/Dev/usecase/buildGraph.js +0 -24
  68. package/dist/Dev/usecase/buildGraph.js.map +0 -1
  69. package/dist/Dev/usecase/buildGraph.spec.d.ts +0 -2
  70. package/dist/Dev/usecase/buildGraph.spec.d.ts.map +0 -1
  71. package/dist/Dev/usecase/buildGraph.spec.js +0 -16
  72. package/dist/Dev/usecase/buildGraph.spec.js.map +0 -1
  73. package/dist/Dev/usecase/decorateDevHtml.d.ts +0 -12
  74. package/dist/Dev/usecase/decorateDevHtml.d.ts.map +0 -1
  75. package/dist/Dev/usecase/decorateDevHtml.js +0 -15
  76. package/dist/Dev/usecase/decorateDevHtml.js.map +0 -1
  77. package/dist/Dev/usecase/decorateDevHtml.spec.d.ts +0 -2
  78. package/dist/Dev/usecase/decorateDevHtml.spec.d.ts.map +0 -1
  79. package/dist/Dev/usecase/decorateDevHtml.spec.js +0 -19
  80. package/dist/Dev/usecase/decorateDevHtml.spec.js.map +0 -1
  81. package/dist/Dev/usecase/invalidate.d.ts +0 -17
  82. package/dist/Dev/usecase/invalidate.d.ts.map +0 -1
  83. package/dist/Dev/usecase/invalidate.js +0 -57
  84. package/dist/Dev/usecase/invalidate.js.map +0 -1
  85. package/dist/Dev/usecase/invalidate.spec.d.ts +0 -2
  86. package/dist/Dev/usecase/invalidate.spec.d.ts.map +0 -1
  87. package/dist/Dev/usecase/invalidate.spec.js +0 -64
  88. package/dist/Dev/usecase/invalidate.spec.js.map +0 -1
  89. package/dist/Dev/usecase/parseImports.d.ts +0 -24
  90. package/dist/Dev/usecase/parseImports.d.ts.map +0 -1
  91. package/dist/Dev/usecase/parseImports.js +0 -40
  92. package/dist/Dev/usecase/parseImports.js.map +0 -1
  93. package/dist/Dev/usecase/parseImports.spec.d.ts +0 -2
  94. package/dist/Dev/usecase/parseImports.spec.d.ts.map +0 -1
  95. package/dist/Dev/usecase/parseImports.spec.js +0 -24
  96. package/dist/Dev/usecase/parseImports.spec.js.map +0 -1
  97. package/dist/Dev/usecase/reloadDecision.d.ts +0 -20
  98. package/dist/Dev/usecase/reloadDecision.d.ts.map +0 -1
  99. package/dist/Dev/usecase/reloadDecision.js +0 -52
  100. package/dist/Dev/usecase/reloadDecision.js.map +0 -1
  101. package/dist/Dev/usecase/reloadDecision.spec.d.ts +0 -2
  102. package/dist/Dev/usecase/reloadDecision.spec.d.ts.map +0 -1
  103. package/dist/Dev/usecase/reloadDecision.spec.js +0 -17
  104. package/dist/Dev/usecase/reloadDecision.spec.js.map +0 -1
  105. package/dist/domain/model/BundleConfig.d.ts +0 -136
  106. package/dist/domain/model/BundleConfig.d.ts.map +0 -1
  107. package/dist/domain/model/BundleConfig.js +0 -18
  108. package/dist/domain/model/BundleConfig.js.map +0 -1
  109. package/dist/domain/model/BundleConfig.spec.d.ts +0 -2
  110. package/dist/domain/model/BundleConfig.spec.d.ts.map +0 -1
  111. package/dist/domain/model/BundleConfig.spec.js +0 -8
  112. package/dist/domain/model/BundleConfig.spec.js.map +0 -1
  113. package/dist/domain/usecase/asBundleConfig.d.ts +0 -17
  114. package/dist/domain/usecase/asBundleConfig.d.ts.map +0 -1
  115. package/dist/domain/usecase/asBundleConfig.js +0 -179
  116. package/dist/domain/usecase/asBundleConfig.js.map +0 -1
  117. package/dist/domain/usecase/asBundleConfig.spec.d.ts +0 -2
  118. package/dist/domain/usecase/asBundleConfig.spec.d.ts.map +0 -1
  119. package/dist/domain/usecase/asBundleConfig.spec.js +0 -119
  120. package/dist/domain/usecase/asBundleConfig.spec.js.map +0 -1
  121. package/dist/domain/usecase/build.d.ts +0 -14
  122. package/dist/domain/usecase/build.d.ts.map +0 -1
  123. package/dist/domain/usecase/build.js +0 -177
  124. package/dist/domain/usecase/build.js.map +0 -1
  125. package/dist/domain/usecase/collectModules.d.ts +0 -53
  126. package/dist/domain/usecase/collectModules.d.ts.map +0 -1
  127. package/dist/domain/usecase/collectModules.js +0 -118
  128. package/dist/domain/usecase/collectModules.js.map +0 -1
  129. package/dist/domain/usecase/deriveExternal.d.ts +0 -25
  130. package/dist/domain/usecase/deriveExternal.d.ts.map +0 -1
  131. package/dist/domain/usecase/deriveExternal.js +0 -79
  132. package/dist/domain/usecase/deriveExternal.js.map +0 -1
  133. package/dist/domain/usecase/deriveExternal.spec.d.ts +0 -2
  134. package/dist/domain/usecase/deriveExternal.spec.d.ts.map +0 -1
  135. package/dist/domain/usecase/deriveExternal.spec.js +0 -56
  136. package/dist/domain/usecase/deriveExternal.spec.js.map +0 -1
  137. package/dist/domain/usecase/discoverWorkspace.d.ts +0 -27
  138. package/dist/domain/usecase/discoverWorkspace.d.ts.map +0 -1
  139. package/dist/domain/usecase/discoverWorkspace.js +0 -116
  140. package/dist/domain/usecase/discoverWorkspace.js.map +0 -1
  141. package/dist/domain/usecase/discoverWorkspace.spec.d.ts +0 -2
  142. package/dist/domain/usecase/discoverWorkspace.spec.d.ts.map +0 -1
  143. package/dist/domain/usecase/discoverWorkspace.spec.js +0 -23
  144. package/dist/domain/usecase/discoverWorkspace.spec.js.map +0 -1
  145. package/dist/domain/usecase/emitBundle.d.ts +0 -43
  146. package/dist/domain/usecase/emitBundle.d.ts.map +0 -1
  147. package/dist/domain/usecase/emitBundle.js +0 -157
  148. package/dist/domain/usecase/emitBundle.js.map +0 -1
  149. package/dist/domain/usecase/emitBundle.spec.d.ts +0 -2
  150. package/dist/domain/usecase/emitBundle.spec.d.ts.map +0 -1
  151. package/dist/domain/usecase/emitBundle.spec.js +0 -80
  152. package/dist/domain/usecase/emitBundle.spec.js.map +0 -1
  153. package/dist/domain/usecase/emitDts.d.ts +0 -32
  154. package/dist/domain/usecase/emitDts.d.ts.map +0 -1
  155. package/dist/domain/usecase/emitDts.js +0 -99
  156. package/dist/domain/usecase/emitDts.js.map +0 -1
  157. package/dist/domain/usecase/isExternal.d.ts +0 -12
  158. package/dist/domain/usecase/isExternal.d.ts.map +0 -1
  159. package/dist/domain/usecase/isExternal.js +0 -16
  160. package/dist/domain/usecase/isExternal.js.map +0 -1
  161. package/dist/domain/usecase/isExternal.spec.d.ts +0 -2
  162. package/dist/domain/usecase/isExternal.spec.d.ts.map +0 -1
  163. package/dist/domain/usecase/isExternal.spec.js +0 -16
  164. package/dist/domain/usecase/isExternal.spec.js.map +0 -1
  165. package/dist/domain/usecase/resolveSpecifier.d.ts +0 -35
  166. package/dist/domain/usecase/resolveSpecifier.d.ts.map +0 -1
  167. package/dist/domain/usecase/resolveSpecifier.js +0 -83
  168. package/dist/domain/usecase/resolveSpecifier.js.map +0 -1
  169. package/dist/domain/usecase/resolveSpecifier.spec.d.ts +0 -2
  170. package/dist/domain/usecase/resolveSpecifier.spec.d.ts.map +0 -1
  171. package/dist/domain/usecase/resolveSpecifier.spec.js +0 -44
  172. package/dist/domain/usecase/resolveSpecifier.spec.js.map +0 -1
  173. package/dist/domain/usecase/resolveWorkspaceSpecifier.d.ts +0 -29
  174. package/dist/domain/usecase/resolveWorkspaceSpecifier.d.ts.map +0 -1
  175. package/dist/domain/usecase/resolveWorkspaceSpecifier.js +0 -89
  176. package/dist/domain/usecase/resolveWorkspaceSpecifier.js.map +0 -1
  177. package/dist/domain/usecase/resolveWorkspaceSpecifier.spec.d.ts +0 -2
  178. package/dist/domain/usecase/resolveWorkspaceSpecifier.spec.d.ts.map +0 -1
  179. package/dist/domain/usecase/resolveWorkspaceSpecifier.spec.js +0 -27
  180. package/dist/domain/usecase/resolveWorkspaceSpecifier.spec.js.map +0 -1
  181. package/dist/domain/usecase/rewriteDtsAliases.d.ts +0 -25
  182. package/dist/domain/usecase/rewriteDtsAliases.d.ts.map +0 -1
  183. package/dist/domain/usecase/rewriteDtsAliases.js +0 -71
  184. package/dist/domain/usecase/rewriteDtsAliases.js.map +0 -1
  185. package/dist/domain/usecase/rewriteDtsAliases.spec.d.ts +0 -2
  186. package/dist/domain/usecase/rewriteDtsAliases.spec.d.ts.map +0 -1
  187. package/dist/domain/usecase/rewriteDtsAliases.spec.js +0 -35
  188. package/dist/domain/usecase/rewriteDtsAliases.spec.js.map +0 -1
  189. package/dist/entrypoints/cli.d.ts +0 -2
  190. package/dist/entrypoints/cli.d.ts.map +0 -1
  191. package/dist/entrypoints/cli.js +0 -79
  192. package/dist/entrypoints/cli.js.map +0 -1
  193. package/dist/index.d.ts +0 -21
  194. package/dist/index.d.ts.map +0 -1
  195. package/dist/index.js +0 -28
  196. package/dist/index.js.map +0 -1
  197. package/dist/vendors/runner.d.ts +0 -20
  198. package/dist/vendors/runner.d.ts.map +0 -1
  199. package/dist/vendors/runner.js +0 -60
  200. package/dist/vendors/runner.js.map +0 -1
  201. package/dist/vendors/runner.spec.d.ts +0 -2
  202. package/dist/vendors/runner.spec.d.ts.map +0 -1
  203. package/dist/vendors/runner.spec.js +0 -20
  204. package/dist/vendors/runner.spec.js.map +0 -1
  205. package/dist/vendors/transpiler.d.ts +0 -19
  206. package/dist/vendors/transpiler.d.ts.map +0 -1
  207. package/dist/vendors/transpiler.js +0 -42
  208. package/dist/vendors/transpiler.js.map +0 -1
package/bin/hook.d.mts ADDED
@@ -0,0 +1,20 @@
1
+ // Hand-written types for the JS loader hook (the hook must
2
+ // stay a plain `.mjs` — it runs as Node's ESM resolver
3
+ // before any type-stripping is active — so it carries no
4
+ // inferable types). Declared here so a `.ts` spec can drive
5
+ // `resolve` type-safely under `allowJs: false`.
6
+
7
+ /** A resolved module, as returned to Node's loader chain. */
8
+ export type Resolved = {
9
+ url: string;
10
+ shortCircuit?: boolean;
11
+ };
12
+
13
+ export const resolve: (
14
+ specifier: string,
15
+ context: { parentURL?: string | undefined },
16
+ nextResolve: (
17
+ specifier: string,
18
+ context: { parentURL?: string | undefined },
19
+ ) => Promise<Resolved>,
20
+ ) => Promise<Resolved>;
package/bin/hook.mjs CHANGED
@@ -19,7 +19,7 @@
19
19
  //
20
20
  // Everything else (typescript, node:*) falls through to
21
21
  // Node's default resolution.
22
- import { existsSync } from "node:fs";
22
+ import { existsSync, statSync } from "node:fs";
23
23
  import { fileURLToPath, pathToFileURL } from "node:url";
24
24
  import { dirname, join } from "node:path";
25
25
 
@@ -27,13 +27,22 @@ const here = dirname(fileURLToPath(import.meta.url));
27
27
  const srcRoot = join(here, "..", "src");
28
28
  const prefix = "plgg-bundle/";
29
29
 
30
+ // Resolve to a FILE, never a directory: a bare-directory
31
+ // self-alias (e.g. `plgg-bundle/foo`) must land on its
32
+ // `index.ts`, not the directory itself — Node would `read`
33
+ // the directory and throw EISDIR. So the raw `base` matches
34
+ // only when it is a real file; a directory falls through to
35
+ // `base/index.ts`.
36
+ const isFile = (c) =>
37
+ existsSync(c) && statSync(c).isFile();
38
+
30
39
  const pick = (base) => {
31
40
  const candidates = [
32
41
  base,
33
42
  `${base}.ts`,
34
43
  join(base, "index.ts"),
35
44
  ];
36
- return candidates.find((c) => existsSync(c));
45
+ return candidates.find(isFile);
37
46
  };
38
47
 
39
48
  // The `?v=<n>` dev version carried by an importer URL, or
@@ -7,6 +7,15 @@
7
7
  import { register } from "node:module";
8
8
  import { fileURLToPath } from "node:url";
9
9
  import { dirname, join } from "node:path";
10
+ import { relocateOutOfNodeModules } from "./relocate.mjs";
11
+
12
+ // Node 24 refuses to strip types from `.ts` under `node_modules`. When this
13
+ // tool is installed from the registry, relocate a copy OUTSIDE `node_modules`
14
+ // and re-exec there; a no-op on a monorepo `file:` link.
15
+ relocateOutOfNodeModules(
16
+ import.meta.url,
17
+ "plgg-bundle.mjs",
18
+ );
10
19
 
11
20
  register("./hook.mjs", import.meta.url);
12
21
 
@@ -0,0 +1,108 @@
1
+ // Shared launcher preamble for the run-from-source plgg CLIs.
2
+ //
3
+ // These tools run their `src/**/*.ts` entry directly and rely on Node stripping
4
+ // types on load. Node refuses to strip types for `.ts` files under
5
+ // `node_modules`, so a registry-installed tool cannot run in place. This helper
6
+ // copies the package to a version-stamped dir OUTSIDE `node_modules` (with the
7
+ // tool's own deps reachable via a `node_modules` symlink) and re-execs the copy
8
+ // there. On a monorepo `file:` link the package realpath is already outside
9
+ // `node_modules`, so it is a no-op.
10
+ //
11
+ // Plain `.mjs`, Node built-ins only — it runs at process entry, before any
12
+ // resolver hook is registered.
13
+ import { spawnSync } from "node:child_process";
14
+ import {
15
+ cpSync,
16
+ existsSync,
17
+ mkdirSync,
18
+ readFileSync,
19
+ realpathSync,
20
+ rmSync,
21
+ symlinkSync,
22
+ writeFileSync,
23
+ } from "node:fs";
24
+ import { tmpdir } from "node:os";
25
+ import {
26
+ dirname,
27
+ join,
28
+ sep,
29
+ } from "node:path";
30
+ import { fileURLToPath } from "node:url";
31
+
32
+ const isUnderNodeModules = (p) =>
33
+ p.split(sep).includes("node_modules");
34
+
35
+ // Relocate the calling launcher's package out of node_modules and re-exec, or
36
+ // return (no-op) when already outside it. Exits the process on re-exec.
37
+ export const relocateOutOfNodeModules = (
38
+ launcherUrl,
39
+ launcherBinName,
40
+ ) => {
41
+ const binDir = dirname(
42
+ fileURLToPath(launcherUrl),
43
+ );
44
+ const pkgRoot = realpathSync(
45
+ join(binDir, ".."),
46
+ );
47
+ if (!isUnderNodeModules(pkgRoot)) {
48
+ return;
49
+ }
50
+
51
+ const pkg = JSON.parse(
52
+ readFileSync(
53
+ join(pkgRoot, "package.json"),
54
+ "utf8",
55
+ ),
56
+ );
57
+ const dest = join(
58
+ tmpdir(),
59
+ `plgg-relocate-${pkg.name}-${pkg.version}`,
60
+ );
61
+ const ready = join(
62
+ dest,
63
+ ".plgg-relocate-ready",
64
+ );
65
+
66
+ if (!existsSync(ready)) {
67
+ rmSync(dest, {
68
+ recursive: true,
69
+ force: true,
70
+ });
71
+ mkdirSync(dest, { recursive: true });
72
+ for (const dir of ["src", "bin"]) {
73
+ const from = join(pkgRoot, dir);
74
+ if (existsSync(from)) {
75
+ cpSync(from, join(dest, dir), {
76
+ recursive: true,
77
+ });
78
+ }
79
+ }
80
+ cpSync(
81
+ join(pkgRoot, "package.json"),
82
+ join(dest, "package.json"),
83
+ );
84
+ // The tool's own deps (typescript; plgg for plgg-test) live in the
85
+ // node_modules that CONTAINS this package (npm hoists there). Symlink it so
86
+ // resolution from the relocated copy finds them.
87
+ try {
88
+ symlinkSync(
89
+ dirname(pkgRoot),
90
+ join(dest, "node_modules"),
91
+ "dir",
92
+ );
93
+ } catch {
94
+ // A pre-existing symlink from a concurrent run is fine.
95
+ }
96
+ writeFileSync(ready, "");
97
+ }
98
+
99
+ const child = spawnSync(
100
+ process.execPath,
101
+ [
102
+ join(dest, "bin", launcherBinName),
103
+ ...process.argv.slice(2),
104
+ ],
105
+ { stdio: "inherit" },
106
+ );
107
+ process.exit(child.status ?? 1);
108
+ };
package/package.json CHANGED
@@ -1,18 +1,15 @@
1
1
  {
2
2
  "name": "plgg-bundle",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "In-house minimal library bundler for the plgg monorepo (ESM+CJS dual output, per-file .d.ts tree), zero new dependencies — reuses the project's own TypeScript, no native binding.",
5
5
  "type": "module",
6
6
  "files": [
7
- "dist",
8
7
  "src",
9
8
  "bin"
10
9
  ],
11
10
  "bin": {
12
11
  "plgg-bundle": "bin/plgg-bundle.mjs"
13
12
  },
14
- "main": "dist/index.js",
15
- "types": "dist/index.d.ts",
16
13
  "scripts": {
17
14
  "build": "tsc",
18
15
  "tsc": "tsc --noEmit",
@@ -26,6 +23,6 @@
26
23
  },
27
24
  "devDependencies": {
28
25
  "@types/node": "^25.6.0",
29
- "plgg-test": "^0.0.2"
26
+ "plgg-test": "^0.0.4"
30
27
  }
31
28
  }
@@ -0,0 +1,6 @@
1
+ // Fixture: a directory whose only module is `index.ts`, so a
2
+ // bare-directory self-alias (`plgg-bundle/Dev/fixtures/aliasDir`)
3
+ // has an index to resolve to. Exercised by
4
+ // ../../usecase/selfAliasResolve.spec.ts to guard the loader
5
+ // hook against resolving to the directory itself (EISDIR).
6
+ export const marker = "aliasDir/index.ts";
@@ -2,11 +2,11 @@ import {
2
2
  resolve,
3
3
  isAbsolute,
4
4
  join,
5
- } from "node:path";
6
- import { existsSync } from "node:fs";
7
- import { pathToFileURL } from "node:url";
8
- import { register } from "node:module";
9
- import { type Server } from "node:http";
5
+ } from "plgg-bundle/vendors/nodePath";
6
+ import { existsSync } from "plgg-bundle/vendors/nodeFs";
7
+ import { pathToFileURL } from "plgg-bundle/vendors/nodeUrl";
8
+ import { register } from "plgg-bundle/vendors/nodeProc";
9
+ import { type Server } from "plgg-bundle/vendors/nodeHttp";
10
10
  import { type Fetch } from "plgg-bundle/Dev/model/Fetch";
11
11
  import { type ModuleGraph } from "plgg-bundle/Dev/model/ModuleGraph";
12
12
  import {
@@ -3,7 +3,7 @@ import {
3
3
  type IncomingMessage,
4
4
  type ServerResponse,
5
5
  type Server,
6
- } from "node:http";
6
+ } from "plgg-bundle/vendors/nodeHttp";
7
7
  import { type Fetch } from "plgg-bundle/Dev/model/Fetch";
8
8
 
9
9
  // The node:http ⇄ Web-standard bridge for the dev server.
@@ -2,12 +2,12 @@ import {
2
2
  readdirSync,
3
3
  readFileSync,
4
4
  statSync,
5
- } from "node:fs";
5
+ } from "plgg-bundle/vendors/nodeFs";
6
6
  import {
7
7
  resolve,
8
8
  dirname,
9
9
  join,
10
- } from "node:path";
10
+ } from "plgg-bundle/vendors/nodePath";
11
11
  import { parseImports } from "plgg-bundle/Dev/usecase/parseImports";
12
12
  import { buildGraph } from "plgg-bundle/Dev/usecase/buildGraph";
13
13
  import { type ModuleGraph } from "plgg-bundle/Dev/model/ModuleGraph";
@@ -1,4 +1,4 @@
1
- import { watch, type FSWatcher } from "node:fs";
1
+ import { watch, type FSWatcher } from "plgg-bundle/vendors/nodeFs";
2
2
 
3
3
  // The fs.watch seam: a debounced, recursive watcher over
4
4
  // several source roots. One save can emit multiple events,
@@ -0,0 +1,68 @@
1
+ import {
2
+ test,
3
+ check,
4
+ all,
5
+ toBe,
6
+ } from "plgg-test";
7
+ import {
8
+ resolve,
9
+ type Resolved,
10
+ } from "../../../bin/hook.mjs";
11
+
12
+ // The loader hook's `resolve` rewrites `plgg-bundle/<sub>`
13
+ // self-alias specifiers to on-disk `src/<sub>` files. These
14
+ // drive it directly (the alias branch short-circuits before
15
+ // `nextResolve`, so a stub suffices).
16
+
17
+ const ctx = { parentURL: undefined };
18
+ const fallthrough = async (): Promise<Resolved> => ({
19
+ url: "file:///fallthrough",
20
+ });
21
+
22
+ test(
23
+ "bare-directory self-alias resolves to its index.ts, not the directory (EISDIR guard)",
24
+ async () => {
25
+ const r = await resolve(
26
+ "plgg-bundle/Dev/fixtures/aliasDir",
27
+ ctx,
28
+ fallthrough,
29
+ );
30
+ return all([
31
+ check(
32
+ r.url.endsWith("/aliasDir/index.ts"),
33
+ toBe(true),
34
+ ),
35
+ check(r.shortCircuit ?? false, toBe(true)),
36
+ ]);
37
+ },
38
+ );
39
+
40
+ test(
41
+ "file self-alias still resolves to the .ts file (no regression)",
42
+ async () => {
43
+ const r = await resolve(
44
+ "plgg-bundle/index",
45
+ ctx,
46
+ fallthrough,
47
+ );
48
+ return check(
49
+ r.url.endsWith("/src/index.ts"),
50
+ toBe(true),
51
+ );
52
+ },
53
+ );
54
+
55
+ test(
56
+ "a self-alias with no matching file falls through to nextResolve",
57
+ async () => {
58
+ const r = await resolve(
59
+ "plgg-bundle/does/not/exist",
60
+ ctx,
61
+ fallthrough,
62
+ );
63
+ return check(
64
+ r.url,
65
+ toBe("file:///fallthrough"),
66
+ );
67
+ },
68
+ );
@@ -4,8 +4,8 @@ import {
4
4
  rmSync,
5
5
  renameSync,
6
6
  existsSync,
7
- } from "node:fs";
8
- import { join, dirname } from "node:path";
7
+ } from "plgg-bundle/vendors/nodeFs";
8
+ import { join, dirname } from "plgg-bundle/vendors/nodePath";
9
9
  import {
10
10
  type BundleConfig,
11
11
  type Entry,
@@ -1,5 +1,5 @@
1
- import { readFileSync } from "node:fs";
2
- import { relative } from "node:path";
1
+ import { readFileSync } from "plgg-bundle/vendors/nodeFs";
2
+ import { relative } from "plgg-bundle/vendors/nodePath";
3
3
  import { type External } from "plgg-bundle/domain/model/BundleConfig";
4
4
  import { resolveSpecifier } from "plgg-bundle/domain/usecase/resolveSpecifier";
5
5
  import { isExternal } from "plgg-bundle/domain/usecase/isExternal";
@@ -1,5 +1,5 @@
1
- import { readFileSync } from "node:fs";
2
- import { join } from "node:path";
1
+ import { readFileSync } from "plgg-bundle/vendors/nodeFs";
2
+ import { join } from "plgg-bundle/vendors/nodePath";
3
3
  import { type External } from "plgg-bundle/domain/model/BundleConfig";
4
4
 
5
5
  /**
@@ -3,8 +3,8 @@ import {
3
3
  readFileSync,
4
4
  existsSync,
5
5
  statSync,
6
- } from "node:fs";
7
- import { join, dirname } from "node:path";
6
+ } from "plgg-bundle/vendors/nodeFs";
7
+ import { join, dirname } from "plgg-bundle/vendors/nodePath";
8
8
 
9
9
  /**
10
10
  * A workspace sibling the app bundler can INLINE from
@@ -1,16 +1,16 @@
1
- import { spawnSync } from "node:child_process";
1
+ import { spawnSync } from "plgg-bundle/vendors/nodeProc";
2
2
  import {
3
3
  join,
4
4
  dirname,
5
5
  basename,
6
6
  relative,
7
- } from "node:path";
7
+ } from "plgg-bundle/vendors/nodePath";
8
8
  import {
9
9
  existsSync,
10
10
  writeFileSync,
11
11
  rmSync,
12
- } from "node:fs";
13
- import { createRequire } from "node:module";
12
+ } from "plgg-bundle/vendors/nodeFs";
13
+ import { createRequire } from "plgg-bundle/vendors/nodeProc";
14
14
  import { rewriteDtsAliases } from "plgg-bundle/domain/usecase/rewriteDtsAliases";
15
15
 
16
16
  /**
@@ -1,9 +1,9 @@
1
- import { existsSync, statSync } from "node:fs";
1
+ import { existsSync, statSync } from "plgg-bundle/vendors/nodeFs";
2
2
  import {
3
3
  dirname,
4
4
  resolve,
5
5
  join,
6
- } from "node:path";
6
+ } from "plgg-bundle/vendors/nodePath";
7
7
 
8
8
  /**
9
9
  * Resolve a bare import specifier to an absolute source
@@ -1,4 +1,4 @@
1
- import { basename, join } from "node:path";
1
+ import { basename, join } from "plgg-bundle/vendors/nodePath";
2
2
  import {
3
3
  resolveSpecifier,
4
4
  isRelative,
@@ -3,12 +3,12 @@ import {
3
3
  statSync,
4
4
  readFileSync,
5
5
  writeFileSync,
6
- } from "node:fs";
6
+ } from "plgg-bundle/vendors/nodeFs";
7
7
  import {
8
8
  join,
9
9
  dirname,
10
10
  relative,
11
- } from "node:path";
11
+ } from "plgg-bundle/vendors/nodePath";
12
12
 
13
13
  /**
14
14
  * Rewrite the package self-alias (`<prefix>/<sub>`) in
@@ -0,0 +1,22 @@
1
+ /**
2
+ * The filesystem anti-corruption layer for plgg-bundle — the
3
+ * ONLY place the bundler's build usecases reach `node:fs`, kept
4
+ * under `vendors/` so the domain speaks these named operations,
5
+ * not the driver. Re-exported (not re-wrapped) to preserve the
6
+ * exact node types; plgg-bundle's throw-at-the-boundary error
7
+ * model (see BundleConfig) means a failed fs call surfaces as a
8
+ * thrown Error the entrypoint catches — the seam is the import
9
+ * chokepoint, so the vendor-boundary gate holds unexempted.
10
+ */
11
+ export {
12
+ writeFileSync,
13
+ mkdirSync,
14
+ rmSync,
15
+ renameSync,
16
+ existsSync,
17
+ readdirSync,
18
+ readFileSync,
19
+ statSync,
20
+ watch,
21
+ type FSWatcher,
22
+ } from "node:fs";
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The HTTP anti-corruption layer for plgg-bundle's DEV server —
3
+ * the ONLY place the node:http ⇄ Web-standard bridge reaches
4
+ * `node:http`. Confined here so the dev orchestration stays
5
+ * `node:`-free (the vendor-boundary gate); a plgg-free
6
+ * reimplementation of `serve` (the toolchain must not import a
7
+ * library it builds).
8
+ */
9
+ export {
10
+ createServer,
11
+ type IncomingMessage,
12
+ type ServerResponse,
13
+ type Server,
14
+ } from "node:http";
@@ -0,0 +1,15 @@
1
+ /**
2
+ * The path anti-corruption layer for plgg-bundle — the ONLY
3
+ * place the build usecases reach `node:path`. Re-exported to
4
+ * preserve exact node types; confining the import here is what
5
+ * keeps the domain free of `node:` specifiers (the
6
+ * vendor-boundary gate).
7
+ */
8
+ export {
9
+ join,
10
+ dirname,
11
+ relative,
12
+ basename,
13
+ resolve,
14
+ isAbsolute,
15
+ } from "node:path";
@@ -0,0 +1,12 @@
1
+ /**
2
+ * The process/module anti-corruption layer for plgg-bundle —
3
+ * the ONLY place the `.d.ts` emitter reaches `node:child_process`
4
+ * (to spawn the target's own `tsc`) and `node:module` (to
5
+ * resolve it against the target's node_modules). Confined here so
6
+ * the domain stays `node:`-free.
7
+ */
8
+ export { spawnSync } from "node:child_process";
9
+ export {
10
+ createRequire,
11
+ register,
12
+ } from "node:module";
@@ -0,0 +1,6 @@
1
+ /**
2
+ * The URL anti-corruption layer for plgg-bundle's dev server —
3
+ * the ONLY place `node:url` is reached (turning a filesystem
4
+ * path into a `file://` URL for the module runner).
5
+ */
6
+ export { pathToFileURL } from "node:url";
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=devPoc.spec.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"devPoc.spec.d.ts","sourceRoot":"","sources":["../../../src/Dev/fixtures/devPoc.spec.ts"],"names":[],"mappings":""}
@@ -1,145 +0,0 @@
1
- import { test, check, all, toBe, } from "plgg-test";
2
- import { spawn } from "node:child_process";
3
- import { mkdtempSync, writeFileSync, } from "node:fs";
4
- import { tmpdir } from "node:os";
5
- import { join } from "node:path";
6
- import { fileURLToPath } from "node:url";
7
- // The end-to-end hot-reload PoC (ticket 041500). It runs
8
- // the REAL toolchain — `node bin/plgg-bundle.mjs dev` on a
9
- // throwaway fixture app — then edits a *deep* source module
10
- // mid-run and proves the served output changes with NO
11
- // process restart, and that the SSE reload channel opens.
12
- // This is the fidelity oracle for the whole chain: bin +
13
- // loader-hook version propagation + module-runner re-import
14
- // + node:http serve + fs.watch + SSE.
15
- /** This spec's dir → the package's bin/plgg-bundle.mjs. */
16
- const BIN = join(fileURLToPath(import.meta.url), "..", "..", "..", "..", "bin", "plgg-bundle.mjs");
17
- /** A dev entry that renders a deep child's message as HTML. */
18
- const ENTRY_SRC = [
19
- `import { message } from "./child.ts";`,
20
- `export default () =>`,
21
- ` (_request) =>`,
22
- ` Promise.resolve(`,
23
- ` new Response(`,
24
- ' `<html><body>${message()}</body></html>`,',
25
- ` { headers: { "content-type": "text/html" } },`,
26
- ` ),`,
27
- ` );`,
28
- ].join("\n");
29
- /** The deep child module the edit targets. */
30
- const childSrc = (word) => `export const message = () => "${word}";\n`;
31
- /** A minimal dev-only bundle config for the fixture app. */
32
- const configSrc = (root) => `export default ${JSON.stringify({
33
- root,
34
- rootDir: ".",
35
- outDir: "dist",
36
- fileNamePattern: "[name].[format].js",
37
- entries: [],
38
- formats: ["es"],
39
- alias: { prefix: "fixture", srcRoot: "." },
40
- dev: {
41
- entry: "entry.ts",
42
- // Port 0 → ephemeral; the real port is read from
43
- // the server's ready line.
44
- port: 0,
45
- watch: [root],
46
- allowedHosts: [],
47
- },
48
- }, null, 2)};\n`;
49
- /** Lay down the fixture app in a fresh temp dir. */
50
- const writeFixture = () => {
51
- const dir = mkdtempSync(join(tmpdir(), "plgg-dev-poc-"));
52
- writeFileSync(join(dir, "child.ts"), childSrc("ALPHA"));
53
- writeFileSync(join(dir, "entry.ts"), ENTRY_SRC);
54
- writeFileSync(join(dir, "bundle.config.ts"), configSrc(dir));
55
- return dir;
56
- };
57
- /** Sleep (test-only pacing for the watch/reload loop). */
58
- const wait = (ms) => new Promise((r) => setTimeout(r, ms));
59
- /**
60
- * Spawn `plgg-bundle dev` on the fixture and resolve the
61
- * served URL once the ready line is printed.
62
- */
63
- const startDev = (dir) => new Promise((resolve, reject) => {
64
- const proc = spawn(process.execPath, [BIN, "dev", "bundle.config.ts"], { cwd: dir });
65
- let out = "";
66
- const onData = (chunk) => {
67
- out += chunk.toString();
68
- const m = out.match(/http:\/\/localhost:\d+\//);
69
- if (m) {
70
- proc.stdout?.off("data", onData);
71
- resolve({ proc, url: m[0] });
72
- }
73
- };
74
- proc.stdout?.on("data", onData);
75
- proc.on("error", reject);
76
- setTimeout(() => reject(new Error(`dev server did not start; output:\n${out}`)), 8000);
77
- });
78
- /** Fetch a URL's body text. */
79
- const body = (url) => fetch(url).then((r) => r.text());
80
- /**
81
- * Poll `body(url)` until it contains `needle`, or throw on
82
- * timeout. Proves the served output actually changed after
83
- * the edit (not a fixed sleep guess).
84
- */
85
- const pollFor = async (url, needle) => {
86
- const deadline = 6000;
87
- const step = 60;
88
- for (let waited = 0; waited < deadline;) {
89
- if ((await body(url)).includes(needle)) {
90
- return true;
91
- }
92
- await wait(step);
93
- waited += step;
94
- }
95
- return false;
96
- };
97
- test("plgg-bundle dev hot-reloads a deep source edit with no restart", async () => {
98
- const dir = writeFixture();
99
- const { proc, url } = await startDev(dir);
100
- try {
101
- const first = await body(url);
102
- // Rewrite the DEEP child (not the entry) mid-run.
103
- writeFileSync(join(dir, "child.ts"), childSrc("BETA"));
104
- const reloaded = await pollFor(url, "BETA");
105
- const stillAlive = proc.exitCode === null;
106
- return all([
107
- // Initial render came from the child module.
108
- check(first.includes("ALPHA"), toBe(true)),
109
- // The dev server injected its live-reload client.
110
- check(first.includes("EventSource"), toBe(true)),
111
- // The deep edit re-evaluated and is now served …
112
- check(reloaded, toBe(true)),
113
- // … by the SAME process (no restart).
114
- check(stillAlive, toBe(true)),
115
- ]);
116
- }
117
- finally {
118
- proc.kill();
119
- }
120
- });
121
- test("plgg-bundle dev opens an SSE reload channel", async () => {
122
- const dir = writeFixture();
123
- const { proc, url } = await startDev(dir);
124
- try {
125
- const res = await fetch(`${url}__plgg_reload`);
126
- const contentType = res.headers.get("content-type") ?? "";
127
- // Read the opener frame, then release the stream.
128
- const reader = res.body?.getReader();
129
- const firstChunk = reader
130
- ? await reader.read()
131
- : { value: undefined };
132
- await reader?.cancel();
133
- const text = firstChunk.value
134
- ? new TextDecoder().decode(firstChunk.value)
135
- : "";
136
- return all([
137
- check(contentType.includes("text/event-stream"), toBe(true)),
138
- check(text.includes("connected"), toBe(true)),
139
- ]);
140
- }
141
- finally {
142
- proc.kill();
143
- }
144
- });
145
- //# sourceMappingURL=devPoc.spec.js.map