evolit 0.1.0-alpha.2 → 0.1.0-alpha.21
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 +73 -3
- package/package.json +13 -6
- package/src/build.js +37 -9
- package/src/cli.js +16 -9
- package/src/client-assets.js +326 -70
- package/src/compiler.js +176 -9
- package/src/deployment-runtime.js +246 -43
- package/src/development-events.js +96 -0
- package/src/navigation-client.js +519 -0
- package/src/navigation-server.js +3 -0
- package/src/navigation-url.js +28 -0
- package/src/render.js +328 -19
- package/src/route-config.js +3 -1
- package/src/route-segments.js +272 -0
- package/src/scaffold.js +4 -0
- package/src/server.js +156 -13
- package/src/ssr-adapter.js +127 -12
- package/src/terminal.js +32 -0
- package/templates/default/yarnrc.yml.template +1 -0
package/src/compiler.js
CHANGED
|
@@ -17,6 +17,15 @@ import { ensureDirectory } from "./fs-utils.js";
|
|
|
17
17
|
|
|
18
18
|
const MODULE_SPECIFIER_PATTERN =
|
|
19
19
|
/\b(?:import|export)\s+(?:[^"']*?\s+from\s+)?["']([^"']+)["']|\bimport\s*\(\s*["']([^"']+)["']\s*\)/g;
|
|
20
|
+
const RESOLVABLE_IMPORT_EXTENSIONS = [
|
|
21
|
+
...MODULE_EXTENSIONS,
|
|
22
|
+
...STATIC_ASSET_EXTENSIONS,
|
|
23
|
+
];
|
|
24
|
+
const developmentGraphCache = new Map();
|
|
25
|
+
const developmentGraphDependencies = new Map();
|
|
26
|
+
const developmentModuleNamespaceCache = new Map();
|
|
27
|
+
const developmentGraphVersions = new Map();
|
|
28
|
+
const developmentUnmanagedImportWarnings = new Set();
|
|
20
29
|
|
|
21
30
|
function isRelativeSpecifier(specifier) {
|
|
22
31
|
return specifier.startsWith("./") || specifier.startsWith("../");
|
|
@@ -44,10 +53,37 @@ function isStaticAssetPath(filePath) {
|
|
|
44
53
|
return STATIC_ASSET_EXTENSIONS.some((extension) => filePath.endsWith(extension));
|
|
45
54
|
}
|
|
46
55
|
|
|
56
|
+
function hasResolvableImportExtension(filePath) {
|
|
57
|
+
return RESOLVABLE_IMPORT_EXTENSIONS.some((extension) => filePath.endsWith(extension));
|
|
58
|
+
}
|
|
59
|
+
|
|
47
60
|
function isStyleAssetPath(filePath) {
|
|
48
61
|
return filePath.endsWith(".css");
|
|
49
62
|
}
|
|
50
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 reportDevelopmentUnmanagedImport(projectRoot, sourcePath, resolvedImportPath, onDevelopmentEvent) {
|
|
74
|
+
const warningKey = `${path.resolve(projectRoot)}::${sourcePath}::${resolvedImportPath}`;
|
|
75
|
+
if (developmentUnmanagedImportWarnings.has(warningKey)) {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
developmentUnmanagedImportWarnings.add(warningKey);
|
|
80
|
+
onDevelopmentEvent?.({
|
|
81
|
+
type: "unmanaged-import",
|
|
82
|
+
sourcePath,
|
|
83
|
+
resolvedImportPath,
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
|
|
51
87
|
function createStaticAssetStubSource(relativeAssetPath, mode, target = "server", staticAssetPublicUrls = null) {
|
|
52
88
|
const normalizedAssetPath = relativeAssetPath.split(path.sep).join("/");
|
|
53
89
|
if (normalizedAssetPath.endsWith(".css")) {
|
|
@@ -65,8 +101,8 @@ async function resolveImportPath(importerPath, specifier) {
|
|
|
65
101
|
const basePath = path.resolve(path.dirname(importerPath), specifier);
|
|
66
102
|
const candidates = [basePath];
|
|
67
103
|
|
|
68
|
-
if (!
|
|
69
|
-
for (const extension of
|
|
104
|
+
if (!hasResolvableImportExtension(basePath)) {
|
|
105
|
+
for (const extension of RESOLVABLE_IMPORT_EXTENSIONS) {
|
|
70
106
|
candidates.push(`${basePath}${extension}`);
|
|
71
107
|
candidates.push(path.join(basePath, `index${extension}`));
|
|
72
108
|
}
|
|
@@ -100,7 +136,7 @@ function getTypedOutputRoot(projectRoot, mode, target = "server") {
|
|
|
100
136
|
}
|
|
101
137
|
|
|
102
138
|
function toOutputPath(projectRoot, outputRoot, sourcePath) {
|
|
103
|
-
const relativePath =
|
|
139
|
+
const relativePath = toOutputRelativePath(projectRoot, sourcePath);
|
|
104
140
|
const extension = path.extname(relativePath);
|
|
105
141
|
if (!extension) {
|
|
106
142
|
return path.join(outputRoot, `${relativePath}.mjs`);
|
|
@@ -112,6 +148,22 @@ function toOutputPath(projectRoot, outputRoot, sourcePath) {
|
|
|
112
148
|
);
|
|
113
149
|
}
|
|
114
150
|
|
|
151
|
+
function toOutputRelativePath(projectRoot, sourcePath) {
|
|
152
|
+
const relativePath = path.relative(projectRoot, sourcePath);
|
|
153
|
+
const isOutsideProject =
|
|
154
|
+
relativePath === ".." ||
|
|
155
|
+
relativePath.startsWith(`..${path.sep}`) ||
|
|
156
|
+
path.isAbsolute(relativePath);
|
|
157
|
+
if (!isOutsideProject) {
|
|
158
|
+
return relativePath;
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
return path.join(
|
|
162
|
+
"__unmanaged__",
|
|
163
|
+
...relativePath.split(path.sep).map((segment) => segment === ".." ? "__up__" : segment),
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
|
|
115
167
|
async function rewriteRelativeSpecifiers({
|
|
116
168
|
projectRoot,
|
|
117
169
|
outputRoot,
|
|
@@ -126,6 +178,7 @@ async function rewriteRelativeSpecifiers({
|
|
|
126
178
|
sourceMaps,
|
|
127
179
|
outputPath,
|
|
128
180
|
inputSourceMap,
|
|
181
|
+
onDevelopmentEvent,
|
|
129
182
|
}) {
|
|
130
183
|
const magicSource = new MagicString(code);
|
|
131
184
|
let didRewrite = false;
|
|
@@ -157,13 +210,17 @@ async function rewriteRelativeSpecifiers({
|
|
|
157
210
|
continue;
|
|
158
211
|
}
|
|
159
212
|
|
|
213
|
+
if (mode === "development" && isPathOutsideProject(projectRoot, resolvedImportPath)) {
|
|
214
|
+
reportDevelopmentUnmanagedImport(projectRoot, sourcePath, resolvedImportPath, onDevelopmentEvent);
|
|
215
|
+
}
|
|
216
|
+
|
|
160
217
|
const importerOutputPath = toOutputPath(projectRoot, outputRoot, sourcePath);
|
|
161
218
|
let compiledImportPath = null;
|
|
162
219
|
|
|
163
220
|
if (shouldCompileModule(resolvedImportPath)) {
|
|
164
221
|
compiledImportPath = await compileModule(resolvedImportPath);
|
|
165
222
|
} else if (isStaticAssetPath(resolvedImportPath)) {
|
|
166
|
-
const relativeAssetPath =
|
|
223
|
+
const relativeAssetPath = toOutputRelativePath(projectRoot, resolvedImportPath);
|
|
167
224
|
const assetOutputPath = path.join(outputRoot, relativeAssetPath);
|
|
168
225
|
const stubOutputPath = `${assetOutputPath}.mjs`;
|
|
169
226
|
|
|
@@ -264,7 +321,54 @@ async function rewriteRelativeSpecifiers({
|
|
|
264
321
|
};
|
|
265
322
|
}
|
|
266
323
|
|
|
267
|
-
|
|
324
|
+
function getDevelopmentGraphCacheKey(entryPath, options) {
|
|
325
|
+
return [
|
|
326
|
+
options.projectRoot,
|
|
327
|
+
entryPath,
|
|
328
|
+
options.target ?? "server",
|
|
329
|
+
options.ssr === true ? "ssr" : "client",
|
|
330
|
+
options.sourceMaps === false ? "without-maps" : "with-maps",
|
|
331
|
+
].join("::");
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
export function invalidateDevelopmentCompilationCache(projectRoot, changedPaths = null) {
|
|
335
|
+
const prefix = `${path.resolve(projectRoot)}::`;
|
|
336
|
+
const normalizedChangedPaths = Array.isArray(changedPaths) && changedPaths.length > 0
|
|
337
|
+
? new Set(changedPaths.map((changedPath) => path.resolve(changedPath)))
|
|
338
|
+
: null;
|
|
339
|
+
let invalidated = false;
|
|
340
|
+
|
|
341
|
+
if (normalizedChangedPaths == null) {
|
|
342
|
+
for (const warningKey of developmentUnmanagedImportWarnings) {
|
|
343
|
+
if (warningKey.startsWith(prefix)) {
|
|
344
|
+
developmentUnmanagedImportWarnings.delete(warningKey);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
for (const key of developmentGraphCache.keys()) {
|
|
350
|
+
if (!key.startsWith(prefix)) {
|
|
351
|
+
continue;
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
const dependencies = developmentGraphDependencies.get(key);
|
|
355
|
+
const shouldInvalidate =
|
|
356
|
+
normalizedChangedPaths == null ||
|
|
357
|
+
!dependencies ||
|
|
358
|
+
[...dependencies].some((dependency) => normalizedChangedPaths.has(dependency));
|
|
359
|
+
if (shouldInvalidate) {
|
|
360
|
+
developmentGraphCache.delete(key);
|
|
361
|
+
developmentGraphDependencies.delete(key);
|
|
362
|
+
developmentModuleNamespaceCache.delete(key);
|
|
363
|
+
developmentGraphVersions.set(key, (developmentGraphVersions.get(key) ?? 0) + 1);
|
|
364
|
+
invalidated = true;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
367
|
+
|
|
368
|
+
return invalidated;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
async function compileModuleGraphUncached(entryPath, options = {}) {
|
|
268
372
|
const {
|
|
269
373
|
projectRoot,
|
|
270
374
|
mode = "development",
|
|
@@ -272,6 +376,7 @@ export async function compileModuleGraph(entryPath, options = {}) {
|
|
|
272
376
|
ssr = false,
|
|
273
377
|
target = "server",
|
|
274
378
|
staticAssetPublicUrls = null,
|
|
379
|
+
onDevelopmentEvent,
|
|
275
380
|
} = options;
|
|
276
381
|
|
|
277
382
|
const outputRoot = getTypedOutputRoot(projectRoot, mode, target);
|
|
@@ -310,6 +415,7 @@ export async function compileModuleGraph(entryPath, options = {}) {
|
|
|
310
415
|
sourceMaps,
|
|
311
416
|
outputPath,
|
|
312
417
|
inputSourceMap: transformed.map ?? null,
|
|
418
|
+
onDevelopmentEvent,
|
|
313
419
|
});
|
|
314
420
|
|
|
315
421
|
await fs.writeFile(outputPath, rewritten.code, "utf8");
|
|
@@ -338,16 +444,77 @@ export async function compileModuleGraph(entryPath, options = {}) {
|
|
|
338
444
|
return {
|
|
339
445
|
entrypoint: await compileModule(entryPath),
|
|
340
446
|
outputRoot,
|
|
447
|
+
sourceFiles: [...visited.keys()],
|
|
448
|
+
};
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
export async function compileModuleGraph(entryPath, options = {}) {
|
|
452
|
+
const mode = options.mode ?? "development";
|
|
453
|
+
if (mode !== "development") {
|
|
454
|
+
return compileModuleGraphUncached(entryPath, options);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
const normalizedOptions = {
|
|
458
|
+
...options,
|
|
459
|
+
projectRoot: path.resolve(options.projectRoot ?? process.cwd()),
|
|
341
460
|
};
|
|
461
|
+
const cacheKey = getDevelopmentGraphCacheKey(
|
|
462
|
+
path.resolve(entryPath),
|
|
463
|
+
normalizedOptions,
|
|
464
|
+
);
|
|
465
|
+
let pendingCompile = developmentGraphCache.get(cacheKey);
|
|
466
|
+
if (!pendingCompile) {
|
|
467
|
+
pendingCompile = compileModuleGraphUncached(entryPath, normalizedOptions);
|
|
468
|
+
developmentGraphCache.set(cacheKey, pendingCompile);
|
|
469
|
+
pendingCompile.then((result) => {
|
|
470
|
+
if (developmentGraphCache.get(cacheKey) === pendingCompile) {
|
|
471
|
+
developmentGraphDependencies.set(cacheKey, new Set(result.sourceFiles));
|
|
472
|
+
}
|
|
473
|
+
}, () => {});
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
try {
|
|
477
|
+
return await pendingCompile;
|
|
478
|
+
} catch (error) {
|
|
479
|
+
if (developmentGraphCache.get(cacheKey) === pendingCompile) {
|
|
480
|
+
developmentGraphCache.delete(cacheKey);
|
|
481
|
+
developmentGraphDependencies.delete(cacheKey);
|
|
482
|
+
}
|
|
483
|
+
throw error;
|
|
484
|
+
}
|
|
342
485
|
}
|
|
343
486
|
|
|
344
487
|
export async function importCompiledModule(entryPath, options = {}) {
|
|
345
|
-
const
|
|
488
|
+
const mode = options.mode ?? "development";
|
|
489
|
+
const normalizedOptions = mode === "development"
|
|
490
|
+
? { ...options, projectRoot: path.resolve(options.projectRoot ?? process.cwd()) }
|
|
491
|
+
: options;
|
|
492
|
+
const cacheKey = mode === "development"
|
|
493
|
+
? getDevelopmentGraphCacheKey(path.resolve(entryPath), normalizedOptions)
|
|
494
|
+
: null;
|
|
495
|
+
const cachedModule = cacheKey ? developmentModuleNamespaceCache.get(cacheKey) : null;
|
|
496
|
+
if (cachedModule) {
|
|
497
|
+
return cachedModule;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
const { entrypoint } = await compileModuleGraph(entryPath, normalizedOptions);
|
|
346
501
|
const moduleUrl = new URL(pathToFileURL(entrypoint).href);
|
|
347
502
|
|
|
348
|
-
if (
|
|
349
|
-
moduleUrl.searchParams.set("t", String(
|
|
503
|
+
if (mode === "development") {
|
|
504
|
+
moduleUrl.searchParams.set("t", String(developmentGraphVersions.get(cacheKey) ?? 0));
|
|
350
505
|
}
|
|
351
506
|
|
|
352
|
-
|
|
507
|
+
const pendingModule = import(moduleUrl.href);
|
|
508
|
+
if (cacheKey) {
|
|
509
|
+
developmentModuleNamespaceCache.set(cacheKey, pendingModule);
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
try {
|
|
513
|
+
return await pendingModule;
|
|
514
|
+
} catch (error) {
|
|
515
|
+
if (developmentModuleNamespaceCache.get(cacheKey) === pendingModule) {
|
|
516
|
+
developmentModuleNamespaceCache.delete(cacheKey);
|
|
517
|
+
}
|
|
518
|
+
throw error;
|
|
519
|
+
}
|
|
353
520
|
}
|