@faapi/faapi 6.21.1 → 6.23.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/dist/cli/index.js +404 -259
- package/dist/cli/index.js.map +1 -1
- package/dist/index.d.ts +31 -2
- package/dist/index.js +184 -114
- package/dist/index.js.map +1 -1
- package/dist/{routeTypes-gyz4PMh7.d.ts → routeTypes-CJV5M90s.d.ts} +39 -3
- package/dist/testing.d.ts +3 -1
- package/dist/testing.js +115 -50
- package/dist/testing.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -2046,14 +2046,14 @@ var ValidationError = class extends FaapiError {
|
|
|
2046
2046
|
issues;
|
|
2047
2047
|
};
|
|
2048
2048
|
var RouteNotFoundError = class extends FaapiError {
|
|
2049
|
-
constructor(
|
|
2050
|
-
super("ROUTE_NOT_FOUND", `Route not found: ${
|
|
2049
|
+
constructor(path32) {
|
|
2050
|
+
super("ROUTE_NOT_FOUND", `Route not found: ${path32}`, 404);
|
|
2051
2051
|
this.name = "RouteNotFoundError";
|
|
2052
2052
|
}
|
|
2053
2053
|
};
|
|
2054
2054
|
var MethodNotAllowedError = class extends FaapiError {
|
|
2055
|
-
constructor(method,
|
|
2056
|
-
super("METHOD_NOT_ALLOWED", `Method ${method} not allowed for ${
|
|
2055
|
+
constructor(method, path32, allowedMethods) {
|
|
2056
|
+
super("METHOD_NOT_ALLOWED", `Method ${method} not allowed for ${path32}`, 405);
|
|
2057
2057
|
this.allowedMethods = allowedMethods;
|
|
2058
2058
|
this.name = "MethodNotAllowedError";
|
|
2059
2059
|
}
|
|
@@ -3442,13 +3442,14 @@ function buildAliasPlugins(rootDir) {
|
|
|
3442
3442
|
}
|
|
3443
3443
|
|
|
3444
3444
|
// src/cli/compileSourceFiles.ts
|
|
3445
|
+
var SOURCE_IGNORE = ["**/*.test.ts", "**/*.e2e.test.ts", "**/*.d.ts", `${APP_DIR}/resources/**`];
|
|
3445
3446
|
async function compileSourceFiles(options) {
|
|
3446
3447
|
const { rootDir, dist, files, logLevel = "silent", production, atomicWrite } = options;
|
|
3447
3448
|
const entryPoints = files ?? await fg2([`${APP_DIR}/**/*.ts`], {
|
|
3448
3449
|
cwd: rootDir,
|
|
3449
3450
|
onlyFiles: true,
|
|
3450
3451
|
absolute: true,
|
|
3451
|
-
ignore:
|
|
3452
|
+
ignore: SOURCE_IGNORE
|
|
3452
3453
|
});
|
|
3453
3454
|
if (entryPoints.length === 0) {
|
|
3454
3455
|
return { compiledFiles: [] };
|
|
@@ -4353,8 +4354,8 @@ function loadEnv(rootDir) {
|
|
|
4353
4354
|
}
|
|
4354
4355
|
|
|
4355
4356
|
// src/cli/createAppCore.ts
|
|
4356
|
-
import
|
|
4357
|
-
import
|
|
4357
|
+
import fs22 from "fs";
|
|
4358
|
+
import path27 from "path";
|
|
4358
4359
|
|
|
4359
4360
|
// src/router/sortRoutes.ts
|
|
4360
4361
|
function sortRoutes(routes) {
|
|
@@ -4418,7 +4419,7 @@ import {
|
|
|
4418
4419
|
import { createSecureServer as createHttp2SecureServer } from "http2";
|
|
4419
4420
|
import { readFileSync } from "fs";
|
|
4420
4421
|
import { Readable as Readable2 } from "stream";
|
|
4421
|
-
import
|
|
4422
|
+
import path20 from "path";
|
|
4422
4423
|
|
|
4423
4424
|
// src/router/matchRoute.ts
|
|
4424
4425
|
var httpIndexCache = /* @__PURE__ */ new WeakMap();
|
|
@@ -4460,25 +4461,25 @@ function getWsIndex(routes) {
|
|
|
4460
4461
|
wsIndexCache.set(routes, index);
|
|
4461
4462
|
return index;
|
|
4462
4463
|
}
|
|
4463
|
-
function matchRoute(routes, method,
|
|
4464
|
+
function matchRoute(routes, method, path32) {
|
|
4464
4465
|
const index = getHttpIndex(routes);
|
|
4465
4466
|
const upper = method.toUpperCase();
|
|
4466
|
-
const hit = matchByMethod(index, upper,
|
|
4467
|
+
const hit = matchByMethod(index, upper, path32);
|
|
4467
4468
|
if (hit) return hit;
|
|
4468
4469
|
if (upper === "HEAD") {
|
|
4469
|
-
return matchByMethod(index, "GET",
|
|
4470
|
+
return matchByMethod(index, "GET", path32);
|
|
4470
4471
|
}
|
|
4471
4472
|
return null;
|
|
4472
4473
|
}
|
|
4473
|
-
function matchByMethod(index, method,
|
|
4474
|
-
const staticHit = index.static.get(`${method}|${
|
|
4474
|
+
function matchByMethod(index, method, path32) {
|
|
4475
|
+
const staticHit = index.static.get(`${method}|${path32}`);
|
|
4475
4476
|
if (staticHit) {
|
|
4476
4477
|
return { route: staticHit, params: {} };
|
|
4477
4478
|
}
|
|
4478
4479
|
if (index.dynamics.length === 0) {
|
|
4479
4480
|
return null;
|
|
4480
4481
|
}
|
|
4481
|
-
const pathSegments =
|
|
4482
|
+
const pathSegments = path32.split("/").filter(Boolean);
|
|
4482
4483
|
for (const entry of index.dynamics) {
|
|
4483
4484
|
const route = entry.route;
|
|
4484
4485
|
if (route.method !== method) {
|
|
@@ -4491,31 +4492,31 @@ function matchByMethod(index, method, path31) {
|
|
|
4491
4492
|
}
|
|
4492
4493
|
return null;
|
|
4493
4494
|
}
|
|
4494
|
-
function matchWsRoute(wsRoutes,
|
|
4495
|
+
function matchWsRoute(wsRoutes, path32) {
|
|
4495
4496
|
const index = getWsIndex(wsRoutes);
|
|
4496
|
-
const staticHit = index.static.get(
|
|
4497
|
+
const staticHit = index.static.get(path32);
|
|
4497
4498
|
if (staticHit) {
|
|
4498
4499
|
return { route: staticHit, params: {} };
|
|
4499
4500
|
}
|
|
4500
4501
|
for (const route of index.dynamics) {
|
|
4501
|
-
const params = matchDynamicPath(route.urlPath,
|
|
4502
|
+
const params = matchDynamicPath(route.urlPath, path32, route.paramNames, route.isCatchAll);
|
|
4502
4503
|
if (params !== null) {
|
|
4503
4504
|
return { route, params };
|
|
4504
4505
|
}
|
|
4505
4506
|
}
|
|
4506
4507
|
return null;
|
|
4507
4508
|
}
|
|
4508
|
-
function findAllowedMethods(routes,
|
|
4509
|
+
function findAllowedMethods(routes, path32) {
|
|
4509
4510
|
const index = getHttpIndex(routes);
|
|
4510
4511
|
const methods = /* @__PURE__ */ new Set();
|
|
4511
|
-
const staticMethods = index.methodsByStaticPath.get(
|
|
4512
|
+
const staticMethods = index.methodsByStaticPath.get(path32);
|
|
4512
4513
|
if (staticMethods) {
|
|
4513
4514
|
for (const method of staticMethods) {
|
|
4514
4515
|
methods.add(method);
|
|
4515
4516
|
}
|
|
4516
4517
|
}
|
|
4517
4518
|
if (index.dynamics.length > 0) {
|
|
4518
|
-
const pathSegments =
|
|
4519
|
+
const pathSegments = path32.split("/").filter(Boolean);
|
|
4519
4520
|
for (const entry of index.dynamics) {
|
|
4520
4521
|
const params = matchSegments(
|
|
4521
4522
|
entry.segments,
|
|
@@ -4533,10 +4534,10 @@ function findAllowedMethods(routes, path31) {
|
|
|
4533
4534
|
}
|
|
4534
4535
|
return Array.from(methods);
|
|
4535
4536
|
}
|
|
4536
|
-
function matchDynamicPath(pattern,
|
|
4537
|
+
function matchDynamicPath(pattern, path32, paramNames, isCatchAll) {
|
|
4537
4538
|
return matchSegments(
|
|
4538
4539
|
pattern.split("/").filter(Boolean),
|
|
4539
|
-
|
|
4540
|
+
path32.split("/").filter(Boolean),
|
|
4540
4541
|
paramNames,
|
|
4541
4542
|
isCatchAll
|
|
4542
4543
|
);
|
|
@@ -4782,13 +4783,28 @@ function encodeSseEvent(event) {
|
|
|
4782
4783
|
return out;
|
|
4783
4784
|
}
|
|
4784
4785
|
function createSseWriter(options = {}) {
|
|
4785
|
-
const { onFirstWrite } = options;
|
|
4786
|
+
const { onFirstWrite, keepOpen = false } = options;
|
|
4786
4787
|
const encoder = new TextEncoder();
|
|
4787
4788
|
let controller = null;
|
|
4788
4789
|
let closed = false;
|
|
4789
4790
|
let aborted = false;
|
|
4790
4791
|
let firstWriteTriggered = false;
|
|
4791
4792
|
let drainWaiters = [];
|
|
4793
|
+
let closeCallbacks = [];
|
|
4794
|
+
let closeCallbacksFired = false;
|
|
4795
|
+
const safeRunCallback = (callback) => {
|
|
4796
|
+
try {
|
|
4797
|
+
callback();
|
|
4798
|
+
} catch {
|
|
4799
|
+
}
|
|
4800
|
+
};
|
|
4801
|
+
const runCloseCallbacks = () => {
|
|
4802
|
+
if (closeCallbacksFired) return;
|
|
4803
|
+
closeCallbacksFired = true;
|
|
4804
|
+
const callbacks = closeCallbacks;
|
|
4805
|
+
closeCallbacks = [];
|
|
4806
|
+
for (const callback of callbacks) safeRunCallback(callback);
|
|
4807
|
+
};
|
|
4792
4808
|
const resolveDrainWaiters = () => {
|
|
4793
4809
|
const waiters = drainWaiters;
|
|
4794
4810
|
drainWaiters = [];
|
|
@@ -4812,6 +4828,7 @@ function createSseWriter(options = {}) {
|
|
|
4812
4828
|
aborted = true;
|
|
4813
4829
|
closed = true;
|
|
4814
4830
|
controller = null;
|
|
4831
|
+
runCloseCallbacks();
|
|
4815
4832
|
resolveDrainWaiters();
|
|
4816
4833
|
}
|
|
4817
4834
|
},
|
|
@@ -4854,6 +4871,7 @@ function createSseWriter(options = {}) {
|
|
|
4854
4871
|
close() {
|
|
4855
4872
|
if (closed) return;
|
|
4856
4873
|
closed = true;
|
|
4874
|
+
runCloseCallbacks();
|
|
4857
4875
|
resolveDrainWaiters();
|
|
4858
4876
|
if (controller) {
|
|
4859
4877
|
try {
|
|
@@ -4863,6 +4881,13 @@ function createSseWriter(options = {}) {
|
|
|
4863
4881
|
controller = null;
|
|
4864
4882
|
}
|
|
4865
4883
|
},
|
|
4884
|
+
onClose(callback) {
|
|
4885
|
+
if (closeCallbacksFired) {
|
|
4886
|
+
safeRunCallback(callback);
|
|
4887
|
+
return;
|
|
4888
|
+
}
|
|
4889
|
+
closeCallbacks.push(callback);
|
|
4890
|
+
},
|
|
4866
4891
|
get closed() {
|
|
4867
4892
|
return closed;
|
|
4868
4893
|
},
|
|
@@ -4879,6 +4904,9 @@ function createSseWriter(options = {}) {
|
|
|
4879
4904
|
get aborted() {
|
|
4880
4905
|
return aborted;
|
|
4881
4906
|
},
|
|
4907
|
+
get keepOpen() {
|
|
4908
|
+
return keepOpen;
|
|
4909
|
+
},
|
|
4882
4910
|
get response() {
|
|
4883
4911
|
return response;
|
|
4884
4912
|
}
|
|
@@ -5012,10 +5040,18 @@ function formatSetCookie(name, value, options) {
|
|
|
5012
5040
|
if (options?.sameSite) cookie += `; SameSite=${options.sameSite}`;
|
|
5013
5041
|
return cookie;
|
|
5014
5042
|
}
|
|
5015
|
-
function createContext(request, params, config = {}, ip = "", registries) {
|
|
5016
|
-
return createContextFromUrl(
|
|
5043
|
+
function createContext(request, params, config = {}, ip = "", registries, resourcesDir) {
|
|
5044
|
+
return createContextFromUrl(
|
|
5045
|
+
request,
|
|
5046
|
+
new URL(request.url),
|
|
5047
|
+
params,
|
|
5048
|
+
config,
|
|
5049
|
+
ip,
|
|
5050
|
+
registries,
|
|
5051
|
+
resourcesDir
|
|
5052
|
+
);
|
|
5017
5053
|
}
|
|
5018
|
-
function createContextFromUrl(request, url, params, config = {}, ip = "", registries) {
|
|
5054
|
+
function createContextFromUrl(request, url, params, config = {}, ip = "", registries, resourcesDir) {
|
|
5019
5055
|
const meta = { headers: {}, setCookies: [] };
|
|
5020
5056
|
const parsedCookies = parseCookies(request.headers.get("cookie") ?? "");
|
|
5021
5057
|
const cookiesObj = {};
|
|
@@ -5043,6 +5079,9 @@ function createContextFromUrl(request, url, params, config = {}, ip = "", regist
|
|
|
5043
5079
|
ua: request.headers.get("user-agent") ?? "",
|
|
5044
5080
|
cookies: cookiesObj,
|
|
5045
5081
|
config,
|
|
5082
|
+
// 运行时资源根目录(HTTP/WS 链路由 createServer/handleWsUpgrade 传入;
|
|
5083
|
+
// testing 直调未传时为 undefined,见 contextTypes.resourcesDir 注释)
|
|
5084
|
+
resourcesDir,
|
|
5046
5085
|
meta,
|
|
5047
5086
|
setStatus(status) {
|
|
5048
5087
|
meta.status = status;
|
|
@@ -5088,10 +5127,15 @@ function createContextFromUrl(request, url, params, config = {}, ip = "", regist
|
|
|
5088
5127
|
* 接入底层连接——流式期间字节即产即达(见 createServer.md「SSE 提前接管」)。
|
|
5089
5128
|
* 无钩子场景(app.inject / 测试直调 invokeHandler)回落为 handler 返回后交出。
|
|
5090
5129
|
*
|
|
5130
|
+
* `{ keepOpen: true }` 声明流生命周期独立于 handler 返回:handler 返回后框架
|
|
5131
|
+
* 不自动 close(长连接订阅模式,清理推送源用 writer.onClose);handler 抛错
|
|
5132
|
+
* 的兜底 close 不受影响。详见 runtime/sse.md「长连接订阅模式」。
|
|
5133
|
+
*
|
|
5091
5134
|
* 与 ctx.json / ctx.html 互斥:一个 handler 只能用一种响应方式。
|
|
5092
5135
|
*/
|
|
5093
|
-
sse() {
|
|
5136
|
+
sse(options) {
|
|
5094
5137
|
const writer = createSseWriter({
|
|
5138
|
+
keepOpen: options?.keepOpen,
|
|
5095
5139
|
onFirstWrite: (response) => {
|
|
5096
5140
|
ctx.__earlyRespond?.(response);
|
|
5097
5141
|
}
|
|
@@ -5491,7 +5535,7 @@ async function invokeHandler(handler, ctx, body, middlewares, injectors) {
|
|
|
5491
5535
|
const pickSseAndAutoClose = () => {
|
|
5492
5536
|
const sseWriter = ctx.__sseWriter;
|
|
5493
5537
|
if (!sseWriter) return null;
|
|
5494
|
-
if (!sseWriter.closed && !sseWriter.aborted) {
|
|
5538
|
+
if (!sseWriter.keepOpen && !sseWriter.closed && !sseWriter.aborted) {
|
|
5495
5539
|
sseWriter.close();
|
|
5496
5540
|
}
|
|
5497
5541
|
return mergeMeta(sseWriter.response, meta);
|
|
@@ -5632,9 +5676,9 @@ async function validateInput(schemaPath, method, inputType, input) {
|
|
|
5632
5676
|
function mapZodIssues(error) {
|
|
5633
5677
|
return error.issues.map((issue) => {
|
|
5634
5678
|
const code = mapZodCode(issue);
|
|
5635
|
-
const
|
|
5679
|
+
const path32 = issue.path.map(String).join(".") || "";
|
|
5636
5680
|
return {
|
|
5637
|
-
path:
|
|
5681
|
+
path: path32,
|
|
5638
5682
|
code,
|
|
5639
5683
|
expected: issue.expected ?? mapExpectedFromMessage(issue.message),
|
|
5640
5684
|
received: issue.received ?? mapReceivedFromMessage(issue.message),
|
|
@@ -5855,9 +5899,17 @@ function etag(options = {}) {
|
|
|
5855
5899
|
}
|
|
5856
5900
|
|
|
5857
5901
|
// src/server/handleWsUpgrade.ts
|
|
5858
|
-
import
|
|
5902
|
+
import fs17 from "fs";
|
|
5859
5903
|
import { WebSocketServer, WebSocket } from "ws";
|
|
5904
|
+
import path19 from "path";
|
|
5905
|
+
|
|
5906
|
+
// src/cli/copyResources.ts
|
|
5860
5907
|
import path18 from "path";
|
|
5908
|
+
import fs16 from "fs";
|
|
5909
|
+
var RESOURCES_OUTPUT_DIR = "resources";
|
|
5910
|
+
function resolveResourcesDir(rootDir, dist) {
|
|
5911
|
+
return path18.resolve(rootDir, dist, RESOURCES_OUTPUT_DIR);
|
|
5912
|
+
}
|
|
5861
5913
|
|
|
5862
5914
|
// src/server/serverUtils.ts
|
|
5863
5915
|
function nodeHttpToWebHeaders(req) {
|
|
@@ -5997,7 +6049,7 @@ async function loadWsHandler(filePath, ctx, rootDir) {
|
|
|
5997
6049
|
const dist = getDevDist();
|
|
5998
6050
|
if (dist) {
|
|
5999
6051
|
const sourcePath = prodPathToSourcePath(filePath, rootDir, dist);
|
|
6000
|
-
if (sourcePath &&
|
|
6052
|
+
if (sourcePath && fs17.existsSync(sourcePath)) {
|
|
6001
6053
|
await ensureCompiled(sourcePath, rootDir, dist);
|
|
6002
6054
|
}
|
|
6003
6055
|
}
|
|
@@ -6095,6 +6147,7 @@ function attachWebSocket(options) {
|
|
|
6095
6147
|
trustedProxy = false,
|
|
6096
6148
|
registries
|
|
6097
6149
|
} = options;
|
|
6150
|
+
const resourcesDir = resolveResourcesDir(rootDir, dist);
|
|
6098
6151
|
const wss = new WebSocketServer({ noServer: true });
|
|
6099
6152
|
server.on("upgrade", async (req, socket, head) => {
|
|
6100
6153
|
try {
|
|
@@ -6126,12 +6179,19 @@ function attachWebSocket(options) {
|
|
|
6126
6179
|
const host = req.headers.host ?? "localhost";
|
|
6127
6180
|
const fullUrl = new URL(`http://${host}${req.url ?? "/"}`);
|
|
6128
6181
|
const request = new Request(fullUrl.toString(), { method: "GET", headers });
|
|
6129
|
-
const ctx = createContext(
|
|
6182
|
+
const ctx = createContext(
|
|
6183
|
+
request,
|
|
6184
|
+
params,
|
|
6185
|
+
config,
|
|
6186
|
+
getClientIp(req, trustedProxy),
|
|
6187
|
+
registries,
|
|
6188
|
+
resourcesDir
|
|
6189
|
+
);
|
|
6130
6190
|
const meta = ctx.meta;
|
|
6131
6191
|
let upgraded = false;
|
|
6132
6192
|
const finalHandler = async () => {
|
|
6133
6193
|
const schemaPath = getRuntimeSchemaPath(route.filePath, dist, rootDir);
|
|
6134
|
-
if (
|
|
6194
|
+
if (fs17.existsSync(schemaPath)) {
|
|
6135
6195
|
if (isDevOnDemandEnabled()) {
|
|
6136
6196
|
const devDist = getDevDist();
|
|
6137
6197
|
if (devDist) {
|
|
@@ -6170,7 +6230,7 @@ function attachWebSocket(options) {
|
|
|
6170
6230
|
}
|
|
6171
6231
|
let handlers;
|
|
6172
6232
|
try {
|
|
6173
|
-
const absoluteFilePath =
|
|
6233
|
+
const absoluteFilePath = path19.resolve(rootDir, route.filePath);
|
|
6174
6234
|
handlers = await loadWsHandler(absoluteFilePath, ctx, rootDir);
|
|
6175
6235
|
} catch (err) {
|
|
6176
6236
|
const reason = err instanceof Error ? err.message : String(err);
|
|
@@ -6330,6 +6390,7 @@ function createServer(options) {
|
|
|
6330
6390
|
trustedProxy = false
|
|
6331
6391
|
} = options;
|
|
6332
6392
|
const routesRef = { current: routes, wsCurrent: wsRoutes ?? [] };
|
|
6393
|
+
const resourcesDir = resolveResourcesDir(rootDir, dist);
|
|
6333
6394
|
const configMiddlewares = [];
|
|
6334
6395
|
if (compressionOption) {
|
|
6335
6396
|
const compOpts = typeof compressionOption === "object" ? compressionOption : {};
|
|
@@ -6376,7 +6437,8 @@ function createServer(options) {
|
|
|
6376
6437
|
bodyLimit,
|
|
6377
6438
|
trustedProxy,
|
|
6378
6439
|
registries,
|
|
6379
|
-
routesRef.wsCurrent
|
|
6440
|
+
routesRef.wsCurrent,
|
|
6441
|
+
resourcesDir
|
|
6380
6442
|
).catch((err) => {
|
|
6381
6443
|
console.error("[faapi] Request pipeline failed after error response attempt:", err);
|
|
6382
6444
|
try {
|
|
@@ -6402,7 +6464,7 @@ function createServer(options) {
|
|
|
6402
6464
|
});
|
|
6403
6465
|
return { server, routesRef };
|
|
6404
6466
|
}
|
|
6405
|
-
function prepareRequest(req, request, url, config, trustedProxy, registries, preMatched) {
|
|
6467
|
+
function prepareRequest(req, request, url, config, trustedProxy, registries, preMatched, resourcesDir) {
|
|
6406
6468
|
const method = request.method.toUpperCase();
|
|
6407
6469
|
const urlPath = url.pathname;
|
|
6408
6470
|
const ctx = createContextFromUrl(
|
|
@@ -6411,7 +6473,8 @@ function prepareRequest(req, request, url, config, trustedProxy, registries, pre
|
|
|
6411
6473
|
preMatched?.params ?? {},
|
|
6412
6474
|
config,
|
|
6413
6475
|
getClientIp(req, trustedProxy),
|
|
6414
|
-
registries
|
|
6476
|
+
registries,
|
|
6477
|
+
resourcesDir
|
|
6415
6478
|
);
|
|
6416
6479
|
const meta = ctx.meta;
|
|
6417
6480
|
return { request, url, ctx, meta, method, urlPath };
|
|
@@ -6430,7 +6493,7 @@ function getRoutePaths(route, rootDir, dist) {
|
|
|
6430
6493
|
let cached = routePathCache.get(route);
|
|
6431
6494
|
if (!cached) {
|
|
6432
6495
|
cached = {
|
|
6433
|
-
absFilePath:
|
|
6496
|
+
absFilePath: path20.resolve(rootDir, route.filePath),
|
|
6434
6497
|
schemaPath: getRuntimeSchemaPath(route.filePath, dist, rootDir)
|
|
6435
6498
|
};
|
|
6436
6499
|
routePathCache.set(route, cached);
|
|
@@ -6553,7 +6616,7 @@ async function sendErrorResponse(err, meta, res, onError, ctx) {
|
|
|
6553
6616
|
}
|
|
6554
6617
|
}
|
|
6555
6618
|
}
|
|
6556
|
-
async function handleRequest(routes, rootDir, dist, req, res, outerMiddlewares, onError, config, globalInjectors, bodyLimit, trustedProxy, registries, wsRoutes) {
|
|
6619
|
+
async function handleRequest(routes, rootDir, dist, req, res, outerMiddlewares, onError, config, globalInjectors, bodyLimit, trustedProxy, registries, wsRoutes, resourcesDir) {
|
|
6557
6620
|
let meta = { headers: {}, setCookies: [] };
|
|
6558
6621
|
let ctx;
|
|
6559
6622
|
let sseEarlySent = false;
|
|
@@ -6573,7 +6636,8 @@ async function handleRequest(routes, rootDir, dist, req, res, outerMiddlewares,
|
|
|
6573
6636
|
config,
|
|
6574
6637
|
trustedProxy,
|
|
6575
6638
|
registries,
|
|
6576
|
-
preMatched
|
|
6639
|
+
preMatched,
|
|
6640
|
+
resourcesDir
|
|
6577
6641
|
);
|
|
6578
6642
|
ctx = prepared.ctx;
|
|
6579
6643
|
meta = prepared.meta;
|
|
@@ -6649,8 +6713,8 @@ function applyPluginWrappers(server, handlerWrappers, upgradeWrappers) {
|
|
|
6649
6713
|
}
|
|
6650
6714
|
|
|
6651
6715
|
// src/cli/generateRoutes.ts
|
|
6652
|
-
import
|
|
6653
|
-
import
|
|
6716
|
+
import fs18 from "fs";
|
|
6717
|
+
import path21 from "path";
|
|
6654
6718
|
async function hydrateRoutes(manifest) {
|
|
6655
6719
|
const hydrateRoute = (serialized) => ({
|
|
6656
6720
|
method: serialized.method,
|
|
@@ -6694,18 +6758,18 @@ function createIdleTaskDriver() {
|
|
|
6694
6758
|
}
|
|
6695
6759
|
|
|
6696
6760
|
// src/cli/loadPlugins.ts
|
|
6697
|
-
import
|
|
6698
|
-
import
|
|
6761
|
+
import path23 from "path";
|
|
6762
|
+
import fs20 from "fs";
|
|
6699
6763
|
import { pathToFileURL as pathToFileURL3 } from "url";
|
|
6700
6764
|
|
|
6701
6765
|
// src/cli/compileConfig.ts
|
|
6702
|
-
import
|
|
6703
|
-
import
|
|
6766
|
+
import path22 from "path";
|
|
6767
|
+
import fs19 from "fs";
|
|
6704
6768
|
async function compileProjectModules(entryPoints, rootDir, dist) {
|
|
6705
6769
|
const { insideFiles, outsideFiles } = await collectRelativeImports(entryPoints, rootDir);
|
|
6706
6770
|
const esbuild = await import("esbuild");
|
|
6707
6771
|
const aliasPlugins = buildAliasPlugins(rootDir);
|
|
6708
|
-
const absDist =
|
|
6772
|
+
const absDist = path22.resolve(rootDir, dist);
|
|
6709
6773
|
await esbuild.build({
|
|
6710
6774
|
entryPoints: [...entryPoints, ...outsideFiles],
|
|
6711
6775
|
outdir: absDist,
|
|
@@ -6719,7 +6783,7 @@ async function compileProjectModules(entryPoints, rootDir, dist) {
|
|
|
6719
6783
|
logLevel: "silent"
|
|
6720
6784
|
});
|
|
6721
6785
|
if (insideFiles.length > 0) {
|
|
6722
|
-
const appOutbase =
|
|
6786
|
+
const appOutbase = path22.resolve(rootDir, "src");
|
|
6723
6787
|
await esbuild.build({
|
|
6724
6788
|
entryPoints: insideFiles,
|
|
6725
6789
|
outdir: absDist,
|
|
@@ -6800,30 +6864,30 @@ async function loadPlugins(declarations, ctx, rootDir, dist) {
|
|
|
6800
6864
|
var TS_EXTS = /\.(ts|tsx|mts|cts)$/;
|
|
6801
6865
|
var JS_EXTS = /\.(js|mjs|cjs|jsx)$/;
|
|
6802
6866
|
function resolveLocalPluginSource(specifier, baseDir) {
|
|
6803
|
-
const base =
|
|
6804
|
-
if ((TS_EXTS.test(base) || JS_EXTS.test(base)) &&
|
|
6867
|
+
const base = path23.isAbsolute(specifier) ? specifier : path23.resolve(baseDir, specifier);
|
|
6868
|
+
if ((TS_EXTS.test(base) || JS_EXTS.test(base)) && fs20.existsSync(base)) return base;
|
|
6805
6869
|
for (const ext of [".ts", ".js"]) {
|
|
6806
|
-
if (
|
|
6870
|
+
if (fs20.existsSync(base + ext)) return base + ext;
|
|
6807
6871
|
}
|
|
6808
6872
|
for (const indexExt of ["/index.ts", "/index.js"]) {
|
|
6809
|
-
if (
|
|
6873
|
+
if (fs20.existsSync(base + indexExt)) return base + indexExt;
|
|
6810
6874
|
}
|
|
6811
6875
|
return null;
|
|
6812
6876
|
}
|
|
6813
6877
|
function mirrorProductPath(sourcePath, baseDir, distDir) {
|
|
6814
|
-
let rel =
|
|
6878
|
+
let rel = path23.relative(baseDir, sourcePath).replace(/\\/g, "/");
|
|
6815
6879
|
if (rel.startsWith("src/")) rel = rel.slice(4);
|
|
6816
|
-
return
|
|
6880
|
+
return path23.resolve(distDir, rel.replace(TS_EXTS, ".js"));
|
|
6817
6881
|
}
|
|
6818
6882
|
async function importPluginModule(specifier, baseDir, dist) {
|
|
6819
6883
|
const isRelative = specifier.startsWith("./") || specifier.startsWith("../");
|
|
6820
|
-
if (!isRelative && !
|
|
6884
|
+
if (!isRelative && !path23.isAbsolute(specifier)) {
|
|
6821
6885
|
return import(specifier);
|
|
6822
6886
|
}
|
|
6823
|
-
const distDir = dist ?
|
|
6887
|
+
const distDir = dist ? path23.resolve(baseDir, dist) : null;
|
|
6824
6888
|
const sourcePath = resolveLocalPluginSource(specifier, baseDir);
|
|
6825
6889
|
const productPath = sourcePath && distDir ? mirrorProductPath(sourcePath, baseDir, distDir) : null;
|
|
6826
|
-
if (productPath !== null &&
|
|
6890
|
+
if (productPath !== null && fs20.existsSync(productPath) && (sourcePath === null || isProductFresh(sourcePath, productPath))) {
|
|
6827
6891
|
return import(pathToFileURL3(productPath).href);
|
|
6828
6892
|
}
|
|
6829
6893
|
if (sourcePath && TS_EXTS.test(sourcePath)) {
|
|
@@ -6832,13 +6896,13 @@ async function importPluginModule(specifier, baseDir, dist) {
|
|
|
6832
6896
|
`Local plugin "${specifier}" has no up-to-date build artifact (dist is stale or missing). Run "faapi build" first, or use "faapi dev" for on-demand compilation.`
|
|
6833
6897
|
);
|
|
6834
6898
|
}
|
|
6835
|
-
const relFromRoot =
|
|
6899
|
+
const relFromRoot = path23.relative(baseDir, sourcePath).replace(/\\/g, "/");
|
|
6836
6900
|
if (relFromRoot.startsWith("src/")) {
|
|
6837
6901
|
await ensureCompiled(sourcePath, baseDir, dist);
|
|
6838
6902
|
} else {
|
|
6839
6903
|
await compileProjectModules([sourcePath], baseDir, dist);
|
|
6840
6904
|
}
|
|
6841
|
-
if (productPath &&
|
|
6905
|
+
if (productPath && fs20.existsSync(productPath)) {
|
|
6842
6906
|
return import(pathToFileURL3(productPath).href);
|
|
6843
6907
|
}
|
|
6844
6908
|
}
|
|
@@ -6850,7 +6914,7 @@ async function importPluginModule(specifier, baseDir, dist) {
|
|
|
6850
6914
|
`${specifier}/index.ts`,
|
|
6851
6915
|
`${specifier}.js`,
|
|
6852
6916
|
`${specifier}/index.js`
|
|
6853
|
-
].map((c) =>
|
|
6917
|
+
].map((c) => path23.isAbsolute(c) ? c : path23.join(baseDir, c));
|
|
6854
6918
|
throw new Error(
|
|
6855
6919
|
`Cannot find local plugin "${specifier}" (resolved from ${baseDir}). Expected one of:
|
|
6856
6920
|
${candidates.join("\n ")}
|
|
@@ -6875,11 +6939,11 @@ function resolveDeclaration(decl) {
|
|
|
6875
6939
|
}
|
|
6876
6940
|
|
|
6877
6941
|
// src/cli/manifestLoader.ts
|
|
6878
|
-
import
|
|
6879
|
-
import
|
|
6942
|
+
import fs21 from "fs";
|
|
6943
|
+
import path26 from "path";
|
|
6880
6944
|
|
|
6881
6945
|
// src/cli/generateAgentArtifacts.ts
|
|
6882
|
-
import
|
|
6946
|
+
import path24 from "path";
|
|
6883
6947
|
|
|
6884
6948
|
// src/ast/extractAgentMetadata.ts
|
|
6885
6949
|
import ts11 from "typescript";
|
|
@@ -7159,9 +7223,9 @@ function validateAgentList(metadata) {
|
|
|
7159
7223
|
}
|
|
7160
7224
|
async function generateAgentArtifacts(agents, rootDir, dist) {
|
|
7161
7225
|
const metadata = [];
|
|
7162
|
-
const programByFile = createPrograms(agents.map((m) =>
|
|
7226
|
+
const programByFile = createPrograms(agents.map((m) => path24.resolve(rootDir, m.filePath)));
|
|
7163
7227
|
for (const manifest of agents) {
|
|
7164
|
-
const absPath =
|
|
7228
|
+
const absPath = path24.resolve(rootDir, manifest.filePath);
|
|
7165
7229
|
const program = programByFile.get(absPath);
|
|
7166
7230
|
const result = extractAgentMetadata(program, absPath, {
|
|
7167
7231
|
name: manifest.name,
|
|
@@ -7177,14 +7241,14 @@ async function generateAgentArtifacts(agents, rootDir, dist) {
|
|
|
7177
7241
|
}
|
|
7178
7242
|
validateAgentList(metadata);
|
|
7179
7243
|
const serialized = serializeAgents(metadata, dist);
|
|
7180
|
-
const agentsPath =
|
|
7244
|
+
const agentsPath = path24.resolve(rootDir, dist, AGENTS_FILE);
|
|
7181
7245
|
await writeAgentsModule(serialized, agentsPath);
|
|
7182
7246
|
return metadata;
|
|
7183
7247
|
}
|
|
7184
7248
|
|
|
7185
7249
|
// src/cli/generateTaskArtifacts.ts
|
|
7186
7250
|
init_generateZodArtifacts();
|
|
7187
|
-
import
|
|
7251
|
+
import path25 from "path";
|
|
7188
7252
|
init_createProgram();
|
|
7189
7253
|
init_atomicWrite();
|
|
7190
7254
|
init_extractHandlerTypes();
|
|
@@ -7222,7 +7286,7 @@ function collectTaskSchemaSources(tasks, rootDir) {
|
|
|
7222
7286
|
const tasksByFile = /* @__PURE__ */ new Map();
|
|
7223
7287
|
for (const task of tasks) {
|
|
7224
7288
|
if (!task.inputTypeName) continue;
|
|
7225
|
-
const absPath =
|
|
7289
|
+
const absPath = path25.resolve(rootDir, task.filePath);
|
|
7226
7290
|
let list = tasksByFile.get(absPath);
|
|
7227
7291
|
if (!list) {
|
|
7228
7292
|
list = [];
|
|
@@ -7279,9 +7343,9 @@ function generateTaskSchemaFileSource(sources, resolveType, helpersImportPath) {
|
|
|
7279
7343
|
async function generateTaskArtifacts(manifests, rootDir, dist) {
|
|
7280
7344
|
const metadata = [];
|
|
7281
7345
|
if (manifests.length > 0) {
|
|
7282
|
-
const programByFile = createPrograms(manifests.map((m) =>
|
|
7346
|
+
const programByFile = createPrograms(manifests.map((m) => path25.resolve(rootDir, m.filePath)));
|
|
7283
7347
|
for (const manifest of manifests) {
|
|
7284
|
-
const absPath =
|
|
7348
|
+
const absPath = path25.resolve(rootDir, manifest.filePath);
|
|
7285
7349
|
const result = extractToolMetadata(programByFile.get(absPath), absPath, "run", {
|
|
7286
7350
|
name: manifest.name,
|
|
7287
7351
|
filePath: manifest.filePath
|
|
@@ -7292,7 +7356,7 @@ async function generateTaskArtifacts(manifests, rootDir, dist) {
|
|
|
7292
7356
|
}
|
|
7293
7357
|
}
|
|
7294
7358
|
const serialized = serializeTasks(manifests, dist);
|
|
7295
|
-
const tasksPath =
|
|
7359
|
+
const tasksPath = path25.resolve(rootDir, dist, TASKS_FILE);
|
|
7296
7360
|
await writeTasksModule(serialized, tasksPath);
|
|
7297
7361
|
if (metadata.length === 0) {
|
|
7298
7362
|
return hydrateTasks(serialized);
|
|
@@ -7314,8 +7378,8 @@ async function generateTaskArtifacts(manifests, rootDir, dist) {
|
|
|
7314
7378
|
var TOOLS_FILE2 = "faapi-tools.js";
|
|
7315
7379
|
var AGENTS_FILE2 = "faapi-agents.js";
|
|
7316
7380
|
async function loadAndHydrateTools(rootDir, dist, registries = defaultRegistries) {
|
|
7317
|
-
const toolsPath =
|
|
7318
|
-
if (!
|
|
7381
|
+
const toolsPath = path26.resolve(rootDir, dist, TOOLS_FILE2);
|
|
7382
|
+
if (!fs21.existsSync(toolsPath)) {
|
|
7319
7383
|
return [];
|
|
7320
7384
|
}
|
|
7321
7385
|
const serialized = await importWithCacheBust(toolsPath);
|
|
@@ -7324,8 +7388,8 @@ async function loadAndHydrateTools(rootDir, dist, registries = defaultRegistries
|
|
|
7324
7388
|
return hydrated;
|
|
7325
7389
|
}
|
|
7326
7390
|
async function loadAndHydrateAgents(rootDir, dist, registries = defaultRegistries) {
|
|
7327
|
-
const agentsPath =
|
|
7328
|
-
if (!
|
|
7391
|
+
const agentsPath = path26.resolve(rootDir, dist, AGENTS_FILE2);
|
|
7392
|
+
if (!fs21.existsSync(agentsPath)) {
|
|
7329
7393
|
return [];
|
|
7330
7394
|
}
|
|
7331
7395
|
const serialized = await importWithCacheBust(agentsPath);
|
|
@@ -7340,8 +7404,8 @@ function getTaskDriverOptions(config) {
|
|
|
7340
7404
|
return void 0;
|
|
7341
7405
|
}
|
|
7342
7406
|
async function loadAndHydrateTasks(rootDir, dist, registries = defaultRegistries) {
|
|
7343
|
-
const tasksPath =
|
|
7344
|
-
if (!
|
|
7407
|
+
const tasksPath = path26.resolve(rootDir, dist, TASKS_FILE);
|
|
7408
|
+
if (!fs21.existsSync(tasksPath)) {
|
|
7345
7409
|
return [];
|
|
7346
7410
|
}
|
|
7347
7411
|
const serialized = await importWithCacheBust(tasksPath);
|
|
@@ -7533,8 +7597,9 @@ function logStartupSummary(routes, wsRoutes, tools, agents, taskMetas, p) {
|
|
|
7533
7597
|
async function createAppBase(options) {
|
|
7534
7598
|
const rootDir = options?.rootDir ?? process.cwd();
|
|
7535
7599
|
const dist = options?.dist ?? process.env.FAAPI_DIST ?? DEFAULT_DIST;
|
|
7536
|
-
const
|
|
7537
|
-
|
|
7600
|
+
const resourcesDir = resolveResourcesDir(rootDir, dist);
|
|
7601
|
+
const routesPath = path27.resolve(rootDir, dist, ROUTES_FILE);
|
|
7602
|
+
if (!fs22.existsSync(routesPath)) {
|
|
7538
7603
|
throw new Error(
|
|
7539
7604
|
`[faapi] ${dist}/${ROUTES_FILE} \u4E0D\u5B58\u5728\uFF0C\u8BF7\u5148\u6267\u884C \`faapi build\`\uFF08\u6216 \`faapi dev\`\uFF09\u751F\u6210\u4EA7\u7269\u3002`
|
|
7540
7605
|
);
|
|
@@ -7613,6 +7678,8 @@ async function createAppBase(options) {
|
|
|
7613
7678
|
routes: sorted,
|
|
7614
7679
|
wsRoutes,
|
|
7615
7680
|
rootDir,
|
|
7681
|
+
dist,
|
|
7682
|
+
resourcesDir,
|
|
7616
7683
|
tasks: taskQueue,
|
|
7617
7684
|
async listen(listenPort) {
|
|
7618
7685
|
const envPort = process.env.PORT ? Number(process.env.PORT) : void 0;
|
|
@@ -7624,7 +7691,8 @@ async function createAppBase(options) {
|
|
|
7624
7691
|
routes: sorted,
|
|
7625
7692
|
server,
|
|
7626
7693
|
registries,
|
|
7627
|
-
tasks: taskQueue
|
|
7694
|
+
tasks: taskQueue,
|
|
7695
|
+
resourcesDir
|
|
7628
7696
|
});
|
|
7629
7697
|
console.log("- onBoot hook executed");
|
|
7630
7698
|
} catch (err) {
|
|
@@ -7659,7 +7727,8 @@ async function createAppBase(options) {
|
|
|
7659
7727
|
routes: sorted,
|
|
7660
7728
|
server,
|
|
7661
7729
|
registries,
|
|
7662
|
-
tasks: taskQueue
|
|
7730
|
+
tasks: taskQueue,
|
|
7731
|
+
resourcesDir
|
|
7663
7732
|
});
|
|
7664
7733
|
console.log("- onReady hook executed");
|
|
7665
7734
|
}
|
|
@@ -7683,7 +7752,8 @@ async function createAppBase(options) {
|
|
|
7683
7752
|
routes: sorted,
|
|
7684
7753
|
server,
|
|
7685
7754
|
registries,
|
|
7686
|
-
tasks: taskQueue
|
|
7755
|
+
tasks: taskQueue,
|
|
7756
|
+
resourcesDir
|
|
7687
7757
|
});
|
|
7688
7758
|
}
|
|
7689
7759
|
registries.tool.clear();
|
|
@@ -7745,21 +7815,21 @@ async function createAppBase(options) {
|
|
|
7745
7815
|
}
|
|
7746
7816
|
|
|
7747
7817
|
// src/cli/createDevApp.ts
|
|
7748
|
-
import
|
|
7818
|
+
import path31 from "path";
|
|
7749
7819
|
|
|
7750
7820
|
// src/router/scanRoutes.ts
|
|
7751
7821
|
import fg3 from "fast-glob";
|
|
7752
|
-
import
|
|
7753
|
-
import
|
|
7822
|
+
import path28 from "path";
|
|
7823
|
+
import fs23 from "fs";
|
|
7754
7824
|
|
|
7755
7825
|
// src/router/constants.ts
|
|
7756
7826
|
var HTTP_METHODS = ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD", "OPTIONS"];
|
|
7757
7827
|
var HTTP_METHOD_SET = new Set(HTTP_METHODS);
|
|
7758
7828
|
|
|
7759
7829
|
// src/utils/normalizePath.ts
|
|
7760
|
-
function normalizePath(
|
|
7761
|
-
if (!
|
|
7762
|
-
let result =
|
|
7830
|
+
function normalizePath(path32) {
|
|
7831
|
+
if (!path32) return "";
|
|
7832
|
+
let result = path32.replace(/\\/g, "/");
|
|
7763
7833
|
result = result.replace(/\/+/g, "/");
|
|
7764
7834
|
result = result.replace(/\/+$/, "");
|
|
7765
7835
|
if (result && !result.startsWith("/")) {
|
|
@@ -7820,34 +7890,34 @@ function extractExportsFromSource(source) {
|
|
|
7820
7890
|
return names;
|
|
7821
7891
|
}
|
|
7822
7892
|
function collectMiddlewarePaths(routeFilePath, rootDir, dist) {
|
|
7823
|
-
const routeDir =
|
|
7824
|
-
const resolvedRoot =
|
|
7893
|
+
const routeDir = path28.dirname(routeFilePath);
|
|
7894
|
+
const resolvedRoot = path28.resolve(rootDir);
|
|
7825
7895
|
const paths = [];
|
|
7826
|
-
let currentDir =
|
|
7896
|
+
let currentDir = path28.resolve(rootDir, routeDir);
|
|
7827
7897
|
while (true) {
|
|
7828
7898
|
if (dist) {
|
|
7829
|
-
const mwTsPath =
|
|
7830
|
-
const mwJsPath =
|
|
7831
|
-
const absTsPath =
|
|
7832
|
-
const absJsPath =
|
|
7833
|
-
const absMwPath =
|
|
7899
|
+
const mwTsPath = path28.join(currentDir, "middlewares.ts");
|
|
7900
|
+
const mwJsPath = path28.join(currentDir, "middlewares.js");
|
|
7901
|
+
const absTsPath = path28.resolve(rootDir, mwTsPath);
|
|
7902
|
+
const absJsPath = path28.resolve(rootDir, mwJsPath);
|
|
7903
|
+
const absMwPath = fs23.existsSync(absTsPath) ? absTsPath : fs23.existsSync(absJsPath) ? absJsPath : null;
|
|
7834
7904
|
if (absMwPath) {
|
|
7835
|
-
const relMwPath =
|
|
7836
|
-
const prodAbsPath =
|
|
7905
|
+
const relMwPath = path28.relative(rootDir, absMwPath);
|
|
7906
|
+
const prodAbsPath = path28.resolve(rootDir, toProdFilePath(relMwPath, dist));
|
|
7837
7907
|
paths.push(prodAbsPath);
|
|
7838
7908
|
}
|
|
7839
7909
|
} else {
|
|
7840
7910
|
for (const ext of [".ts", ".js"]) {
|
|
7841
|
-
const mwPath =
|
|
7842
|
-
const absMwPath =
|
|
7843
|
-
if (
|
|
7911
|
+
const mwPath = path28.join(currentDir, `middlewares${ext}`);
|
|
7912
|
+
const absMwPath = path28.resolve(rootDir, mwPath);
|
|
7913
|
+
if (fs23.existsSync(absMwPath)) {
|
|
7844
7914
|
paths.push(absMwPath);
|
|
7845
7915
|
break;
|
|
7846
7916
|
}
|
|
7847
7917
|
}
|
|
7848
7918
|
}
|
|
7849
7919
|
if (currentDir === resolvedRoot) break;
|
|
7850
|
-
const parentDir =
|
|
7920
|
+
const parentDir = path28.dirname(currentDir);
|
|
7851
7921
|
if (parentDir === currentDir) break;
|
|
7852
7922
|
currentDir = parentDir;
|
|
7853
7923
|
}
|
|
@@ -7866,7 +7936,7 @@ async function scanRoutes(rootDir, patterns, dist) {
|
|
|
7866
7936
|
const normalizedFile = file.replace(/\\/g, "/");
|
|
7867
7937
|
const fileName = normalizedFile.split("/").pop();
|
|
7868
7938
|
if (fileName === "handler.ts" || fileName === "handler.js") {
|
|
7869
|
-
const absPath =
|
|
7939
|
+
const absPath = path28.resolve(rootDir, normalizedFile);
|
|
7870
7940
|
const urlPath = filePathToUrlPath(normalizedFile);
|
|
7871
7941
|
const paramNames = extractParamNames(urlPath);
|
|
7872
7942
|
const isDynamic = paramNames.length > 0;
|
|
@@ -7879,7 +7949,7 @@ async function scanRoutes(rootDir, patterns, dist) {
|
|
|
7879
7949
|
const mwPaths = collectMiddlewarePaths(normalizedFile, rootDir);
|
|
7880
7950
|
middlewareBundle = await loadMergedMiddlewares(mwPaths);
|
|
7881
7951
|
}
|
|
7882
|
-
const source = await
|
|
7952
|
+
const source = await fs23.promises.readFile(absPath, "utf8").catch(() => "");
|
|
7883
7953
|
const exportNames = extractExportsFromSource(source);
|
|
7884
7954
|
const methods = HTTP_METHODS.filter((m) => exportNames.has(m));
|
|
7885
7955
|
for (const method of methods) {
|
|
@@ -7915,8 +7985,8 @@ async function scanRoutes(rootDir, patterns, dist) {
|
|
|
7915
7985
|
|
|
7916
7986
|
// src/tools/scanTools.ts
|
|
7917
7987
|
import fg4 from "fast-glob";
|
|
7918
|
-
import
|
|
7919
|
-
import
|
|
7988
|
+
import path29 from "path";
|
|
7989
|
+
import fs24 from "fs";
|
|
7920
7990
|
var TOOL_PATTERNS = ["src/tools/**/*.ts"];
|
|
7921
7991
|
var TOOL_EXPORT_RE = new RegExp(
|
|
7922
7992
|
String.raw`export\s+(?:async\s+)?(?:function\s+|const\s+)([A-Za-z_$][\w$]*)\s*(?:\(|=)`,
|
|
@@ -7966,8 +8036,8 @@ async function scanTools(rootDir, patterns) {
|
|
|
7966
8036
|
if (fileName !== "handler.ts" && fileName !== "handler.js") {
|
|
7967
8037
|
continue;
|
|
7968
8038
|
}
|
|
7969
|
-
const absPath =
|
|
7970
|
-
const source = await
|
|
8039
|
+
const absPath = path29.resolve(rootDir, normalizedFile);
|
|
8040
|
+
const source = await fs24.promises.readFile(absPath, "utf8").catch(() => "");
|
|
7971
8041
|
const exportNames = extractToolExportsFromSource(source);
|
|
7972
8042
|
const namespace = filePathToToolNamespace(normalizedFile);
|
|
7973
8043
|
for (const fnName of exportNames) {
|
|
@@ -7991,8 +8061,8 @@ async function scanTools(rootDir, patterns) {
|
|
|
7991
8061
|
|
|
7992
8062
|
// src/agents/scanAgents.ts
|
|
7993
8063
|
import fg5 from "fast-glob";
|
|
7994
|
-
import
|
|
7995
|
-
import
|
|
8064
|
+
import path30 from "path";
|
|
8065
|
+
import fs25 from "fs";
|
|
7996
8066
|
var DEFAULT_AGENT_PATTERNS = ["src/agents/**/handler.ts"];
|
|
7997
8067
|
var RUN_EXPORT_RE = /export\s+(?:async\s+)?(?:function\s+|const\s+)run\b/;
|
|
7998
8068
|
function extractAgentNameFromPath(filePath) {
|
|
@@ -8024,8 +8094,8 @@ async function scanAgents(rootDir, patterns) {
|
|
|
8024
8094
|
if (fileName !== "handler.ts" && fileName !== "handler.js") {
|
|
8025
8095
|
continue;
|
|
8026
8096
|
}
|
|
8027
|
-
const absPath =
|
|
8028
|
-
const source = await
|
|
8097
|
+
const absPath = path30.resolve(rootDir, normalizedFile);
|
|
8098
|
+
const source = await fs25.promises.readFile(absPath, "utf8").catch(() => "");
|
|
8029
8099
|
const { hasRun } = detectAgentExports(source);
|
|
8030
8100
|
const name = extractAgentNameFromPath(normalizedFile);
|
|
8031
8101
|
const prevFile = seen.get(name);
|
|
@@ -8096,7 +8166,7 @@ async function createDevApp(options) {
|
|
|
8096
8166
|
if (!suppressProgramInvalidation) invalidateProgramCache();
|
|
8097
8167
|
const tasks = await scanTasks(ctx.rootDir, TASK_PATTERNS);
|
|
8098
8168
|
for (const task of tasks) {
|
|
8099
|
-
await ensureCompiled(
|
|
8169
|
+
await ensureCompiled(path31.resolve(ctx.rootDir, task.filePath), ctx.rootDir, ctx.dist);
|
|
8100
8170
|
}
|
|
8101
8171
|
await generateTaskArtifacts(tasks, ctx.rootDir, ctx.dist);
|
|
8102
8172
|
ctx.taskQueue.invalidateModules();
|