@tanstack/start-plugin-core 1.142.11 → 1.142.13
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/dist/esm/create-server-fn-plugin/compiler.d.ts +25 -4
- package/dist/esm/create-server-fn-plugin/compiler.js +242 -79
- package/dist/esm/create-server-fn-plugin/compiler.js.map +1 -1
- package/dist/esm/create-server-fn-plugin/plugin.js +24 -24
- package/dist/esm/create-server-fn-plugin/plugin.js.map +1 -1
- package/package.json +7 -7
- package/src/create-server-fn-plugin/compiler.ts +397 -111
- package/src/create-server-fn-plugin/plugin.ts +37 -32
|
@@ -22,6 +22,13 @@ type ExportEntry = {
|
|
|
22
22
|
};
|
|
23
23
|
type Kind = 'None' | `Root` | `Builder` | LookupKind;
|
|
24
24
|
export type LookupKind = 'ServerFn' | 'Middleware' | 'IsomorphicFn' | 'ServerOnlyFn' | 'ClientOnlyFn';
|
|
25
|
+
export declare const KindDetectionPatterns: Record<LookupKind, RegExp>;
|
|
26
|
+
export declare const LookupKindsPerEnv: Record<'client' | 'server', Set<LookupKind>>;
|
|
27
|
+
/**
|
|
28
|
+
* Detects which LookupKinds are present in the code using string matching.
|
|
29
|
+
* This is a fast pre-scan before AST parsing to limit the work done during compilation.
|
|
30
|
+
*/
|
|
31
|
+
export declare function detectKindsInCode(code: string, env: 'client' | 'server'): Set<LookupKind>;
|
|
25
32
|
export type LookupConfig = {
|
|
26
33
|
libName: string;
|
|
27
34
|
rootExport: string;
|
|
@@ -38,8 +45,8 @@ export declare class ServerFnCompiler {
|
|
|
38
45
|
private moduleCache;
|
|
39
46
|
private initialized;
|
|
40
47
|
private validLookupKinds;
|
|
41
|
-
private
|
|
42
|
-
private
|
|
48
|
+
private resolveIdCache;
|
|
49
|
+
private exportResolutionCache;
|
|
43
50
|
private knownRootImports;
|
|
44
51
|
constructor(options: {
|
|
45
52
|
env: 'client' | 'server';
|
|
@@ -48,8 +55,21 @@ export declare class ServerFnCompiler {
|
|
|
48
55
|
lookupKinds: Set<LookupKind>;
|
|
49
56
|
loadModule: (id: string) => Promise<void>;
|
|
50
57
|
resolveId: (id: string, importer?: string) => Promise<string | null>;
|
|
58
|
+
/**
|
|
59
|
+
* In 'build' mode, resolution results are cached for performance.
|
|
60
|
+
* In 'dev' mode (default), caching is disabled to avoid invalidation complexity with HMR.
|
|
61
|
+
*/
|
|
62
|
+
mode?: 'dev' | 'build';
|
|
51
63
|
});
|
|
64
|
+
private get mode();
|
|
65
|
+
private resolveIdCached;
|
|
66
|
+
private getExportResolutionCache;
|
|
52
67
|
private init;
|
|
68
|
+
/**
|
|
69
|
+
* Extracts bindings and exports from an already-parsed AST.
|
|
70
|
+
* This is the core logic shared by ingestModule and ingestModuleFromAst.
|
|
71
|
+
*/
|
|
72
|
+
private extractModuleInfo;
|
|
53
73
|
ingestModule({ code, id }: {
|
|
54
74
|
code: string;
|
|
55
75
|
id: string;
|
|
@@ -58,12 +78,13 @@ export declare class ServerFnCompiler {
|
|
|
58
78
|
ast: import('@tanstack/router-utils').ParseAstResult;
|
|
59
79
|
};
|
|
60
80
|
invalidateModule(id: string): boolean;
|
|
61
|
-
compile({ code, id, isProviderFile, }: {
|
|
81
|
+
compile({ code, id, isProviderFile, detectedKinds, }: {
|
|
62
82
|
code: string;
|
|
63
83
|
id: string;
|
|
64
84
|
isProviderFile: boolean;
|
|
85
|
+
/** Pre-detected kinds present in this file. If not provided, all valid kinds are checked. */
|
|
86
|
+
detectedKinds?: Set<LookupKind>;
|
|
65
87
|
}): Promise<import('@tanstack/router-utils').GeneratorResult | null>;
|
|
66
|
-
private collectCandidates;
|
|
67
88
|
private resolveIdentifierKind;
|
|
68
89
|
/**
|
|
69
90
|
* Recursively find an export in a module, following `export * from` chains.
|
|
@@ -24,6 +24,38 @@ const LookupSetup = {
|
|
|
24
24
|
ServerOnlyFn: { type: "directCall" },
|
|
25
25
|
ClientOnlyFn: { type: "directCall" }
|
|
26
26
|
};
|
|
27
|
+
const KindDetectionPatterns = {
|
|
28
|
+
ServerFn: /\.handler\s*\(/,
|
|
29
|
+
Middleware: /createMiddleware/,
|
|
30
|
+
IsomorphicFn: /createIsomorphicFn/,
|
|
31
|
+
ServerOnlyFn: /createServerOnlyFn/,
|
|
32
|
+
ClientOnlyFn: /createClientOnlyFn/
|
|
33
|
+
};
|
|
34
|
+
const LookupKindsPerEnv = {
|
|
35
|
+
client: /* @__PURE__ */ new Set([
|
|
36
|
+
"Middleware",
|
|
37
|
+
"ServerFn",
|
|
38
|
+
"IsomorphicFn",
|
|
39
|
+
"ServerOnlyFn",
|
|
40
|
+
"ClientOnlyFn"
|
|
41
|
+
]),
|
|
42
|
+
server: /* @__PURE__ */ new Set([
|
|
43
|
+
"ServerFn",
|
|
44
|
+
"IsomorphicFn",
|
|
45
|
+
"ServerOnlyFn",
|
|
46
|
+
"ClientOnlyFn"
|
|
47
|
+
])
|
|
48
|
+
};
|
|
49
|
+
function detectKindsInCode(code, env) {
|
|
50
|
+
const detected = /* @__PURE__ */ new Set();
|
|
51
|
+
const validForEnv = LookupKindsPerEnv[env];
|
|
52
|
+
for (const [kind, pattern] of Object.entries(KindDetectionPatterns)) {
|
|
53
|
+
if (validForEnv.has(kind) && pattern.test(code)) {
|
|
54
|
+
detected.add(kind);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return detected;
|
|
58
|
+
}
|
|
27
59
|
const IdentifierToKinds = /* @__PURE__ */ new Map();
|
|
28
60
|
for (const [kind, setup] of Object.entries(LookupSetup)) {
|
|
29
61
|
if (setup.type === "methodChain") {
|
|
@@ -37,31 +69,86 @@ for (const [kind, setup] of Object.entries(LookupSetup)) {
|
|
|
37
69
|
}
|
|
38
70
|
}
|
|
39
71
|
}
|
|
72
|
+
const DirectCallFactoryNames = /* @__PURE__ */ new Set([
|
|
73
|
+
"createServerOnlyFn",
|
|
74
|
+
"createClientOnlyFn",
|
|
75
|
+
"createIsomorphicFn"
|
|
76
|
+
]);
|
|
77
|
+
function needsDirectCallDetection(kinds) {
|
|
78
|
+
for (const kind of kinds) {
|
|
79
|
+
const setup = LookupSetup[kind];
|
|
80
|
+
if (setup.type === "directCall" || setup.allowRootAsCandidate) {
|
|
81
|
+
return true;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return false;
|
|
85
|
+
}
|
|
86
|
+
function areAllKindsTopLevelOnly(kinds) {
|
|
87
|
+
return kinds.size === 1 && kinds.has("ServerFn");
|
|
88
|
+
}
|
|
89
|
+
function isNestedDirectCallCandidate(node) {
|
|
90
|
+
let calleeName;
|
|
91
|
+
if (t.isIdentifier(node.callee)) {
|
|
92
|
+
calleeName = node.callee.name;
|
|
93
|
+
} else if (t.isMemberExpression(node.callee) && t.isIdentifier(node.callee.property)) {
|
|
94
|
+
calleeName = node.callee.property.name;
|
|
95
|
+
}
|
|
96
|
+
return calleeName !== void 0 && DirectCallFactoryNames.has(calleeName);
|
|
97
|
+
}
|
|
98
|
+
function isTopLevelDirectCallCandidate(path) {
|
|
99
|
+
const node = path.node;
|
|
100
|
+
const isSimpleCall = t.isIdentifier(node.callee) || t.isMemberExpression(node.callee) && t.isIdentifier(node.callee.object) && t.isIdentifier(node.callee.property);
|
|
101
|
+
if (!isSimpleCall) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
const parent = path.parent;
|
|
105
|
+
if (!t.isVariableDeclarator(parent) || parent.init !== node) {
|
|
106
|
+
return false;
|
|
107
|
+
}
|
|
108
|
+
const grandParent = path.parentPath.parent;
|
|
109
|
+
if (!t.isVariableDeclaration(grandParent)) {
|
|
110
|
+
return false;
|
|
111
|
+
}
|
|
112
|
+
return t.isProgram(path.parentPath.parentPath?.parent);
|
|
113
|
+
}
|
|
40
114
|
class ServerFnCompiler {
|
|
41
115
|
constructor(options) {
|
|
42
116
|
this.options = options;
|
|
43
117
|
this.validLookupKinds = options.lookupKinds;
|
|
44
|
-
this.hasDirectCallKinds = false;
|
|
45
|
-
this.hasRootAsCandidateKinds = false;
|
|
46
|
-
for (const kind of options.lookupKinds) {
|
|
47
|
-
const setup = LookupSetup[kind];
|
|
48
|
-
if (setup.type === "directCall") {
|
|
49
|
-
this.hasDirectCallKinds = true;
|
|
50
|
-
} else if (setup.allowRootAsCandidate) {
|
|
51
|
-
this.hasRootAsCandidateKinds = true;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
118
|
}
|
|
55
119
|
moduleCache = /* @__PURE__ */ new Map();
|
|
56
120
|
initialized = false;
|
|
57
121
|
validLookupKinds;
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
hasRootAsCandidateKinds;
|
|
122
|
+
resolveIdCache = /* @__PURE__ */ new Map();
|
|
123
|
+
exportResolutionCache = /* @__PURE__ */ new Map();
|
|
61
124
|
// Fast lookup for direct imports from known libraries (e.g., '@tanstack/react-start')
|
|
62
125
|
// Maps: libName → (exportName → Kind)
|
|
63
126
|
// This allows O(1) resolution for the common case without async resolveId calls
|
|
64
127
|
knownRootImports = /* @__PURE__ */ new Map();
|
|
128
|
+
get mode() {
|
|
129
|
+
return this.options.mode ?? "dev";
|
|
130
|
+
}
|
|
131
|
+
async resolveIdCached(id, importer) {
|
|
132
|
+
if (this.mode === "dev") {
|
|
133
|
+
return this.options.resolveId(id, importer);
|
|
134
|
+
}
|
|
135
|
+
const cacheKey = importer ? `${importer}::${id}` : id;
|
|
136
|
+
const cached = this.resolveIdCache.get(cacheKey);
|
|
137
|
+
if (cached !== void 0) {
|
|
138
|
+
return cached;
|
|
139
|
+
}
|
|
140
|
+
const resolved = await this.options.resolveId(id, importer);
|
|
141
|
+
this.resolveIdCache.set(cacheKey, resolved);
|
|
142
|
+
return resolved;
|
|
143
|
+
}
|
|
144
|
+
getExportResolutionCache(moduleId) {
|
|
145
|
+
let cache = this.exportResolutionCache.get(moduleId);
|
|
146
|
+
if (!cache) {
|
|
147
|
+
cache = /* @__PURE__ */ new Map();
|
|
148
|
+
this.exportResolutionCache.set(moduleId, cache);
|
|
149
|
+
}
|
|
150
|
+
return cache;
|
|
151
|
+
}
|
|
65
152
|
async init() {
|
|
66
153
|
this.knownRootImports.set(
|
|
67
154
|
"@tanstack/start-fn-stubs",
|
|
@@ -79,7 +166,7 @@ class ServerFnCompiler {
|
|
|
79
166
|
this.knownRootImports.set(config.libName, libExports);
|
|
80
167
|
}
|
|
81
168
|
libExports.set(config.rootExport, config.kind);
|
|
82
|
-
const libId = await this.
|
|
169
|
+
const libId = await this.resolveIdCached(config.libName);
|
|
83
170
|
if (!libId) {
|
|
84
171
|
throw new Error(`could not resolve "${config.libName}"`);
|
|
85
172
|
}
|
|
@@ -113,8 +200,11 @@ class ServerFnCompiler {
|
|
|
113
200
|
);
|
|
114
201
|
this.initialized = true;
|
|
115
202
|
}
|
|
116
|
-
|
|
117
|
-
|
|
203
|
+
/**
|
|
204
|
+
* Extracts bindings and exports from an already-parsed AST.
|
|
205
|
+
* This is the core logic shared by ingestModule and ingestModuleFromAst.
|
|
206
|
+
*/
|
|
207
|
+
extractModuleInfo(ast, id) {
|
|
118
208
|
const bindings = /* @__PURE__ */ new Map();
|
|
119
209
|
const exports = /* @__PURE__ */ new Map();
|
|
120
210
|
const reExportAllSources = [];
|
|
@@ -199,6 +289,11 @@ class ServerFnCompiler {
|
|
|
199
289
|
reExportAllSources
|
|
200
290
|
};
|
|
201
291
|
this.moduleCache.set(id, info);
|
|
292
|
+
return info;
|
|
293
|
+
}
|
|
294
|
+
ingestModule({ code, id }) {
|
|
295
|
+
const ast = parseAst({ code });
|
|
296
|
+
const info = this.extractModuleInfo(ast, id);
|
|
202
297
|
return { info, ast };
|
|
203
298
|
}
|
|
204
299
|
invalidateModule(id) {
|
|
@@ -207,43 +302,111 @@ class ServerFnCompiler {
|
|
|
207
302
|
async compile({
|
|
208
303
|
code,
|
|
209
304
|
id,
|
|
210
|
-
isProviderFile
|
|
305
|
+
isProviderFile,
|
|
306
|
+
detectedKinds
|
|
211
307
|
}) {
|
|
212
308
|
if (!this.initialized) {
|
|
213
309
|
await this.init();
|
|
214
310
|
}
|
|
215
|
-
const
|
|
216
|
-
|
|
217
|
-
|
|
311
|
+
const fileKinds = detectedKinds ? new Set([...detectedKinds].filter((k) => this.validLookupKinds.has(k))) : this.validLookupKinds;
|
|
312
|
+
if (fileKinds.size === 0) {
|
|
313
|
+
return null;
|
|
314
|
+
}
|
|
315
|
+
const checkDirectCalls = needsDirectCallDetection(fileKinds);
|
|
316
|
+
const canUseFastPath = areAllKindsTopLevelOnly(fileKinds);
|
|
317
|
+
const { ast } = this.ingestModule({ code, id });
|
|
318
|
+
const candidatePaths = [];
|
|
319
|
+
const chainCallPaths = /* @__PURE__ */ new Map();
|
|
320
|
+
if (canUseFastPath) {
|
|
321
|
+
const candidateIndices = [];
|
|
322
|
+
for (let i = 0; i < ast.program.body.length; i++) {
|
|
323
|
+
const node = ast.program.body[i];
|
|
324
|
+
let declarations;
|
|
325
|
+
if (t.isVariableDeclaration(node)) {
|
|
326
|
+
declarations = node.declarations;
|
|
327
|
+
} else if (t.isExportNamedDeclaration(node) && node.declaration) {
|
|
328
|
+
if (t.isVariableDeclaration(node.declaration)) {
|
|
329
|
+
declarations = node.declaration.declarations;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
if (declarations) {
|
|
333
|
+
for (const decl of declarations) {
|
|
334
|
+
if (decl.init && t.isCallExpression(decl.init)) {
|
|
335
|
+
if (isMethodChainCandidate(decl.init, fileKinds)) {
|
|
336
|
+
candidateIndices.push(i);
|
|
337
|
+
break;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
if (candidateIndices.length === 0) {
|
|
344
|
+
return null;
|
|
345
|
+
}
|
|
346
|
+
babel.traverse(ast, {
|
|
347
|
+
Program(programPath) {
|
|
348
|
+
const bodyPaths = programPath.get("body");
|
|
349
|
+
for (const idx of candidateIndices) {
|
|
350
|
+
const stmtPath = bodyPaths[idx];
|
|
351
|
+
if (!stmtPath) continue;
|
|
352
|
+
stmtPath.traverse({
|
|
353
|
+
CallExpression(path) {
|
|
354
|
+
const node = path.node;
|
|
355
|
+
const parent = path.parent;
|
|
356
|
+
if (t.isMemberExpression(parent) && t.isCallExpression(path.parentPath.parent)) {
|
|
357
|
+
chainCallPaths.set(node, path);
|
|
358
|
+
return;
|
|
359
|
+
}
|
|
360
|
+
if (isMethodChainCandidate(node, fileKinds)) {
|
|
361
|
+
candidatePaths.push(path);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
});
|
|
365
|
+
}
|
|
366
|
+
programPath.stop();
|
|
367
|
+
}
|
|
368
|
+
});
|
|
369
|
+
} else {
|
|
370
|
+
babel.traverse(ast, {
|
|
371
|
+
CallExpression: (path) => {
|
|
372
|
+
const node = path.node;
|
|
373
|
+
const parent = path.parent;
|
|
374
|
+
if (t.isMemberExpression(parent) && t.isCallExpression(path.parentPath.parent)) {
|
|
375
|
+
chainCallPaths.set(node, path);
|
|
376
|
+
return;
|
|
377
|
+
}
|
|
378
|
+
if (isMethodChainCandidate(node, fileKinds)) {
|
|
379
|
+
candidatePaths.push(path);
|
|
380
|
+
return;
|
|
381
|
+
}
|
|
382
|
+
if (checkDirectCalls) {
|
|
383
|
+
if (isTopLevelDirectCallCandidate(path)) {
|
|
384
|
+
candidatePaths.push(path);
|
|
385
|
+
} else if (isNestedDirectCallCandidate(node)) {
|
|
386
|
+
candidatePaths.push(path);
|
|
387
|
+
}
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
if (candidatePaths.length === 0) {
|
|
218
393
|
return null;
|
|
219
394
|
}
|
|
220
395
|
const resolvedCandidates = await Promise.all(
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
kind: await this.resolveExprKind(
|
|
396
|
+
candidatePaths.map(async (path) => ({
|
|
397
|
+
path,
|
|
398
|
+
kind: await this.resolveExprKind(path.node, id)
|
|
224
399
|
}))
|
|
225
400
|
);
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
}
|
|
231
|
-
}
|
|
232
|
-
if (toRewriteMap.size === 0) {
|
|
401
|
+
const validCandidates = resolvedCandidates.filter(
|
|
402
|
+
({ kind }) => this.validLookupKinds.has(kind)
|
|
403
|
+
);
|
|
404
|
+
if (validCandidates.length === 0) {
|
|
233
405
|
return null;
|
|
234
406
|
}
|
|
235
407
|
const pathsToRewrite = [];
|
|
236
|
-
const
|
|
237
|
-
|
|
238
|
-
CallExpression(path) {
|
|
239
|
-
callExprPaths.set(path.node, path);
|
|
240
|
-
}
|
|
241
|
-
});
|
|
242
|
-
for (const [node, kind] of toRewriteMap) {
|
|
243
|
-
const path = callExprPaths.get(node);
|
|
244
|
-
if (!path) {
|
|
245
|
-
continue;
|
|
246
|
-
}
|
|
408
|
+
for (const { path, kind } of validCandidates) {
|
|
409
|
+
const node = path.node;
|
|
247
410
|
const methodChain = {
|
|
248
411
|
middleware: null,
|
|
249
412
|
inputValidator: null,
|
|
@@ -252,6 +415,7 @@ class ServerFnCompiler {
|
|
|
252
415
|
client: null
|
|
253
416
|
};
|
|
254
417
|
let currentNode = node;
|
|
418
|
+
let currentPath = path;
|
|
255
419
|
while (true) {
|
|
256
420
|
const callee = currentNode.callee;
|
|
257
421
|
if (!t.isMemberExpression(callee)) {
|
|
@@ -260,7 +424,6 @@ class ServerFnCompiler {
|
|
|
260
424
|
if (t.isIdentifier(callee.property)) {
|
|
261
425
|
const name = callee.property.name;
|
|
262
426
|
if (name in methodChain) {
|
|
263
|
-
const currentPath = callExprPaths.get(currentNode);
|
|
264
427
|
const args = currentPath.get("arguments");
|
|
265
428
|
const firstArgPath = Array.isArray(args) && args.length > 0 ? args[0] ?? null : null;
|
|
266
429
|
methodChain[name] = {
|
|
@@ -273,14 +436,14 @@ class ServerFnCompiler {
|
|
|
273
436
|
break;
|
|
274
437
|
}
|
|
275
438
|
currentNode = callee.object;
|
|
439
|
+
const nextPath = chainCallPaths.get(currentNode);
|
|
440
|
+
if (!nextPath) {
|
|
441
|
+
break;
|
|
442
|
+
}
|
|
443
|
+
currentPath = nextPath;
|
|
276
444
|
}
|
|
277
445
|
pathsToRewrite.push({ path, kind, methodChain });
|
|
278
446
|
}
|
|
279
|
-
if (pathsToRewrite.length !== toRewriteMap.size) {
|
|
280
|
-
throw new Error(
|
|
281
|
-
`Internal error: could not find all paths to rewrite. please file an issue`
|
|
282
|
-
);
|
|
283
|
-
}
|
|
284
447
|
const refIdents = findReferencedIdentifiers(ast);
|
|
285
448
|
for (const { path, kind, methodChain } of pathsToRewrite) {
|
|
286
449
|
const candidate = { path, methodChain };
|
|
@@ -313,28 +476,6 @@ class ServerFnCompiler {
|
|
|
313
476
|
filename: id
|
|
314
477
|
});
|
|
315
478
|
}
|
|
316
|
-
// collects all candidate CallExpressions at top-level
|
|
317
|
-
collectCandidates(bindings) {
|
|
318
|
-
const candidates = [];
|
|
319
|
-
for (const binding of bindings.values()) {
|
|
320
|
-
if (binding.type === "var" && t.isCallExpression(binding.init)) {
|
|
321
|
-
const methodChainCandidate = isCandidateCallExpression(
|
|
322
|
-
binding.init,
|
|
323
|
-
this.validLookupKinds
|
|
324
|
-
);
|
|
325
|
-
if (methodChainCandidate) {
|
|
326
|
-
candidates.push(methodChainCandidate);
|
|
327
|
-
continue;
|
|
328
|
-
}
|
|
329
|
-
if (this.hasDirectCallKinds || this.hasRootAsCandidateKinds) {
|
|
330
|
-
if (t.isIdentifier(binding.init.callee) || t.isMemberExpression(binding.init.callee) && t.isIdentifier(binding.init.callee.property)) {
|
|
331
|
-
candidates.push(binding.init);
|
|
332
|
-
}
|
|
333
|
-
}
|
|
334
|
-
}
|
|
335
|
-
}
|
|
336
|
-
return candidates;
|
|
337
|
-
}
|
|
338
479
|
async resolveIdentifierKind(ident, id, visited = /* @__PURE__ */ new Set()) {
|
|
339
480
|
const info = await this.getModuleInfo(id);
|
|
340
481
|
const binding = info.bindings.get(ident);
|
|
@@ -358,6 +499,16 @@ class ServerFnCompiler {
|
|
|
358
499
|
* Returns the module info and binding if found, or undefined if not found.
|
|
359
500
|
*/
|
|
360
501
|
async findExportInModule(moduleInfo, exportName, visitedModules = /* @__PURE__ */ new Set()) {
|
|
502
|
+
const isBuildMode = this.mode === "build";
|
|
503
|
+
if (isBuildMode && visitedModules.size === 0) {
|
|
504
|
+
const moduleCache = this.exportResolutionCache.get(moduleInfo.id);
|
|
505
|
+
if (moduleCache) {
|
|
506
|
+
const cached = moduleCache.get(exportName);
|
|
507
|
+
if (cached !== void 0) {
|
|
508
|
+
return cached ?? void 0;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
361
512
|
if (visitedModules.has(moduleInfo.id)) {
|
|
362
513
|
return void 0;
|
|
363
514
|
}
|
|
@@ -366,13 +517,17 @@ class ServerFnCompiler {
|
|
|
366
517
|
if (directExport) {
|
|
367
518
|
const binding = moduleInfo.bindings.get(directExport.name);
|
|
368
519
|
if (binding) {
|
|
369
|
-
|
|
520
|
+
const result = { moduleInfo, binding };
|
|
521
|
+
if (isBuildMode) {
|
|
522
|
+
this.getExportResolutionCache(moduleInfo.id).set(exportName, result);
|
|
523
|
+
}
|
|
524
|
+
return result;
|
|
370
525
|
}
|
|
371
526
|
}
|
|
372
527
|
if (moduleInfo.reExportAllSources.length > 0) {
|
|
373
528
|
const results = await Promise.all(
|
|
374
529
|
moduleInfo.reExportAllSources.map(async (reExportSource) => {
|
|
375
|
-
const reExportTarget = await this.
|
|
530
|
+
const reExportTarget = await this.resolveIdCached(
|
|
376
531
|
reExportSource,
|
|
377
532
|
moduleInfo.id
|
|
378
533
|
);
|
|
@@ -389,10 +544,16 @@ class ServerFnCompiler {
|
|
|
389
544
|
);
|
|
390
545
|
for (const result of results) {
|
|
391
546
|
if (result) {
|
|
547
|
+
if (isBuildMode) {
|
|
548
|
+
this.getExportResolutionCache(moduleInfo.id).set(exportName, result);
|
|
549
|
+
}
|
|
392
550
|
return result;
|
|
393
551
|
}
|
|
394
552
|
}
|
|
395
553
|
}
|
|
554
|
+
if (isBuildMode) {
|
|
555
|
+
this.getExportResolutionCache(moduleInfo.id).set(exportName, null);
|
|
556
|
+
}
|
|
396
557
|
return void 0;
|
|
397
558
|
}
|
|
398
559
|
async resolveBindingKind(binding, fileId, visited = /* @__PURE__ */ new Set()) {
|
|
@@ -408,7 +569,7 @@ class ServerFnCompiler {
|
|
|
408
569
|
return kind;
|
|
409
570
|
}
|
|
410
571
|
}
|
|
411
|
-
const target = await this.
|
|
572
|
+
const target = await this.resolveIdCached(binding.source, fileId);
|
|
412
573
|
if (!target) {
|
|
413
574
|
return "None";
|
|
414
575
|
}
|
|
@@ -501,7 +662,7 @@ class ServerFnCompiler {
|
|
|
501
662
|
const info = await this.getModuleInfo(fileId);
|
|
502
663
|
const binding = info.bindings.get(callee.object.name);
|
|
503
664
|
if (binding && binding.type === "import" && binding.importedName === "*") {
|
|
504
|
-
const targetModuleId = await this.
|
|
665
|
+
const targetModuleId = await this.resolveIdCached(
|
|
505
666
|
binding.source,
|
|
506
667
|
fileId
|
|
507
668
|
);
|
|
@@ -542,23 +703,25 @@ class ServerFnCompiler {
|
|
|
542
703
|
return cached;
|
|
543
704
|
}
|
|
544
705
|
}
|
|
545
|
-
function
|
|
546
|
-
if (!t.isCallExpression(node)) return void 0;
|
|
706
|
+
function isMethodChainCandidate(node, lookupKinds) {
|
|
547
707
|
const callee = node.callee;
|
|
548
708
|
if (!t.isMemberExpression(callee) || !t.isIdentifier(callee.property)) {
|
|
549
|
-
return
|
|
709
|
+
return false;
|
|
550
710
|
}
|
|
551
711
|
const possibleKinds = IdentifierToKinds.get(callee.property.name);
|
|
552
712
|
if (possibleKinds) {
|
|
553
713
|
for (const kind of possibleKinds) {
|
|
554
714
|
if (lookupKinds.has(kind)) {
|
|
555
|
-
return
|
|
715
|
+
return true;
|
|
556
716
|
}
|
|
557
717
|
}
|
|
558
718
|
}
|
|
559
|
-
return
|
|
719
|
+
return false;
|
|
560
720
|
}
|
|
561
721
|
export {
|
|
562
|
-
|
|
722
|
+
KindDetectionPatterns,
|
|
723
|
+
LookupKindsPerEnv,
|
|
724
|
+
ServerFnCompiler,
|
|
725
|
+
detectKindsInCode
|
|
563
726
|
};
|
|
564
727
|
//# sourceMappingURL=compiler.js.map
|