chore: update schema and prettify, fix package.json and Makefile

This commit is contained in:
yusing 2025-04-16 05:46:37 +08:00
parent 49d062a94b
commit 7e56fce4c9
24 changed files with 778 additions and 583 deletions

View file

@ -31,12 +31,12 @@ ifeq ($(debug), 1)
else ifeq ($(pprof), 1) else ifeq ($(pprof), 1)
CGO_ENABLED = 1 CGO_ENABLED = 1
GORACE = log_path=logs/pprof strip_path_prefix=$(shell pwd)/ halt_on_error=1 GORACE = log_path=logs/pprof strip_path_prefix=$(shell pwd)/ halt_on_error=1
BUILD_FLAGS = -tags pprof BUILD_FLAGS += -tags pprof
VERSION := ${VERSION}-pprof VERSION := ${VERSION}-pprof
else else
CGO_ENABLED = 0 CGO_ENABLED = 0
LDFLAGS += -s -w LDFLAGS += -s -w
BUILD_FLAGS = -pgo=auto -tags production BUILD_FLAGS += -pgo=auto -tags production
endif endif
BUILD_FLAGS += -ldflags='$(LDFLAGS)' BUILD_FLAGS += -ldflags='$(LDFLAGS)'
@ -94,43 +94,5 @@ cloc:
link-binary: link-binary:
ln -s /app/${NAME} bin/run ln -s /app/${NAME} bin/run
# To generate schema
# comment out this part from typescript-json-schema.js#L884
#
# if (indexType.flags !== ts.TypeFlags.Number && !isIndexedObject) {
# throw new Error("Not supported: IndexSignatureDeclaration with index symbol other than a number or a string");
# }
gen-schema-single:
bun --bun run typescript-json-schema --noExtraProps --required --skipLibCheck --tsNodeRegister=true -o schemas/${OUT} schemas/${IN} ${CLASS}
# minify
python3 -c "import json; f=open('schemas/${OUT}', 'r'); j=json.load(f); f.close(); f=open('schemas/${OUT}', 'w'); json.dump(j, f, separators=(',', ':'));"
gen-schema:
cd schemas && bun --bun tsc
make IN=config/config.ts \
CLASS=Config \
OUT=config.schema.json \
gen-schema-single
make IN=providers/routes.ts \
CLASS=Routes \
OUT=routes.schema.json \
gen-schema-single
make IN=middlewares/middleware_compose.ts \
CLASS=MiddlewareCompose \
OUT=middleware_compose.schema.json \
gen-schema-single
make IN=docker.ts \
CLASS=DockerRoutes \
OUT=docker_routes.schema.json \
gen-schema-single
cd ..
publish-schema:
cd schemas && bun publish && cd ..
update-schema-generator:
pnpm up -g typescript-json-schema
push-github: push-github:
git push origin $(shell git rev-parse --abbrev-ref HEAD) git push origin $(shell git rev-parse --abbrev-ref HEAD)

33
schemas/Makefile Normal file
View file

@ -0,0 +1,33 @@
# To generate schema
# comment out this part from typescript-json-schema.js#L884
#
# if (indexType.flags !== ts.TypeFlags.Number && !isIndexedObject) {
# throw new Error("Not supported: IndexSignatureDeclaration with index symbol other than a number or a string");
# }
gen-schema-single:
bun -bun typescript-json-schema --noExtraProps --required --skipLibCheck --tsNodeRegister=true -o "${OUT}" "${IN}" ${CLASS}
# minify
python3 -c "import json; f=open('${OUT}', 'r'); j=json.load(f); f.close(); f=open('${OUT}', 'w'); json.dump(j, f, separators=(',', ':'));"
gen-schema:
bun -bun tsc
sed -i 's#"type": "module"#"type": "commonjs"#' package.json
make IN=config/config.ts \
CLASS=Config \
OUT=config.schema.json \
gen-schema-single
make IN=providers/routes.ts \
CLASS=Routes \
OUT=routes.schema.json \
gen-schema-single
make IN=middlewares/middleware_compose.ts \
CLASS=MiddlewareCompose \
OUT=middleware_compose.schema.json \
gen-schema-single
make IN=docker.ts \
CLASS=DockerRoutes \
OUT=docker_routes.schema.json \
gen-schema-single
sed -i 's#"type": "commonjs"#"type": "module"#' package.json
bun format:write

View file

