evolit 0.2.1 → 0.4.0
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 +108 -0
- package/package.json +8 -2
- package/src/build.js +88 -11
- package/src/client-assets.js +1 -0
- package/src/compiler.js +301 -34
- package/src/deployment-runtime.js +77 -8
- package/src/index.js +3 -0
- package/src/litsx-pipeline.d.ts +137 -0
- package/src/litsx-pipeline.js +705 -0
- package/src/render.js +1 -0
- package/src/server-setup.js +65 -0
- package/src/server.js +41 -1
- package/src/urql-ssr.js +67 -2
|
@@ -41,12 +41,19 @@ import {
|
|
|
41
41
|
} from "./response-cache.js";
|
|
42
42
|
import { createSsrAdapter, renderRouteTreeWithAdapter } from "./ssr-adapter.js";
|
|
43
43
|
import { createNavigationResponseFromDocument } from "./route-segments.js";
|
|
44
|
-
import {
|
|
44
|
+
import {
|
|
45
|
+
appendSsrUrqlData,
|
|
46
|
+
applySsrUrqlRequestContext,
|
|
47
|
+
createSsrUrqlRequestContext,
|
|
48
|
+
runWithOptionalSsrUrqlScope,
|
|
49
|
+
} from "./urql-ssr.js";
|
|
45
50
|
import {
|
|
46
51
|
getExtensionClientDescriptors,
|
|
47
52
|
resolveEvolitExtensions,
|
|
48
53
|
runRequestExtensions,
|
|
49
54
|
} from "./extensions.js";
|
|
55
|
+
import { runServerSetup } from "./server-setup.js";
|
|
56
|
+
import { createLitsxPipeline, mergeLitsxAssetsIntoManifest } from "./litsx-pipeline.js";
|
|
50
57
|
|
|
51
58
|
function isBarePackageModuleId(value) {
|
|
52
59
|
return typeof value === "string"
|
|
@@ -253,6 +260,7 @@ export async function createRequestRenderer({
|
|
|
253
260
|
onDevelopmentEvent,
|
|
254
261
|
managedSourceRoots,
|
|
255
262
|
extensions = [],
|
|
263
|
+
litsxPipeline = null,
|
|
256
264
|
}) {
|
|
257
265
|
let currentAssetManifest = normalizeClientAssetManifest(assetManifest);
|
|
258
266
|
const extensionClientDescriptors = getExtensionClientDescriptors(extensions);
|
|
@@ -319,7 +327,11 @@ export async function createRequestRenderer({
|
|
|
319
327
|
function getDevelopmentEntryInventory(entryPath) {
|
|
320
328
|
let inventory = devInventoryByEntry.get(entryPath);
|
|
321
329
|
if (!inventory) {
|
|
322
|
-
inventory = collectClientGraphInventory([entryPath], {
|
|
330
|
+
inventory = collectClientGraphInventory([entryPath], {
|
|
331
|
+
projectRoot,
|
|
332
|
+
managedSourceRoots,
|
|
333
|
+
litsxPipeline,
|
|
334
|
+
});
|
|
323
335
|
devInventoryByEntry.set(entryPath, inventory);
|
|
324
336
|
inventory.catch(() => {
|
|
325
337
|
if (devInventoryByEntry.get(entryPath) === inventory) devInventoryByEntry.delete(entryPath);
|
|
@@ -331,6 +343,7 @@ export async function createRequestRenderer({
|
|
|
331
343
|
const resolver = await createRouteResolver(projectRoot, mode, {
|
|
332
344
|
onDevelopmentEvent,
|
|
333
345
|
managedSourceRoots,
|
|
346
|
+
litsxPipeline,
|
|
334
347
|
segmentRenderCache: sharedSegmentRenderCache,
|
|
335
348
|
getStaticAssetPublicUrls() {
|
|
336
349
|
return createStaticAssetPublicUrlMap(currentAssetManifest);
|
|
@@ -353,6 +366,7 @@ export async function createRequestRenderer({
|
|
|
353
366
|
target: "client",
|
|
354
367
|
onDevelopmentEvent,
|
|
355
368
|
managedSourceRoots,
|
|
369
|
+
litsxPipeline,
|
|
356
370
|
});
|
|
357
371
|
devPreparedClientModules.add(clientModuleKey);
|
|
358
372
|
devClientModuleDependencies.set(
|
|
@@ -381,7 +395,13 @@ export async function createRequestRenderer({
|
|
|
381
395
|
clientBoundariesByEntry: devClientBoundariesByEntry,
|
|
382
396
|
additionalVendorSpecifiers: [...packageClientSpecifiers],
|
|
383
397
|
});
|
|
384
|
-
|
|
398
|
+
const integrationOutputs = await litsxPipeline?.finalize({
|
|
399
|
+
assetManifest: bundledClientAssets.manifest,
|
|
400
|
+
});
|
|
401
|
+
currentAssetManifest = mergeLitsxAssetsIntoManifest(
|
|
402
|
+
bundledClientAssets.manifest,
|
|
403
|
+
integrationOutputs,
|
|
404
|
+
);
|
|
385
405
|
devPreviousAssetOutputPaths = new Set();
|
|
386
406
|
currentAssetResolver = createAssetResolver(projectRoot, {
|
|
387
407
|
assetManifest: currentAssetManifest,
|
|
@@ -619,6 +639,7 @@ export async function createRequestRenderer({
|
|
|
619
639
|
: [];
|
|
620
640
|
const styleUrls = currentAssetManifest
|
|
621
641
|
? [...new Set([
|
|
642
|
+
...(currentAssetManifest.documentStyles ?? []),
|
|
622
643
|
...collectTransitiveStyleUrls(clientImports, currentAssetManifest),
|
|
623
644
|
...resolveServerStyleUrls(routeResult, projectRoot, currentAssetManifest),
|
|
624
645
|
])]
|
|
@@ -851,6 +872,7 @@ export async function createRequestRenderer({
|
|
|
851
872
|
target: "client",
|
|
852
873
|
onDevelopmentEvent,
|
|
853
874
|
managedSourceRoots,
|
|
875
|
+
litsxPipeline,
|
|
854
876
|
});
|
|
855
877
|
}
|
|
856
878
|
return;
|
|
@@ -882,7 +904,8 @@ export async function createRequestRenderer({
|
|
|
882
904
|
return effectiveRouteResolver.resolveRoutePolicy(request, options);
|
|
883
905
|
},
|
|
884
906
|
async renderRoute(request, routePolicyResult = null, options = {}) {
|
|
885
|
-
|
|
907
|
+
const urqlRequestContext = createSsrUrqlRequestContext(request);
|
|
908
|
+
return runWithOptionalSsrUrqlScope(urqlRequestContext, async (urqlAdapter) => {
|
|
886
909
|
const shouldPrepareBeforeResolve = mode === "development" && !currentAssetManifest;
|
|
887
910
|
let resolvedRoutePolicyResult = routePolicyResult;
|
|
888
911
|
if (shouldPrepareBeforeResolve) {
|
|
@@ -895,9 +918,14 @@ export async function createRequestRenderer({
|
|
|
895
918
|
await this.prepareRouteClientArtifacts(routeResult);
|
|
896
919
|
}
|
|
897
920
|
const renderedResponse = await renderRouteTreeWithAdapter(routeResult, ssrAdapter);
|
|
898
|
-
const
|
|
921
|
+
const responseWithData = urqlAdapter
|
|
899
922
|
? appendSsrUrqlData(renderedResponse, await urqlAdapter.getUrqlSsrData())
|
|
900
923
|
: renderedResponse;
|
|
924
|
+
const response = applySsrUrqlRequestContext(
|
|
925
|
+
routeResult,
|
|
926
|
+
responseWithData,
|
|
927
|
+
urqlRequestContext,
|
|
928
|
+
);
|
|
901
929
|
return {
|
|
902
930
|
routeResult,
|
|
903
931
|
response,
|
|
@@ -921,8 +949,13 @@ export async function createDeploymentRuntime({
|
|
|
921
949
|
routeResolver,
|
|
922
950
|
onDevelopmentEvent,
|
|
923
951
|
managedSourceRoots,
|
|
952
|
+
evolitConfig: configuredEvolitConfig,
|
|
924
953
|
} = {}) {
|
|
925
|
-
const evolitConfig = await loadEvolitConfig(projectRoot);
|
|
954
|
+
const evolitConfig = configuredEvolitConfig ?? await loadEvolitConfig(projectRoot);
|
|
955
|
+
const litsxPipeline = await createLitsxPipeline({ projectRoot, mode, config: evolitConfig });
|
|
956
|
+
let serverSetupCleanup = null;
|
|
957
|
+
try {
|
|
958
|
+
serverSetupCleanup = await runServerSetup({ projectRoot, mode, evolitConfig, litsxPipeline });
|
|
926
959
|
const extensions = resolveEvolitExtensions(evolitConfig);
|
|
927
960
|
const extensionClientSpecifiers = getExtensionClientDescriptors(extensions).map((descriptor) => descriptor.module);
|
|
928
961
|
const effectiveManagedSourceRoots = managedSourceRoots
|
|
@@ -980,18 +1013,26 @@ export async function createDeploymentRuntime({
|
|
|
980
1013
|
onDevelopmentEvent,
|
|
981
1014
|
managedSourceRoots: effectiveManagedSourceRoots,
|
|
982
1015
|
extensions,
|
|
1016
|
+
litsxPipeline,
|
|
983
1017
|
});
|
|
1018
|
+
let closed = false;
|
|
984
1019
|
|
|
985
1020
|
return {
|
|
986
1021
|
assets,
|
|
987
1022
|
cache: renderer.responseCacheController,
|
|
988
1023
|
renderer,
|
|
1024
|
+
get litsxDependencies() {
|
|
1025
|
+
return litsxPipeline?.dependencies ?? [];
|
|
1026
|
+
},
|
|
989
1027
|
async invalidateDevelopmentState(changedPaths = null) {
|
|
990
1028
|
if (mode !== "development") {
|
|
991
1029
|
return;
|
|
992
1030
|
}
|
|
993
1031
|
|
|
994
|
-
const
|
|
1032
|
+
const litsxInvalidated = await litsxPipeline?.invalidate(changedPaths);
|
|
1033
|
+
const invalidationResult = await renderer.invalidateDevelopmentState(
|
|
1034
|
+
litsxInvalidated ? null : changedPaths,
|
|
1035
|
+
);
|
|
995
1036
|
if (typeof effectiveResponseCacheRuntime.store.clear === "function") {
|
|
996
1037
|
await effectiveResponseCacheRuntime.store.clear();
|
|
997
1038
|
}
|
|
@@ -1061,6 +1102,7 @@ export async function createDeploymentRuntime({
|
|
|
1061
1102
|
const { routeResult, response } = await renderer.renderRoute(resolvedRequest, routePolicyResult, {
|
|
1062
1103
|
extensionState: extensionResult,
|
|
1063
1104
|
});
|
|
1105
|
+
await litsxPipeline?.finalize({ routeResult, assetManifest: renderer.assetManifest });
|
|
1064
1106
|
runtimeState.assetManifest = normalizeClientAssetManifest(renderer.assetManifest);
|
|
1065
1107
|
return formatResponseForRequest(
|
|
1066
1108
|
request,
|
|
@@ -1068,12 +1110,39 @@ export async function createDeploymentRuntime({
|
|
|
1068
1110
|
);
|
|
1069
1111
|
},
|
|
1070
1112
|
async close() {
|
|
1113
|
+
if (closed) return;
|
|
1114
|
+
closed = true;
|
|
1115
|
+
let cleanupError = null;
|
|
1071
1116
|
const revalidationTasks = this.revalidationTasks;
|
|
1072
1117
|
if (revalidationTasks) {
|
|
1073
|
-
|
|
1118
|
+
try {
|
|
1119
|
+
await Promise.all(revalidationTasks.values());
|
|
1120
|
+
} catch (error) {
|
|
1121
|
+
cleanupError = error;
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
try {
|
|
1125
|
+
await serverSetupCleanup?.();
|
|
1126
|
+
} catch (error) {
|
|
1127
|
+
cleanupError = error;
|
|
1074
1128
|
}
|
|
1129
|
+
try {
|
|
1130
|
+
await litsxPipeline?.dispose();
|
|
1131
|
+
} catch (error) {
|
|
1132
|
+
cleanupError ??= error;
|
|
1133
|
+
}
|
|
1134
|
+
if (cleanupError) throw cleanupError;
|
|
1075
1135
|
},
|
|
1076
1136
|
};
|
|
1137
|
+
} catch (error) {
|
|
1138
|
+
try {
|
|
1139
|
+
await serverSetupCleanup?.();
|
|
1140
|
+
} catch {}
|
|
1141
|
+
try {
|
|
1142
|
+
await litsxPipeline?.dispose();
|
|
1143
|
+
} catch {}
|
|
1144
|
+
throw error;
|
|
1145
|
+
}
|
|
1077
1146
|
}
|
|
1078
1147
|
|
|
1079
1148
|
function addNavigationVaryHeader(response) {
|
package/src/index.js
CHANGED
|
@@ -124,6 +124,9 @@ export { getRequestContext } from "./request-context.js";
|
|
|
124
124
|
/** Defines an Evolit extension for use in evolit.config.js. */
|
|
125
125
|
export { defineEvolitPlugin } from "./extensions.js";
|
|
126
126
|
|
|
127
|
+
/** Defines a typed Evolit configuration, including the native LitSX pipeline. */
|
|
128
|
+
export { defineEvolitConfig, defineLitsxIntegration } from "./litsx-pipeline.js";
|
|
129
|
+
|
|
127
130
|
/**
|
|
128
131
|
* Returns the incoming request URL. Reading it makes the current route dynamic.
|
|
129
132
|
*
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
TransformLitsxOptions,
|
|
3
|
+
TransformLitsxResult,
|
|
4
|
+
} from "@litsx/compiler";
|
|
5
|
+
|
|
6
|
+
export type EvolitMode = "development" | "production";
|
|
7
|
+
export type EvolitLitsxTarget = "server" | "client";
|
|
8
|
+
|
|
9
|
+
export type EvolitLitsxCompilerOptions = Omit<
|
|
10
|
+
TransformLitsxOptions,
|
|
11
|
+
"filename" | "ssr" | "reactCompat"
|
|
12
|
+
> & {
|
|
13
|
+
/** Evolit always uses native LitSX lowering. */
|
|
14
|
+
reactCompat?: false;
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
export type EvolitLitsxOutput = {
|
|
18
|
+
id: string;
|
|
19
|
+
kind: "asset" | "module" | "style";
|
|
20
|
+
content: string | Uint8Array;
|
|
21
|
+
specifier?: string;
|
|
22
|
+
document?: boolean;
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
export type EvolitLitsxContribution = Partial<TransformLitsxResult> & {
|
|
26
|
+
dependencies?: string[];
|
|
27
|
+
outputs?: EvolitLitsxOutput[];
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
export type EvolitLitsxIntegrationContext = {
|
|
31
|
+
readonly projectRoot: string;
|
|
32
|
+
readonly mode: EvolitMode;
|
|
33
|
+
readonly identity: Readonly<{ id: string }>;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export type EvolitLitsxModuleContext = {
|
|
37
|
+
readonly sourcePath: string;
|
|
38
|
+
readonly source: string;
|
|
39
|
+
readonly target: EvolitLitsxTarget;
|
|
40
|
+
readonly ssr: boolean;
|
|
41
|
+
readonly sourceMaps: boolean;
|
|
42
|
+
readonly generation: number;
|
|
43
|
+
readonly result: TransformLitsxResult;
|
|
44
|
+
};
|
|
45
|
+
|
|
46
|
+
export type EvolitLitsxIntegrationInstance = {
|
|
47
|
+
compiler?: EvolitLitsxCompilerOptions | ((context: {
|
|
48
|
+
filename: string;
|
|
49
|
+
ssr: boolean;
|
|
50
|
+
sourceMaps: boolean;
|
|
51
|
+
mode: EvolitMode;
|
|
52
|
+
}) => EvolitLitsxCompilerOptions);
|
|
53
|
+
resolveModule?(context: Readonly<{
|
|
54
|
+
specifier: string;
|
|
55
|
+
importer: string;
|
|
56
|
+
target: EvolitLitsxTarget;
|
|
57
|
+
ssr: boolean;
|
|
58
|
+
sourceMaps: boolean;
|
|
59
|
+
generation: number;
|
|
60
|
+
mode: EvolitMode;
|
|
61
|
+
}>): null | void | {
|
|
62
|
+
code: string;
|
|
63
|
+
map?: unknown;
|
|
64
|
+
dependencies?: string[];
|
|
65
|
+
} | Promise<null | void | {
|
|
66
|
+
code: string;
|
|
67
|
+
map?: unknown;
|
|
68
|
+
dependencies?: string[];
|
|
69
|
+
}>;
|
|
70
|
+
processModule?(context: EvolitLitsxModuleContext): EvolitLitsxContribution | void | Promise<EvolitLitsxContribution | void>;
|
|
71
|
+
finalize?(context: Readonly<Record<string, unknown> & {
|
|
72
|
+
generation: number;
|
|
73
|
+
mode: EvolitMode;
|
|
74
|
+
}>): EvolitLitsxContribution | void | Promise<EvolitLitsxContribution | void>;
|
|
75
|
+
invalidate?(context: Readonly<{
|
|
76
|
+
paths: string[] | null;
|
|
77
|
+
affected: boolean;
|
|
78
|
+
generation: number;
|
|
79
|
+
mode: EvolitMode;
|
|
80
|
+
}>): void | Promise<void>;
|
|
81
|
+
forget?(context: Readonly<{
|
|
82
|
+
moduleId: string;
|
|
83
|
+
generation: number;
|
|
84
|
+
mode: EvolitMode;
|
|
85
|
+
}>): void | Promise<void>;
|
|
86
|
+
dispose?(): void | Promise<void>;
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
export type EvolitLitsxIntegration = {
|
|
90
|
+
readonly name: string;
|
|
91
|
+
create(context: EvolitLitsxIntegrationContext): EvolitLitsxIntegrationInstance | Promise<EvolitLitsxIntegrationInstance>;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export type EvolitLitsxConfig = {
|
|
95
|
+
compiler?: EvolitLitsxCompilerOptions;
|
|
96
|
+
integrations?: EvolitLitsxIntegration[];
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export type EvolitConfig = {
|
|
100
|
+
litsx?: EvolitLitsxConfig;
|
|
101
|
+
[key: string]: unknown;
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
export type EvolitLitsxPipeline = {
|
|
105
|
+
readonly identity: Readonly<{ id: string }>;
|
|
106
|
+
readonly generation: number;
|
|
107
|
+
readonly dependencies: string[];
|
|
108
|
+
getCompilerOptions(context: { filename: string; ssr: boolean; sourceMaps: boolean }): TransformLitsxOptions;
|
|
109
|
+
resolveModule(specifier: string, context: {
|
|
110
|
+
importer: string;
|
|
111
|
+
target: EvolitLitsxTarget;
|
|
112
|
+
ssr: boolean;
|
|
113
|
+
sourceMaps: boolean;
|
|
114
|
+
}): Promise<string | null>;
|
|
115
|
+
registerResolvedModule(specifier: string, sourcePath: string, outputPath: string): void;
|
|
116
|
+
processModule(result: TransformLitsxResult, context: Omit<EvolitLitsxModuleContext, "result" | "generation">): Promise<TransformLitsxResult & { evolitDependencies: string[] }>;
|
|
117
|
+
finalize(context?: Record<string, unknown>): Promise<null | {
|
|
118
|
+
assets: Array<{ integration: string; id: string; kind: string; outputPath: string; hash: string; size: number }>;
|
|
119
|
+
documentStyles: Array<{ integration: string; id: string; kind: string; outputPath: string; hash: string; size: number }>;
|
|
120
|
+
}>;
|
|
121
|
+
invalidate(changedPaths?: string[] | null): Promise<boolean>;
|
|
122
|
+
forget(moduleId: string): Promise<void>;
|
|
123
|
+
dispose(): Promise<void>;
|
|
124
|
+
};
|
|
125
|
+
|
|
126
|
+
export function createLitsxPipeline(options: {
|
|
127
|
+
projectRoot: string;
|
|
128
|
+
mode: EvolitMode;
|
|
129
|
+
config?: EvolitConfig;
|
|
130
|
+
}): Promise<EvolitLitsxPipeline | null>;
|
|
131
|
+
|
|
132
|
+
export function defineEvolitConfig<T extends EvolitConfig>(config: T): T;
|
|
133
|
+
export function defineLitsxIntegration<T extends EvolitLitsxIntegration>(integration: T): T;
|
|
134
|
+
export function mergeLitsxAssetsIntoManifest<T extends Record<string, unknown>>(
|
|
135
|
+
manifest: T,
|
|
136
|
+
integrationManifest: Awaited<ReturnType<EvolitLitsxPipeline["finalize"]>>,
|
|
137
|
+
): T;
|