@ecopages/core 0.2.0-alpha.47 → 0.2.0-alpha.48

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ecopages/core",
3
- "version": "0.2.0-alpha.47",
3
+ "version": "0.2.0-alpha.48",
4
4
  "description": "Core package for Ecopages",
5
5
  "keywords": [
6
6
  "ecopages",
@@ -17,7 +17,7 @@
17
17
  "directory": "packages/core"
18
18
  },
19
19
  "dependencies": {
20
- "@ecopages/file-system": "0.2.0-alpha.47",
20
+ "@ecopages/file-system": "0.2.0-alpha.48",
21
21
  "@ecopages/logger": "^0.2.3",
22
22
  "@ecopages/scripts-injector": "^0.1.5",
23
23
  "@worker-tools/html-rewriter": "0.1.0-pre.19",
@@ -12,8 +12,8 @@ export interface NodeBootstrapResolutionOptions {
12
12
  */
13
13
  projectDir: string;
14
14
  /**
15
- * Runtime-local node_modules directory that receives symlinks to resolved
16
- * package roots so transpiled Node imports share one package graph.
15
+ * Runtime-local node_modules directory retained for backwards-compatible
16
+ * option shape. Third-party packages now resolve through native Node lookup.
17
17
  */
18
18
  runtimeNodeModulesDir: string;
19
19
  }
@@ -26,17 +26,13 @@ export declare function resolveNodeBootstrapDependency(args: Pick<EcoBuildOnReso
26
26
  /**
27
27
  * Creates the Node bootstrap plugin used by app-owned server module loads.
28
28
  *
29
- * The resolver anchors third-party imports to the nearest package boundary for
30
- * the importing file, then mirrors the resolved package root into the runtime
31
- * node_modules directory. That keeps transpiled Node execution aligned with the
32
- * package graph each source file was authored against.
29
+ * The resolver keeps third-party imports external so native Node package
30
+ * semantics decide exports, subpaths, and CommonJS interop at runtime.
33
31
  */
34
32
  export declare function createNodeBootstrapPlugin(options: NodeBootstrapResolutionOptions): EcoBuildPlugin;
35
33
  /**
36
34
  * Creates the default Node bootstrap plugin for one Ecopages app runtime.
37
35
  *
38
- * This binds the shared resolution policy to the app's internal execution
39
- * directory so transpiled server modules can externalize packages into one
40
- * stable runtime node_modules graph.
36
+ * This binds the shared resolution policy to one Ecopages app runtime.
41
37
  */
42
38
  export declare function createAppNodeBootstrapPlugin(appConfig: Pick<EcoPagesAppConfig, 'rootDir' | 'workDir' | 'absolutePaths'>): EcoBuildPlugin;
@@ -1,5 +1,5 @@
1
1
  import path from "node:path";
2
- import { existsSync, lstatSync, mkdirSync, readFileSync, realpathSync, rmSync, symlinkSync, unlinkSync } from "node:fs";
2
+ import { existsSync, readFileSync } from "node:fs";
3
3
  import { createRequire } from "node:module";
4
4
  import { fileURLToPath, pathToFileURL } from "node:url";
5
5
  import { resolveInternalExecutionDir } from "../../utils/resolve-work-dir.js";
@@ -13,139 +13,6 @@ function getPackageNameFromSpecifier(specifier) {
13
13
  }
14
14
  return specifier.split("/")[0] ?? specifier;
15
15
  }
16
- function findPackageRoot(resolvedPath) {
17
- let currentPath = path.dirname(resolvedPath);
18
- while (true) {
19
- const packageJsonPath = path.join(currentPath, "package.json");
20
- if (existsSync(packageJsonPath)) {
21
- return currentPath;
22
- }
23
- const parentPath = path.dirname(currentPath);
24
- if (parentPath === currentPath) {
25
- throw new Error(`Could not find package root for resolved dependency path: ${resolvedPath}`);
26
- }
27
- currentPath = parentPath;
28
- }
29
- }
30
- function pathEntryExists(filePath) {
31
- try {
32
- lstatSync(filePath);
33
- return true;
34
- } catch {
35
- return false;
36
- }
37
- }
38
- function linkPointsToPackage(linkPath, packageRoot) {
39
- try {
40
- return realpathSync(linkPath) === realpathSync(packageRoot);
41
- } catch {
42
- return false;
43
- }
44
- }
45
- function resolveRuntimePackageRoot(specifier, resolvedPath, parentPath) {
46
- const packageName = getPackageNameFromSpecifier(specifier);
47
- return findInstalledPackageDir(packageName, parentPath) ?? findPackageRoot(resolvedPath);
48
- }
49
- function isPackageExportedSubpath(specifier, resolvedPath, parentPath) {
50
- const packageName = getPackageNameFromSpecifier(specifier);
51
- if (specifier === packageName) {
52
- return false;
53
- }
54
- const packageRoot = resolveRuntimePackageRoot(specifier, resolvedPath, parentPath);
55
- const manifest = readPackageManifest(packageRoot);
56
- if (!manifest?.exports || typeof manifest.exports !== "object" || Array.isArray(manifest.exports)) {
57
- return false;
58
- }
59
- const subpath = `.${specifier.slice(packageName.length)}`;
60
- return subpath in manifest.exports;
61
- }
62
- function getNodeExternalSpecifier(specifier, resolvedPath, parentPath) {
63
- const packageName = getPackageNameFromSpecifier(specifier);
64
- if (specifier === packageName) {
65
- return specifier;
66
- }
67
- if (path.extname(specifier)) {
68
- return specifier;
69
- }
70
- if (isPackageExportedSubpath(specifier, resolvedPath, parentPath)) {
71
- return specifier;
72
- }
73
- for (const extension of [".js", ".mjs", ".cjs", ".json"]) {
74
- const candidateSpecifier = `${specifier}${extension}`;
75
- try {
76
- const candidateResolvedPath = resolveSpecifier(candidateSpecifier, parentPath);
77
- if (existsSync(candidateResolvedPath)) {
78
- return candidateSpecifier;
79
- }
80
- } catch {
81
- }
82
- }
83
- for (const candidatePath of [
84
- resolvedPath,
85
- ...[".js", ".mjs", ".cjs", ".json"].map((extension) => `${specifier}${extension}`)
86
- ]) {
87
- const candidateResolvedPath = candidatePath === resolvedPath ? resolvedPath : (() => {
88
- try {
89
- return resolveSpecifier(candidatePath, parentPath);
90
- } catch {
91
- return void 0;
92
- }
93
- })();
94
- if (!candidateResolvedPath) {
95
- continue;
96
- }
97
- if (!existsSync(candidateResolvedPath)) {
98
- continue;
99
- }
100
- const resolvedExtension = path.extname(candidateResolvedPath);
101
- if (![".js", ".mjs", ".cjs", ".json"].includes(resolvedExtension)) {
102
- continue;
103
- }
104
- const packageRoot = resolveRuntimePackageRoot(specifier, candidateResolvedPath, parentPath);
105
- const requestedSubpath = specifier.slice(packageName.length + 1);
106
- const resolvedSubpath = path.relative(packageRoot, candidateResolvedPath);
107
- if (resolvedSubpath === `${requestedSubpath}${resolvedExtension}`) {
108
- return `${specifier}${resolvedExtension}`;
109
- }
110
- }
111
- return specifier;
112
- }
113
- function ensureRuntimePackageLink(nodeModulesDir, specifier, resolvedPath, parentPath) {
114
- const packageName = getPackageNameFromSpecifier(specifier);
115
- const packageRoot = resolveRuntimePackageRoot(specifier, resolvedPath, parentPath);
116
- const linkPath = path.join(nodeModulesDir, packageName);
117
- mkdirSync(path.dirname(linkPath), { recursive: true });
118
- if (pathEntryExists(linkPath)) {
119
- if (linkPointsToPackage(linkPath, packageRoot)) {
120
- return;
121
- }
122
- removeRuntimePackageLink(linkPath);
123
- }
124
- try {
125
- symlinkSync(packageRoot, linkPath, "dir");
126
- } catch (error) {
127
- if (error.code !== "EEXIST") {
128
- throw error;
129
- }
130
- if (linkPointsToPackage(linkPath, packageRoot)) {
131
- return;
132
- }
133
- removeRuntimePackageLink(linkPath);
134
- symlinkSync(packageRoot, linkPath, "dir");
135
- }
136
- }
137
- function removeRuntimePackageLink(linkPath) {
138
- try {
139
- const stats = lstatSync(linkPath);
140
- if (stats.isSymbolicLink()) {
141
- unlinkSync(linkPath);
142
- return;
143
- }
144
- } catch {
145
- return;
146
- }
147
- rmSync(linkPath, { recursive: true, force: true });
148
- }
149
16
  function getNodeUnsupportedBuiltinError(specifier, importer) {
150
17
  return `Node bootstrap transpilation does not support Bun builtin specifier ${JSON.stringify(specifier)}${importer ? ` imported from ${importer}` : ""}.`;
151
18
  }
@@ -248,27 +115,6 @@ function findResolutionParent(importer, projectDir) {
248
115
  currentPath = parentPath;
249
116
  }
250
117
  }
