evolit 0.1.0-alpha.13 → 0.1.0-alpha.15

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": "evolit",
3
- "version": "0.1.0-alpha.13",
3
+ "version": "0.1.0-alpha.15",
4
4
  "description": "A convention-driven application framework for LitSX and web components.",
5
5
  "type": "module",
6
6
  "packageManager": "yarn@4.10.3",
@@ -36,6 +36,23 @@ const sharedRuntimeBuildCache = new Map();
36
36
  const clientVendorSpecifierCache = new Map();
37
37
  const clientModuleMetadataCache = new Map();
38
38
 
39
+ export function resetDevelopmentAssetCaches(projectRoot) {
40
+ const normalizedProjectRoot = path.resolve(projectRoot);
41
+ const developmentPrefix = `${normalizedProjectRoot}::development::`;
42
+
43
+ for (const cache of [
44
+ sharedRuntimeBuildCache,
45
+ clientVendorSpecifierCache,
46
+ clientModuleMetadataCache,
47
+ ]) {
48
+ for (const key of cache.keys()) {
49
+ if (key.startsWith(developmentPrefix)) {
50
+ cache.delete(key);
51
+ }
52
+ }
53
+ }
54
+ }
55
+
39
56
  function isBareSpecifier(specifier) {
40
57
  return (
41
58
  typeof specifier === "string" &&
@@ -69,6 +86,19 @@ function resolveRelativeClientImportPath(fromClientModule, specifier) {
69
86
  .join("/");
70
87
  }
71
88
 
89
+ function normalizeClientMetadataAssetPath(fromClientModule, importedAsset) {
90
+ if (typeof importedAsset !== "string") {
91
+ return null;
92
+ }
93
+
94
+ const normalizedAsset = stripImportSearchAndHash(importedAsset);
95
+ if (isRelativeSpecifier(normalizedAsset)) {
96
+ return resolveRelativeClientImportPath(fromClientModule, normalizedAsset);
97
+ }
98
+
99
+ return path.normalize(normalizedAsset).split(path.sep).join("/");
100
+ }
101
+
72
102
  function parsePackageSpecifier(specifier) {
73
103
  if (!isBareSpecifier(specifier)) {
74
104
  return null;
@@ -738,10 +768,16 @@ async function collectTransitiveClientModuleMetadata(projectRoot, mode, clientMo
738
768
  }
739
769
 
740
770
  for (const styleImport of metadata.styleImports) {
741
- styleImports.add(styleImport);
771
+ const normalizedStyleImport = normalizeClientMetadataAssetPath(currentModule, styleImport);
772
+ if (normalizedStyleImport) {
773
+ styleImports.add(normalizedStyleImport);
774
+ }
742
775
  }
743
776
  for (const assetImport of metadata.assetImports) {
744
- assetImports.add(assetImport);
777
+ const normalizedAssetImport = normalizeClientMetadataAssetPath(currentModule, assetImport);
778
+ if (normalizedAssetImport) {
779
+ assetImports.add(normalizedAssetImport);
780
+ }
745
781
  }
746
782
  for (const importedModule of metadata.moduleImports) {
747
783
  pendingModules.push(importedModule);
@@ -1395,8 +1431,12 @@ export async function emitHashedClientAssets(projectRoot, options = {}) {
1395
1431
  if (entry.type === "script") {
1396
1432
  try {
1397
1433
  const metadata = JSON.parse(await fs.readFile(`${entry.filePath}.meta.json`, "utf8"));
1398
- styleImports = Array.isArray(metadata?.styleImports) ? metadata.styleImports : [];
1399
- assetImports = Array.isArray(metadata?.assetImports) ? metadata.assetImports : [];
1434
+ styleImports = (Array.isArray(metadata?.styleImports) ? metadata.styleImports : [])
1435
+ .map((importedStyle) => normalizeClientMetadataAssetPath(entry.relativePath, importedStyle))
1436
+ .filter((importedStyle) => typeof importedStyle === "string");
1437
+ assetImports = (Array.isArray(metadata?.assetImports) ? metadata.assetImports : [])
1438
+ .map((importedAsset) => normalizeClientMetadataAssetPath(entry.relativePath, importedAsset))
1439
+ .filter((importedAsset) => typeof importedAsset === "string");
1400
1440
  } catch {
1401
1441
  styleImports = [];
1402
1442
  assetImports = [];
package/src/compiler.js CHANGED
@@ -25,6 +25,7 @@ const developmentGraphCache = new Map();
25
25
  const developmentGraphDependencies = new Map();
26
26
  const developmentModuleNamespaceCache = new Map();
27
27
  const developmentGraphVersions = new Map();
28
+ const developmentExternalImportWarnings = new Set();
28
29
 
29
30
  function isRelativeSpecifier(specifier) {
30
31
  return specifier.startsWith("./") || specifier.startsWith("../");
@@ -60,6 +61,27 @@ function isStyleAssetPath(filePath) {
60
61
  return filePath.endsWith(".css");
61
62
  }
62
63
 
64
+ function isPathOutsideProject(projectRoot, filePath) {
65
+ const relativePath = path.relative(projectRoot, filePath);
66
+ return (
67
+ relativePath === ".." ||
68
+ relativePath.startsWith(`..${path.sep}`) ||
69
+ path.isAbsolute(relativePath)
70
+ );
71
+ }
72
+
73
+ function warnForDevelopmentExternalImport(projectRoot, sourcePath, resolvedImportPath) {
74
+ const warningKey = `${path.resolve(projectRoot)}::${sourcePath}::${resolvedImportPath}`;
75
+ if (developmentExternalImportWarnings.has(warningKey)) {
76
+ return;
77
+ }
78
+
79
+ developmentExternalImportWarnings.add(warningKey);
80
+ console.warn(
81
+ `[evolit] Development import ${JSON.stringify(resolvedImportPath)} from ${JSON.stringify(sourcePath)} is outside the project root. It will be emitted under /_evolit/static/__external__/.`,
82
+ );
83
+ }
84
+
63
85
  function createStaticAssetStubSource(relativeAssetPath, mode, target = "server", staticAssetPublicUrls = null) {
64
86
  const normalizedAssetPath = relativeAssetPath.split(path.sep).join("/");
65
87
  if (normalizedAssetPath.endsWith(".css")) {
@@ -112,7 +134,7 @@ function getTypedOutputRoot(projectRoot, mode, target = "server") {
112
134
  }
113
135
 
114
136
  function toOutputPath(projectRoot, outputRoot, sourcePath) {
115
- const relativePath = path.relative(projectRoot, sourcePath);
137
+ const relativePath = toOutputRelativePath(projectRoot, sourcePath);
116
138
  const extension = path.extname(relativePath);
117
139
  if (!extension) {
118
140
  return path.join(outputRoot, `${relativePath}.mjs`);
@@ -124,6 +146,22 @@ function toOutputPath(projectRoot, outputRoot, sourcePath) {
124
146
  );
125
147
  }
126
148
 
149
+ function toOutputRelativePath(projectRoot, sourcePath) {
150
+ const relativePath = path.relative(projectRoot, sourcePath);
151
+ const isOutsideProject =
152
+ relativePath === ".." ||
153
+ relativePath.startsWith(`..${path.sep}`) ||
154
+ path.isAbsolute(relativePath);
155
+ if (!isOutsideProject) {
156
+ return relativePath;
157
+ }
158
+
159
+ return path.join(
160
+ "__external__",
161
+ ...relativePath.split(path.sep).map((segment) => segment === ".." ? "__up__" : segment),
162
+ );
163
+ }
164
+
127
165
  async function rewriteRelativeSpecifiers({
128
166
  projectRoot,
129
167
  outputRoot,
@@ -169,13 +207,17 @@ async function rewriteRelativeSpecifiers({
169
207
  continue;
170
208
  }
171
209
 
210
+ if (mode === "development" && isPathOutsideProject(projectRoot, resolvedImportPath)) {
211
+ warnForDevelopmentExternalImport(projectRoot, sourcePath, resolvedImportPath);
212
+ }
213
+
172
214
  const importerOutputPath = toOutputPath(projectRoot, outputRoot, sourcePath);
173
215
  let compiledImportPath = null;
174
216
 
175
217
  if (shouldCompileModule(resolvedImportPath)) {
176
218
  compiledImportPath = await compileModule(resolvedImportPath);
177
219
  } else if (isStaticAssetPath(resolvedImportPath)) {
178
- const relativeAssetPath = path.relative(projectRoot, resolvedImportPath);
220
+ const relativeAssetPath = toOutputRelativePath(projectRoot, resolvedImportPath);
179
221
  const assetOutputPath = path.join(outputRoot, relativeAssetPath);
180
222
  const stubOutputPath = `${assetOutputPath}.mjs`;
181
223
 
@@ -293,6 +335,14 @@ export function invalidateDevelopmentCompilationCache(projectRoot, changedPaths
293
335
  : null;
294
336
  let invalidated = false;
295
337
 
338
+ if (normalizedChangedPaths == null) {
339
+ for (const warningKey of developmentExternalImportWarnings) {
340
+ if (warningKey.startsWith(prefix)) {
341
+ developmentExternalImportWarnings.delete(warningKey);
342
+ }
343
+ }
344
+ }
345
+
296
346
  for (const key of developmentGraphCache.keys()) {
297
347
  if (!key.startsWith(prefix)) {
298
348
  continue;
@@ -10,17 +10,20 @@ import {
10
10
  createAssetResolver,
11
11
  createHydrationBootstrap,
12
12
  createStaticAssetPublicUrlMap,
13
+ buildSharedVendorRuntime,
13
14
  emitBundledClientAssetsWithState,
14
15
  getAssetByPublicUrl,
15
16
  getSharedOutputRoot,
16
17
  normalizeHydrationDataForClient,
17
18
  normalizeClientAssetManifest,
19
+ resetDevelopmentAssetCaches,
18
20
  resolveRouteClientImports,
19
21
  resolveSharedVendorModuleUrl,
20
22
  resolveBrowserPackageAssetFilePath,
21
23
  rewriteHydrationDataScript,
22
24
  } from "./client-assets.js";
23
25
  import { loadEvolitConfig } from "./config.js";
26
+ import { DEV_DIRECTORY, INTERNAL_DIRECTORY } from "./constants.js";
24
27
  import { createRouteResolver } from "./render.js";
25
28
  import {
26
29
  createCachedRouteResponse,
@@ -454,6 +457,16 @@ export async function createDeploymentRuntime({
454
457
  responseCacheRuntime,
455
458
  routeResolver,
456
459
  } = {}) {
460
+ if (mode === "development") {
461
+ const developmentRoot = path.join(projectRoot, INTERNAL_DIRECTORY, DEV_DIRECTORY);
462
+ await fs.rm(developmentRoot, { recursive: true, force: true });
463
+ invalidateDevelopmentCompilationCache(projectRoot);
464
+ resetDevelopmentAssetCaches(projectRoot);
465
+ await buildSharedVendorRuntime(projectRoot, "development", {
466
+ additionalEntrySpecifiers: [],
467
+ });
468
+ }
469
+
457
470
  const effectiveResponseCacheRuntime = responseCacheRuntime
458
471
  ?? await resolveResponseCacheRuntime(
459
472
  projectRoot,
@@ -461,7 +474,7 @@ export async function createDeploymentRuntime({
461
474
  await loadEvolitConfig(projectRoot),
462
475
  );
463
476
  const runtimeState = {
464
- assetManifest: normalizeClientAssetManifest(assetManifest),
477
+ assetManifest: mode === "development" ? null : normalizeClientAssetManifest(assetManifest),
465
478
  };
466
479
  const assets = createPublicAssetOrigin({
467
480
  projectRoot,