@ -2,10 +2,10 @@
"lockfileVersion": 1, "lockfileVersion": 1,
"workspaces": { "workspaces": {
"": { "": {
"name": "godoxy-types", "name": "godoxy-schemas",
"devDependencies": { "devDependencies": {
"prettier": "^3.4.2", "prettier": "^3.5.3",
"typescript": "^5.7.3", "typescript": "^5.8.3",
"typescript-json-schema": "^0.65.1", "typescript-json-schema": "^0.65.1",
}, },
}, },
@ -29,9 +29,9 @@
"@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="], "@types/json-schema": ["@types/json-schema@7.0.15", "", {}, "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="],
"@types/node": ["@types/node@18.19.74", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-HMwEkkifei3L605gFdV+/UwtpxP6JSzM+xFk2Ia6DNFSwSVBRh9qp5Tgf4lNFOMfPVuU0WnkcWpXZpgn5ufO4A=="], "@types/node": ["@types/node@18.19.86", "", { "dependencies": { "undici-types": "~5.26.4" } }, "sha512-fifKayi175wLyKyc5qUfyENhQ1dCNI1UNjp653d8kuYcPQN5JhX3dGuP/XmvPTg/xRBn1VTLpbmi+H/Mr7tLfQ=="],
"acorn": ["acorn@8.14.0", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA=="], "acorn": ["acorn@8.14.1", "", { "bin": { "acorn": "bin/acorn" } }, "sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg=="],
"acorn-walk": ["acorn-walk@8.3.4", "", { "dependencies": { "acorn": "^8.11.0" } }, "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g=="], "acorn-walk": ["acorn-walk@8.3.4", "", { "dependencies": { "acorn": "^8.11.0" } }, "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g=="],
@ -83,7 +83,7 @@
"path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="], "path-is-absolute": ["path-is-absolute@1.0.1", "", {}, "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg=="],
"prettier": ["prettier@3.4.2", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ=="], "prettier": ["prettier@3.5.3", "", { "bin": { "prettier": "bin/prettier.cjs" } }, "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw=="],
"require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="], "require-directory": ["require-directory@2.1.1", "", {}, "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q=="],
@ -95,7 +95,7 @@
"ts-node": ["ts-node@10.9.2", "", { "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", "@tsconfig/node16": "^1.0.2", "acorn": "^8.4.1", "acorn-walk": "^8.1.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "peerDependencies": { "@swc/core": ">=1.2.50", "@swc/wasm": ">=1.2.50", "@types/node": "*", "typescript": ">=2.7" }, "optionalPeers": ["@swc/core", "@swc/wasm"], "bin": { "ts-node": "dist/bin.js", "ts-script": "dist/bin-script-deprecated.js", "ts-node-cwd": "dist/bin-cwd.js", "ts-node-esm": "dist/bin-esm.js", "ts-node-script": "dist/bin-script.js", "ts-node-transpile-only": "dist/bin-transpile.js" } }, "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ=="], "ts-node": ["ts-node@10.9.2", "", { "dependencies": { "@cspotcode/source-map-support": "^0.8.0", "@tsconfig/node10": "^1.0.7", "@tsconfig/node12": "^1.0.7", "@tsconfig/node14": "^1.0.0", "@tsconfig/node16": "^1.0.2", "acorn": "^8.4.1", "acorn-walk": "^8.1.1", "arg": "^4.1.0", "create-require": "^1.1.0", "diff": "^4.0.1", "make-error": "^1.1.1", "v8-compile-cache-lib": "^3.0.1", "yn": "3.1.1" }, "peerDependencies": { "@swc/core": ">=1.2.50", "@swc/wasm": ">=1.2.50", "@types/node": "*", "typescript": ">=2.7" }, "optionalPeers": ["@swc/core", "@swc/wasm"], "bin": { "ts-node": "dist/bin.js", "ts-script": "dist/bin-script-deprecated.js", "ts-node-cwd": "dist/bin-cwd.js", "ts-node-esm": "dist/bin-esm.js", "ts-node-script": "dist/bin-script.js", "ts-node-transpile-only": "dist/bin-transpile.js" } }, "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ=="],
"typescript": ["typescript@5.7.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw=="], "typescript": ["typescript@5.8.3", "", { "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" } }, "sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ=="],
"typescript-json-schema": ["typescript-json-schema@0.65.1", "", { "dependencies": { "@types/json-schema": "^7.0.9", "@types/node": "^18.11.9", "glob": "^7.1.7", "path-equal": "^1.2.5", "safe-stable-stringify": "^2.2.0", "ts-node": "^10.9.1", "typescript": "~5.5.0", "yargs": "^17.1.1" }, "bin": { "typescript-json-schema": "bin/typescript-json-schema" } }, "sha512-tuGH7ff2jPaUYi6as3lHyHcKpSmXIqN7/mu50x3HlYn0EHzLpmt3nplZ7EuhUkO0eqDRc9GqWNkfjgBPIS9kxg=="], "typescript-json-schema": ["typescript-json-schema@0.65.1", "", { "dependencies": { "@types/json-schema": "^7.0.9", "@types/node": "^18.11.9", "glob": "^7.1.7", "path-equal": "^1.2.5", "safe-stable-stringify": "^2.2.0", "ts-node": "^10.9.1", "typescript": "~5.5.0", "yargs": "^17.1.1" }, "bin": { "typescript-json-schema": "bin/typescript-json-schema" } }, "sha512-tuGH7ff2jPaUYi6as3lHyHcKpSmXIqN7/mu50x3HlYn0EHzLpmt3nplZ7EuhUkO0eqDRc9GqWNkfjgBPIS9kxg=="],

View file

@ -1,49 +1,57 @@
import { CIDR, HTTPHeader, HTTPMethod, StatusCodeRange, URI } from "../types"; import { CIDR, HTTPHeader, HTTPMethod, StatusCodeRange, URI } from "../types";
export declare const ACCESS_LOG_FORMATS: readonly ["combined", "common", "json"]; export declare const ACCESS_LOG_FORMATS: readonly [
"combined",
"common",
"json",
];
export type AccessLogFormat = (typeof ACCESS_LOG_FORMATS)[number]; export type AccessLogFormat = (typeof ACCESS_LOG_FORMATS)[number];
export type AccessLogConfig = { export type AccessLogConfig = {
/** /**
* The size of the buffer. * The size of the buffer.
* *
* @minimum 0 * @minimum 0
* @default 65536 * @default 65536
* @TJS-type integer * @TJS-type integer
*/ */
buffer_size?: number; buffer_size?: number;
/** The format of the access log. /** The format of the access log.
* *
* @default "combined" * @default "combined"
*/ */
format?: AccessLogFormat; format?: AccessLogFormat;
path: URI; path: URI;
filters?: AccessLogFilters; filters?: AccessLogFilters;
fields?: AccessLogFields; fields?: AccessLogFields;
}; };
export type AccessLogFilter<T> = { export type AccessLogFilter<T> = {
/** Whether the filter is negative. /** Whether the filter is negative.
* *
* @default false * @default false
*/ */
negative?: boolean; negative?: boolean;
values: T[]; values: T[];
}; };
export type AccessLogFilters = { export type AccessLogFilters = {
status_code?: AccessLogFilter<StatusCodeRange>; status_code?: AccessLogFilter<StatusCodeRange>;
method?: AccessLogFilter<HTTPMethod>; method?: AccessLogFilter<HTTPMethod>;
host?: AccessLogFilter<string>; host?: AccessLogFilter<string>;
headers?: AccessLogFilter<HTTPHeader>; headers?: AccessLogFilter<HTTPHeader>;
cidr?: AccessLogFilter<CIDR>; cidr?: AccessLogFilter<CIDR>;
}; };
export declare const ACCESS_LOG_FIELD_MODES: readonly ["keep", "drop", "redact"]; export declare const ACCESS_LOG_FIELD_MODES: readonly [
"keep",
"drop",
"redact",
];
export type AccessLogFieldMode = (typeof ACCESS_LOG_FIELD_MODES)[number]; export type AccessLogFieldMode = (typeof ACCESS_LOG_FIELD_MODES)[number];
export type AccessLogField = { export type AccessLogField = {
default?: AccessLogFieldMode; default?: AccessLogFieldMode;
config: { config: {
[key: string]: AccessLogFieldMode; [key: string]: AccessLogFieldMode;
}; };
}; };
export type AccessLogFields = { export type AccessLogFields = {
header?: AccessLogField; header?: AccessLogField;
query?: AccessLogField; query?: AccessLogField;
cookie?: AccessLogField; cookie?: AccessLogField;
}; };

View file

@ -1,66 +1,88 @@
import { DomainOrWildcard, Email } from "../types"; import { DomainOrWildcard, Email } from "../types";
export declare const AUTOCERT_PROVIDERS: readonly ["local", "cloudflare", "clouddns", "duckdns", "ovh", "porkbun"]; export declare const AUTOCERT_PROVIDERS: readonly [
"local",
"cloudflare",
"clouddns",
"duckdns",
"ovh",
"porkbun",
];
export type AutocertProvider = (typeof AUTOCERT_PROVIDERS)[number]; export type AutocertProvider = (typeof AUTOCERT_PROVIDERS)[number];
export type AutocertConfig = LocalOptions | CloudflareOptions | CloudDNSOptions | DuckDNSOptions | OVHOptionsWithAppKey | OVHOptionsWithOAuth2Config | PorkbunOptions; export type AutocertConfig =
| LocalOptions
| CloudflareOptions
| CloudDNSOptions
| DuckDNSOptions
| OVHOptionsWithAppKey
| OVHOptionsWithOAuth2Config
| PorkbunOptions;
export interface AutocertConfigBase { export interface AutocertConfigBase {
email: Email; email: Email;
domains: DomainOrWildcard[]; domains: DomainOrWildcard[];
cert_path?: string; cert_path?: string;
key_path?: string; key_path?: string;
} }
export interface LocalOptions { export interface LocalOptions {
provider: "local"; provider: "local";
cert_path?: string; cert_path?: string;
key_path?: string; key_path?: string;
options?: {} | null; options?: {} | null;
} }
export interface CloudflareOptions extends AutocertConfigBase { export interface CloudflareOptions extends AutocertConfigBase {
provider: "cloudflare"; provider: "cloudflare";
options: { options: {
auth_token: string; auth_token: string;
}; };
} }
export interface CloudDNSOptions extends AutocertConfigBase { export interface CloudDNSOptions extends AutocertConfigBase {
provider: "clouddns"; provider: "clouddns";
options: { options: {
client_id: string; client_id: string;
email: Email; email: Email;
password: string; password: string;
}; };
} }
export interface DuckDNSOptions extends AutocertConfigBase { export interface DuckDNSOptions extends AutocertConfigBase {
provider: "duckdns"; provider: "duckdns";
options: { options: {
token: string; token: string;
}; };
} }
export interface PorkbunOptions extends AutocertConfigBase { export interface PorkbunOptions extends AutocertConfigBase {
provider: "porkbun"; provider: "porkbun";
options: { options: {
api_key: string; api_key: string;
secret_api_key: string; secret_api_key: string;
}; };
} }
export declare const OVH_ENDPOINTS: readonly ["ovh-eu", "ovh-ca", "ovh-us", "kimsufi-eu", "kimsufi-ca", "soyoustart-eu", "soyoustart-ca"]; export declare const OVH_ENDPOINTS: readonly [
"ovh-eu",
"ovh-ca",
"ovh-us",
"kimsufi-eu",
"kimsufi-ca",
"soyoustart-eu",
"soyoustart-ca",
];
export type OVHEndpoint = (typeof OVH_ENDPOINTS)[number]; export type OVHEndpoint = (typeof OVH_ENDPOINTS)[number];
export interface OVHOptionsWithAppKey extends AutocertConfigBase { export interface OVHOptionsWithAppKey extends AutocertConfigBase {
provider: "ovh"; provider: "ovh";
options: { options: {
application_secret: string; application_secret: string;
consumer_key: string; consumer_key: string;
api_endpoint?: OVHEndpoint; api_endpoint?: OVHEndpoint;
application_key: string; application_key: string;
}; };
} }
export interface OVHOptionsWithOAuth2Config extends AutocertConfigBase { export interface OVHOptionsWithOAuth2Config extends AutocertConfigBase {
provider: "ovh"; provider: "ovh";
options: { options: {
application_secret: string; application_secret: string;
consumer_key: string; consumer_key: string;
api_endpoint?: OVHEndpoint; api_endpoint?: OVHEndpoint;
oauth2_config: { oauth2_config: {
client_id: string; client_id: string;
client_secret: string; client_secret: string;
};
}; };
};
} }

View file

@ -4,51 +4,58 @@ import { EntrypointConfig } from "./entrypoint";
import { HomepageConfig } from "./homepage"; import { HomepageConfig } from "./homepage";
import { Providers } from "./providers"; import { Providers } from "./providers";
export type Config = { export type Config = {
/** Optional autocert configuration /** Optional autocert configuration
* *
* @examples require(".").autocertExamples * @examples require(".").autocertExamples
*/ */
autocert?: AutocertConfig; autocert?: AutocertConfig;
entrypoint?: EntrypointConfig; entrypoint?: EntrypointConfig;
providers: Providers; providers: Providers;
/** Optional list of domains to match /** Optional list of domains to match
* *
* @minItems 1 * @minItems 1
* @examples require(".").matchDomainsExamples * @examples require(".").matchDomainsExamples
*/ */
match_domains?: DomainName[]; match_domains?: DomainName[];
homepage?: HomepageConfig; homepage?: HomepageConfig;
/** /**
* Optional timeout before shutdown * Optional timeout before shutdown
* @default 3 * @default 3
* @minimum 1 * @minimum 1
*/ */
timeout_shutdown?: number; timeout_shutdown?: number;
}; };
export declare const autocertExamples: ({ export declare const autocertExamples: (
provider: string; | {
email?: undefined; provider: string;
domains?: undefined; email?: undefined;
options?: undefined; domains?: undefined;
} | { options?: undefined;
provider: string; }
email: string; | {
domains: string[]; provider: string;
options: { email: string;
domains: string[];
options: {
auth_token: string; auth_token: string;
client_id?: undefined; client_id?: undefined;
email?: undefined; email?: undefined;
password?: undefined; password?: undefined;
}; };
} | { }
provider: string; | {
email: string; provider: string;
domains: string[]; email: string;
options: { domains: string[];
options: {
client_id: string; client_id: string;
email: string; email: string;
password: string; password: string;
auth_token?: undefined; auth_token?: undefined;
}; };
})[]; }
export declare const matchDomainsExamples: readonly ["example.com", "*.example.com"]; )[];
export declare const matchDomainsExamples: readonly [
"example.com",
"*.example.com",
];

View file

@ -1,39 +1,49 @@
import { MiddlewareCompose } from "../middlewares/middleware_compose"; import { MiddlewareCompose } from "../middlewares/middleware_compose";
import { AccessLogConfig } from "./access_log"; import { AccessLogConfig } from "./access_log";
export type EntrypointConfig = { export type EntrypointConfig = {
/** Entrypoint middleware configuration /** Entrypoint middleware configuration
* *
* @examples require(".").middlewaresExamples * @examples require(".").middlewaresExamples
*/ */
middlewares?: MiddlewareCompose; middlewares?: MiddlewareCompose;
/** Entrypoint access log configuration /** Entrypoint access log configuration
* *
* @examples require(".").accessLogExamples * @examples require(".").accessLogExamples
*/ */
access_log?: AccessLogConfig; access_log?: AccessLogConfig;
}; };
export declare const accessLogExamples: readonly [{ export declare const accessLogExamples: readonly [
{
readonly path: "/var/log/access.log"; readonly path: "/var/log/access.log";
readonly format: "combined"; readonly format: "combined";
readonly filters: { readonly filters: {
readonly status_codes: { readonly status_codes: {
readonly values: readonly ["200-299"]; readonly values: readonly ["200-299"];
}; };
}; };
readonly fields: { readonly fields: {
readonly headers: { readonly headers: {
readonly default: "keep"; readonly default: "keep";
readonly config: { readonly config: {
readonly foo: "redact"; readonly foo: "redact";
};
}; };
};
}; };
}]; },
export declare const middlewaresExamples: readonly [{ ];
export declare const middlewaresExamples: readonly [
{
readonly use: "RedirectHTTP"; readonly use: "RedirectHTTP";
}, { },
{
readonly use: "CIDRWhitelist"; readonly use: "CIDRWhitelist";
readonly allow: readonly ["127.0.0.1", "10.0.0.0/8", "172.16.0.0/12", "192.168.0.0/16"]; readonly allow: readonly [
"127.0.0.1",
"10.0.0.0/8",
"172.16.0.0/12",
"192.168.0.0/16",
];
readonly status: 403; readonly status: 403;
readonly message: "Forbidden"; readonly message: "Forbidden";
}]; },
];

View file

@ -1,7 +1,7 @@
export type HomepageConfig = { export type HomepageConfig = {
/** /**
* Use default app categories (uses docker image name) * Use default app categories (uses docker image name)
* @default true * @default true
*/ */
use_default_categories: boolean; use_default_categories: boolean;
}; };

View file

@ -1,60 +1,69 @@
import { URL } from "../types"; import { URL } from "../types";
export declare const NOTIFICATION_PROVIDERS: readonly ["webhook", "gotify", "ntfy"]; export declare const NOTIFICATION_PROVIDERS: readonly [
"webhook",
"gotify",
"ntfy",
];
export type NotificationProvider = (typeof NOTIFICATION_PROVIDERS)[number]; export type NotificationProvider = (typeof NOTIFICATION_PROVIDERS)[number];
export type NotificationConfig = { export type NotificationConfig = {
name: string; name: string;
url: URL; url: URL;
}; };
export interface GotifyConfig extends NotificationConfig { export interface GotifyConfig extends NotificationConfig {
provider: "gotify"; provider: "gotify";
token: string; token: string;
} }
export declare const NTFY_MSG_STYLES: string[]; export declare const NTFY_MSG_STYLES: string[];
export type NtfyStyle = (typeof NTFY_MSG_STYLES)[number]; export type NtfyStyle = (typeof NTFY_MSG_STYLES)[number];
export interface NtfyConfig extends NotificationConfig { export interface NtfyConfig extends NotificationConfig {
provider: "ntfy"; provider: "ntfy";
topic: string; topic: string;
token?: string; token?: string;
style?: NtfyStyle; style?: NtfyStyle;
} }
export declare const WEBHOOK_TEMPLATES: readonly ["", "discord"]; export declare const WEBHOOK_TEMPLATES: readonly ["", "discord"];
export declare const WEBHOOK_METHODS: readonly ["POST", "GET", "PUT"]; export declare const WEBHOOK_METHODS: readonly ["POST", "GET", "PUT"];
export declare const WEBHOOK_MIME_TYPES: readonly ["application/json", "application/x-www-form-urlencoded", "text/plain", "text/markdown"]; export declare const WEBHOOK_MIME_TYPES: readonly [
"application/json",
"application/x-www-form-urlencoded",
"text/plain",
"text/markdown",
];
export declare const WEBHOOK_COLOR_MODES: readonly ["hex", "dec"]; export declare const WEBHOOK_COLOR_MODES: readonly ["hex", "dec"];
export type WebhookTemplate = (typeof WEBHOOK_TEMPLATES)[number]; export type WebhookTemplate = (typeof WEBHOOK_TEMPLATES)[number];
export type WebhookMethod = (typeof WEBHOOK_METHODS)[number]; export type WebhookMethod = (typeof WEBHOOK_METHODS)[number];
export type WebhookMimeType = (typeof WEBHOOK_MIME_TYPES)[number]; export type WebhookMimeType = (typeof WEBHOOK_MIME_TYPES)[number];
export type WebhookColorMode = (typeof WEBHOOK_COLOR_MODES)[number]; export type WebhookColorMode = (typeof WEBHOOK_COLOR_MODES)[number];
export interface WebhookConfig extends NotificationConfig { export interface WebhookConfig extends NotificationConfig {
provider: "webhook"; provider: "webhook";
/** /**
* Webhook template * Webhook template
* *
* @default "discord" * @default "discord"
*/ */
template?: WebhookTemplate; template?: WebhookTemplate;
token?: string; token?: string;
/** /**
* Webhook message (usally JSON), * Webhook message (usally JSON),
* required when template is not defined * required when template is not defined
*/ */
payload?: string; payload?: string;
/** /**
* Webhook method * Webhook method
* *
* @default "POST" * @default "POST"
*/ */
method?: WebhookMethod; method?: WebhookMethod;
/** /**
* Webhook mime type * Webhook mime type
* *
* @default "application/json" * @default "application/json"
*/ */
mime_type?: WebhookMimeType; mime_type?: WebhookMimeType;
/** /**
* Webhook color mode * Webhook color mode
* *
* @default "hex" * @default "hex"
*/ */
color_mode?: WebhookColorMode; color_mode?: WebhookColorMode;
} }

View file

@ -1,51 +1,58 @@
import { URI, URL } from "../types"; import { URI, URL } from "../types";
import { GotifyConfig, NtfyConfig, WebhookConfig } from "./notification"; import { GotifyConfig, NtfyConfig, WebhookConfig } from "./notification";
export type Providers = { export type Providers = {
/** List of route definition files to include /** List of route definition files to include
* *
* @minItems 1 * @minItems 1
* @examples require(".").includeExamples * @examples require(".").includeExamples
* @items.pattern ^[\w\d\-_]+\.(yaml|yml)$ * @items.pattern ^[\w\d\-_]+\.(yaml|yml)$
*/ */
include?: URI[]; include?: URI[];
/** Name-value mapping of docker hosts to retrieve routes from /** Name-value mapping of docker hosts to retrieve routes from
* *
* @minProperties 1 * @minProperties 1
* @examples require(".").dockerExamples * @examples require(".").dockerExamples
*/ */
docker?: { docker?: {
[name: string]: URL | "$DOCKER_HOST"; [name: string]: URL | "$DOCKER_HOST";
}; };
/** List of GoDoxy agents /** List of GoDoxy agents
* *
* @minItems 1 * @minItems 1
* @examples require(".").agentExamples * @examples require(".").agentExamples
*/ */
agents?: `${string}:${number}`[]; agents?: `${string}:${number}`[];
/** List of notification providers /** List of notification providers
* *
* @minItems 1 * @minItems 1
* @examples require(".").notificationExamples * @examples require(".").notificationExamples
*/ */
notification?: (WebhookConfig | GotifyConfig | NtfyConfig)[]; notification?: (WebhookConfig | GotifyConfig | NtfyConfig)[];
}; };
export declare const includeExamples: readonly ["file1.yml", "file2.yml"]; export declare const includeExamples: readonly ["file1.yml", "file2.yml"];
export declare const dockerExamples: readonly [{ export declare const dockerExamples: readonly [
{
readonly local: "$DOCKER_HOST"; readonly local: "$DOCKER_HOST";
}, { },
{
readonly remote: "tcp://10.0.2.1:2375"; readonly remote: "tcp://10.0.2.1:2375";
}, { },
{
readonly remote2: "ssh://root:1234@10.0.2.2"; readonly remote2: "ssh://root:1234@10.0.2.2";
}]; },
export declare const notificationExamples: readonly [{ ];
export declare const notificationExamples: readonly [
{
readonly name: "gotify"; readonly name: "gotify";
readonly provider: "gotify"; readonly provider: "gotify";
readonly url: "https://gotify.domain.tld"; readonly url: "https://gotify.domain.tld";
readonly token: "abcd"; readonly token: "abcd";
}, { },
{
readonly name: "discord"; readonly name: "discord";
readonly provider: "webhook"; readonly provider: "webhook";
readonly template: "discord"; readonly template: "discord";
readonly url: "https://discord.com/api/webhooks/1234/abcd"; readonly url: "https://discord.com/api/webhooks/1234/abcd";
}]; },
];
export declare const agentExamples: readonly ["10.0.2.3:8890", "10.0.2.4:8890"]; export declare const agentExamples: readonly ["10.0.2.3:8890", "10.0.2.4:8890"];

2
schemas/docker.d.ts vendored
View file

@ -1,5 +1,5 @@
import { IdleWatcherConfig } from "./providers/idlewatcher"; import { IdleWatcherConfig } from "./providers/idlewatcher";
import { Route } from "./providers/routes"; import { Route } from "./providers/routes";
export type DockerRoutes = { export type DockerRoutes = {
[key: string]: Route & IdleWatcherConfig; [key: string]: Route & IdleWatcherConfig;
}; };

File diff suppressed because one or more lines are too long

21
schemas/index.d.ts vendored
View file

@ -16,4 +16,23 @@ import ConfigSchema from "./config.schema.json";
import DockerRoutesSchema from "./docker_routes.schema.json"; import DockerRoutesSchema from "./docker_routes.schema.json";
import MiddlewareComposeSchema from "./middleware_compose.schema.json"; import MiddlewareComposeSchema from "./middleware_compose.schema.json";
import RoutesSchema from "./routes.schema.json"; import RoutesSchema from "./routes.schema.json";
export { AccessLog, Autocert, Config, ConfigSchema, DockerRoutesSchema, Entrypoint, GoDoxy, Healthcheck, Homepage, IdleWatcher, LoadBalance, MiddlewareCompose, MiddlewareComposeSchema, Middlewares, Notification, Providers, Routes, RoutesSchema, }; export {
AccessLog,
Autocert,
Config,
ConfigSchema,
DockerRoutesSchema,
Entrypoint,
GoDoxy,
Healthcheck,
Homepage,
IdleWatcher,
LoadBalance,
MiddlewareCompose,
MiddlewareComposeSchema,
Middlewares,
Notification,
Providers,
Routes,
RoutesSchema,
};

View file

@ -1,133 +1,186 @@
import * as types from "../types"; import * as types from "../types";
export type KeyOptMapping<T extends { export type KeyOptMapping<
T extends {
use: string; use: string;
}> = { },
[key in T["use"]]?: Omit<T, "use">; > = {
[key in T["use"]]?: Omit<T, "use">;
}; };
export declare const ALL_MIDDLEWARES: readonly ["ErrorPage", "RedirectHTTP", "SetXForwarded", "HideXForwarded", "CIDRWhitelist", "CloudflareRealIP", "ModifyRequest", "ModifyResponse", "OIDC", "RateLimit", "RealIP"]; export declare const ALL_MIDDLEWARES: readonly [
"ErrorPage",
"RedirectHTTP",
"SetXForwarded",
"HideXForwarded",
"CIDRWhitelist",
"CloudflareRealIP",
"ModifyRequest",
"ModifyResponse",
"OIDC",
"RateLimit",
"RealIP",
];
/** /**
* @type object * @type object
* @patternProperties {"^.*@file$": {"type": "null"}} * @patternProperties {"^.*@file$": {"type": "null"}}
*/ */
export type MiddlewareFileRef = { export type MiddlewareFileRef = {
[key: `${string}@file`]: null; [key: `${string}@file`]: null;
}; };
export type MiddlewaresMap = (KeyOptMapping<CustomErrorPage> & KeyOptMapping<RedirectHTTP> & KeyOptMapping<SetXForwarded> & KeyOptMapping<HideXForwarded> & KeyOptMapping<CIDRWhitelist> & KeyOptMapping<CloudflareRealIP> & KeyOptMapping<ModifyRequest> & KeyOptMapping<ModifyResponse> & KeyOptMapping<OIDC> & KeyOptMapping<RateLimit> & KeyOptMapping<RealIP>) | MiddlewareFileRef; export type MiddlewaresMap =
export type MiddlewareComposeMap = CustomErrorPage | RedirectHTTP | SetXForwarded | HideXForwarded | CIDRWhitelist | CloudflareRealIP | ModifyRequest | ModifyResponse | OIDC | RateLimit | RealIP; | (KeyOptMapping<CustomErrorPage> &
KeyOptMapping<RedirectHTTP> &
KeyOptMapping<SetXForwarded> &
KeyOptMapping<HideXForwarded> &
KeyOptMapping<CIDRWhitelist> &
KeyOptMapping<CloudflareRealIP> &
KeyOptMapping<ModifyRequest> &
KeyOptMapping<ModifyResponse> &
KeyOptMapping<OIDC> &
KeyOptMapping<RateLimit> &
KeyOptMapping<RealIP>)
| MiddlewareFileRef;
export type MiddlewareComposeMap =
| CustomErrorPage
| RedirectHTTP
| SetXForwarded
| HideXForwarded
| CIDRWhitelist
| CloudflareRealIP
| ModifyRequest
| ModifyResponse
| OIDC
| RateLimit
| RealIP;
export type CustomErrorPage = { export type CustomErrorPage = {
use: "error_page" | "errorPage" | "ErrorPage" | "custom_error_page" | "customErrorPage" | "CustomErrorPage"; use:
| "error_page"
| "errorPage"
| "ErrorPage"
| "custom_error_page"
| "customErrorPage"
| "CustomErrorPage";
}; };
export type RedirectHTTP = { export type RedirectHTTP = {
use: "redirect_http" | "redirectHTTP" | "RedirectHTTP"; use: "redirect_http" | "redirectHTTP" | "RedirectHTTP";
/** Bypass redirect */ /** Bypass redirect */
bypass?: { bypass?: {
/** Bypass redirect for user agents */ /** Bypass redirect for user agents */
user_agents?: string[]; user_agents?: string[];
}; };
}; };
export type SetXForwarded = { export type SetXForwarded = {
use: "set_x_forwarded" | "setXForwarded" | "SetXForwarded"; use: "set_x_forwarded" | "setXForwarded" | "SetXForwarded";
}; };
export type HideXForwarded = { export type HideXForwarded = {
use: "hide_x_forwarded" | "hideXForwarded" | "HideXForwarded"; use: "hide_x_forwarded" | "hideXForwarded" | "HideXForwarded";
}; };
export type CIDRWhitelist = { export type CIDRWhitelist = {
use: "cidr_whitelist" | "cidrWhitelist" | "CIDRWhitelist"; use: "cidr_whitelist" | "cidrWhitelist" | "CIDRWhitelist";
allow: types.CIDR[]; allow: types.CIDR[];
/** HTTP status code when blocked /** HTTP status code when blocked
* *
* @default 403 * @default 403
*/ */
status_code?: types.StatusCode; status_code?: types.StatusCode;
/** HTTP status code when blocked (alias of status_code) /** HTTP status code when blocked (alias of status_code)
* *
* @default 403 * @default 403
*/ */
status?: types.StatusCode; status?: types.StatusCode;
/** Error message when blocked /** Error message when blocked
* *
* @default "IP not allowed" * @default "IP not allowed"
*/ */
message?: string; message?: string;
}; };
export type CloudflareRealIP = { export type CloudflareRealIP = {
use: "cloudflare_real_ip" | "cloudflareRealIp" | "CloudflareRealIP"; use: "cloudflare_real_ip" | "cloudflareRealIp" | "CloudflareRealIP";
/** Recursively resolve the IP /** Recursively resolve the IP
* *
* @default false * @default false
*/ */
recursive?: boolean; recursive?: boolean;
}; };
export type ModifyRequest = { export type ModifyRequest = {
use: "request" | "Request" | "modify_request" | "modifyRequest" | "ModifyRequest"; use:
/** Set HTTP headers */ | "request"
set_headers?: { | "Request"
[key: types.HTTPHeader]: string; | "modify_request"
}; | "modifyRequest"
/** Add HTTP headers */ | "ModifyRequest";
add_headers?: { /** Set HTTP headers */
[key: types.HTTPHeader]: string; set_headers?: {
}; [key: types.HTTPHeader]: string;
/** Hide HTTP headers */ };
hide_headers?: types.HTTPHeader[]; /** Add HTTP headers */
/** Add prefix to request URL */ add_headers?: {
add_prefix?: string; [key: types.HTTPHeader]: string;
};
/** Hide HTTP headers */
hide_headers?: types.HTTPHeader[];
/** Add prefix to request URL */
add_prefix?: string;
}; };
export type ModifyResponse = { export type ModifyResponse = {
use: "response" | "Response" | "modify_response" | "modifyResponse" | "ModifyResponse"; use:
/** Set HTTP headers */ | "response"
set_headers?: { | "Response"
[key: types.HTTPHeader]: string; | "modify_response"
}; | "modifyResponse"
/** Add HTTP headers */ | "ModifyResponse";
add_headers?: { /** Set HTTP headers */
[key: types.HTTPHeader]: string; set_headers?: {
}; [key: types.HTTPHeader]: string;
/** Hide HTTP headers */ };
hide_headers?: types.HTTPHeader[]; /** Add HTTP headers */
add_headers?: {
[key: types.HTTPHeader]: string;
};
/** Hide HTTP headers */
hide_headers?: types.HTTPHeader[];
}; };
export type OIDC = { export type OIDC = {
use: "oidc" | "OIDC"; use: "oidc" | "OIDC";
/** Allowed users /** Allowed users
* *
* @minItems 1 * @minItems 1
*/ */
allowed_users?: string[]; allowed_users?: string[];
/** Allowed groups /** Allowed groups
* *
* @minItems 1 * @minItems 1
*/ */
allowed_groups?: string[]; allowed_groups?: string[];
}; };
export type RateLimit = { export type RateLimit = {
use: "rate_limit" | "rateLimit" | "RateLimit"; use: "rate_limit" | "rateLimit" | "RateLimit";
/** Average number of requests allowed in a period /** Average number of requests allowed in a period
* *
* @min 1 * @min 1
*/ */
average: number; average: number;
/** Maximum number of requests allowed in a period /** Maximum number of requests allowed in a period
* *
* @min 1 * @min 1
*/ */
burst: number; burst: number;
/** Duration of the rate limit /** Duration of the rate limit
* *
* @default 1s * @default 1s
*/ */
period?: types.Duration; period?: types.Duration;
}; };
export type RealIP = { export type RealIP = {
use: "real_ip" | "realIP" | "RealIP"; use: "real_ip" | "realIP" | "RealIP";
/** Header to get the client IP from /** Header to get the client IP from
* *
* @default "X-Real-IP" * @default "X-Real-IP"
*/ */
header?: types.HTTPHeader; header?: types.HTTPHeader;
from: types.CIDR[]; from: types.CIDR[];
/** Recursive resolve the IP /** Recursive resolve the IP
* *
* @default false * @default false
*/ */
recursive?: boolean; recursive?: boolean;
}; };

View file

@ -1,6 +1,6 @@
{ {
"name": "godoxy-schemas", "name": "godoxy-schemas",
"version": "0.10.0-3", "version": "0.10.1-6",
"description": "JSON Schema and typescript types for GoDoxy configuration", "description": "JSON Schema and typescript types for GoDoxy configuration",
"license": "MIT", "license": "MIT",
"repository": { "repository": {
@ -8,9 +8,11 @@
"url": "https://github.com/yusing/godoxy" "url": "https://github.com/yusing/godoxy"
}, },
"files": [ "files": [
"schemas/", "**/*.ts",
"README.md", "**/*.js",
"LICENSE" "*.schema.json",
"../README.md",
"../LICENSE"
], ],
"type": "module", "type": "module",
"main": "./index.ts", "main": "./index.ts",
@ -22,15 +24,14 @@
} }
}, },
"devDependencies": { "devDependencies": {
"prettier": "^3.4.2", "prettier": "^3.5.3",
"typescript": "^5.7.3", "typescript": "^5.8.3",
"typescript-json-schema": "^0.65.1" "typescript-json-schema": "^0.65.1"
}, },
"displayName": "GoDoxy Types", "displayName": "GoDoxy Types",
"packageManager": "bun@1.2.0", "packageManager": "bun@1.2.9",
"publisher": "yusing", "publisher": "yusing",
"scripts": { "scripts": {
"gen-schema": "make gen-schema", "format:write": "prettier --write \"**/*.ts\" --cache"
"format:write": "prettier --write \"schemas/**/*.ts\" --cache"
} }
} }