251
- function getBootstrapBuildLoaderForPath(filePath) {
252
- switch (path.extname(filePath).toLowerCase()) {
253
- case ".ts":
254
- case ".mts":
255
- case ".cts":
256
- return "ts";
257
- case ".tsx":
258
- return "tsx";
259
- case ".jsx":
260
- return "jsx";
261
- case ".json":
262
- return "json";
263
- default:
264
- return "js";
265
- }
266
- }
267
- function shouldRewriteBootstrapSource(filePath, projectDir) {
268
- const normalizedPath = path.resolve(filePath);
269
- const normalizedProjectDir = path.resolve(projectDir);
270
- return normalizedPath.startsWith(`${normalizedProjectDir}${path.sep}`) && !normalizedPath.includes(`${path.sep}node_modules${path.sep}`);
271
- }
272
118
  function resolveNodeBootstrapDependency(args, options) {
273
119
  if (args.path.startsWith("./") || args.path.startsWith("../") || args.path.startsWith("@/") || args.path.startsWith("/") || args.path.startsWith("node:")) {
274
120
  return void 0;
@@ -285,70 +131,43 @@ function resolveNodeBootstrapDependency(args, options) {
285
131
  const resolvedSubpath = resolveSpecifier(args.path, resolveParent);
286
132
  return { path: resolvedSubpath };
287
133
  }
288
- let resolvedPath2;
134
+ let resolvedPath;
289
135
  try {
290
- resolvedPath2 = resolveFromCore(args.path);
136
+ resolvedPath = resolveFromCore(args.path);
291
137
  } catch {
292
138
  try {
293
- resolvedPath2 = resolveSpecifier(args.path, resolveParent);
139
+ resolvedPath = resolveSpecifier(args.path, resolveParent);
294
140
  } catch {
295
141
  const candidatePath = path.join(options.projectDir, "node_modules", packageName);
296
142
  const candidatePackageJson = path.join(candidatePath, "package.json");
297
143
  if (existsSync(candidatePackageJson)) {
298
- ensureRuntimePackageLink(
299
- options.runtimeNodeModulesDir,
300
- args.path,
301
- candidatePackageJson,
302
- resolveParent
303
- );
304
144
  return { path: args.path, external: true };
305
145
  }
306
146
  }
307
147
  }
308
- if (!resolvedPath2) {
148
+ if (!resolvedPath) {
309
149
  return void 0;
310
150
  }
311
- if (resolvedPath2.includes(`${path.sep}node_modules${path.sep}`)) {
312
- ensureRuntimePackageLink(options.runtimeNodeModulesDir, args.path, resolvedPath2, resolveParent);
151
+ if (resolvedPath.includes(`${path.sep}node_modules${path.sep}`)) {
313
152
  return {
314
153
  path: args.path,
315
154
  external: true
316
155
  };
317
156
  }
318
- return { path: resolvedPath2 };
157
+ return { path: resolvedPath };
319
158
  }
320
- const resolvedPath = resolveSpecifier(args.path, resolveParent);
321
- ensureRuntimePackageLink(options.runtimeNodeModulesDir, args.path, resolvedPath, resolveParent);
322
159
  return {
323
- path: getNodeExternalSpecifier(args.path, resolvedPath, resolveParent),
160
+ path: args.path,
324
161
  external: true
325
162
  };
326
163
  }
327
164
  function createNodeBootstrapPlugin(options) {
328
- const projectDir = path.resolve(options.projectDir);
329
165
  return {
330
166
  name: "node-bootstrap-plugin",
331
167
  setup(build) {
332
168
  build.onResolve({ filter: /^bun:/ }, (args) => {
333
169
  throw new Error(getNodeUnsupportedBuiltinError(args.path, args.importer));
334
170
  });
335
- build.onLoad({ filter: /\.[cm]?[jt]sx?$/ }, async (args) => {
336
- const absolutePath = path.resolve(args.path);
337
- const shouldRewriteImportMeta = shouldRewriteBootstrapSource(absolutePath, projectDir);
338
- if (!shouldRewriteImportMeta) {
339
- return void 0;
340
- }
341
- const originalContents = readFileSync(args.path, "utf8");
342
- const contents = originalContents.replaceAll("import.meta.env", "process.env").replaceAll("import.meta.dirname", JSON.stringify(path.dirname(args.path))).replaceAll("import.meta.filename", JSON.stringify(args.path)).replaceAll("import.meta.dir", JSON.stringify(path.dirname(args.path))).replaceAll("import.meta.path", JSON.stringify(args.path));
343
- if (contents === originalContents) {
344
- return void 0;
345
- }
346
- return {
347
- contents,
348
- loader: getBootstrapBuildLoaderForPath(args.path),
349
- resolveDir: path.dirname(args.path)
350
- };
351
- });
352
171
  build.onResolve({ filter: /^[@A-Za-z0-9][^:]*$/ }, (args) => {
353
172
  return resolveNodeBootstrapDependency(args, options);
354
173
  });