This commit is contained in:
commit
37047cee22
9 changed files with 489 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
dist
|
||||||
|
node_modules
|
||||||
|
config.juml
|
1
.npmignore
Normal file
1
.npmignore
Normal file
|
@ -0,0 +1 @@
|
||||||
|
config.juml
|
23
.woodpecker.yml
Normal file
23
.woodpecker.yml
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
# .woodpecker.yml
|
||||||
|
platform: linux/arm64
|
||||||
|
|
||||||
|
pipeline:
|
||||||
|
build:
|
||||||
|
image: node:18-alpine
|
||||||
|
commands:
|
||||||
|
- apk add git zip tar
|
||||||
|
- npm install
|
||||||
|
- npm install git+https://jusax.de/git/jusax23/gitea-release.git
|
||||||
|
- mkdir build
|
||||||
|
- mkdir juml
|
||||||
|
- mkdir juml/dist
|
||||||
|
- mkdir upload
|
||||||
|
- npm run prepublish
|
||||||
|
- cp dist/* juml/dist
|
||||||
|
- cp package.json juml
|
||||||
|
- cp package-lock.json juml
|
||||||
|
- cp readme.md juml
|
||||||
|
- zip -r upload/juml.zip juml/*
|
||||||
|
- tar -czvf upload/juml.tar.gz juml/*
|
||||||
|
- npx gitea-release "https://jusax.de/git/api/v1/" "$${GITEA_TOKEN}" "$${CI_REPO}" "$${CI_COMMIT_BRANCH}" "$${CI_COMMIT_TAG}" "upload" "$${CI_COMMIT_MESSAGE}"
|
||||||
|
secrets: [ gitea_token ]
|
33
example.js
Normal file
33
example.js
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
import juml from "./dist/juml.js";
|
||||||
|
|
||||||
|
const conf_struct = {
|
||||||
|
System:{
|
||||||
|
PORT:{type:"number",default:80},
|
||||||
|
URL:{type:"string",default:"https://google.de/",comment:"The exposed URL:"}
|
||||||
|
},
|
||||||
|
ssl:{
|
||||||
|
enable:{type:"boolean",default:true,env:"FMI_SSL_ENABELED"},
|
||||||
|
privkey:{type:"string",default:"privkey.pem"},
|
||||||
|
cert:{type:"string",default:"cert.pem"},
|
||||||
|
chain:{type:"string",default:"chain.pem"}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
console.log()
|
||||||
|
|
||||||
|
const mc = new juml(conf_struct);
|
||||||
|
|
||||||
|
mc.connect("./config.juml");
|
||||||
|
|
||||||
|
if(mc.get("ssl","enable")){
|
||||||
|
console.log("SSL Enabled");
|
||||||
|
mc.readPathes(mc.get("ssl","privkey"),mc.get("ssl","cert"),mc.get("ssl","chain"))
|
||||||
|
.then(([privkey,cert,chain])=>{
|
||||||
|
console.log("privkey: ",privkey,"\ncert: ",cert,"\nchain: ",chain);
|
||||||
|
}).catch(err=>{
|
||||||
|
console.error(err);
|
||||||
|
process.exit();
|
||||||
|
});
|
||||||
|
}else{
|
||||||
|
console.log("SSL Disabled");
|
||||||
|
}
|
126
package-lock.json
generated
Normal file
126
package-lock.json
generated
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
{
|
||||||
|
"name": "juml",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"lockfileVersion": 3,
|
||||||
|
"requires": true,
|
||||||
|
"packages": {
|
||||||
|
"": {
|
||||||
|
"name": "juml",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"license": "UNLICENSED",
|
||||||
|
"dependencies": {
|
||||||
|
"node-fetch": "^3.3.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^18.11.18",
|
||||||
|
"typescript": "^4.9.4"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@types/node": {
|
||||||
|
"version": "18.14.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.14.1.tgz",
|
||||||
|
"integrity": "sha512-QH+37Qds3E0eDlReeboBxfHbX9omAcBCXEzswCu6jySP642jiM3cYSIkU/REqwhCUqXdonHFuBfJDiAJxMNhaQ==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"node_modules/data-uri-to-buffer": {
|
||||||
|
"version": "4.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
|
||||||
|
"integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 12"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/fetch-blob": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/jimmywarting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "paypal",
|
||||||
|
"url": "https://paypal.me/jimmywarting"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"node-domexception": "^1.0.0",
|
||||||
|
"web-streams-polyfill": "^3.0.3"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.20 || >= 14.13"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/formdata-polyfill": {
|
||||||
|
"version": "4.0.10",
|
||||||
|
"resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
|
||||||
|
"integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
|
||||||
|
"dependencies": {
|
||||||
|
"fetch-blob": "^3.1.2"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.20.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/node-domexception": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
|
||||||
|
"funding": [
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/jimmywarting"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://paypal.me/jimmywarting"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.5.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/node-fetch": {
|
||||||
|
"version": "3.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.0.tgz",
|
||||||
|
"integrity": "sha512-BKwRP/O0UvoMKp7GNdwPlObhYGB5DQqwhEDQlNKuoqwVYSxkSZCSbHjnFFmUEtwSKRPU4kNK8PbDYYitwaE3QA==",
|
||||||
|
"dependencies": {
|
||||||
|
"data-uri-to-buffer": "^4.0.0",
|
||||||
|
"fetch-blob": "^3.1.4",
|
||||||
|
"formdata-polyfill": "^4.0.10"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": "^12.20.0 || ^14.13.1 || >=16.0.0"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "opencollective",
|
||||||
|
"url": "https://opencollective.com/node-fetch"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/typescript": {
|
||||||
|
"version": "4.9.5",
|
||||||
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
|
||||||
|
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
|
||||||
|
"dev": true,
|
||||||
|
"bin": {
|
||||||
|
"tsc": "bin/tsc",
|
||||||
|
"tsserver": "bin/tsserver"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/web-streams-polyfill": {
|
||||||
|
"version": "3.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.2.1.tgz",
|
||||||
|
"integrity": "sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 8"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
30
package.json
Normal file
30
package.json
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
{
|
||||||
|
"name": "juml",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "dist/juml.js",
|
||||||
|
"types": "dist/juml.d.ts",
|
||||||
|
"type": "module",
|
||||||
|
"directories": {
|
||||||
|
"dist": "dist"
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"dist/*"
|
||||||
|
],
|
||||||
|
"private": false,
|
||||||
|
"scripts": {
|
||||||
|
"prepublish": "tsc"
|
||||||
|
},
|
||||||
|
"author": "jusax23",
|
||||||
|
"license": "UNLICENSED",
|
||||||
|
"dependencies": {
|
||||||
|
"node-fetch": "^3.3.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 16"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"@types/node": "^18.11.18",
|
||||||
|
"typescript": "^4.9.4"
|
||||||
|
}
|
||||||
|
}
|
6
readme.md
Normal file
6
readme.md
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
# nMan
|
||||||
|
|
||||||
|
A simple way of shutting down a Server.
|
||||||
|
|
||||||
|
## Example
|
||||||
|
See example.mjs
|
247
src/juml.ts
Normal file
247
src/juml.ts
Normal file
|
@ -0,0 +1,247 @@
|
||||||
|
import fs from "fs";
|
||||||
|
import fetch from 'node-fetch';
|
||||||
|
import path from "path";
|
||||||
|
|
||||||
|
export default class juml {
|
||||||
|
#groups: { [key: string]: Group } = {};
|
||||||
|
#pathfile: string | null = null;
|
||||||
|
|
||||||
|
constructor(struct: { [x: string]: { [x: string]: any; }; }) {
|
||||||
|
for (let g in struct) {
|
||||||
|
this.#groups[g] = new Group(struct[g]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
connect(file: string, dir = process.cwd()) {
|
||||||
|
var exists = true;
|
||||||
|
this.#pathfile = jpath(dir, file);
|
||||||
|
if (!fs.existsSync(this.#pathfile) || !fs.lstatSync(this.#pathfile).isFile()) {
|
||||||
|
console.warn("Config does't exists. It will be created: " + this.#pathfile);
|
||||||
|
exists = false;
|
||||||
|
} else {
|
||||||
|
this.fromJUML(fs.readFileSync(this.#pathfile).toString());
|
||||||
|
}
|
||||||
|
this.save();
|
||||||
|
return exists;
|
||||||
|
}
|
||||||
|
|
||||||
|
get(group: string, name: string, empty: any = null) {
|
||||||
|
if ((this.#groups[group] ?? {})[name] == null) {
|
||||||
|
return empty;
|
||||||
|
}
|
||||||
|
return this.#groups[group][name].valueOf();
|
||||||
|
}
|
||||||
|
set(group: string, name: string, value: any) {
|
||||||
|
if ((this.#groups[group] ?? {})[name] == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
this.#groups[group][name].set(value);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
save() {
|
||||||
|
if (this.#pathfile != null) fs.writeFileSync(this.#pathfile, this.toJUML());
|
||||||
|
}
|
||||||
|
|
||||||
|
fromJUML(juml: string) {
|
||||||
|
var comment: string[] = [];
|
||||||
|
let nowGroup: Group | null = null;
|
||||||
|
|
||||||
|
juml.split("\n").map(s => s.trim()).forEach(now => {
|
||||||
|
if (now.startsWith("#")) {
|
||||||
|
comment.push(now.slice(1));
|
||||||
|
} else if (now.startsWith("[") && now.endsWith("]")) {
|
||||||
|
let groupName = now.slice(1, -1);
|
||||||
|
nowGroup = this.#groups[groupName] || null;
|
||||||
|
nowGroup.setComment(comment.join("\n"));
|
||||||
|
comment = [];
|
||||||
|
} else if (now.includes("=") && nowGroup != null) {
|
||||||
|
let nows = now.split("=");
|
||||||
|
let name = nows.splice(0, 1)[0].trim();
|
||||||
|
let data = nows.join("=").trim();
|
||||||
|
if (nowGroup[name] != null) {
|
||||||
|
nowGroup[name].set = data;
|
||||||
|
nowGroup[name].comment = comment.join("\n");
|
||||||
|
comment = [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
toJUML() {
|
||||||
|
let json = this.#groups;
|
||||||
|
var out = "";
|
||||||
|
for (let group in json) {
|
||||||
|
if (json[group].comment() != "") {
|
||||||
|
out += "\n";
|
||||||
|
out += json[group].comment().split("\n").map(d => "#" + d).join("\n");
|
||||||
|
}
|
||||||
|
out += `\n[${group}]\n`;
|
||||||
|
for (let name in json[group]) {
|
||||||
|
if (json[group][name].comment != "") {
|
||||||
|
out += json[group][name].comment.split("\n").map((d: string) => "#" + d).join("\n");
|
||||||
|
out += "\n";
|
||||||
|
}
|
||||||
|
out += name + "=" + json[group][name] + "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
readPath(path: string, dir = process.cwd()) {
|
||||||
|
return new Promise((res, rej) => {
|
||||||
|
if (path.startsWith("http")) {
|
||||||
|
fetch(path)
|
||||||
|
.then(d => d.text())
|
||||||
|
.then(d => res(d))
|
||||||
|
.catch(() => {
|
||||||
|
rej("Error occurred while fetching: " + path)
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
const pathf = jpath(dir, path);
|
||||||
|
if (!fs.existsSync(pathf) || !fs.statSync(pathf).isFile()) {
|
||||||
|
rej("Coud not find File: " + pathf);
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
var content = fs.readFileSync(pathf).toString();
|
||||||
|
res(content);
|
||||||
|
} catch (e) {
|
||||||
|
rej("Error occurred while reading: " + pathf);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
readPathes(...pathes: string[]) {
|
||||||
|
return new Promise(async (res, rej) => {
|
||||||
|
var out = [];
|
||||||
|
for (var i = 0; i < pathes.length; i++) {
|
||||||
|
try {
|
||||||
|
out[i] = await this.readPath(pathes[i]);
|
||||||
|
} catch (e) {
|
||||||
|
rej(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
res(out);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
class Group extends Object {
|
||||||
|
#comment = "";
|
||||||
|
[key: string]: Field | any;
|
||||||
|
constructor(struct: { [x: string]: any; }) {
|
||||||
|
super({});
|
||||||
|
for (let e in struct) {
|
||||||
|
let elem = struct[e];
|
||||||
|
switch (elem.type || "string") {
|
||||||
|
case "number": {
|
||||||
|
this[e] = new NField(elem.default ?? 0, elem.comment ?? "", elem.env ?? "");
|
||||||
|
} break;
|
||||||
|
case "boolean": {
|
||||||
|
this[e] = new BField(elem.default ?? false, elem.comment ?? "", elem.env ?? "");
|
||||||
|
} break;
|
||||||
|
case "string": {
|
||||||
|
this[e] = new SField(elem.default ?? "", elem.comment ?? "", elem.env ?? "");
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
comment() {
|
||||||
|
return this.#comment
|
||||||
|
}
|
||||||
|
setComment(c: string) {
|
||||||
|
this.#comment = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class Field {
|
||||||
|
command = "";
|
||||||
|
valueOf() { }
|
||||||
|
set set(v: any) { }
|
||||||
|
}
|
||||||
|
|
||||||
|
class NField extends Field {
|
||||||
|
comment = "";
|
||||||
|
#value = 0;
|
||||||
|
|
||||||
|
constructor(v: any, comment: string, env: string) {
|
||||||
|
super();
|
||||||
|
if (env != "" && process.env[env]) {
|
||||||
|
this.#value = Number(createType(process.env[env]));
|
||||||
|
} else {
|
||||||
|
this.#value = Number(createType(v));
|
||||||
|
}
|
||||||
|
this.comment = comment;
|
||||||
|
}
|
||||||
|
set set(v: number) {
|
||||||
|
this.#value = Number(createType(v));
|
||||||
|
}
|
||||||
|
valueOf() {
|
||||||
|
return this.#value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class BField extends Field {
|
||||||
|
comment = "";
|
||||||
|
#value = false;
|
||||||
|
|
||||||
|
constructor(v: any, comment: string, env: string) {
|
||||||
|
super();
|
||||||
|
if (env != "" && process.env[env]) {
|
||||||
|
this.#value = Boolean(createType(process.env[env]));
|
||||||
|
} else {
|
||||||
|
this.#value = Boolean(createType(v));
|
||||||
|
}
|
||||||
|
this.comment = comment;
|
||||||
|
}
|
||||||
|
set set(v: boolean) {
|
||||||
|
this.#value = Boolean(createType(v));
|
||||||
|
}
|
||||||
|
valueOf() {
|
||||||
|
return this.#value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class SField extends Field {
|
||||||
|
comment = "";
|
||||||
|
#value = "";
|
||||||
|
|
||||||
|
constructor(v: any, comment: string, env: string) {
|
||||||
|
super();
|
||||||
|
if (env != "" && process.env[env]) {
|
||||||
|
this.#value = String(createType(process.env[env]));
|
||||||
|
} else {
|
||||||
|
this.#value = String(createType(v));
|
||||||
|
}
|
||||||
|
this.comment = comment;
|
||||||
|
}
|
||||||
|
set set(v: string) {
|
||||||
|
this.#value = String(createType(v));
|
||||||
|
}
|
||||||
|
valueOf() {
|
||||||
|
return this.#value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function createType(data: any) {
|
||||||
|
if (data == "true") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (data == "false") {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (String(data).toLowerCase() == "infinity") {
|
||||||
|
return Infinity;
|
||||||
|
}
|
||||||
|
if (String(data).toLowerCase() == "-infinity") {
|
||||||
|
return -Infinity;
|
||||||
|
}
|
||||||
|
if (!isNaN(data)) {
|
||||||
|
return Number(data);
|
||||||
|
}
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
function jpath(a: string, b: string) {
|
||||||
|
if (b.startsWith("/")) {
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
return path.join(a, b);
|
||||||
|
}
|
20
tsconfig.json
Normal file
20
tsconfig.json
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"target": "ES2022",
|
||||||
|
"module": "ESNext",
|
||||||
|
"moduleResolution": "node",
|
||||||
|
"declaration": true,
|
||||||
|
"outDir": "./dist",
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"forceConsistentCasingInFileNames": true,
|
||||||
|
"strict": true,
|
||||||
|
"skipLibCheck": true
|
||||||
|
},
|
||||||
|
"files": [
|
||||||
|
"src/juml.ts"
|
||||||
|
],
|
||||||
|
"exclude": [
|
||||||
|
"node_modules",
|
||||||
|
"dist"
|
||||||
|
]
|
||||||
|
}
|
Loading…
Reference in a new issue