edgeaegis 2026.10.1
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/LICENSE +202 -0
- package/NOTICE +10 -0
- package/README.md +215 -0
- package/config.yml +29 -0
- package/origin/cloudflare/app/config.yml +2 -0
- package/origin/cloudflare/app/index.js +4 -0
- package/origin/edgeone/app/config.yml +2 -0
- package/origin/edgeone/app/index.js +4 -0
- package/origin/esa/app/config.yml +2 -0
- package/origin/esa/app/index.js +4 -0
- package/origin/netlify/app/config.yml +2 -0
- package/origin/netlify/app/index.js +4 -0
- package/origin/vercel/app/config.yml +2 -0
- package/origin/vercel/app/index.js +4 -0
- package/package.json +123 -0
- package/respond/403.html +2 -0
- package/respond/403.json +1 -0
- package/rules/allowlist.yml +2 -0
- package/rules/emergency.conf +4 -0
- package/rules/local.conf +2 -0
- package/rules/seclang-bundle.json +360 -0
- package/rules/seclang-upstreams.json +14 -0
- package/rules/setup.conf +15 -0
- package/secret/credentials.example.yml +7 -0
- package/secret/relay-server.example.yml +10 -0
- package/tools/.build/scr/adapters/cloudflare/runtime.d.ts +18 -0
- package/tools/.build/scr/adapters/cloudflare/runtime.js +16 -0
- package/tools/.build/scr/adapters/cloudflare/runtime.js.map +1 -0
- package/tools/.build/scr/adapters/cloudflare/worker.js +25 -0
- package/tools/.build/scr/adapters/edgeone/worker.js +7 -0
- package/tools/.build/scr/adapters/esa/worker.js +5 -0
- package/tools/.build/scr/adapters/forward.d.ts +4 -0
- package/tools/.build/scr/adapters/forward.js +25 -0
- package/tools/.build/scr/adapters/forward.js.map +1 -0
- package/tools/.build/scr/adapters/handler.js +39 -0
- package/tools/.build/scr/adapters/ingress.d.ts +10 -0
- package/tools/.build/scr/adapters/ingress.js +62 -0
- package/tools/.build/scr/adapters/ingress.js.map +1 -0
- package/tools/.build/scr/adapters/netlify/worker.js +7 -0
- package/tools/.build/scr/adapters/runtime.d.ts +33 -0
- package/tools/.build/scr/adapters/runtime.js +50 -0
- package/tools/.build/scr/adapters/runtime.js.map +1 -0
- package/tools/.build/scr/adapters/vercel/worker.js +7 -0
- package/tools/.build/scr/cli/config.d.ts +2 -0
- package/tools/.build/scr/cli/config.js +23 -0
- package/tools/.build/scr/cli/config.js.map +1 -0
- package/tools/.build/scr/cli/deployment.d.ts +15 -0
- package/tools/.build/scr/cli/deployment.js +108 -0
- package/tools/.build/scr/cli/deployment.js.map +1 -0
- package/tools/.build/scr/cli/init.d.ts +2 -0
- package/tools/.build/scr/cli/init.js +62 -0
- package/tools/.build/scr/cli/init.js.map +1 -0
- package/tools/.build/scr/cli/main.d.ts +2 -0
- package/tools/.build/scr/cli/main.js +99 -0
- package/tools/.build/scr/cli/main.js.map +1 -0
- package/tools/.build/scr/cli/relay-serve.d.ts +1 -0
- package/tools/.build/scr/cli/relay-serve.js +48 -0
- package/tools/.build/scr/cli/relay-serve.js.map +1 -0
- package/tools/.build/scr/cli/responses.d.ts +2 -0
- package/tools/.build/scr/cli/responses.js +31 -0
- package/tools/.build/scr/cli/responses.js.map +1 -0
- package/tools/.build/scr/cli/serve.d.ts +1 -0
- package/tools/.build/scr/cli/serve.js +132 -0
- package/tools/.build/scr/cli/serve.js.map +1 -0
- package/tools/.build/scr/config.d.ts +39 -0
- package/tools/.build/scr/config.js +89 -0
- package/tools/.build/scr/config.js.map +1 -0
- package/tools/.build/scr/core/types.d.ts +27 -0
- package/tools/.build/scr/core/types.js +34 -0
- package/tools/.build/scr/core/types.js.map +1 -0
- package/tools/.build/scr/core/version.d.ts +1 -0
- package/tools/.build/scr/core/version.js +3 -0
- package/tools/.build/scr/core/version.js.map +1 -0
- package/tools/.build/scr/http-boundary/index.d.ts +19 -0
- package/tools/.build/scr/http-boundary/index.js +173 -0
- package/tools/.build/scr/http-boundary/index.js.map +1 -0
- package/tools/.build/scr/http-boundary/json.d.ts +2 -0
- package/tools/.build/scr/http-boundary/json.js +90 -0
- package/tools/.build/scr/http-boundary/json.js.map +1 -0
- package/tools/.build/scr/origin/relay.d.ts +20 -0
- package/tools/.build/scr/origin/relay.js +221 -0
- package/tools/.build/scr/origin/relay.js.map +1 -0
- package/tools/.build/scr/origin/replay-node.d.ts +8 -0
- package/tools/.build/scr/origin/replay-node.js +36 -0
- package/tools/.build/scr/origin/replay-node.js.map +1 -0
- package/tools/.build/scr/origin/types.d.ts +18 -0
- package/tools/.build/scr/origin/types.js +2 -0
- package/tools/.build/scr/origin/types.js.map +1 -0
- package/tools/.build/scr/runtime/allowlist.d.ts +21 -0
- package/tools/.build/scr/runtime/allowlist.js +84 -0
- package/tools/.build/scr/runtime/allowlist.js.map +1 -0
- package/tools/.build/scr/runtime/browser-cache.d.ts +7 -0
- package/tools/.build/scr/runtime/browser-cache.js +50 -0
- package/tools/.build/scr/runtime/browser-cache.js.map +1 -0
- package/tools/.build/scr/runtime/error-pages.d.ts +10 -0
- package/tools/.build/scr/runtime/error-pages.js +72 -0
- package/tools/.build/scr/runtime/error-pages.js.map +1 -0
- package/tools/.build/scr/runtime/index.d.ts +54 -0
- package/tools/.build/scr/runtime/index.js +355 -0
- package/tools/.build/scr/runtime/index.js.map +1 -0
- package/tools/.build/scr/runtime/node.d.ts +3 -0
- package/tools/.build/scr/runtime/node.js +97 -0
- package/tools/.build/scr/runtime/node.js.map +1 -0
- package/tools/.build/scr/runtime/proxy.d.ts +12 -0
- package/tools/.build/scr/runtime/proxy.js +177 -0
- package/tools/.build/scr/runtime/proxy.js.map +1 -0
- package/tools/.build/scr/runtime/stream.d.ts +8 -0
- package/tools/.build/scr/runtime/stream.js +72 -0
- package/tools/.build/scr/runtime/stream.js.map +1 -0
- package/tools/.build/scr/seclang/body.d.ts +13 -0
- package/tools/.build/scr/seclang/body.js +109 -0
- package/tools/.build/scr/seclang/body.js.map +1 -0
- package/tools/.build/scr/seclang/bytes.d.ts +5 -0
- package/tools/.build/scr/seclang/bytes.js +38 -0
- package/tools/.build/scr/seclang/bytes.js.map +1 -0
- package/tools/.build/scr/seclang/index.d.ts +166 -0
- package/tools/.build/scr/seclang/index.js +1519 -0
- package/tools/.build/scr/seclang/index.js.map +1 -0
- package/tools/.build/scr/seclang/json.d.ts +2 -0
- package/tools/.build/scr/seclang/json.js +87 -0
- package/tools/.build/scr/seclang/json.js.map +1 -0
- package/tools/.build/scr/seclang/libinjection.d.ts +9 -0
- package/tools/.build/scr/seclang/libinjection.js +59 -0
- package/tools/.build/scr/seclang/libinjection.js.map +1 -0
- package/tools/.build/scr/seclang/node.d.ts +22 -0
- package/tools/.build/scr/seclang/node.js +113 -0
- package/tools/.build/scr/seclang/node.js.map +1 -0
- package/tools/.build/scr/seclang/pcre2.d.ts +23 -0
- package/tools/.build/scr/seclang/pcre2.js +153 -0
- package/tools/.build/scr/seclang/pcre2.js.map +1 -0
- package/tools/.build/scr/seclang/sources.d.ts +6 -0
- package/tools/.build/scr/seclang/sources.js +59 -0
- package/tools/.build/scr/seclang/sources.js.map +1 -0
- package/tools/.build/scr/seclang/state.d.ts +17 -0
- package/tools/.build/scr/seclang/state.js +53 -0
- package/tools/.build/scr/seclang/state.js.map +1 -0
- package/tools/.build/scr/seclang/syntax.d.ts +9 -0
- package/tools/.build/scr/seclang/syntax.js +74 -0
- package/tools/.build/scr/seclang/syntax.js.map +1 -0
- package/tools/.build/scr/seclang/transforms.d.ts +3 -0
- package/tools/.build/scr/seclang/transforms.js +157 -0
- package/tools/.build/scr/seclang/transforms.js.map +1 -0
- package/tools/.build/scr/seclang/unicode.d.ts +2 -0
- package/tools/.build/scr/seclang/unicode.js +19 -0
- package/tools/.build/scr/seclang/unicode.js.map +1 -0
- package/tools/.build/scr/seclang/vendor/LIBINJECTION-LICENSE +33 -0
- package/tools/.build/scr/seclang/vendor/PCRE2-NOTICE +47 -0
- package/tools/.build/scr/seclang/vendor/PCRE2-WRAPPER-LICENSE +21 -0
- package/tools/.build/scr/seclang/vendor/UNICODE-DATA-NOTICE +6 -0
- package/tools/.build/scr/seclang/vendor/libinjection.json +7 -0
- package/tools/.build/scr/seclang/vendor/libinjection.wasm +0 -0
- package/tools/.build/scr/seclang/vendor/pcre2.json +7 -0
- package/tools/.build/scr/seclang/vendor/pcre2.wasm +0 -0
- package/tools/.build/scr/seclang/vendor/unicode.json +378 -0
- package/tools/build-platform.mjs +199 -0
- package/tools/platform-command.mjs +59 -0
- package/tools/sync-native-seclang.mjs +155 -0
- package/tools/verify-full-crs.mjs +118 -0
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { randomBytes } from "node:crypto";
|
|
2
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, join, resolve } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
import { SHIELD_VERSION } from "../core/version.js";
|
|
6
|
+
/** Materialize operator files outside node_modules; existing files are never overwritten. */
|
|
7
|
+
export async function initProject(target) {
|
|
8
|
+
let root = dirname(fileURLToPath(import.meta.url));
|
|
9
|
+
let found = false;
|
|
10
|
+
for (let i = 0; i < 6; i++) {
|
|
11
|
+
try {
|
|
12
|
+
if (JSON.parse(await readFile(join(root, "package.json"), "utf8")).name === "edgeaegis") {
|
|
13
|
+
found = true;
|
|
14
|
+
break;
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
catch { }
|
|
18
|
+
root = dirname(root);
|
|
19
|
+
}
|
|
20
|
+
if (!found)
|
|
21
|
+
throw new Error("Cannot locate installed EdgeAegis package");
|
|
22
|
+
const directory = resolve(target);
|
|
23
|
+
const files = [
|
|
24
|
+
"config.yml",
|
|
25
|
+
"rules/seclang-bundle.json",
|
|
26
|
+
"rules/seclang-upstreams.json",
|
|
27
|
+
"rules/allowlist.yml",
|
|
28
|
+
"rules/local.conf",
|
|
29
|
+
"rules/setup.conf",
|
|
30
|
+
"rules/emergency.conf",
|
|
31
|
+
"secret/credentials.example.yml",
|
|
32
|
+
"respond/403.html",
|
|
33
|
+
"respond/403.json",
|
|
34
|
+
"secret/relay-server.example.yml",
|
|
35
|
+
...["cloudflare", "vercel", "netlify", "esa", "edgeone"].flatMap((platform) => [
|
|
36
|
+
`origin/${platform}/app/config.yml`,
|
|
37
|
+
`origin/${platform}/app/index.js`,
|
|
38
|
+
]),
|
|
39
|
+
];
|
|
40
|
+
async function put(path, data) {
|
|
41
|
+
const destination = join(directory, path);
|
|
42
|
+
await mkdir(dirname(destination), { recursive: true });
|
|
43
|
+
try {
|
|
44
|
+
await writeFile(destination, data, { flag: "wx", mode: 0o600 });
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
if (error.code !== "EEXIST")
|
|
48
|
+
throw error;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
for (const file of files)
|
|
52
|
+
await put(file, await readFile(join(root, file)));
|
|
53
|
+
await put("secret/credentials.yml", `originToken: ${randomBytes(32).toString("base64url")}\ningressKey: ${randomBytes(32).toString("base64url")}\n`);
|
|
54
|
+
const scripts = {};
|
|
55
|
+
for (const platform of ["cloudflare", "vercel", "netlify", "esa", "edgeone", "local"])
|
|
56
|
+
for (const command of ["build", "start", "deploy"])
|
|
57
|
+
scripts[`${command}:${platform}`] = `edgeaegis ${command} ${platform}`;
|
|
58
|
+
await put("package.json", `${JSON.stringify({ private: true, type: "module", scripts, dependencies: { edgeaegis: `^${SHIELD_VERSION}` } }, null, 2)}\n`);
|
|
59
|
+
await put(".gitignore", "secret/*\n!secret/credentials.example.yml\ntools/.state/\n");
|
|
60
|
+
console.log(`Initialized operator files in ${directory}`);
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../../../scr/cli/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { execFileSync } from "node:child_process";
|
|
3
|
+
import { realpathSync } from "node:fs";
|
|
4
|
+
import { fileURLToPath, pathToFileURL } from "node:url";
|
|
5
|
+
import { SHIELD_VERSION } from "../core/version.js";
|
|
6
|
+
export async function main(args = process.argv.slice(2)) {
|
|
7
|
+
const [command, file] = args;
|
|
8
|
+
if (command === "--version" || command === "-v") {
|
|
9
|
+
console.log(SHIELD_VERSION);
|
|
10
|
+
return;
|
|
11
|
+
}
|
|
12
|
+
if (!command || command === "--help") {
|
|
13
|
+
console.log("edgeaegis init [directory]\nedgeaegis build <cloudflare|vercel|netlify|esa|edgeone|local> [config.yml]\nedgeaegis start <platform|local> [config.yml] [--plan]\nedgeaegis deploy <platform|local> [config.yml] [--plan]\nedgeaegis serve [config.yml]\nedgeaegis serve-relay <secret/relay-server.yml>\nedgeaegis check <SecLang file or source bundle>\nedgeaegis sync [--registry path] [--output path] [--latest]\nedgeaegis --version");
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
if (command === "init") {
|
|
17
|
+
await (await import("./init.js")).initProject(file ?? ".");
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
if (["build", "start", "deploy"].includes(command) && file) {
|
|
21
|
+
if (file === "local") {
|
|
22
|
+
const rest = args.slice(2).filter((value) => value !== "--plan");
|
|
23
|
+
if (rest.length > 1)
|
|
24
|
+
throw new Error("Unexpected command arguments");
|
|
25
|
+
const configFile = rest[0] ?? "config.yml";
|
|
26
|
+
if (args.includes("--plan")) {
|
|
27
|
+
console.log(JSON.stringify({
|
|
28
|
+
platform: "local",
|
|
29
|
+
tool: "node",
|
|
30
|
+
args: ["edgeaegis", "start", "local", configFile],
|
|
31
|
+
}));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (command !== "build") {
|
|
35
|
+
await (await import("./serve.js")).serve(configFile);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
const { config } = await (await import("./deployment.js")).readDeployment(configFile);
|
|
39
|
+
await (await import("./config.js")).readCredentials(config.secretFile);
|
|
40
|
+
const native = await (await import("../seclang/node.js")).loadSecLangDeployment(config.secLangFile, config.localRulesFile, config.setupRulesFile);
|
|
41
|
+
const program = (await import("../seclang/index.js")).compileSecLang(native.secLang, {
|
|
42
|
+
...native.secLangOptions,
|
|
43
|
+
strict: true,
|
|
44
|
+
});
|
|
45
|
+
try {
|
|
46
|
+
console.log(JSON.stringify({
|
|
47
|
+
platform: "local",
|
|
48
|
+
sourceRules: program.sourceRules,
|
|
49
|
+
unsupported: program.unsupported.length,
|
|
50
|
+
}));
|
|
51
|
+
}
|
|
52
|
+
finally {
|
|
53
|
+
program.dispose();
|
|
54
|
+
}
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
execFileSync(process.execPath, [fileURLToPath(new URL("../../../platform-command.mjs", import.meta.url)), ...args], { stdio: "inherit", windowsHide: true });
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
if (command === "sync") {
|
|
61
|
+
execFileSync(process.execPath, [
|
|
62
|
+
fileURLToPath(new URL("../../../sync-native-seclang.mjs", import.meta.url)),
|
|
63
|
+
...args.slice(1),
|
|
64
|
+
], { stdio: "inherit" });
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
if (command === "serve") {
|
|
68
|
+
await (await import("./serve.js")).serve(file ?? "config.yml");
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
if (command === "serve-relay" && file) {
|
|
72
|
+
await (await import("./relay-serve.js")).serveRelay(file);
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
if (command === "check" && file) {
|
|
76
|
+
const { loadSecLangFile } = await import("../seclang/node.js");
|
|
77
|
+
const { compileSecLang } = await import("../seclang/index.js");
|
|
78
|
+
const loaded = await loadSecLangFile(file);
|
|
79
|
+
const program = compileSecLang(loaded.secLang, { ...loaded.secLangOptions, strict: true });
|
|
80
|
+
try {
|
|
81
|
+
console.log(JSON.stringify({
|
|
82
|
+
sourceRules: program.sourceRules,
|
|
83
|
+
rootRules: program.supportedRules,
|
|
84
|
+
unsupported: program.unsupported.length,
|
|
85
|
+
}));
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
program.dispose();
|
|
89
|
+
}
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
throw new Error("Unknown command or missing rule file");
|
|
93
|
+
}
|
|
94
|
+
if (process.argv[1] && import.meta.url === pathToFileURL(realpathSync(process.argv[1])).href)
|
|
95
|
+
main().catch((error) => {
|
|
96
|
+
process.stderr.write(`${error.message}\n`);
|
|
97
|
+
process.exitCode = 1;
|
|
98
|
+
});
|
|
99
|
+
//# sourceMappingURL=main.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../../../../scr/cli/main.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function serveRelay(path: string): Promise<void>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { once } from "node:events";
|
|
2
|
+
import { mkdir, readFile } from "node:fs/promises";
|
|
3
|
+
import { dirname, resolve } from "node:path";
|
|
4
|
+
import { createRelayServer } from "../origin/relay.js";
|
|
5
|
+
import { SqliteReplayStore } from "../origin/replay-node.js";
|
|
6
|
+
import { createNodeServer } from "../runtime/node.js";
|
|
7
|
+
import { readCredentials, readData } from "./config.js";
|
|
8
|
+
import { readBusinessFunction } from "./deployment.js";
|
|
9
|
+
export async function serveRelay(path) {
|
|
10
|
+
const input = (await readData(path));
|
|
11
|
+
const base = dirname(resolve(path));
|
|
12
|
+
if (!["127.0.0.1", "::1"].includes(input.listen?.host) ||
|
|
13
|
+
!Number.isInteger(input.listen.port) ||
|
|
14
|
+
input.listen.port < 0 ||
|
|
15
|
+
input.listen.port > 65535 ||
|
|
16
|
+
typeof input.publicHost !== "string")
|
|
17
|
+
throw new Error("Relay server requires an explicit loopback listener behind TLS ingress");
|
|
18
|
+
const stateFile = resolve(base, input.stateFile);
|
|
19
|
+
await mkdir(dirname(stateFile), { recursive: true });
|
|
20
|
+
const store = new SqliteReplayStore(stateFile);
|
|
21
|
+
const credentials = await readCredentials(resolve(base, input.credentialsFile));
|
|
22
|
+
const business = await readBusinessFunction(resolve(base, input.businessFile));
|
|
23
|
+
const handler = await createRelayServer({
|
|
24
|
+
serverPrivateKey: JSON.parse(await readFile(resolve(base, input.privateKeyFile), "utf8")),
|
|
25
|
+
authenticationKey: (await readFile(resolve(base, input.authenticationKeyFile), "utf8")).trim(),
|
|
26
|
+
originToken: credentials.originToken,
|
|
27
|
+
business: (request) => Promise.resolve(business.fetch(request)),
|
|
28
|
+
replay: store,
|
|
29
|
+
...(input.maxBytes ? { maxBytes: input.maxBytes } : {}),
|
|
30
|
+
});
|
|
31
|
+
const server = createNodeServer(async (request) => new URL(request.url).pathname === "/_edgeshield/relay"
|
|
32
|
+
? handler(request)
|
|
33
|
+
: new Response(null, { status: 404 }), input.publicHost);
|
|
34
|
+
server.listen(input.listen.port, input.listen.host);
|
|
35
|
+
await once(server, "listening");
|
|
36
|
+
const address = server.address();
|
|
37
|
+
if (!address || typeof address === "string")
|
|
38
|
+
throw new Error("Missing relay listener");
|
|
39
|
+
process.stderr.write(`Relay listening at http://${input.listen.host}:${address.port}; HTTPS ingress required\n`);
|
|
40
|
+
const stop = () => {
|
|
41
|
+
server.close(() => store.close());
|
|
42
|
+
server.closeIdleConnections();
|
|
43
|
+
setTimeout(() => server.closeAllConnections(), 5000).unref();
|
|
44
|
+
};
|
|
45
|
+
process.once("SIGTERM", stop);
|
|
46
|
+
process.once("SIGINT", stop);
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=relay-serve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"relay-serve.js","sourceRoot":"","sources":["../../../../scr/cli/relay-serve.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { readdir, readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { parseStrictJson } from "../http-boundary/json.js";
|
|
4
|
+
export async function readResponsePages(directory, csp) {
|
|
5
|
+
const pages = {};
|
|
6
|
+
const names = await readdir(directory);
|
|
7
|
+
if (names.length > 100)
|
|
8
|
+
throw new Error("Too many custom response files");
|
|
9
|
+
for (const name of names) {
|
|
10
|
+
const match = /^([45]\d\d)\.html$/.exec(name);
|
|
11
|
+
if (!match)
|
|
12
|
+
continue;
|
|
13
|
+
const bytes = await readFile(join(directory, name));
|
|
14
|
+
if (bytes.length > 262144)
|
|
15
|
+
throw new Error("Custom response HTML exceeds 256 KiB");
|
|
16
|
+
const status = Number(match[1]);
|
|
17
|
+
pages[status] = {
|
|
18
|
+
html: new TextDecoder("utf-8", { fatal: true }).decode(bytes),
|
|
19
|
+
contentSecurityPolicy: csp,
|
|
20
|
+
};
|
|
21
|
+
const jsonName = `${status}.json`;
|
|
22
|
+
if (names.includes(jsonName)) {
|
|
23
|
+
const raw = await readFile(join(directory, jsonName));
|
|
24
|
+
if (raw.length > 65536)
|
|
25
|
+
throw new Error("Custom response JSON exceeds 64 KiB");
|
|
26
|
+
pages[status].json = parseStrictJson(new TextDecoder("utf-8", { fatal: true }).decode(raw));
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return pages;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=responses.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"responses.js","sourceRoot":"","sources":["../../../../scr/cli/responses.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAE3D,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,SAAiB,EAAE,GAAW;IACpE,MAAM,KAAK,GAAe,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC;IACvC,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAC;IAC1E,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;QACzB,MAAM,KAAK,GAAG,oBAAoB,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC9C,IAAI,CAAC,KAAK;YAAE,SAAS;QACrB,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;QACpD,IAAI,KAAK,CAAC,MAAM,GAAG,MAAM;YAAE,MAAM,IAAI,KAAK,CAAC,sCAAsC,CAAC,CAAC;QACnF,MAAM,MAAM,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAChC,KAAK,CAAC,MAAM,CAAC,GAAG;YACd,IAAI,EAAE,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;YAC7D,qBAAqB,EAAE,GAAG;SAC3B,CAAC;QACF,MAAM,QAAQ,GAAG,GAAG,MAAM,OAAO,CAAC;QAClC,IAAI,KAAK,CAAC,QAAQ,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;YACtD,IAAI,GAAG,CAAC,MAAM,GAAG,KAAK;gBAAE,MAAM,IAAI,KAAK,CAAC,qCAAqC,CAAC,CAAC;YAC/E,KAAK,CAAC,MAAM,CAAE,CAAC,IAAI,GAAG,eAAe,CAAC,IAAI,WAAW,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;QAC/F,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function serve(path: string): Promise<void>;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { timingSafeEqual } from "node:crypto";
|
|
2
|
+
import { once } from "node:events";
|
|
3
|
+
import { digest, stableJson } from "../core/types.js";
|
|
4
|
+
import { createRelayTransport } from "../origin/relay.js";
|
|
5
|
+
import { createShield } from "../runtime/index.js";
|
|
6
|
+
import { createNodeServer } from "../runtime/node.js";
|
|
7
|
+
import { loadSecLangDeployment } from "../seclang/node.js";
|
|
8
|
+
import { readCredentials, readData } from "./config.js";
|
|
9
|
+
import { readBusinessFunction, readDeployment } from "./deployment.js";
|
|
10
|
+
import { readResponsePages } from "./responses.js";
|
|
11
|
+
function authorized(header, secret) {
|
|
12
|
+
const given = Buffer.from(header?.startsWith("Bearer ") ? header.slice(7) : "");
|
|
13
|
+
const expected = Buffer.from(secret);
|
|
14
|
+
return given.length === expected.length && timingSafeEqual(given, expected);
|
|
15
|
+
}
|
|
16
|
+
export async function serve(path) {
|
|
17
|
+
let fingerprint = "";
|
|
18
|
+
async function candidate() {
|
|
19
|
+
const { config, businesses } = await readDeployment(path);
|
|
20
|
+
const credentials = await readCredentials(config.secretFile), native = await loadSecLangDeployment(config.secLangFile, config.localRulesFile, config.setupRulesFile);
|
|
21
|
+
const allowlist = config.allowlistFile
|
|
22
|
+
? (await readData(config.allowlistFile))
|
|
23
|
+
: [];
|
|
24
|
+
const errorPages = config.responses
|
|
25
|
+
? await readResponsePages(config.responses.directory, config.responses.contentSecurityPolicy)
|
|
26
|
+
: {};
|
|
27
|
+
const origins = Object.create(null);
|
|
28
|
+
for (const [name, { settings, businessFile }] of Object.entries(businesses)) {
|
|
29
|
+
const business = settings.mode === "function" ? await readBusinessFunction(businessFile) : undefined;
|
|
30
|
+
const originFetch = business
|
|
31
|
+
? (input, init) => Promise.resolve(business.fetch(new Request(input, init)))
|
|
32
|
+
: settings.mode === "relay"
|
|
33
|
+
? await createRelayTransport({
|
|
34
|
+
endpoint: settings.endpoint,
|
|
35
|
+
serverPublicKey: (await readData(settings.publicKeyFile, 16384)),
|
|
36
|
+
authenticationKey: (await readData(settings.authenticationKeyFile, 4096)),
|
|
37
|
+
maxBytes: config.limits?.maxBodyBytes ?? 8388608,
|
|
38
|
+
})
|
|
39
|
+
: undefined;
|
|
40
|
+
origins[name] = {
|
|
41
|
+
...config.origins[name],
|
|
42
|
+
originToken: credentials.originToken,
|
|
43
|
+
allowLoopbackHttp: config.allowLoopbackHttp ?? false,
|
|
44
|
+
...(originFetch ? { fetch: originFetch } : {}),
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
const hash = await digest(stableJson({
|
|
48
|
+
config,
|
|
49
|
+
businesses,
|
|
50
|
+
errorPages,
|
|
51
|
+
credentials,
|
|
52
|
+
source: native.secLang,
|
|
53
|
+
files: native.secLangOptions.files,
|
|
54
|
+
allowlist,
|
|
55
|
+
}));
|
|
56
|
+
if (hash === fingerprint)
|
|
57
|
+
return undefined;
|
|
58
|
+
const engine = await createShield({
|
|
59
|
+
tenant: config.tenant,
|
|
60
|
+
service: config.service,
|
|
61
|
+
publicHosts: config.publicHosts,
|
|
62
|
+
routes: config.routes,
|
|
63
|
+
...native,
|
|
64
|
+
allowlist,
|
|
65
|
+
errorPages,
|
|
66
|
+
...(config.limits ? { limits: config.limits } : {}),
|
|
67
|
+
...(config.maxConcurrentRequests
|
|
68
|
+
? { maxConcurrentRequests: config.maxConcurrentRequests }
|
|
69
|
+
: {}),
|
|
70
|
+
origins,
|
|
71
|
+
event: (event) => process.stdout.write(`${JSON.stringify(event)}\n`),
|
|
72
|
+
});
|
|
73
|
+
return { config, credentials, engine, hash };
|
|
74
|
+
}
|
|
75
|
+
let current = (await candidate());
|
|
76
|
+
fingerprint = current.hash;
|
|
77
|
+
let nextReload = Date.now() + 1000, reloading;
|
|
78
|
+
const server = createNodeServer(async (request, incoming) => {
|
|
79
|
+
if (Date.now() >= nextReload && !reloading) {
|
|
80
|
+
nextReload = Date.now() + 1000;
|
|
81
|
+
reloading = candidate()
|
|
82
|
+
.then((next) => {
|
|
83
|
+
if (!next)
|
|
84
|
+
return;
|
|
85
|
+
if (stableJson(next.config.listen) !== stableJson(current.config.listen)) {
|
|
86
|
+
next.engine.dispose();
|
|
87
|
+
throw new Error("Listener changes require restart");
|
|
88
|
+
}
|
|
89
|
+
const previous = current;
|
|
90
|
+
current = next;
|
|
91
|
+
fingerprint = next.hash;
|
|
92
|
+
previous.engine.dispose();
|
|
93
|
+
process.stderr.write('{"event":"rules-reloaded"}\n');
|
|
94
|
+
})
|
|
95
|
+
.catch(() => process.stderr.write('{"event":"reload-rejected"}\n'))
|
|
96
|
+
.then(() => { })
|
|
97
|
+
.finally(() => {
|
|
98
|
+
reloading = undefined;
|
|
99
|
+
});
|
|
100
|
+
}
|
|
101
|
+
await reloading;
|
|
102
|
+
return current.engine.handle(request, {
|
|
103
|
+
tenant: current.config.tenant,
|
|
104
|
+
verifiedClientIp: incoming.socket.remoteAddress ?? "127.0.0.1",
|
|
105
|
+
httpProtocol: `HTTP/${incoming.httpVersion}`,
|
|
106
|
+
...(current.credentials.clientToken &&
|
|
107
|
+
authorized(request.headers.get("authorization"), current.credentials.clientToken)
|
|
108
|
+
? { identity: "configured-api-client" }
|
|
109
|
+
: {}),
|
|
110
|
+
}, incoming.url);
|
|
111
|
+
}, () => current.config.publicHosts[0]);
|
|
112
|
+
server.listen(current.config.listen.port, current.config.listen.host);
|
|
113
|
+
await once(server, "listening");
|
|
114
|
+
const address = server.address();
|
|
115
|
+
if (!address || typeof address === "string")
|
|
116
|
+
throw new Error("Missing TCP listener");
|
|
117
|
+
process.stderr.write(`listening at http://${current.config.listen.host}:${address.port}; native SecLang\n`);
|
|
118
|
+
let stopping = false;
|
|
119
|
+
const stop = () => {
|
|
120
|
+
if (stopping)
|
|
121
|
+
return;
|
|
122
|
+
stopping = true;
|
|
123
|
+
server.close(() => {
|
|
124
|
+
current.engine.dispose();
|
|
125
|
+
});
|
|
126
|
+
server.closeIdleConnections();
|
|
127
|
+
setTimeout(() => server.closeAllConnections(), 5000).unref();
|
|
128
|
+
};
|
|
129
|
+
process.once("SIGINT", stop);
|
|
130
|
+
process.once("SIGTERM", stop);
|
|
131
|
+
}
|
|
132
|
+
//# sourceMappingURL=serve.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"serve.js","sourceRoot":"","sources":["../../../../scr/cli/serve.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { BoundaryLimits } from "./http-boundary/index.js";
|
|
2
|
+
import type { PlatformName } from "./origin/types.js";
|
|
3
|
+
import type { Route } from "./runtime/index.js";
|
|
4
|
+
export interface DeploymentConfig {
|
|
5
|
+
platform: PlatformName;
|
|
6
|
+
tenant: string;
|
|
7
|
+
service: string;
|
|
8
|
+
publicHosts: string[];
|
|
9
|
+
routes: Route[];
|
|
10
|
+
secLangFile: string;
|
|
11
|
+
localRulesFile?: string;
|
|
12
|
+
setupRulesFile?: string;
|
|
13
|
+
allowlistFile?: string;
|
|
14
|
+
secretFile: string;
|
|
15
|
+
originDirectory: string;
|
|
16
|
+
origins: Record<string, {
|
|
17
|
+
origin: string;
|
|
18
|
+
allowedOrigins: string[];
|
|
19
|
+
}>;
|
|
20
|
+
listen: {
|
|
21
|
+
host: "127.0.0.1" | "::1" | "0.0.0.0" | "::";
|
|
22
|
+
port: number;
|
|
23
|
+
};
|
|
24
|
+
allowLoopbackHttp?: boolean;
|
|
25
|
+
limits?: Partial<BoundaryLimits>;
|
|
26
|
+
maxConcurrentRequests?: number;
|
|
27
|
+
responses?: {
|
|
28
|
+
directory: string;
|
|
29
|
+
contentSecurityPolicy: string;
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export interface ProjectCredentials {
|
|
33
|
+
originToken: string;
|
|
34
|
+
clientToken?: string;
|
|
35
|
+
ingressKey?: string;
|
|
36
|
+
}
|
|
37
|
+
export declare function parseConfigText(text: string): unknown;
|
|
38
|
+
export declare function validateDeploymentConfig(value: unknown): DeploymentConfig;
|
|
39
|
+
export declare function validateCredentials(value: unknown): ProjectCredentials;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { parseDocument } from "yaml";
|
|
2
|
+
export function parseConfigText(text) {
|
|
3
|
+
if (new TextEncoder().encode(text).length > 8_000_000)
|
|
4
|
+
throw new Error("Configuration exceeds 8MB");
|
|
5
|
+
const doc = parseDocument(text, { uniqueKeys: true, merge: false });
|
|
6
|
+
if (doc.errors.length)
|
|
7
|
+
throw new Error(doc.errors.map((e) => e.message).join("; "));
|
|
8
|
+
return doc.toJS({ maxAliasCount: 0 });
|
|
9
|
+
}
|
|
10
|
+
export function validateDeploymentConfig(value) {
|
|
11
|
+
const config = value;
|
|
12
|
+
const keys = [
|
|
13
|
+
"tenant",
|
|
14
|
+
"platform",
|
|
15
|
+
"service",
|
|
16
|
+
"publicHosts",
|
|
17
|
+
"routes",
|
|
18
|
+
"secLangFile",
|
|
19
|
+
"localRulesFile",
|
|
20
|
+
"setupRulesFile",
|
|
21
|
+
"allowlistFile",
|
|
22
|
+
"secretFile",
|
|
23
|
+
"originDirectory",
|
|
24
|
+
"origins",
|
|
25
|
+
"listen",
|
|
26
|
+
"allowLoopbackHttp",
|
|
27
|
+
"limits",
|
|
28
|
+
"maxConcurrentRequests",
|
|
29
|
+
"responses",
|
|
30
|
+
];
|
|
31
|
+
if (!config ||
|
|
32
|
+
typeof config !== "object" ||
|
|
33
|
+
Object.keys(config).some((k) => !keys.includes(k)) ||
|
|
34
|
+
!["cloudflare", "vercel", "netlify", "esa", "edgeone"].includes(config.platform) ||
|
|
35
|
+
!Array.isArray(config.routes) ||
|
|
36
|
+
!Array.isArray(config.publicHosts) ||
|
|
37
|
+
config.publicHosts.length < 1 ||
|
|
38
|
+
config.publicHosts.length > 16 ||
|
|
39
|
+
!["tenant", "service", "secLangFile", "secretFile", "originDirectory"].every((k) => typeof config[k] === "string" && config[k].length) ||
|
|
40
|
+
!config.origins ||
|
|
41
|
+
typeof config.origins !== "object" ||
|
|
42
|
+
Array.isArray(config.origins) ||
|
|
43
|
+
!["127.0.0.1", "::1", "0.0.0.0", "::"].includes(config.listen?.host) ||
|
|
44
|
+
!Number.isInteger(config.listen.port) ||
|
|
45
|
+
config.listen.port < 0 ||
|
|
46
|
+
config.listen.port > 65535)
|
|
47
|
+
throw new Error("Invalid deployment configuration");
|
|
48
|
+
for (const route of config.routes) {
|
|
49
|
+
if (!route ||
|
|
50
|
+
typeof route.business !== "string" ||
|
|
51
|
+
!/^[A-Za-z0-9][A-Za-z0-9_-]{0,63}$/.test(route.business) ||
|
|
52
|
+
!Object.hasOwn(config.origins, route.business))
|
|
53
|
+
throw new Error("Every route must select a configured business");
|
|
54
|
+
}
|
|
55
|
+
for (const host of config.publicHosts) {
|
|
56
|
+
const publicUrl = new URL(`https://${host}`);
|
|
57
|
+
if (publicUrl.host !== host ||
|
|
58
|
+
publicUrl.pathname !== "/" ||
|
|
59
|
+
publicUrl.username ||
|
|
60
|
+
publicUrl.password ||
|
|
61
|
+
publicUrl.search ||
|
|
62
|
+
publicUrl.hash)
|
|
63
|
+
throw new Error("An exact public host is required");
|
|
64
|
+
}
|
|
65
|
+
if (config.responses &&
|
|
66
|
+
(typeof config.responses.directory !== "string" ||
|
|
67
|
+
!config.responses.directory ||
|
|
68
|
+
typeof config.responses.contentSecurityPolicy !== "string" ||
|
|
69
|
+
!config.responses.contentSecurityPolicy ||
|
|
70
|
+
Object.keys(config.responses).some((k) => !["directory", "contentSecurityPolicy"].includes(k))))
|
|
71
|
+
throw new Error("Invalid custom response configuration");
|
|
72
|
+
return config;
|
|
73
|
+
}
|
|
74
|
+
export function validateCredentials(value) {
|
|
75
|
+
const credentials = value;
|
|
76
|
+
if (!credentials ||
|
|
77
|
+
typeof credentials !== "object" ||
|
|
78
|
+
Object.keys(credentials).some((k) => !["originToken", "clientToken", "ingressKey"].includes(k)) ||
|
|
79
|
+
typeof credentials.originToken !== "string" ||
|
|
80
|
+
!/^[\x21-\x7e]{32,2048}$/.test(credentials.originToken) ||
|
|
81
|
+
(credentials.clientToken !== undefined &&
|
|
82
|
+
(!/^[\x21-\x7e]{32,2048}$/.test(credentials.clientToken) ||
|
|
83
|
+
credentials.clientToken === credentials.originToken)))
|
|
84
|
+
throw new Error("Invalid project credentials");
|
|
85
|
+
if (credentials.ingressKey !== undefined && !/^[\w-]{43,256}$/.test(credentials.ingressKey))
|
|
86
|
+
throw new Error("Invalid ingress signing key");
|
|
87
|
+
return credentials;
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../../../scr/config.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/** Only a platform adapter or verified authentication middleware may supply these values. */
|
|
2
|
+
export interface TrustedContext {
|
|
3
|
+
/** Actual protocol reported by the ingress transport, never a forwarded request header. */
|
|
4
|
+
httpProtocol?: string;
|
|
5
|
+
verifiedClientIp?: string;
|
|
6
|
+
identity?: string;
|
|
7
|
+
tenant: string;
|
|
8
|
+
}
|
|
9
|
+
export interface SecurityEvent {
|
|
10
|
+
id: string;
|
|
11
|
+
tenant: string;
|
|
12
|
+
at: number;
|
|
13
|
+
kind: "allow" | "block" | "detect" | "error";
|
|
14
|
+
source: "boundary" | "route" | "identity" | "rule" | "proxy";
|
|
15
|
+
policy: string;
|
|
16
|
+
ruleId?: string;
|
|
17
|
+
reason: string;
|
|
18
|
+
}
|
|
19
|
+
export declare class ShieldError extends Error {
|
|
20
|
+
readonly code: string;
|
|
21
|
+
readonly status: number;
|
|
22
|
+
constructor(code: string, status?: number);
|
|
23
|
+
}
|
|
24
|
+
export type Fetch = (input: RequestInfo | URL, init?: RequestInit) => Promise<Response>;
|
|
25
|
+
export declare function requireInteger(value: number, min: number, max: number, name: string): number;
|
|
26
|
+
export declare function digest(value: string | Uint8Array): Promise<string>;
|
|
27
|
+
export declare function stableJson(value: unknown): string;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export class ShieldError extends Error {
|
|
2
|
+
code;
|
|
3
|
+
status;
|
|
4
|
+
constructor(code, status = 400) {
|
|
5
|
+
super(code);
|
|
6
|
+
this.code = code;
|
|
7
|
+
this.status = status;
|
|
8
|
+
this.name = "ShieldError";
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
export function requireInteger(value, min, max, name) {
|
|
12
|
+
if (!Number.isSafeInteger(value) || value < min || value > max) {
|
|
13
|
+
throw new Error(`Invalid ${name}: expected integer ${min}..${max}`);
|
|
14
|
+
}
|
|
15
|
+
return value;
|
|
16
|
+
}
|
|
17
|
+
export async function digest(value) {
|
|
18
|
+
const data = typeof value === "string" ? new TextEncoder().encode(value) : value;
|
|
19
|
+
const hash = await crypto.subtle.digest("SHA-256", data);
|
|
20
|
+
return Array.from(new Uint8Array(hash), (b) => b.toString(16).padStart(2, "0")).join("");
|
|
21
|
+
}
|
|
22
|
+
export function stableJson(value) {
|
|
23
|
+
if (Array.isArray(value))
|
|
24
|
+
return `[${value.map(stableJson).join(",")}]`;
|
|
25
|
+
if (value !== null && typeof value === "object") {
|
|
26
|
+
const obj = value;
|
|
27
|
+
return `{${Object.keys(obj)
|
|
28
|
+
.sort()
|
|
29
|
+
.map((key) => `${JSON.stringify(key)}:${stableJson(obj[key])}`)
|
|
30
|
+
.join(",")}}`;
|
|
31
|
+
}
|
|
32
|
+
return JSON.stringify(value) ?? "null";
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../../scr/core/types.ts"],"names":[],"mappings":"AAqBA,MAAM,OAAO,WAAY,SAAQ,KAAK;IAElB,IAAI;IACJ,MAAM;IAFxB,YACkB,IAAY,EACZ,MAAM,GAAG,GAAG;QAE5B,KAAK,CAAC,IAAI,CAAC,CAAC;oBAHI,IAAI;sBACJ,MAAM;QAGtB,IAAI,CAAC,IAAI,GAAG,aAAa,CAAC;IAC5B,CAAC;CACF;AAID,MAAM,UAAU,cAAc,CAAC,KAAa,EAAE,GAAW,EAAE,GAAW,EAAE,IAAY;IAClF,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,GAAG,IAAI,KAAK,GAAG,GAAG,EAAE,CAAC;QAC/D,MAAM,IAAI,KAAK,CAAC,WAAW,IAAI,sBAAsB,GAAG,KAAK,GAAG,EAAE,CAAC,CAAC;IACtE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,MAAM,CAAC,KAA0B;IACrD,MAAM,IAAI,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,WAAW,EAAE,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;IACjF,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,SAAS,EAAE,IAAoB,CAAC,CAAC;IACzE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,QAAQ,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;AAC3F,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,KAAc;IACvC,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC;QAAE,OAAO,IAAI,KAAK,CAAC,GAAG,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IACxE,IAAI,KAAK,KAAK,IAAI,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAChD,MAAM,GAAG,GAAG,KAAgC,CAAC;QAC7C,OAAO,IAAI,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC;aACxB,IAAI,EAAE;aACN,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;aAC9D,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC;IAClB,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC;AACzC,CAAC"}
|