View file

@ -3,30 +3,30 @@ import { Duration, URI } from "../types";
* @additionalProperties false * @additionalProperties false
*/ */
export type HealthcheckConfig = { export type HealthcheckConfig = {
/** Disable healthcheck /** Disable healthcheck
* *
* @default false * @default false
*/ */
disable?: boolean; disable?: boolean;
/** Healthcheck path /** Healthcheck path
* *
* @default / * @default /
*/ */
path?: URI; path?: URI;
/** /**
* Use GET instead of HEAD * Use GET instead of HEAD
* *
* @default false * @default false
*/ */
use_get?: boolean; use_get?: boolean;
/** Healthcheck interval /** Healthcheck interval
* *
* @default 5s * @default 5s
*/ */
interval?: Duration; interval?: Duration;
/** Healthcheck timeout /** Healthcheck timeout
* *
* @default 5s * @default 5s
*/ */
timeout?: Duration; timeout?: Duration;
}; };

View file

@ -3,19 +3,19 @@ import { URL } from "../types";
* @additionalProperties false * @additionalProperties false
*/ */
export type HomepageConfig = { export type HomepageConfig = {
/** Whether show in dashboard /** Whether show in dashboard
* *
* @default true * @default true
*/ */
show?: boolean; show?: boolean;
name?: string; name?: string;
icon?: URL | WalkxcodeIcon | ExternalIcon | TargetRelativeIconPath; icon?: URL | WalkxcodeIcon | ExternalIcon | TargetRelativeIconPath;
description?: string; description?: string;
url?: URL; url?: URL;
category?: string; category?: string;
widget_config?: { widget_config?: {
[key: string]: any; [key: string]: any;
}; };
}; };
/** Walkxcode icon /** Walkxcode icon
* *

View file

@ -1,25 +1,35 @@
import { Duration, URI } from "../types"; import { Duration, URI } from "../types";
export declare const STOP_METHODS: readonly ["pause", "stop", "kill"]; export declare const STOP_METHODS: readonly ["pause", "stop", "kill"];
export type StopMethod = (typeof STOP_METHODS)[number]; export type StopMethod = (typeof STOP_METHODS)[number];
export declare const STOP_SIGNALS: readonly ["", "SIGINT", "SIGTERM", "SIGHUP", "SIGQUIT", "INT", "TERM", "HUP", "QUIT"]; export declare const STOP_SIGNALS: readonly [
"",
"SIGINT",
"SIGTERM",
"SIGHUP",
"SIGQUIT",
"INT",
"TERM",
"HUP",
"QUIT",
];
export type Signal = (typeof STOP_SIGNALS)[number]; export type Signal = (typeof STOP_SIGNALS)[number];
export type IdleWatcherConfig = { export type IdleWatcherConfig = {
idle_timeout?: Duration; idle_timeout?: Duration;
/** Wake timeout /** Wake timeout
* *
* @default 30s * @default 30s
*/ */
wake_timeout?: Duration; wake_timeout?: Duration;
/** Stop timeout /** Stop timeout
* *
* @default 30s * @default 30s
*/ */
stop_timeout?: Duration; stop_timeout?: Duration;
/** Stop method /** Stop method
* *
* @default stop * @default stop
*/ */
stop_method?: StopMethod; stop_method?: StopMethod;
stop_signal?: Signal; stop_signal?: Signal;
start_endpoint?: URI; start_endpoint?: URI;
}; };

