@axiom-lattice/gateway 3.0.2 → 3.0.3
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/index.js +31 -9
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +31 -9
- package/dist/index.mjs.map +1 -1
- package/package.json +9 -6
- package/.eslintrc.json +0 -22
- package/.turbo/turbo-build.log +0 -46
- package/AGENTS.md +0 -112
- package/CHANGELOG.md +0 -1190
- package/LOGGER_CONFIG.md +0 -135
- package/RESUME_STREAM_CONTENT_BASED.md +0 -326
- package/RESUME_STREAM_README.md +0 -388
- package/jest.config.js +0 -72
- package/public/sdk/README.md +0 -695
- package/public/sdk/dashboard-engine-skill.md +0 -1122
- package/public/sdk/dashboard-single-file-spec.md +0 -357
- package/public/sdk/data-query-sdk-skill.md +0 -307
- package/public/sdk/data-query-sdk.d.ts +0 -252
- package/public/sdk/data-query-sdk.js +0 -970
- package/public/sdk/occupancy-dashboard.html +0 -363
- package/public/sdk/test-dashboard.html +0 -690
- package/scripts/seed-lark-installation.ts +0 -54
- package/src/__tests__/__mocks__/e2b.ts +0 -1
- package/src/__tests__/a2a.test.ts +0 -428
- package/src/__tests__/channel-installations.test.ts +0 -199
- package/src/__tests__/data-query.test.ts +0 -77
- package/src/__tests__/sandbox-provider-registration.test.ts +0 -74
- package/src/__tests__/setup.ts +0 -5
- package/src/__tests__/workspace.test.ts +0 -400
- package/src/channels/__tests__/routes.test.ts +0 -50
- package/src/channels/lark/LarkChannelAdapter.ts +0 -217
- package/src/channels/lark/README.md +0 -187
- package/src/channels/lark/__tests__/controller.test.ts +0 -136
- package/src/channels/lark/__tests__/mapping-service.test.ts +0 -118
- package/src/channels/lark/__tests__/parser.test.ts +0 -72
- package/src/channels/lark/__tests__/sender.test.ts +0 -37
- package/src/channels/lark/__tests__/verification.test.ts +0 -157
- package/src/channels/lark/controller.ts +0 -48
- package/src/channels/lark/mapping-service.ts +0 -138
- package/src/channels/lark/parser.ts +0 -68
- package/src/channels/lark/routes.ts +0 -22
- package/src/channels/lark/sender.ts +0 -58
- package/src/channels/lark/types.ts +0 -20
- package/src/channels/lark/verification.ts +0 -32
- package/src/channels/registry.ts +0 -20
- package/src/channels/routes.ts +0 -30
- package/src/channels/wechat/WechatChannelAdapter.ts +0 -294
- package/src/channels/wechat/__tests__/context-store.test.ts +0 -148
- package/src/channels/wechat/context-store.ts +0 -54
- package/src/channels/wechat/controller.ts +0 -59
- package/src/channels/wechat/routes.ts +0 -7
- package/src/channels/wechat/types.ts +0 -62
- package/src/channels/wechat/wechat-client.ts +0 -162
- package/src/config/local-a2a-templates.ts +0 -59
- package/src/config.ts +0 -124
- package/src/controllers/__tests__/assistant-local-a2a.test.ts +0 -147
- package/src/controllers/__tests__/local-a2a-templates.test.ts +0 -112
- package/src/controllers/__tests__/mime.test.ts +0 -74
- package/src/controllers/__tests__/resources.test.ts +0 -122
- package/src/controllers/__tests__/run.test.ts +0 -115
- package/src/controllers/__tests__/tasks.test.ts +0 -215
- package/src/controllers/__tests__/workflow-tracking.test.ts +0 -113
- package/src/controllers/agent_task.ts +0 -72
- package/src/controllers/assistant.ts +0 -490
- package/src/controllers/auth.ts +0 -524
- package/src/controllers/channel-bindings.ts +0 -135
- package/src/controllers/channel-installations.ts +0 -409
- package/src/controllers/collections.ts +0 -176
- package/src/controllers/config.ts +0 -126
- package/src/controllers/connections.ts +0 -181
- package/src/controllers/data-query.ts +0 -236
- package/src/controllers/database-configs.ts +0 -440
- package/src/controllers/embeddings.ts +0 -22
- package/src/controllers/entries.ts +0 -167
- package/src/controllers/eval.ts +0 -513
- package/src/controllers/export-import.ts +0 -166
- package/src/controllers/health.ts +0 -36
- package/src/controllers/local-a2a-templates.ts +0 -18
- package/src/controllers/local-a2a.ts +0 -149
- package/src/controllers/mcp-configs.ts +0 -673
- package/src/controllers/memory.ts +0 -257
- package/src/controllers/menu-items.ts +0 -114
- package/src/controllers/metrics-configs.ts +0 -1061
- package/src/controllers/middleware-types.ts +0 -15
- package/src/controllers/models.ts +0 -199
- package/src/controllers/personal-assistant.ts +0 -191
- package/src/controllers/resources.ts +0 -477
- package/src/controllers/run.ts +0 -338
- package/src/controllers/sandbox.ts +0 -255
- package/src/controllers/schedules.ts +0 -336
- package/src/controllers/skills.ts +0 -256
- package/src/controllers/tasks.ts +0 -213
- package/src/controllers/tenants.ts +0 -121
- package/src/controllers/thread_status.ts +0 -66
- package/src/controllers/threads.ts +0 -260
- package/src/controllers/tools.ts +0 -139
- package/src/controllers/users.ts +0 -135
- package/src/controllers/workflow-tracking.ts +0 -693
- package/src/controllers/workspace.ts +0 -879
- package/src/export_registrations/a2a-api-key.registration.ts +0 -89
- package/src/export_registrations/agent.registration.ts +0 -80
- package/src/export_registrations/binding.registration.ts +0 -106
- package/src/export_registrations/channel-installation.registration.ts +0 -88
- package/src/export_registrations/collection.registration.ts +0 -85
- package/src/export_registrations/connection.registration.ts +0 -97
- package/src/export_registrations/database-config.registration.ts +0 -94
- package/src/export_registrations/eval.registration.ts +0 -334
- package/src/export_registrations/index.ts +0 -31
- package/src/export_registrations/mcp-config.registration.ts +0 -97
- package/src/export_registrations/menu.registration.ts +0 -91
- package/src/export_registrations/metrics-config.registration.ts +0 -94
- package/src/export_registrations/skill.registration.ts +0 -88
- package/src/export_registrations/task.registration.ts +0 -99
- package/src/index.ts +0 -497
- package/src/logger/Logger.ts +0 -186
- package/src/router/MessageContext.ts +0 -14
- package/src/router/MessageRouter.ts +0 -490
- package/src/router/middlewares/auditLogger.ts +0 -34
- package/src/router/middlewares/deduplication.ts +0 -38
- package/src/router/middlewares/index.ts +0 -3
- package/src/router/middlewares/rateLimit.ts +0 -46
- package/src/routes/__tests__/a2a-test-connection.test.ts +0 -177
- package/src/routes/a2a-bridge.ts +0 -266
- package/src/routes/a2a-test-connection.ts +0 -126
- package/src/routes/a2a.ts +0 -851
- package/src/routes/channel-bindings.ts +0 -11
- package/src/routes/channel-installations.ts +0 -33
- package/src/routes/index.ts +0 -640
- package/src/routes/menu-items.ts +0 -10
- package/src/routes/resource-routes.ts +0 -35
- package/src/routes/stt.ts +0 -102
- package/src/schemas/data-query.ts +0 -69
- package/src/schemas/index.ts +0 -852
- package/src/services/ExportImportService.ts +0 -296
- package/src/services/__tests__/ExportImportService.test.ts +0 -130
- package/src/services/__tests__/eval-runner.test.ts +0 -131
- package/src/services/__tests__/local-a2a.test.ts +0 -124
- package/src/services/agent_task_consumer.ts +0 -348
- package/src/services/collection_service.ts +0 -258
- package/src/services/eval-runner.ts +0 -283
- package/src/services/local-a2a.ts +0 -354
- package/src/services/queue_service.ts +0 -104
- package/src/services/sandbox_service.ts +0 -223
- package/src/services/skill_service.ts +0 -97
- package/src/services/supabase.ts +0 -60
- package/src/swagger.ts +0 -77
- package/src/types/index.ts +0 -118
- package/src/types/koa.d.ts +0 -7
- package/src/utils/__tests__/local-a2a-runtime.test.ts +0 -77
- package/src/utils/__tests__/path-containment.test.ts +0 -35
- package/src/utils/a2a-url.ts +0 -20
- package/src/utils/local-a2a-runtime.ts +0 -107
- package/src/utils/mime.ts +0 -44
- package/src/utils/path-containment.ts +0 -38
- package/tsconfig.json +0 -26
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
import type { LocalRuntimeConfig } from "@axiom-lattice/protocols";
|
|
2
|
-
import {
|
|
3
|
-
getAgentCardPort,
|
|
4
|
-
validateLocalRuntimeCommand,
|
|
5
|
-
validateLocalRuntimePort,
|
|
6
|
-
} from "../local-a2a-runtime";
|
|
7
|
-
|
|
8
|
-
function runtime(args: string[]): LocalRuntimeConfig {
|
|
9
|
-
return {
|
|
10
|
-
agentCardUrl: "http://localhost:4301/.well-known/agent-card.json",
|
|
11
|
-
command: {
|
|
12
|
-
executable: "node",
|
|
13
|
-
args,
|
|
14
|
-
},
|
|
15
|
-
};
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
describe("validateLocalRuntimePort", () => {
|
|
19
|
-
it.each([
|
|
20
|
-
["localhost", "http://localhost:4301/.well-known/agent-card.json"],
|
|
21
|
-
["127.0.0.1", "http://127.0.0.1:4301/.well-known/agent-card.json"],
|
|
22
|
-
["ipv6 loopback", "http://[::1]:4301/.well-known/agent-card.json"],
|
|
23
|
-
])("detects port mismatches for %s", (_label, agentCardUrl) => {
|
|
24
|
-
const result = validateLocalRuntimePort(runtime(["--port=4302"]), agentCardUrl);
|
|
25
|
-
|
|
26
|
-
expect(result.ok).toBe(false);
|
|
27
|
-
if (!result.ok) {
|
|
28
|
-
expect(result.error).toContain("command port (4302) does not match agentCardUrl port (4301)");
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
it.each([
|
|
33
|
-
["--port next arg", ["--port", "4301"]],
|
|
34
|
-
["--port inline", ["--port=4301"]],
|
|
35
|
-
["-p next arg", ["-p", "4301"]],
|
|
36
|
-
["-p inline", ["-p=4301"]],
|
|
37
|
-
])("accepts matching %s", (_label, args) => {
|
|
38
|
-
expect(validateLocalRuntimePort(runtime(args), "http://localhost:4301/.well-known/agent-card.json")).toEqual({ ok: true });
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
it("does not block remote URLs or commands without parseable ports", () => {
|
|
42
|
-
expect(validateLocalRuntimePort(runtime(["--port=4302"]), "https://example.com:4301/.well-known/agent-card.json")).toEqual({ ok: true });
|
|
43
|
-
expect(validateLocalRuntimePort(runtime(["--listen", "4302"]), "http://localhost:4301/.well-known/agent-card.json")).toEqual({ ok: true });
|
|
44
|
-
});
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
describe("validateLocalRuntimeCommand", () => {
|
|
48
|
-
it.each(["", " "])("rejects executable %j", (executable) => {
|
|
49
|
-
const result = validateLocalRuntimeCommand({
|
|
50
|
-
...runtime([]),
|
|
51
|
-
command: { executable, args: [] },
|
|
52
|
-
});
|
|
53
|
-
|
|
54
|
-
expect(result).toEqual({
|
|
55
|
-
ok: false,
|
|
56
|
-
error: "Local managed A2A command executable is required",
|
|
57
|
-
});
|
|
58
|
-
});
|
|
59
|
-
|
|
60
|
-
it("accepts a complete command", () => {
|
|
61
|
-
expect(validateLocalRuntimeCommand(runtime(["cli.js"]))).toEqual({
|
|
62
|
-
ok: true,
|
|
63
|
-
});
|
|
64
|
-
});
|
|
65
|
-
});
|
|
66
|
-
|
|
67
|
-
describe("getAgentCardPort", () => {
|
|
68
|
-
it.each([
|
|
69
|
-
["explicit localhost port", "http://localhost:4301/.well-known/agent-card.json", 4301],
|
|
70
|
-
["explicit 127 port", "http://127.0.0.1:4302/.well-known/agent-card.json", 4302],
|
|
71
|
-
["default http port", "http://localhost/.well-known/agent-card.json", 80],
|
|
72
|
-
["default https port", "https://localhost/.well-known/agent-card.json", 443],
|
|
73
|
-
["invalid URL", "not a url", null],
|
|
74
|
-
])("returns %s", (_label, agentCardUrl, expected) => {
|
|
75
|
-
expect(getAgentCardPort(agentCardUrl)).toBe(expected);
|
|
76
|
-
});
|
|
77
|
-
});
|
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
import * as fs from "node:fs/promises";
|
|
2
|
-
import * as os from "node:os";
|
|
3
|
-
import * as path from "node:path";
|
|
4
|
-
import {
|
|
5
|
-
isPathWithinRoot,
|
|
6
|
-
PathOutsideRootError,
|
|
7
|
-
resolvePathWithinRoot,
|
|
8
|
-
} from "../path-containment";
|
|
9
|
-
|
|
10
|
-
describe("path containment", () => {
|
|
11
|
-
it("does not accept a sibling with the same path prefix", () => {
|
|
12
|
-
expect(isPathWithinRoot("/Users/alice", "/Users/alice-other")).toBe(false);
|
|
13
|
-
});
|
|
14
|
-
|
|
15
|
-
it("accepts the root and its descendants", () => {
|
|
16
|
-
expect(isPathWithinRoot("/Users/alice", "/Users/alice")).toBe(true);
|
|
17
|
-
expect(isPathWithinRoot("/Users/alice", "/Users/alice/project")).toBe(true);
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
it("rejects a symlink that resolves outside the root", async () => {
|
|
21
|
-
const testRoot = await fs.mkdtemp(path.join(os.tmpdir(), "path-root-"));
|
|
22
|
-
const outside = await fs.mkdtemp(path.join(os.tmpdir(), "path-outside-"));
|
|
23
|
-
const linkPath = path.join(testRoot, "outside-link");
|
|
24
|
-
await fs.symlink(outside, linkPath, "dir");
|
|
25
|
-
|
|
26
|
-
try {
|
|
27
|
-
await expect(resolvePathWithinRoot(testRoot, linkPath)).rejects.toBeInstanceOf(
|
|
28
|
-
PathOutsideRootError,
|
|
29
|
-
);
|
|
30
|
-
} finally {
|
|
31
|
-
await fs.rm(testRoot, { recursive: true, force: true });
|
|
32
|
-
await fs.rm(outside, { recursive: true, force: true });
|
|
33
|
-
}
|
|
34
|
-
});
|
|
35
|
-
});
|
package/src/utils/a2a-url.ts
DELETED
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
const AGENT_CARD_PATH = "/.well-known/agent-card.json";
|
|
2
|
-
|
|
3
|
-
export function normalizeA2AAgentCardUrl(
|
|
4
|
-
value: string | undefined,
|
|
5
|
-
defaultProtocol: "http://" | "https://" = "https://"
|
|
6
|
-
): string {
|
|
7
|
-
const raw = value?.trim() ?? "";
|
|
8
|
-
if (!raw) return "";
|
|
9
|
-
|
|
10
|
-
const withProtocol = /^https?:\/\//i.test(raw)
|
|
11
|
-
? raw
|
|
12
|
-
: `${defaultProtocol}${raw.replace(/^\/+/, "")}`;
|
|
13
|
-
const trimmed = withProtocol.replace(/\/+$/, "");
|
|
14
|
-
|
|
15
|
-
if (trimmed.endsWith(AGENT_CARD_PATH)) {
|
|
16
|
-
return trimmed;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
return `${trimmed}${AGENT_CARD_PATH}`;
|
|
20
|
-
}
|
|
@@ -1,107 +0,0 @@
|
|
|
1
|
-
import type { LocalRuntimeConfig } from "@axiom-lattice/protocols";
|
|
2
|
-
|
|
3
|
-
export type LocalRuntimeValidationResult =
|
|
4
|
-
| { ok: true }
|
|
5
|
-
| { ok: false; error: string };
|
|
6
|
-
|
|
7
|
-
export function validateLocalRuntimeCommand(
|
|
8
|
-
localRuntime: LocalRuntimeConfig,
|
|
9
|
-
): LocalRuntimeValidationResult {
|
|
10
|
-
const runtime = localRuntime as unknown as {
|
|
11
|
-
command?: { executable?: unknown; args?: unknown };
|
|
12
|
-
};
|
|
13
|
-
const executable = runtime.command?.executable;
|
|
14
|
-
if (typeof executable !== "string" || executable.trim().length === 0) {
|
|
15
|
-
return {
|
|
16
|
-
ok: false,
|
|
17
|
-
error: "Local managed A2A command executable is required",
|
|
18
|
-
};
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
const args = runtime.command?.args;
|
|
22
|
-
if (!Array.isArray(args) || !args.every((arg) => typeof arg === "string")) {
|
|
23
|
-
return {
|
|
24
|
-
ok: false,
|
|
25
|
-
error: "Local managed A2A command args must be an array of strings",
|
|
26
|
-
};
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
return { ok: true };
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function getAgentCardPort(agentCardUrl: string): number | null {
|
|
33
|
-
let url: URL;
|
|
34
|
-
try {
|
|
35
|
-
url = new URL(agentCardUrl);
|
|
36
|
-
} catch {
|
|
37
|
-
return null;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
if (url.port) {
|
|
41
|
-
const port = Number(url.port);
|
|
42
|
-
return Number.isInteger(port) ? port : null;
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
if (url.protocol === "http:") return 80;
|
|
46
|
-
if (url.protocol === "https:") return 443;
|
|
47
|
-
return null;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function parseCommandPort(args: string[]): number | null {
|
|
51
|
-
for (let index = 0; index < args.length; index += 1) {
|
|
52
|
-
const arg = args[index];
|
|
53
|
-
const match = /^(--port|-p)(?:[=\s]+(\d+))?$/.exec(arg);
|
|
54
|
-
if (!match) continue;
|
|
55
|
-
|
|
56
|
-
const inlinePort = match[2];
|
|
57
|
-
if (inlinePort) return Number(inlinePort);
|
|
58
|
-
|
|
59
|
-
const nextArg = args[index + 1];
|
|
60
|
-
if (nextArg && /^\d+$/.test(nextArg)) {
|
|
61
|
-
return Number(nextArg);
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
return null;
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
function isLoopbackHost(hostname: string): boolean {
|
|
69
|
-
const normalized = hostname.toLowerCase();
|
|
70
|
-
return (
|
|
71
|
-
normalized === "localhost" ||
|
|
72
|
-
normalized === "127.0.0.1" ||
|
|
73
|
-
normalized === "::1" ||
|
|
74
|
-
normalized === "[::1]"
|
|
75
|
-
);
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
export function validateLocalRuntimePort(
|
|
79
|
-
localRuntime: LocalRuntimeConfig,
|
|
80
|
-
agentCardUrl: string,
|
|
81
|
-
): LocalRuntimeValidationResult {
|
|
82
|
-
let url: URL;
|
|
83
|
-
try {
|
|
84
|
-
url = new URL(agentCardUrl);
|
|
85
|
-
} catch {
|
|
86
|
-
return { ok: true };
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
if (!isLoopbackHost(url.hostname) || !url.port) {
|
|
90
|
-
return { ok: true };
|
|
91
|
-
}
|
|
92
|
-
|
|
93
|
-
const commandPort = parseCommandPort(localRuntime.command.args);
|
|
94
|
-
if (commandPort === null) {
|
|
95
|
-
return { ok: true };
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
const agentCardPort = Number(url.port);
|
|
99
|
-
if (commandPort === agentCardPort) {
|
|
100
|
-
return { ok: true };
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
return {
|
|
104
|
-
ok: false,
|
|
105
|
-
error: `Local managed A2A command port (${commandPort}) does not match agentCardUrl port (${agentCardPort}). Update the command args or Agent Card URL so they use the same port.`,
|
|
106
|
-
};
|
|
107
|
-
}
|
package/src/utils/mime.ts
DELETED
|
@@ -1,44 +0,0 @@
|
|
|
1
|
-
const EXT_TO_MIME: Record<string, string> = {
|
|
2
|
-
".txt": "text/plain",
|
|
3
|
-
".md": "text/markdown",
|
|
4
|
-
".html": "text/html",
|
|
5
|
-
".htm": "text/html",
|
|
6
|
-
".css": "text/css",
|
|
7
|
-
".js": "application/javascript",
|
|
8
|
-
".mjs": "application/javascript",
|
|
9
|
-
".json": "application/json",
|
|
10
|
-
".pdf": "application/pdf",
|
|
11
|
-
".png": "image/png",
|
|
12
|
-
".jpg": "image/jpeg",
|
|
13
|
-
".jpeg": "image/jpeg",
|
|
14
|
-
".gif": "image/gif",
|
|
15
|
-
".webp": "image/webp",
|
|
16
|
-
".svg": "image/svg+xml",
|
|
17
|
-
".ico": "image/x-icon",
|
|
18
|
-
".zip": "application/zip",
|
|
19
|
-
".csv": "text/csv",
|
|
20
|
-
".xml": "application/xml",
|
|
21
|
-
".xlsx": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
|
22
|
-
".xls": "application/vnd.ms-excel",
|
|
23
|
-
".pptx": "application/vnd.openxmlformats-officedocument.presentationml.presentation",
|
|
24
|
-
".ppt": "application/vnd.ms-powerpoint",
|
|
25
|
-
".docx": "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
|
26
|
-
".doc": "application/msword",
|
|
27
|
-
".mp4": "video/mp4",
|
|
28
|
-
".webm": "video/webm",
|
|
29
|
-
".mp3": "audio/mpeg",
|
|
30
|
-
".wav": "audio/wav",
|
|
31
|
-
".ogg": "audio/ogg",
|
|
32
|
-
};
|
|
33
|
-
|
|
34
|
-
export function getContentTypeFromFilename(filename: string): string {
|
|
35
|
-
const ext = filename.includes(".")
|
|
36
|
-
? filename.slice(filename.lastIndexOf(".")).toLowerCase()
|
|
37
|
-
: "";
|
|
38
|
-
return EXT_TO_MIME[ext] ?? "application/octet-stream";
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function getFilenameFromPath(path: string): string {
|
|
42
|
-
const segments = path.replace(/\/+$/, "").split("/");
|
|
43
|
-
return segments[segments.length - 1] || "download";
|
|
44
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
import * as fs from "node:fs/promises";
|
|
2
|
-
import * as path from "node:path";
|
|
3
|
-
|
|
4
|
-
export class PathOutsideRootError extends Error {
|
|
5
|
-
constructor(
|
|
6
|
-
public readonly rootPath: string,
|
|
7
|
-
public readonly targetPath: string,
|
|
8
|
-
) {
|
|
9
|
-
super(`Path is outside the allowed root: ${targetPath}`);
|
|
10
|
-
this.name = "PathOutsideRootError";
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export function isPathWithinRoot(rootPath: string, targetPath: string): boolean {
|
|
15
|
-
const relative = path.relative(rootPath, targetPath);
|
|
16
|
-
return (
|
|
17
|
-
relative === "" ||
|
|
18
|
-
(relative !== ".." &&
|
|
19
|
-
!relative.startsWith(`..${path.sep}`) &&
|
|
20
|
-
!path.isAbsolute(relative))
|
|
21
|
-
);
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
export async function resolvePathWithinRoot(
|
|
25
|
-
rootPath: string,
|
|
26
|
-
targetPath: string,
|
|
27
|
-
): Promise<{ rootPath: string; targetPath: string }> {
|
|
28
|
-
const [resolvedRoot, resolvedTarget] = await Promise.all([
|
|
29
|
-
fs.realpath(rootPath),
|
|
30
|
-
fs.realpath(targetPath),
|
|
31
|
-
]);
|
|
32
|
-
|
|
33
|
-
if (!isPathWithinRoot(resolvedRoot, resolvedTarget)) {
|
|
34
|
-
throw new PathOutsideRootError(resolvedRoot, resolvedTarget);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
return { rootPath: resolvedRoot, targetPath: resolvedTarget };
|
|
38
|
-
}
|
package/tsconfig.json
DELETED
|
@@ -1,26 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"compilerOptions": {
|
|
3
|
-
"target": "ES2020",
|
|
4
|
-
"module": "preserve",
|
|
5
|
-
"lib": ["ES2020"],
|
|
6
|
-
"outDir": "./dist",
|
|
7
|
-
"rootDir": "./src",
|
|
8
|
-
"strict": true,
|
|
9
|
-
"moduleResolution": "Bundler",
|
|
10
|
-
"esModuleInterop": true,
|
|
11
|
-
"skipLibCheck": true,
|
|
12
|
-
"forceConsistentCasingInFileNames": true,
|
|
13
|
-
"resolveJsonModule": true,
|
|
14
|
-
"declaration": true,
|
|
15
|
-
"declarationMap": true,
|
|
16
|
-
"types": ["node", "jest"],
|
|
17
|
-
"paths": {
|
|
18
|
-
"@*": ["./src/*"]
|
|
19
|
-
},
|
|
20
|
-
"sourceMap": true,
|
|
21
|
-
"incremental": true, // 确保启用增量编译
|
|
22
|
-
"tsBuildInfoFile": "./.tsbuildinfo" // 指定构建信息文件位置
|
|
23
|
-
},
|
|
24
|
-
"include": ["src/index.ts"],
|
|
25
|
-
"exclude": ["node_modules", "dist"]
|
|
26
|
-
}
|