Rename to 'ngx'

main
Charlotte Som 2023-11-16 04:28:37 +00:00
parent 9200d10ad8
commit 1b718dae86
2 changed files with 129 additions and 13 deletions

129
ngx.ts Normal file
View File

@ -0,0 +1,129 @@
// #region Implementation
type ConfigNode = ConfigStatement | ConfigBlock | ConfigBreak | ConfigFile;
class ConfigBuildable {
build(): string {
throw new Error("build(..) not implemented!");
}
write(path: string) {
const contents = this.build();
Deno.writeTextFileSync(path, contents);
}
}
class ConfigBlock extends ConfigBuildable {
value: string;
children: ConfigNode[];
constructor(value: string, children: ConfigNode[]) {
super();
this.value = value;
this.children = children;
}
build(): string {
let output = this.value;
output += " {\n ";
output += this.children
.map((child) => child.build().split("\n").join("\n "))
.join("\n ");
output += "\n}";
return output;
}
}
class ConfigStatement extends ConfigBuildable {
value: string;
constructor(value: string) {
super();
this.value = value;
}
build(): string {
return this.value + ";";
}
}
class ConfigBreak extends ConfigBuildable {
build(): string {
return "";
}
}
class ConfigFile extends ConfigBuildable {
nodes: ConfigNode[];
constructor(nodes: ConfigNode[]) {
super();
this.nodes = nodes;
}
build(): string {
return this.nodes.map((n) => n.build()).join("\n");
}
}
type LooseConfigNode = ConfigNode | string | LooseConfigNode[];
function conform(looseNode: LooseConfigNode): ConfigNode[] {
if (typeof looseNode === "string") {
return [new ConfigStatement(looseNode)];
}
if (typeof looseNode === "object" && looseNode instanceof Array) {
if (looseNode.length === 0) {
return [new ConfigBreak()];
} else if (looseNode.length === 1) {
return conform(looseNode[0]);
} else {
return looseNode
.map((n) => conform(n))
.reduceRight((b, a) =>
a.length === 1 ? [...a, ...b] : [...a, new ConfigBreak(), ...b]
);
}
}
return [looseNode];
}
// #endregion
export function ngx(value?: string, children?: LooseConfigNode[]): ConfigNode {
const hasValue = value !== undefined && value !== "";
const hasChildren = children !== undefined;
if (!hasValue && !hasChildren) {
return new ConfigBreak();
} else if (hasValue && !hasChildren) {
return new ConfigStatement(value);
} else if (hasValue && hasChildren) {
return new ConfigBlock(value, conform(children));
} else if (!hasValue && hasChildren) {
return new ConfigFile(conform(children));
}
throw new Error("unreachable");
}
export const br = new ConfigBreak();
export const listen = (...extras: string[]) =>
conform([
`listen 443 ${["ssl", "http2", ...extras].join(" ")}`,
`listen [::]:443 ${["ssl", "http2", ...extras].join(" ")}`,
]);
export const letsEncrypt = (
domain: string,
liveDir = "/etc/letsencrypt/live"
) =>
conform([
`ssl_certificate ${liveDir}/${domain}/fullchain.pem`,
`ssl_certificate_key ${liveDir}/${domain}/privkey.pem`,
]);
export default Object.assign(
(value?: string, children?: LooseConfigNode[]) => ngx(value, children),
{ br, listen, letsEncrypt }
);

13
test.ts
View File

@ -1,13 +0,0 @@
import { letsEncrypt, listenv4v6, br, ng } from "./ngineer.ts";
const conf = ng("server", [
...listenv4v6(),
br,
"server_name mydomain.com",
br,
...letsEncrypt("mydomain.com"),
br,
ng("location /", ["root /srv/http/mydomain.com"]),
]);
console.log(conf.build());