View file

@ -1,28 +1,38 @@
import { RealIP } from "../middlewares/middlewares"; import { RealIP } from "../middlewares/middlewares";
export declare const LOAD_BALANCE_MODES: readonly ["round_robin", "least_conn", "ip_hash"]; export declare const LOAD_BALANCE_MODES: readonly [
"round_robin",
"least_conn",
"ip_hash",
];
export type LoadBalanceMode = (typeof LOAD_BALANCE_MODES)[number]; export type LoadBalanceMode = (typeof LOAD_BALANCE_MODES)[number];
export type LoadBalanceConfigBase = { export type LoadBalanceConfigBase = {
/** Alias (subdomain or FDN) of load-balancer /** Alias (subdomain or FDN) of load-balancer
* *
* @minLength 1 * @minLength 1
*/ */
link: string; link: string;
/** Load-balance weight (reserved for future use) /** Load-balance weight (reserved for future use)
* *
* @minimum 0 * @minimum 0
* @maximum 100 * @maximum 100
*/ */
weight?: number; weight?: number;
}; };
export type LoadBalanceConfig = LoadBalanceConfigBase & ({} | RoundRobinLoadBalanceConfig | LeastConnLoadBalanceConfig | IPHashLoadBalanceConfig); export type LoadBalanceConfig = LoadBalanceConfigBase &
(
| {}
| RoundRobinLoadBalanceConfig
| LeastConnLoadBalanceConfig
| IPHashLoadBalanceConfig
);
export type IPHashLoadBalanceConfig = { export type IPHashLoadBalanceConfig = {
mode: "ip_hash"; mode: "ip_hash";
/** Real IP config, header to get client IP from */ /** Real IP config, header to get client IP from */
config: RealIP; config: RealIP;
}; };
export type LeastConnLoadBalanceConfig = { export type LeastConnLoadBalanceConfig = {
mode: "least_conn"; mode: "least_conn";
}; };
export type RoundRobinLoadBalanceConfig = { export type RoundRobinLoadBalanceConfig = {
mode: "round_robin"; mode: "round_robin";
}; };

View file

@ -1,7 +1,15 @@
import { AccessLogConfig } from "../config/access_log"; import { AccessLogConfig } from "../config/access_log";
import { accessLogExamples } from "../config/entrypoint"; import { accessLogExamples } from "../config/entrypoint";
import { MiddlewaresMap } from "../middlewares/middlewares"; import { MiddlewaresMap } from "../middlewares/middlewares";
import { Duration, Hostname, IPv4, IPv6, PathPattern, Port, StreamPort } from "../types"; import {
Duration,
Hostname,
IPv4,
IPv6,
PathPattern,
Port,
StreamPort,
} from "../types";
import { HealthcheckConfig } from "./healthcheck"; import { HealthcheckConfig } from "./healthcheck";
import { HomepageConfig } from "./homepage"; import { HomepageConfig } from "./homepage";
import { LoadBalanceConfig } from "./loadbalance"; import { LoadBalanceConfig } from "./loadbalance";
@ -11,122 +19,130 @@ export type ProxyScheme = (typeof PROXY_SCHEMES)[number];
export type StreamScheme = (typeof STREAM_SCHEMES)[number]; export type StreamScheme = (typeof STREAM_SCHEMES)[number];
export type Route = ReverseProxyRoute | FileServerRoute | StreamRoute; export type Route = ReverseProxyRoute | FileServerRoute | StreamRoute;
export type Routes = { export type Routes = {
[key: string]: Route; [key: string]: Route;
}; };
export type ReverseProxyRoute = { export type ReverseProxyRoute = {
/** Alias (subdomain or FDN) /** Alias (subdomain or FDN)
* @minLength 1 * @minLength 1
*/ */
alias?: string; alias?: string;
/** Proxy scheme /** Proxy scheme
* *
* @default http * @default http
*/ */
scheme?: ProxyScheme; scheme?: ProxyScheme;
/** Proxy host /** Proxy host
* *
* @default localhost * @default localhost
*/ */
host?: Hostname | IPv4 | IPv6; host?: Hostname | IPv4 | IPv6;
/** Proxy port /** Proxy port
* *
* @default 80 * @default 80
*/ */
port?: Port; port?: Port;
/** Skip TLS verification /** Skip TLS verification
* *
* @default false * @default false
*/ */
no_tls_verify?: boolean; no_tls_verify?: boolean;
/** Response header timeout /** Response header timeout
* *
* @default 60s * @default 60s
*/ */
response_header_timeout?: Duration; response_header_timeout?: Duration;
/** Path patterns (only patterns that match will be proxied). /** Path patterns (only patterns that match will be proxied).
* *
* See https://pkg.go.dev/net/http#hdr-Patterns-ServeMux * See https://pkg.go.dev/net/http#hdr-Patterns-ServeMux
*/ */
path_patterns?: PathPattern[]; path_patterns?: PathPattern[];
/** Healthcheck config */ /** Healthcheck config */
healthcheck?: HealthcheckConfig; healthcheck?: HealthcheckConfig;
/** Load balance config */ /** Load balance config */
load_balance?: LoadBalanceConfig; load_balance?: LoadBalanceConfig;
/** Middlewares */ /** Middlewares */
middlewares?: MiddlewaresMap; middlewares?: MiddlewaresMap;
/** Homepage config /** Homepage config
* *
* @examples require(".").homepageExamples * @examples require(".").homepageExamples
*/ */
homepage?: HomepageConfig; homepage?: HomepageConfig;
/** Access log config /** Access log config
* *
* @examples require(".").accessLogExamples * @examples require(".").accessLogExamples
*/ */
access_log?: AccessLogConfig; access_log?: AccessLogConfig;
}; };
export type FileServerRoute = { export type FileServerRoute = {
/** Alias (subdomain or FDN) /** Alias (subdomain or FDN)
* @minLength 1 * @minLength 1
*/ */
alias?: string; alias?: string;
scheme: "fileserver"; scheme: "fileserver";
root: string; root: string;
/** Path patterns (only patterns that match will be proxied). /** Path patterns (only patterns that match will be proxied).
* *
* See https://pkg.go.dev/net/http#hdr-Patterns-ServeMux * See https://pkg.go.dev/net/http#hdr-Patterns-ServeMux
*/ */
path_patterns?: PathPattern[]; path_patterns?: PathPattern[];
/** Middlewares */ /** Middlewares */
middlewares?: MiddlewaresMap; middlewares?: MiddlewaresMap;
/** Homepage config /** Homepage config
* *
* @examples require(".").homepageExamples * @examples require(".").homepageExamples
*/ */
homepage?: HomepageConfig; homepage?: HomepageConfig;
/** Access log config /** Access log config
* *
* @examples require(".").accessLogExamples * @examples require(".").accessLogExamples
*/ */
access_log?: AccessLogConfig; access_log?: AccessLogConfig;
/** Healthcheck config */
healthcheck?: HealthcheckConfig;
}; };
export type StreamRoute = { export type StreamRoute = {
/** Alias (subdomain or FDN) /** Alias (subdomain or FDN)
* @minLength 1 * @minLength 1
*/ */
alias?: string; alias?: string;
/** Stream scheme /** Stream scheme
* *
* @default tcp * @default tcp
*/ */
scheme?: StreamScheme; scheme?: StreamScheme;
/** Stream host /** Stream host
* *
* @default localhost * @default localhost
*/ */
host?: Hostname | IPv4 | IPv6; host?: Hostname | IPv4 | IPv6;
port: StreamPort; port: StreamPort;
/** Healthcheck config */ /** Healthcheck config */
healthcheck?: HealthcheckConfig; healthcheck?: HealthcheckConfig;
}; };
export declare const homepageExamples: ({ export declare const homepageExamples: (
name: string; | {
icon: string; name: string;
category: string; icon: string;
} | { category: string;
name: string; }
icon: string; | {
category?: undefined; name: string;
})[]; icon: string;
export declare const loadBalanceExamples: ({ category?: undefined;
link: string; }
mode: string; )[];
config?: undefined; export declare const loadBalanceExamples: (
} | { | {
link: string; link: string;
mode: string; mode: string;
config: { config?: undefined;
}
| {
link: string;
mode: string;
config: {
header: string; header: string;
}; };
})[]; }
)[];
export { accessLogExamples }; export { accessLogExamples };

View file

@ -1,7 +1,15 @@
import { AccessLogConfig } from "../config/access_log"; import { AccessLogConfig } from "../config/access_log";
import { accessLogExamples } from "../config/entrypoint"; import { accessLogExamples } from "../config/entrypoint";
import { MiddlewaresMap } from "../middlewares/middlewares"; import { MiddlewaresMap } from "../middlewares/middlewares";
import { Duration, Hostname, IPv4, IPv6, PathPattern, Port, StreamPort } from "../types"; import {
Duration,
Hostname,
IPv4,
IPv6,
PathPattern,
Port,
StreamPort,
} from "../types";
import { HealthcheckConfig } from "./healthcheck"; import { HealthcheckConfig } from "./healthcheck";
import { HomepageConfig } from "./homepage"; import { HomepageConfig } from "./homepage";
import { LoadBalanceConfig } from "./loadbalance"; import { LoadBalanceConfig } from "./loadbalance";
@ -94,7 +102,9 @@ export type FileServerRoute = {
* @examples require(".").accessLogExamples * @examples require(".").accessLogExamples
*/ */
access_log?: AccessLogConfig; access_log?: AccessLogConfig;
} /** Healthcheck config */
healthcheck?: HealthcheckConfig;
};
export type StreamRoute = { export type StreamRoute = {
/** Alias (subdomain or FDN) /** Alias (subdomain or FDN)

File diff suppressed because one or more lines are too long

View file

@ -5,12 +5,14 @@
"target": "ESNext", "target": "ESNext",
"module": "ESNext", "module": "ESNext",
"moduleResolution": "Node", "moduleResolution": "Node",
"strict": true, "strict": false,
"esModuleInterop": true, "esModuleInterop": false,
"forceConsistentCasingInFileNames": true, "forceConsistentCasingInFileNames": true,
"allowJs": true, "allowJs": false,
"resolveJsonModule": true, "resolveJsonModule": true,
"declaration": true "declaration": true,
"allowSyntheticDefaultImports": true
}, },
"include": ["."] "include": ["**/*.ts"],
"exclude": ["node_modules"]
} }

20
schemas/types.d.ts vendored
View file

@ -4,7 +4,17 @@
export type Null = null; export type Null = null;
export type Nullable<T> = T | Null; export type Nullable<T> = T | Null;
export type NullOrEmptyMap = {} | Null; export type NullOrEmptyMap = {} | Null;
export declare const HTTP_METHODS: readonly ["GET", "POST", "PUT", "PATCH", "DELETE", "CONNECT", "HEAD", "OPTIONS", "TRACE"]; export declare const HTTP_METHODS: readonly [
"GET",
"POST",
"PUT",
"PATCH",
"DELETE",
"CONNECT",
"HEAD",
"OPTIONS",
"TRACE",
];
export type HTTPMethod = (typeof HTTP_METHODS)[number]; export type HTTPMethod = (typeof HTTP_METHODS)[number];
/** /**
* HTTP Header * HTTP Header
@ -49,7 +59,13 @@ export type IPv4 = string & {};
* @type string * @type string
*/ */
export type IPv6 = string & {}; export type IPv6 = string & {};
export type CIDR = `${number}.${number}.${number}.${number}` | `${string}:${string}:${string}:${string}:${string}:${string}:${string}:${string}` | `${number}.${number}.${number}.${number}/${number}` | `::${number}` | `${string}::/${number}` | `${string}:${string}::/${number}`; export type CIDR =
| `${number}.${number}.${number}.${number}`
| `${string}:${string}:${string}:${string}:${string}:${string}:${string}:${string}`
| `${number}.${number}.${number}.${number}/${number}`
| `::${number}`
| `${string}::/${number}`
| `${string}:${string}::/${number}`;
/** /**
* @type integer * @type integer
* @minimum 0 * @minimum 0