jitar 0.8.2 → 0.9.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/dist/cli.js CHANGED
@@ -1,2 +1,2 @@
1
1
  #!/usr/bin/env node
2
- import fs from"fs-extra";import{glob}from"glob";import mime from"mime-types";import path from"path";import{B as BadRequest,N as NotFound,F as Forbidden,a as NamedParameter,A as ArrayParameter,O as ObjectParameter,b as NotImplemented,P as PaymentRequired,T as Teapot,U as Unauthorized,S as ServerError,V as Version,c as Segment$1,R as Response,d as AccessLevels,e as Request}from"./Response-D49TlRAU.js";import dotenv from"dotenv";import express from"express";class MissingArgument extends Error{constructor(name){super(`Missing argument '${name}'`)}}class ArgumentProcessor{#command;#args;constructor(args){this.#command=args[2],this.#args=this.#parseArguments(args)}getCommand(){return this.#command}getRequiredArgument(name){const value=this.#args.get(name);if(void 0===value)throw new MissingArgument(name);return value}getOptionalArgument(name,defaultValue){return this.#args.get(name)??defaultValue}#parseArguments(args){const commandArgs=args.slice(3),map=new Map;return commandArgs.forEach((arg=>{const[key,value]=arg.split("=");map.set(key.trim(),value?.trim())})),map}}class ShowHelp{async execute(args){console.log("\nUsage: jitar <command> [options]\n\nCommands:\n build Builds the application (creates segment bundles)\n start Starts a server with the configured service\n about Shows information about Jitar\n version Shows the installed version of Jitar\n help Shows help (this message)\n\nOptions:\n --config Path to the configuration file (default: jitar.json)\n --service Path to the service configuration file (required for 'start' command)\n --env-file Path to the environment file (default: none)\n --log-level Optional for 'start' and 'build' commands (default: info, other options: debug, warn, error, fatal)\n --http-body-limit Optional for 'start' command (default: 204,800 bytes)\nMore information can be found at https://docs.jitar.dev\n")}}class ShowAbout{async execute(args){console.log("\nJitar is a JavaScript Distributed Runtime created and maintained by Masking Technology.\n\nMore information can be found at:\n- https://jitar.dev\n- https://masking.tech\n")}}class ShowVersion{async execute(args){console.log("v0.8.0")}}const LogLevels_DEBUG=0,LogLevels_INFO=1,LogLevels_WARN=2,LogLevels_ERROR=3,LogLevels_FATAL=4;class Logger{#logLevel;#writer;constructor(logLevel=LogLevels_INFO,writer=console){this.#logLevel=logLevel,this.#writer=writer}debug(...message){if(this.#logLevel>LogLevels_DEBUG)return;const messageString=this.#createMessage("DEBUG",message);this.#writer.debug(messageString)}info(...message){if(this.#logLevel>LogLevels_INFO)return;const messageString=this.#createMessage("INFO",message);this.#writer.info(messageString)}warn(...message){if(this.#logLevel>LogLevels_WARN)return;const messageString=this.#createMessage("WARN",message);this.#writer.warn(messageString)}error(...message){if(this.#logLevel>LogLevels_ERROR)return;const messageString=this.#createMessage("ERROR",message);this.#writer.error(messageString)}fatal(...message){const messageString=this.#createMessage("FATAL",message);this.#writer.error(messageString)}#createMessage(logLevel,messages){return`[${logLevel}][${(new Date).toISOString()}] ${messages.map((value=>this.#interpretValue(value))).join(" ")}`}#interpretValue(value,level=0){let result;switch(typeof value){case"string":result=value;break;case"object":result=this.#interpretObject(value,level+1);break;case"undefined":result="undefined";break;case"function":result="function";break;default:result=String(value)}return`${this.#indent(level)}${result}`}#interpretObject(object,level){if(null===object)return"null";if(Array.isArray(object)){return`[\n${object.map((value=>this.#interpretValue(value,level))).join(",\n")}\n${this.#indent(level-1)}]`}return object instanceof Error?object.stack??object.message:JSON.stringify(object)}#indent(level){return" ".repeat(level)}}class InvalidLogLevel extends Error{constructor(logLevel){super(`Invalid log level: ${logLevel}`)}}class LogLevelParser{parse(logLevel){switch(logLevel.toUpperCase()){case"DEBUG":return LogLevels_DEBUG;case"INFO":return LogLevels_INFO;case"WARN":return LogLevels_WARN;case"ERROR":return LogLevels_ERROR;case"FATAL":return LogLevels_FATAL;default:throw new InvalidLogLevel(logLevel)}}}const Files_MODULE_PATTERN="**/*.js",Files_SEGMENT_PATTERN="**/*.segment.json";class FileNotFound extends Error{#filename;constructor(filename){super(`The file '${filename}' could not be found`),this.#filename=filename}get filename(){return this.#filename}}let ModuleNotLoaded$1=class extends Error{#url;#reason;constructor(url,reason){super(`Module '${url}' could not be loaded${void 0!==reason?` | ${reason}`:""}`),this.#url=url,this.#reason=reason}get url(){return this.#url}get reason(){return this.#reason}};class File{#location;#type;#content;constructor(location,type,content){this.#location=location,this.#type=type,this.#content=content}get location(){return this.#location}get type(){return this.#type}get content(){return this.#content}get size(){return this.#content.length}}class LocalFileManager{#location;constructor(location){this.#location=location}getRootLocation(){return path.resolve(this.#location)}getAbsoluteLocation(filename){const location=filename.startsWith("/")?filename:path.join(this.#location,filename);return path.resolve(location)}getRelativeLocation(filename){return path.relative(this.#location,filename)}async getType(filename){const location=this.getAbsoluteLocation(filename);return mime.lookup(location)||"application/octet-stream"}async getContent(filename){const location=this.getAbsoluteLocation(filename);if(!1===fs.existsSync(location))throw new FileNotFound(filename);return fs.readFile(location)}async exists(filename){const location=this.getAbsoluteLocation(filename);return fs.exists(location)}async read(filename){const rootPath=this.getRootLocation(),absoluteFilename=this.getAbsoluteLocation(filename);if(!1===absoluteFilename.startsWith(rootPath))throw new FileNotFound(filename);const type=await this.getType(absoluteFilename),content=await this.getContent(absoluteFilename);return new File(filename,type,content)}async write(filename,content){const location=this.getAbsoluteLocation(filename),directory=path.dirname(location);return await fs.mkdir(directory,{recursive:!0}),fs.writeFile(location,content)}async copy(source,destination){const sourceLocation=this.getAbsoluteLocation(source),destinationLocation=this.getAbsoluteLocation(destination);return fs.copy(sourceLocation,destinationLocation,{overwrite:!0})}async delete(filename){const location=this.getAbsoluteLocation(filename);return fs.remove(location)}async filter(pattern){const location=this.getAbsoluteLocation("./");return glob(`${location}/${pattern}`)}}class SourceManager{#fileManager;constructor(fileManager){this.#fileManager=fileManager}async filter(...patterns){return(await Promise.all(patterns.map((pattern=>this.#fileManager.filter(pattern))))).flat().map((file=>this.#fileManager.getRelativeLocation(file)))}async exists(filename){return this.#fileManager.exists(filename)}async read(filename){return this.#fileManager.read(filename)}async import(filename){const specifier=filename.startsWith("/")?this.#fileManager.getAbsoluteLocation(`.${filename}`):this.#fileManager.getAbsoluteLocation(filename);try{return await import(specifier)}catch(error){const message=error instanceof Error?error.message:String(error);throw new ModuleNotLoaded$1(specifier,message)}}}let Application$1=class{#repository;#segmentation;constructor(repository,segmentation){this.#repository=repository,this.#segmentation=segmentation}get repository(){return this.#repository}get segmentation(){return this.#segmentation}},Module$1=class{#filename;#code;#model;constructor(filename,code,model){this.#code=code,this.#filename=filename,this.#model=model}get filename(){return this.#filename}get code(){return this.#code}get model(){return this.#model}};class Repository{#modules;constructor(modules){this.#modules=modules}get modules(){return this.#modules}get(filename){return this.#modules.find((module=>module.filename===filename))}}class ESAlias{#name;#as;constructor(name,as){this.#name=name,this.#as=as}get name(){return this.#name}get as(){return this.#as}toString(){return`${this.#name} as ${this.#as}`}}class ESValue{#definition;constructor(definition){this.#definition=definition}get definition(){return this.#definition}toString(){return this.#definition}}class ESArray extends ESValue{}class ESMember{#name;#isStatic;#isPrivate;constructor(name,isStatic=!1,isPrivate=!1){this.#name=name,this.#isStatic=isStatic,this.#isPrivate=isPrivate}get name(){return this.#name}get isStatic(){return this.#isStatic}get isPrivate(){return this.#isPrivate}get isPublic(){return!1===this.#isPrivate}}class ESClass extends ESMember{#parentName;#scope;constructor(name,parentName,scope){super(name),this.#parentName=parentName,this.#scope=scope}get parentName(){return this.#parentName}get scope(){return this.#scope}get members(){return this.#scope.members}get declarations(){return this.#scope.declarations}get functions(){return this.#scope.functions}get getters(){return this.#scope.getters}get setters(){return this.#scope.setters}get generators(){return this.#scope.generators}get readable(){const members=new Map;return this.getters.forEach((getter=>{members.set(getter.name,getter)})),this.declarations.forEach((declaration=>{declaration.isPublic&&members.set(declaration.name,declaration)})),[...members.values()]}get writable(){const members=new Map;return this.setters.forEach((setter=>{members.set(setter.name,setter)})),this.declarations.forEach((declaration=>{declaration.isPublic&&members.set(declaration.name,declaration)})),[...members.values()]}get callable(){return this.functions.filter((funktion=>funktion.isPublic))}getMember(name){return this.#scope.getMember(name)}getDeclaration(name){return this.#scope.getDeclaration(name)}getFunction(name){return this.#scope.getFunction(name)}getGetter(name){return this.#scope.getGetter(name)}getSetter(name){return this.#scope.getSetter(name)}getGenerator(name){return this.#scope.getGenerator(name)}hasMember(name){return this.#scope.hasMember(name)}hasDeclaration(name){return this.#scope.hasDeclaration(name)}hasFunction(name){return this.#scope.hasFunction(name)}hasGetter(name){return this.#scope.hasGetter(name)}hasSetter(name){return this.#scope.hasSetter(name)}hasGenerator(name){return this.#scope.hasGenerator(name)}canRead(name){const declaration=this.getDeclaration(name);return declaration?.isPublic||this.hasGetter(name)}canWrite(name){const declaration=this.getDeclaration(name);return declaration?.isPublic||this.hasSetter(name)}canCall(name){const funktion=this.getFunction(name);return funktion?.isPublic??!1}toString(){const infix=void 0!==this.#parentName?` extends ${this.#parentName}`:"";return`class ${this.name}${infix} { ${this.#scope.toString()} }`}}class ESDeclaration extends ESMember{#identifier;#value;constructor(identifier,value,isStatic=!1,isPrivate=!1){super(identifier.toString(),isStatic,isPrivate),this.#identifier=identifier,this.#value=value}get identifier(){return this.#identifier}get value(){return this.#value}toString(){return`${this.name}${this.value?" = "+this.value.toString():""}`}}class ESDestructuredValue{#members;constructor(members){this.#members=members}get members(){return this.#members}toString(){return this.#members.map((member=>member.toString())).join(" , ")}}class ESDestructuredArray extends ESDestructuredValue{toString(){return`[ ${super.toString()} ]`}}class ESDestructuredObject extends ESDestructuredValue{toString(){return`{ ${super.toString()} }`}}class ESExport extends ESMember{#members;#from;constructor(members,from){super(""),this.#members=members,this.#from=from}get members(){return this.#members}get from(){return this.#from}toString(){const postfix=this.#from?` from '${this.#from}'`:"";return`export { ${this.#members.join(", ")} }${postfix}`}}class ESExpression extends ESValue{}class ESField{#name;#value;constructor(name,value){this.#name=name,this.#value=value}get name(){return this.#name}get value(){return this.#value}toString(){return`${this.name}${this.value?" = "+this.value.toString():""}`}}class ESFunction extends ESMember{#parameters;#body;#isAsync;constructor(name,parameters,body,isStatic=!1,isAsync=!1,isPrivate=!1){super(name,isStatic,isPrivate),this.#parameters=parameters,this.#body=body,this.#isAsync=isAsync}get parameters(){return this.#parameters}get body(){return this.#body}get isAsync(){return this.#isAsync}toString(){const parameters=this.parameters.map((parameter=>parameter.toString()));return`${this.isAsync?"async ":""}${this.name}(${parameters.join(", ")}) { ${this.body} }`}}class ESGenerator extends ESFunction{toString(){const parameters=this.parameters.map((parameter=>parameter.toString()));return`${this.isAsync?"async ":""}${this.name}*(${parameters.join(", ")}) { ${this.body} }`}}class ESGetter extends ESFunction{toString(){return`get ${super.toString()}`}}class ESImport extends ESMember{#members;#from;constructor(members,from){super(""),this.#members=members,this.#from=from}get members(){return this.#members}get from(){return this.#from}toString(){return`import { ${this.#members.map((member=>member.toString())).join(", ")} } from '${this.#from}';`}}class ESModule{#scope;constructor(scope){this.#scope=scope}get scope(){return this.#scope}get members(){return this.#scope.members}get exportedMembers(){return this.#filterExported(this.#scope.members)}get imports(){return this.#scope.imports}get exports(){return this.#scope.exports}get declarations(){return this.#scope.declarations}get exportedDeclarations(){return this.#filterExported(this.#scope.declarations)}get functions(){return this.#scope.functions}get exportedFunctions(){return this.#filterExported(this.#scope.functions)}get generators(){return this.#scope.generators}get exportedGenerators(){return this.#filterExported(this.#scope.generators)}get classes(){return this.#scope.classes}get exportedClasses(){return this.#filterExported(this.#scope.classes)}get exported(){const exported=new Map;for(const exportItem of this.exports)for(const alias of exportItem.members){const member=this.getMember(alias.name);void 0!==member&&exported.set(alias.as,member)}return exported}getMember(name){return this.#scope.getMember(name)}getDeclaration(name){return this.#scope.getDeclaration(name)}getFunction(name){return this.#scope.getFunction(name)}getGenerator(name){return this.#scope.getGenerator(name)}getClass(name){return this.#scope.getClass(name)}hasMember(name){return this.#scope.hasMember(name)}hasDeclaration(name){return this.#scope.hasDeclaration(name)}hasFunction(name){return this.#scope.hasFunction(name)}hasGenerator(name){return this.#scope.hasGenerator(name)}hasClass(name){return this.#scope.hasClass(name)}isExported(member){for(const exportItem of this.exports)for(const alias of exportItem.members)if(alias.name===member.name)return!0;return!1}getExported(name){for(const exportItem of this.exports)for(const alias of exportItem.members)if(alias.as===name)return this.getMember(alias.name)}#filterExported(members){return members.filter((member=>this.isExported(member)))}}class ESObject extends ESValue{}class ESSetter extends ESFunction{toString(){return`set ${super.toString()}`}}const IMPORT_NAME=ESImport.name,EXPORT_NAME=ESExport.name,DECLARATION_NAME=ESDeclaration.name,FUNCTION_NAME=ESFunction.name,GETTER_NAME=ESGetter.name,SETTER_NAME=ESSetter.name,GENERATOR_NAME=ESGenerator.name,CLASS_NAME=ESClass.name;class ESScope{#members;constructor(members){this.#members=members}get members(){return this.#members}get imports(){return this.#members.filter((member=>member.constructor.name===IMPORT_NAME))}get exports(){return this.#members.filter((member=>member.constructor.name===EXPORT_NAME))}get declarations(){return this.#members.filter((member=>member.constructor.name===DECLARATION_NAME))}get functions(){return this.#members.filter((member=>member.constructor.name===FUNCTION_NAME))}get getters(){return this.#members.filter((member=>member.constructor.name===GETTER_NAME))}get setters(){return this.#members.filter((member=>member.constructor.name===SETTER_NAME))}get generators(){return this.#members.filter((member=>member.constructor.name===GENERATOR_NAME))}get classes(){return this.#members.filter((member=>member.constructor.name===CLASS_NAME))}getMember(name){return this.#members.find((member=>member.name===name))}getDeclaration(name){return this.declarations.find((member=>member.name===name))}getFunction(name){return this.functions.find((member=>member.name===name))}getGetter(name){return this.getters.find((member=>member.name===name))}getSetter(name){return this.setters.find((member=>member.name===name))}getGenerator(name){return this.generators.find((member=>member.name===name))}getClass(name){return this.classes.find((member=>member.name===name))}hasMember(name){return void 0!==this.getMember(name)}hasDeclaration(name){return void 0!==this.getDeclaration(name)}hasFunction(name){return void 0!==this.getFunction(name)}hasGetter(name){return void 0!==this.getGetter(name)}hasSetter(name){return void 0!==this.getSetter(name)}hasGenerator(name){return void 0!==this.getGenerator(name)}hasClass(name){return void 0!==this.getClass(name)}toString(){return this.#members.map((member=>member.toString())).join("\n")}}const Comment={SINGLE:"//",MULTI_START:"/*",MULTI_END:"*/"},Comments=Object.values(Comment);const Punctuation_DOT=".",Punctuation_LEFT_PARENTHESIS="(",Punctuation_RIGHT_PARENTHESIS=")",Punctuation_LEFT_BRACKET="[",Punctuation_RIGHT_BRACKET="]",Punctuation_LEFT_BRACE="{",Punctuation_RIGHT_BRACE="}",Divider={SCOPE:":",SEPARATOR:",",TERMINATOR:";"},Divisions=Object.values(Divider);function isDivider(value){return Divisions.includes(value)}const Empty={UNDEFINED:void 0,NULL:null,STRING:""},Empties=Object.values(Empty);function isEmpty(value){return Empties.includes(value)}const Group={OPEN:Punctuation_LEFT_PARENTHESIS,CLOSE:Punctuation_RIGHT_PARENTHESIS};function isGroup(value){return value===Group.OPEN||value===Group.CLOSE}const Keyword={EXPORT:"export",DEFAULT:"default",CLASS:"class",FUNCTION:"function",CONST:"const",LET:"let",VAR:"var",AS:"as",FROM:"from",IMPORT:"import",GET:"get",SET:"set",EXTENDS:"extends",STATIC:"static",ASYNC:"async",RETURN:"return"},Keywords=Object.values(Keyword);function isKeyword(value){return Keywords.includes(value)}function isNotReserved(value){return value===Keyword.AS||value===Keyword.ASYNC||value===Keyword.FROM||value===Keyword.GET||value===Keyword.SET}const List={OPEN:Punctuation_LEFT_BRACKET,CLOSE:Punctuation_RIGHT_BRACKET};function isList(value){return value===List.OPEN||value===List.CLOSE}const Literals=Object.values({SINGLE:"'",DOUBLE:'"',BACKTICK:"`"});function isLiteral(value){return Literals.includes(value)}const Operator={ADD:"+",ARROW:"=>",ASSIGN:"=",ASSIGN_ADD:"+=",ASSIGN_BITWISE_AND:"&=",ASSIGN_BITWISE_OR:"|=",ASSIGN_DIVIDE:"/=",ASSIGN_LEFT_SHIFT:"<<=",ASSIGN_LOGICAL_AND:"&&=",ASSIGN_LOGICAL_OR:"||=",ASSIGN_MODULO:"%=",ASSIGN_MULTIPLY:"*=",ASSIGN_RIGHT_SHIFT:">>=",ASSIGN_SUBTRACT:"-=",ASSIGN_XOR:"^=",BITWISE_AND:"&",BITWISE_OR:"|",DECREMENT:"--",DIVIDE:"/",EQUAL:"==",EQUAL_STRICT:"===",GREATER:">",GREATER_EQUAL:">=",INCREMENT:"++",LEFT_SHIFT:"<<",LESS:"<",LESS_EQUAL:"<=",LOGICAL_AND:"&&",LOGICAL_OR:"||",MODULO:"%",MULTIPLY:"*",NOT:"!",NOT_EQUAL:"!=",NOT_EQUAL_STRICT:"!==",RIGHT_SHIFT:">>",SUBTRACT:"-",TERNARY:"?",XOR:"^"},Operators=Object.values(Operator);function isOperator(value){return Operators.includes(value)}const Scope={OPEN:Punctuation_LEFT_BRACE,CLOSE:Punctuation_RIGHT_BRACE};function isScope(value){return value===Scope.OPEN||value===Scope.CLOSE}const TokenType={COMMENT:"comment",DIVIDER:"divider",GROUP:"group",IDENTIFIER:"identifier",KEYWORD:"keyword",LIST:"list",LITERAL:"literal",OPERATOR:"operator",REGEX:"regex",SCOPE:"scope",WHITESPACE:"whitespace"},Whitespace={SPACE:" ",TAB:"\t",NEWLINE:"\n",CARRIAGE_RETURN:"\r"},Whitespaces=Object.values(Whitespace);function isWhitespace(value){return Whitespaces.includes(value)}class ItemList{#items;#position;constructor(items){this.#items=items,this.#position=0}get items(){return this.#items}get position(){return this.#position}get size(){return this.#items.length}get eol(){return this.#position>=this.#items.length}get current(){return this.#items[this.#position]}get next(){return this.#items[this.#position+1]}get previous(){return this.#items[this.#position-1]}notAtEnd(){return!1===this.eol}get(index){return this.#items[index]}step(amount=1){return this.#position+=amount,this.current}stepBack(amount=1){return this.#position-=amount,this.current}hasNext(){return this.#position+1<this.#items.length}}class CharList extends ItemList{constructor(code){super(code.split(""))}}class Token{#type;#value;#start;#end;constructor(type,value,start,end){this.#type=type,this.#value=value,this.#start=start,this.#end=end}get type(){return this.#type}get value(){return this.#value}get start(){return this.#start}get end(){return this.#end}isType(type){return this.#type===type}hasValue(value){return this.#value===value}toString(){return`${this.#value}`}}class TokenList extends ItemList{}class Lexer{tokenize(code){const charList=new CharList(code),tokens=[];let last;for(;charList.notAtEnd();){const token=this.#getNextToken(charList,last);if(void 0===token)break;token.isType(TokenType.WHITESPACE)||token.isType(TokenType.COMMENT)?charList.step():(tokens.push(token),this.#isCodeToken(token)&&(last=token),charList.step())}return new TokenList(tokens)}#isCodeToken(token){return!1===[TokenType.WHITESPACE,TokenType.COMMENT].includes(token.type)}#getNextToken(charList,lastToken){const char=charList.current,start=charList.position;if(isWhitespace(char)){const end=charList.position;return new Token(TokenType.WHITESPACE,char,start,end)}if(function(value){return Comments.includes(value)}(char+charList.next)){const value=this.#readComment(charList),end=charList.position;return new Token(TokenType.COMMENT,value,start,end)}if(this.#startsRegex(char,lastToken)){const value=this.#readRegex(charList),end=charList.position;return new Token(TokenType.REGEX,value,start,end)}if(isLiteral(char)){const value=this.#readLiteral(charList),end=charList.position;return new Token(TokenType.LITERAL,value,start,end)}if(isOperator(char)){const value=this.#readOperation(charList),end=charList.position;return new Token(TokenType.OPERATOR,value,start,end)}if(isDivider(char)){const end=charList.position;return new Token(TokenType.DIVIDER,char,start,end)}if(isGroup(char)){const end=charList.position;return new Token(TokenType.GROUP,char,start,end)}if(isScope(char)){const end=charList.position;return new Token(TokenType.SCOPE,char,start,end)}if(isList(char)){const end=charList.position;return new Token(TokenType.LIST,char,start,end)}if(isEmpty(char))return;const value=this.#readIdentifier(charList),type=isKeyword(value)?TokenType.KEYWORD:TokenType.IDENTIFIER,end=charList.position;return new Token(type,value,start,end)}#readComment(charList){const isMulti=charList.current+charList.next===Comment.MULTI_START,terminator=isMulti?Comment.MULTI_END:Whitespace.NEWLINE;let value=isMulti?Comment.MULTI_START:Comment.SINGLE;for(charList.step(2);charList.notAtEnd();){const char=charList.current;if((isMulti?char+charList.next:char)===terminator){charList.step(terminator.length-1);break}value+=char,charList.step()}return isMulti?value+Comment.MULTI_END:value.trim()}#startsRegex(char,lastToken){return char===Operator.DIVIDE&&(void 0===lastToken||([TokenType.OPERATOR,TokenType.DIVIDER,TokenType.KEYWORD].includes(lastToken.type)||[Group.OPEN,List.OPEN].includes(lastToken.value)))}#endsRegex(char){return isWhitespace(char)||char==Punctuation_DOT||!1===this.#isIdentifier(char)}#readRegex(charList){let value=charList.current,closed=!1;for(charList.step();charList.notAtEnd();){const current=charList.current,previous=charList.previous;if(current===Operator.DIVIDE&&"\\"!==previous)closed=!0;else if(!0===closed&&this.#endsRegex(current)){charList.stepBack();break}value+=current,charList.step()}return value}#readLiteral(charList){const identifier=charList.current;let value=identifier,escaped=!1;for(charList.step();charList.notAtEnd();){const char=charList.current;if(!1===escaped){if(char===identifier){value+=char;break}"\\"===char&&(escaped=!0)}else escaped=!1;value+=char,charList.step()}return value}#isIdentifier(char){return!1===(isEmpty(char)||isWhitespace(char)||isOperator(char)||isLiteral(char)||isDivider(char)||isGroup(char)||isScope(char)||isList(char))}#readIdentifier(charList){let value="";for(;charList.notAtEnd();){const char=charList.current;if(!1===this.#isIdentifier(char)){charList.stepBack();break}value+=char,charList.step()}return value}#readOperation(charList){let value=charList.current;for(charList.step();charList.notAtEnd();){const char=charList.current;if(!1===isOperator(char)||!1===isOperator(value+char)){charList.stepBack();break}value+=char,charList.step()}return value}}class ExpectedKeyword extends Error{constructor(value,position){super(`Expected keyword '${value}' at position ${position}`)}}class ExpectedToken extends Error{constructor(value,position){super(`Expected token '${value}' at position ${position}`)}}class UnexpectedKeyword extends Error{constructor(keyword,position){super(`Unexpected keyword '${keyword}' at position ${position}`)}}class UnexpectedParseResult extends Error{constructor(expected){super(`The given code does not contain ${expected}`)}}class UnexpectedToken extends Error{constructor(value,position){super(`Unexpected token '${value}' at position ${position}`)}}class Parser{#lexer;constructor(lexer=new Lexer){this.#lexer=lexer}parse(code){const tokenList=this.#lexer.tokenize(code),scope=this.#parseScope(tokenList);return new ESModule(scope)}parseFirst(code){const tokenList=this.#lexer.tokenize(code);return this.#parseNext(tokenList)}parseValue(code){const model=this.parseFirst(code);if(model instanceof ESValue==!1)throw new UnexpectedParseResult("a value definition");return model}parseImport(code){const model=this.parseFirst(code);if(model instanceof ESImport==!1)throw new UnexpectedParseResult("an import definition");return model}parseExport(code){const model=this.parseFirst(code);if(model instanceof ESExport==!1)throw new UnexpectedParseResult("an export definition");return model}parseDeclaration(code){const model=this.parseFirst(code);if(model instanceof ESDeclaration==!1)throw new UnexpectedParseResult("a declaration definition");return model}parseFunction(code){const tokenList=this.#lexer.tokenize(code),model=this.#parseMember(tokenList);if(model instanceof ESFunction==!1)throw new UnexpectedParseResult("a function definition");return model}parseClass(code){const tokenList=this.#lexer.tokenize(code),model=this.#parseMember(tokenList);if(model instanceof ESClass==!1)throw new UnexpectedParseResult("a class definition");return model}#parseScope(tokenList){const members=[];for(;tokenList.notAtEnd();){const member=this.#parseNext(tokenList);member instanceof ESMember&&members.push(member)}return new ESScope(members)}#parseNext(tokenList,isAsync=!1){const token=tokenList.current;if(token.isType(TokenType.LITERAL))return this.#parseExpression(tokenList);if(token.isType(TokenType.IDENTIFIER)){const next=tokenList.next;return next?.hasValue(Operator.ARROW)?this.#parseArrowFunction(tokenList,isAsync):this.#parseExpression(tokenList)}if(token.isType(TokenType.KEYWORD)){if(isNotReserved(token.value)){const next=tokenList.next,nextIsFunction=void 0!==next&&(next.hasValue(Keyword.FUNCTION)||next.hasValue(Group.OPEN));if(token.hasValue(Keyword.ASYNC)&&nextIsFunction)return tokenList.step(),this.#parseNext(tokenList,!0);if(void 0===next||this.#atEndOfStatement(next))return this.#parseExpression(tokenList)}return token.hasValue(Keyword.RETURN)?this.#parseExpression(tokenList):this.#parseMember(tokenList,isAsync)}if(token.isType(TokenType.REGEX))return this.#parseExpression(tokenList);if(token.hasValue(Group.OPEN)){const next=this.#peekAfterBlock(tokenList,Group.OPEN,Group.CLOSE);return next?.hasValue(Operator.ARROW)?this.#parseArrowFunction(tokenList,isAsync):this.#parseExpression(tokenList)}if(token.hasValue(Scope.OPEN))return this.#parseObject(tokenList);if(token.hasValue(List.OPEN))return this.#parseArray(tokenList);if(token.hasValue(Operator.NOT)||token.hasValue(Operator.SUBTRACT))return this.#parseExpression(tokenList);if(!isDivider(token.value))throw new UnexpectedToken(token.value,token.start);tokenList.step()}#parseMember(tokenList,isAsync=!1){const token=tokenList.current;switch(tokenList.step(),token.value){case Keyword.IMPORT:return this.#parseImport(tokenList);case Keyword.EXPORT:return this.#parseExport(tokenList);case Keyword.CLASS:return this.#parseClass(tokenList);case Keyword.FUNCTION:return this.#parseFunction(tokenList,isAsync);case Keyword.VAR:case Keyword.LET:case Keyword.CONST:return this.#parseDeclaration(tokenList,!1,!0);case Keyword.ASYNC:return this.#parseMember(tokenList,!0);default:throw new UnexpectedKeyword(token.value,token.start)}}#parseImport(tokenList){const members=[];let token=tokenList.current;if(token.isType(TokenType.LITERAL))return new ESImport(members,token.value);if(token.hasValue(Group.OPEN)){token=tokenList.step();const from=token.value;return tokenList.step(2),new ESImport(members,from)}if(!1===token.hasValue(Scope.OPEN)){const name=token.hasValue(Operator.MULTIPLY)?Operator.MULTIPLY:"default";let as=token.value;token=tokenList.step(),token.hasValue(Keyword.AS)&&(token=tokenList.step(),as=token.value,token=tokenList.step()),members.push(new ESAlias(name,as))}if(token.hasValue(Divider.SEPARATOR)&&(token=tokenList.step()),token.hasValue(Scope.OPEN)){const aliases=this.#parseAliasList(tokenList);members.push(...aliases),token=tokenList.current}if(!1===token.hasValue(Keyword.FROM))throw new ExpectedKeyword(Keyword.FROM,token.start);token=tokenList.step();const from=token.value;return tokenList.step(),new ESImport(members,from)}#parseExport(tokenList){switch(tokenList.current.value){case Keyword.DEFAULT:return tokenList.step(),this.#parseSingleExport(tokenList,!0);case Scope.OPEN:return this.#parseMultiExport(tokenList);default:return this.#parseSingleExport(tokenList,!1)}}#parseSingleExport(tokenList,isDefault){let token=tokenList.current,stepSize=0;var value;token.hasValue(Keyword.ASYNC)&&(token=tokenList.step(),stepSize++),((value=token.value)===Keyword.CLASS||value===Keyword.FUNCTION||value===Keyword.CONST||value===Keyword.LET||value===Keyword.VAR)&&(token=tokenList.step(),stepSize++);const name=this.#isIdentifier(token)?token.value:"",as=isDefault?"default":name;let from;token=tokenList.step(),token?.hasValue(Keyword.FROM)&&(token=tokenList.step(),from=token.value),stepSize>0&&(stepSize++,tokenList.stepBack(stepSize));const alias=new ESAlias(name,as);return new ESExport([alias],from)}#parseMultiExport(tokenList){const members=this.#parseAliasList(tokenList);let from,token=tokenList.current;return token?.hasValue(Keyword.FROM)&&(token=tokenList.step(),from=token.value),tokenList.step(),new ESExport(members,from)}#parseAliasList(tokenList){const aliases=[];let token=tokenList.step();for(;tokenList.notAtEnd();){if(token.hasValue(Scope.CLOSE)){tokenList.step();break}if(token.hasValue(Divider.SEPARATOR)){token=tokenList.step();continue}const alias=this.#parseAlias(tokenList);aliases.push(alias),token=tokenList.step()}return aliases}#parseAlias(tokenList){let token=tokenList.current;const name=token.value;let as=name;return tokenList.next.hasValue(Keyword.AS)&&(token=tokenList.step(2),as=token.value),new ESAlias(name,as)}#parseDeclaration(tokenList,isStatic,parseMultiple=!1){let value,token=tokenList.current,identifier="",isPrivate=!1;return token.hasValue(List.OPEN)?(identifier=this.#parseDestructuredArray(tokenList),token=tokenList.current):token.hasValue(Scope.OPEN)?(identifier=this.#parseDestructuredObject(tokenList),token=tokenList.current):(isPrivate=token.value.startsWith("#"),identifier=isPrivate?token.value.substring(1):token.value,token=tokenList.step()),token.hasValue(Operator.ASSIGN)&&(tokenList.step(),value=this.#parseNext(tokenList,!1),token=tokenList.current),void 0!==token&&(token.hasValue(Divider.TERMINATOR)?tokenList.step():!0===parseMultiple&&token.hasValue(Divider.SEPARATOR)&&(tokenList.step(),this.#parseDeclaration(tokenList,isStatic,!0))),value instanceof ESGenerator?new ESGenerator(identifier.toString(),value.parameters,value.body,isStatic,value.isAsync,isPrivate):value instanceof ESFunction?new ESFunction(identifier.toString(),value.parameters,value.body,isStatic,value.isAsync,isPrivate):value instanceof ESClass?new ESClass(identifier.toString(),value.parentName,value.scope):new ESDeclaration(identifier,value,isStatic,isPrivate)}#parseFunction(tokenList,isAsync,isStatic=!1,isGetter=!1,isSetter=!1){let token=tokenList.current,name="",isGenerator=!1,isPrivate=!1;token.hasValue(Operator.MULTIPLY)&&(isGenerator=!0,token=tokenList.step()),this.#isIdentifier(token)&&(isPrivate=token.value.startsWith("#"),name=isPrivate?token.value.substring(1):token.value,token=tokenList.step());const parameters=this.#parseParameters(tokenList,Group.CLOSE);if(token=tokenList.current,!1===token.hasValue(Scope.OPEN))throw new ExpectedToken(Scope.OPEN,token.start);const body=this.#parseBlock(tokenList,Scope.OPEN,Scope.CLOSE);return isGenerator?new ESGenerator(name,parameters,body,isStatic,isAsync,isPrivate):isGetter?new ESGetter(name,parameters,body,isStatic,isAsync,isPrivate):isSetter?new ESSetter(name,parameters,body,isStatic,isAsync,isPrivate):new ESFunction(name,parameters,body,isStatic,isAsync,isPrivate)}#parseArrowFunction(tokenList,isAsync){let parameters,token=tokenList.current;if(token.hasValue(Group.OPEN)?(parameters=this.#parseParameters(tokenList,Group.CLOSE),token=tokenList.current):(parameters=[new ESField(token.value,void 0)],token=tokenList.step()),!1===token.hasValue(Operator.ARROW))throw new ExpectedToken(Operator.ARROW,token.start);token=tokenList.step();const body=token.hasValue(Scope.OPEN)?this.#parseBlock(tokenList,Scope.OPEN,Scope.CLOSE):this.#parseExpression(tokenList).definition;return new ESFunction("",parameters,body,!1,isAsync,!1)}#parseParameters(tokenList,closeId){const parameters=[];for(tokenList.step();tokenList.notAtEnd();){const token=tokenList.current;if(token.hasValue(closeId)){tokenList.step();break}if(token.hasValue(Divider.SEPARATOR)){tokenList.step();continue}let parameter;parameter=token.hasValue(Scope.OPEN)?this.#parseDestructuredObject(tokenList):token.hasValue(List.OPEN)?this.#parseDestructuredArray(tokenList):this.#parseField(tokenList),parameters.push(parameter)}return parameters}#parseClass(tokenList){let parent,token=tokenList.current,name="";if(this.#isIdentifier(token)&&(name=token.value,token=tokenList.step()),token.hasValue(Keyword.EXTENDS)&&(token=tokenList.step(),parent=token.value,token=tokenList.step()),!1===token.hasValue(Scope.OPEN))throw new ExpectedToken(Scope.OPEN,token.start);const scope=this.#parseClassScope(tokenList);return new ESClass(name,parent,scope)}#parseClassScope(tokenList){let token=tokenList.step();const members=[];for(;tokenList.notAtEnd();){if(token.hasValue(Scope.CLOSE)){tokenList.step();break}const member=this.#parseClassMember(tokenList);members.push(member),token=tokenList.current}return new ESScope(members)}#parseClassMember(tokenList){let token=tokenList.current,isAsync=!1,isStatic=!1,isGetter=!1,isSetter=!1;for(;tokenList.notAtEnd();){if(token.hasValue(Keyword.STATIC))isStatic=!0;else if(token.hasValue(Keyword.ASYNC))isAsync=!0;else if(token.hasValue(Keyword.GET))isGetter=!0;else{if(!token.hasValue(Keyword.SET)){if(token.hasValue(Operator.MULTIPLY))return this.#parseFunction(tokenList,isAsync,isStatic,!1,!1);break}isSetter=!0}token=tokenList.step()}return tokenList.next.hasValue(Group.OPEN)?this.#parseFunction(tokenList,isAsync,isStatic,isGetter,isSetter):this.#parseDeclaration(tokenList,isStatic)}#parseArray(tokenList){const items=this.#parseBlock(tokenList,List.OPEN,List.CLOSE);return new ESArray(items)}#parseDestructuredArray(tokenList){const fields=this.#parseParameters(tokenList,List.CLOSE);return new ESDestructuredArray(fields)}#parseObject(tokenList){const fields=this.#parseBlock(tokenList,Scope.OPEN,Scope.CLOSE);return new ESObject(fields)}#parseDestructuredObject(tokenList){const fields=this.#parseParameters(tokenList,Scope.CLOSE);return new ESDestructuredObject(fields)}#parseField(tokenList){let token=tokenList.current;const name=token.value;let value;return token=tokenList.step(),token.hasValue(Operator.ASSIGN)&&(tokenList.step(),value=this.#parseNext(tokenList,!1)),new ESField(name,value)}#parseExpression(tokenList){let token=tokenList.current,code="";for(;tokenList.notAtEnd();){if(token.hasValue(List.OPEN)){code+=this.#parseBlock(tokenList,List.OPEN,List.CLOSE)+" ",token=tokenList.current}else if(token.hasValue(Group.OPEN)){code+=this.#parseBlock(tokenList,Group.OPEN,Group.CLOSE)+" ",token=tokenList.current}else if(token.hasValue(Scope.OPEN)){code+=this.#parseBlock(tokenList,Scope.OPEN,Scope.CLOSE)+" ",token=tokenList.current}else code+=token.toString()+" ",token=tokenList.step();if(void 0===token||this.#atEndOfStatement(token))break}return new ESExpression(code.trim())}#parseBlock(tokenList,openId,closeId){let token=tokenList.step(),code=openId+" ";for(;tokenList.notAtEnd();)if(token.hasValue(openId))code+=this.#parseBlock(tokenList,openId,closeId)+" ",token=tokenList.current;else{if(token.hasValue(closeId))return tokenList.step(),code+=closeId,code;code+=token.toString()+" ",token=tokenList.step()}return code}#peekAfterBlock(tokenList,openId,closeId){const start=tokenList.position;this.#parseBlock(tokenList,openId,closeId);const token=tokenList.current,end=tokenList.position;return tokenList.stepBack(end-start),token}#atEndOfStatement(token){return[Divider.TERMINATOR,Divider.SEPARATOR].includes(token.value)||[List.CLOSE,Group.CLOSE,Scope.CLOSE].includes(token.value)||isKeyword(token.value)}#isIdentifier(token){return token.isType(TokenType.IDENTIFIER)||token.isType(TokenType.KEYWORD)&&isNotReserved(token.value)}}class ClassMerger{merge(model,parent){const declarations=this.#mergeDeclarations(model.declarations,parent.declarations),functions=this.#mergeFunctions(model.functions,parent.functions),getters=this.#mergeFunctions(model.getters,parent.getters),setters=this.#mergeFunctions(model.setters,parent.setters),members=[...declarations.values(),...functions.values(),...getters.values(),...setters.values()];return new ESClass(model.name,parent.name,new ESScope(members))}#mergeDeclarations(model,parent){const declarations=new Map;return parent.forEach((declaration=>declarations.set(declaration.name,declaration))),model.forEach((declaration=>declarations.set(declaration.name,declaration))),[...declarations.values()]}#mergeFunctions(model,parent){const functions=new Map;return parent.forEach((funktion=>functions.set(funktion.name,funktion))),model.forEach((funktion=>functions.set(funktion.name,funktion))),[...functions.values()]}}class Reflector{#parser=new Parser;#merger=new ClassMerger;fromModule(module,inherit=!1){const entries=Object.entries(module),members=[];for(const[key,member]of entries){if("function"!=typeof member.toString)continue;const code=member.toString();if(code.startsWith("class"))members.push(this.fromClass(member,inherit));else if(code.startsWith("function"))members.push(this.fromFunction(member));else{const expression=new ESExpression(code);members.push(new ESDeclaration(key,expression))}}return new ESModule(new ESScope(members))}fromClass(clazz,inherit=!1){const model=this.isClass(clazz)?this.#reflectStatic(clazz):this.#reflectDynamic(clazz);if(!1===inherit)return model;const parentClazz=this.getParentClass(clazz);if(""===parentClazz.name)return model;const parentModel=this.fromClass(parentClazz,!0);return this.#merger.merge(model,parentModel)}fromObject(object,inherit=!0){const clazz=this.getClass(object);return this.fromClass(clazz,inherit)}fromFunction(funktion){const code=funktion.toString();return this.#parser.parseFunction(code)}createInstance(clazz,args=[]){return new clazz(...args)}getClass(object){return object.constructor}getParentClass(clazz){return Object.getPrototypeOf(clazz)}isClassObject(object){return this.isClass(object.constructor)}isFunctionObject(object){return this.isFunction(object.constructor)}isClass(clazz){return clazz.toString().startsWith("class")}isFunction(clazz){return clazz.toString().startsWith("function")||clazz.toString().startsWith("async function")}#reflectStatic(clazz){const code=clazz.toString();return this.#parser.parseClass(code)}#reflectDynamic(clazz){const object=this.createInstance(clazz),members=this.#getMembers(clazz,object),scope=new ESScope(members);return new ESClass(clazz.name,void 0,scope)}#getMembers(clazz,object){return[...this.#getDeclarations(object),...this.#getFunctions(clazz)]}#getDeclarations(object){const fieldNames=Object.getOwnPropertyNames(object),values=object,models=[];for(const fieldName of fieldNames){const content=values[fieldName],value=void 0!==content?new ESValue(String(content)):void 0,model=new ESDeclaration(fieldName,value);models.push(model)}return models}#getFunctions(clazz){const functionDescriptions=Object.getOwnPropertyDescriptors(clazz.prototype),models=[];for(const functionName in functionDescriptions){const description=functionDescriptions[functionName],funktion=description.value;if(funktion instanceof Function==!1)continue;const model=this.fromFunction(funktion);void 0!==description.get?models.push(new ESGetter(model.name,model.parameters,model.body,model.isStatic,model.isAsync,model.isPrivate)):void 0!==description.set?models.push(new ESSetter(model.name,model.parameters,model.body,model.isStatic,model.isAsync,model.isPrivate)):models.push(model)}return models}}let FileNotLoaded$1=class extends Error{constructor(filename,message){super(`Failed to load module file '${filename}' because of: ${message}`)}},Reader$1=class{#fileManager;#parser;constructor(fileManager,parser=new Parser){this.#fileManager=fileManager,this.#parser=parser}async readAll(filenames){const modules=await Promise.all(filenames.map((filename=>this.read(filename))));return new Repository(modules)}async read(filename){const relativeLocation=this.#fileManager.getRelativeLocation(filename),code=await this.#loadCode(filename),module=this.#parser.parse(code);return new Module$1(relativeLocation,code,module)}async#loadCode(filename){try{return(await this.#fileManager.getContent(filename)).toString()}catch(error){const message=error instanceof Error?error.message:String(error);throw new FileNotLoaded$1(filename,message)}}};class Segment{#name;#modules;#classes;#procedures;constructor(name,modules,classes,procedures){this.#name=name,this.#modules=modules,this.#classes=classes,this.#procedures=procedures}get name(){return this.#name}get modules(){return this.#modules}get classes(){return this.#classes}get procedures(){return this.#procedures}hasModule(filename){return this.#modules.some((module=>module.filename===filename))}getModule(filename){return this.#modules.find((module=>module.filename===filename))}hasProcedure(fqn){return this.#procedures.some((procedure=>procedure.fqn===fqn))}getProcedure(fqn){return this.#procedures.find((procedure=>procedure.fqn===fqn))}}class Member{#id;#importKey;#fqn;constructor(id,importKey,fqn){this.#id=id,this.#importKey=importKey,this.#fqn=fqn}get id(){return this.#id}get importKey(){return this.#importKey}get fqn(){return this.#fqn}}class Class extends Member{#model;constructor(id,importKey,fqn,model){super(id,importKey,fqn),this.#model=model}get model(){return this.#model}}class Implementation extends Member{#access;#version;#model;constructor(id,importKey,fqn,access,version,model){super(id,importKey,fqn),this.#access=access,this.#version=version,this.#model=model}get access(){return this.#access}get version(){return this.#version}get model(){return this.#model}}class Module{#filename;#location;#imports;#members=[];constructor(filename,location,imports){this.#filename=filename,this.#location=location,this.#imports=imports}get filename(){return this.#filename}get location(){return this.#location}get imports(){return this.#imports}get members(){return this.#members}hasClasses(){return this.#members.some((member=>member instanceof Class))}getClasses(){return this.#members.filter((member=>member instanceof Class))}hasImplementations(){return this.#members.some((member=>member instanceof Implementation))}getImplementations(){return this.#members.filter((member=>member instanceof Implementation))}addMember(members){this.#members.push(members)}}class Procedure{#fqn;#implementations=[];constructor(fqn,implementations=[]){this.#fqn=fqn,this.#implementations=implementations}get fqn(){return this.#fqn}get implementations(){return this.#implementations}addImplementation(implementation){this.#implementations.push(implementation)}}class Segmentation{#segments;constructor(segments){this.#segments=segments}get segments(){return this.#segments}getSegment(segmentName){return this.#segments.find((segment=>segment.name===segmentName))}isModuleSegmented(moduleFilename){return this.#segments.some((segment=>segment.hasModule(moduleFilename)))}getSegments(moduleFilename){return this.#segments.filter((segment=>segment.hasModule(moduleFilename)))}}class IdGenerator{#id=0;next(){return"$"+ ++this.#id}}const EXTENSION_PATTERN=/\.js$/;class FileHelper{translatePath(filename){const parts=filename.split("/"),translated=[];for(let index=0;index<parts.length;index++){const part=parts[index].trim();switch(part){case"":case".":continue;case"..":translated.pop();continue}translated.push(part)}return translated.join("/")}makePathRelative(absoluteFilename,relativeToPath){if(""===relativeToPath)return`./${absoluteFilename}`;const absoluteFilenameParts=absoluteFilename.split("/"),relativeToParts=relativeToPath.split("/");for(;absoluteFilenameParts[0]===relativeToParts[0];)absoluteFilenameParts.shift(),relativeToParts.shift();const relativePath=relativeToParts.map((()=>"..")).join("/");return`${relativeToParts.length>0?relativePath:"."}/${absoluteFilenameParts.join("/")}`}makePathAbsolute(relativeFilename,relativeToPath){const fullPath=""!==relativeToPath?`${relativeToPath}/${relativeFilename}`:relativeFilename;return this.translatePath(fullPath)}extractPath(filename){return filename.split("/").slice(0,-1).join("/")}extractFilename(filename){return filename.split("/").pop()}assureExtension(filename){return filename.endsWith(".js")?filename:`${filename}.js`}addSubExtension(filename,subExtension){return filename.replace(EXTENSION_PATTERN,`.${subExtension}.js`)}}class FunctionNotAsync extends Error{constructor(filename,functionName){super(`Function '${functionName}' from file '${filename}' is not async`)}}class InvalidFilename extends Error{constructor(filename){super(`Segment filename '${filename}' is invalid`)}}class MissingModuleExport extends Error{constructor(filename,key){super(`Module '${filename}' does not export '${key}'`)}}class FileNotLoaded extends Error{constructor(filename,message){super(`Failed to load segment file '${filename}' because of: ${message}`)}}class InvalidModuleExport extends Error{constructor(filename,exportKey){super(`The export '${exportKey}' from file '${filename}' is not a function or a class.`)}}class ModuleNotLoaded extends Error{constructor(filename){super(`Segmented module not found '${filename}'`)}}class SegmentReader{#fileManager;#repository;#fileHelper=new FileHelper;constructor(fileManager,repository){this.#fileManager=fileManager,this.#repository=repository}async readAll(filenames){const segments=await Promise.all(filenames.map((filename=>this.read(filename))));return new Segmentation(segments)}async read(filename){const definition=await this.#loadSegmentDefinition(filename),name=this.#extractSegmentName(filename),modules=this.#createModules(definition),members=this.#createMembers(modules),classes=[...members.classes.values()],procedures=[...members.procedures.values()];return new Segment(name,modules,classes,procedures)}#extractSegmentName(filename){const file=filename.split("/").pop();if(void 0===file||""===file)throw new InvalidFilename(filename);return file.replace(".segment.json","")}async#loadSegmentDefinition(filename){try{const content=await this.#fileManager.getContent(filename);return JSON.parse(content.toString())}catch(error){const message=error instanceof Error?error.message:String(error);throw new FileNotLoaded(filename,message)}}#createModules(definition){const modules=[];for(const[filename,moduleImports]of Object.entries(definition)){const moduleFilename=this.#makeModuleFilename(filename),location=this.#extractLocation(moduleFilename),module=new Module(moduleFilename,location,moduleImports);modules.push(module)}return modules}#makeModuleFilename(filename){const fullFilename=this.#fileHelper.assureExtension(filename);return fullFilename.startsWith("./")?fullFilename.substring(2):fullFilename.startsWith("/")?fullFilename.substring(1):fullFilename}#extractLocation(filename){const moduleParts=filename.split("/");return moduleParts.pop(),moduleParts.join("/")}#createMembers(modules){const members={classes:new Map,procedures:new Map},idGenerator=new IdGenerator;for(const module of modules)this.#extractModuleMembers(module,members,idGenerator);return members}#extractModuleMembers(module,members,idGenerator){for(const importKey in module.imports){const id=idGenerator.next(),model=this.#getMember(module.filename,importKey),properties=module.imports[importKey],name=properties.as??model.name,memberProperties={id:id,importKey:importKey,name:name,access:properties.access??"private",version:properties.version??"0.0.0",fqn:""!==module.location?`${module.location}/${name}`:name};if(model instanceof ESClass)this.#registerClassMember(module,members,model,memberProperties);else{if(!(model instanceof ESFunction))throw new InvalidModuleExport(module.filename,importKey);this.#registerProcedureMember(module,members,model,memberProperties)}}}#registerClassMember(module,members,model,properties){const clazz=new Class(properties.id,properties.importKey,properties.fqn,model);module.addMember(clazz),members.classes.set(properties.fqn,clazz)}#registerProcedureMember(module,members,model,properties){if(!1===model.isAsync)throw new FunctionNotAsync(module.filename,properties.name);const implementation=new Implementation(properties.id,properties.importKey,properties.fqn,properties.access,properties.version,model);module.addMember(implementation);const procedure=members.procedures.has(implementation.fqn)?members.procedures.get(implementation.fqn):new Procedure(implementation.fqn);procedure.addImplementation(implementation),members.procedures.set(implementation.fqn,procedure)}#getMember(filename,importKey){const module=this.#repository.get(filename);if(void 0===module)throw new ModuleNotLoaded(filename);const member=module.model.getExported(importKey);if(void 0===member)throw new MissingModuleExport(filename,importKey);return member}}class Reader{#fileManager;constructor(fileManager){this.#fileManager=fileManager}async read(moduleFiles,segmentFiles){const moduleReader=new Reader$1(this.#fileManager),repository=await moduleReader.readAll(moduleFiles),segmentReader=new SegmentReader(this.#fileManager,repository),segmentation=await segmentReader.readAll(segmentFiles);return new Application$1(repository,segmentation)}}const RunModes_NORMAL="normal",RunModes_DRY="dry",StatusCodes$1_OK=200,StatusCodes$1_BAD_REQUEST=400,StatusCodes$1_UNAUTHORIZED=401,StatusCodes$1_PAYMENT_REQUIRED=402,StatusCodes$1_FORBIDDEN=403,StatusCodes$1_NOT_FOUND=404,StatusCodes$1_TEAPOT=418,StatusCodes$1_SERVER_ERROR=500,StatusCodes$1_NOT_IMPLEMENTED=501;class InvalidVersionNumber extends BadRequest{#number;constructor(number){super(`Invalid version number '${number}'`),this.#number=number}get number(){return this.#number}}class ProcedureNotFound extends NotFound{#fqn;constructor(fqn){super(`Procedure '${fqn}' not found`),this.#fqn=fqn}get fqn(){return this.#fqn}}class ProcedureNotAccessible extends Forbidden{constructor(fqn,versionNumber){super(`Procedure '${fqn}' (v${versionNumber}) is not accessible`)}}class UnknownParameter extends BadRequest{#parameterName;constructor(parameterName){super(`Unknown parameter ${parameterName}`),this.#parameterName=parameterName}get parameterName(){return this.#parameterName}}class MissingParameterValue extends BadRequest{#parameterName;constructor(parameterName){super(`Missing value for parameter '${parameterName}'`),this.#parameterName=parameterName}get parameterName(){return this.#parameterName}}class InvalidParameterValue extends BadRequest{#parameterName;constructor(parameterName){super(`Invalid value for parameter '${parameterName}'`),this.#parameterName=parameterName}get parameterName(){return this.#parameterName}}class ArgumentExtractor{extract(parameters,args){const argsCopy=this.#copyArguments(parameters,args),values=[];for(const parameter of parameters){const value=this.#extractArgumentValue(parameter,argsCopy);values.push(value)}if(argsCopy.size>0){const name=argsCopy.keys().next().value;throw new UnknownParameter(name)}return values}#copyArguments(parameters,args){const copy=new Map;for(const[key,value]of args)if(this.#isOptionalArgument(key)){const name=this.#getParameterName(key);!0===this.#containsParameter(parameters,name)&&copy.set(name,value)}else copy.set(key,value);return copy}#isOptionalArgument(argument){return argument.startsWith("*")}#getParameterName(argument){return argument.substring(1)}#containsParameter(parameters,name){return void 0!==parameters.find((parameter=>parameter.name===name))}#extractArgumentValue(parameter,args,parent){return parameter instanceof NamedParameter?this.#extractNamedArgumentValue(parameter,args,parent):this.#extractDestructedArgumentValue(parameter,args)}#extractNamedArgumentValue(parameter,args,parent){const value=args.get(parameter.name);if(this.#isMissingParameterValue(parameter,value,parent))throw new MissingParameterValue(parameter.name);if(this.#isInvalidRestParameter(parameter,value,parent))throw new InvalidParameterValue(parameter.name);return args.delete(parameter.name),value}#extractDestructedArgumentValue(parameter,args){return parameter instanceof ArrayParameter?this.#extractArrayArgumentValue(parameter,args):this.#extractObjectArgumentValue(parameter,args)}#extractArrayArgumentValue(parameter,args){const values=this.#extractVariableValues(parameter,args);return void 0!==values?Object.values(values):void 0}#extractObjectArgumentValue(parameter,args){return this.#extractVariableValues(parameter,args)}#extractVariableValues(parameter,args){const useIndex=parameter instanceof ArrayParameter,values={},missingValues=[];let containsValues=!1,index=0;for(const variable of parameter.variables){const key=useIndex?index++:variable.name,value=this.#extractArgumentValue(variable,args,parameter);void 0!==value?containsValues=!0:!1===variable.isOptional&&missingValues.push(variable.name),values[key]=value}if(!0===containsValues&&missingValues.length>0)throw new MissingParameterValue(missingValues[0]);return containsValues?values:void 0}#isMissingParameterValue(parameter,value,parent){return void 0===value&&(!0!==parameter.isOptional&&!0!==parent?.isOptional)}#isInvalidRestParameter(parameter,value,parent){return!1!==parameter.name.startsWith("...")&&(void 0===parent&&value instanceof Array==!1||parent instanceof ArrayParameter&&value instanceof Array==!1||parent instanceof ObjectParameter&&value instanceof Object==!1)}}class ErrorConverter{toStatus(error){return error instanceof BadRequest?StatusCodes$1_BAD_REQUEST:error instanceof Forbidden?StatusCodes$1_FORBIDDEN:error instanceof NotFound?StatusCodes$1_NOT_FOUND:error instanceof NotImplemented?StatusCodes$1_NOT_IMPLEMENTED:error instanceof PaymentRequired?StatusCodes$1_PAYMENT_REQUIRED:error instanceof Teapot?StatusCodes$1_TEAPOT:error instanceof Unauthorized?StatusCodes$1_UNAUTHORIZED:StatusCodes$1_SERVER_ERROR}fromStatus(status,message){switch(status){case StatusCodes$1_BAD_REQUEST:return new BadRequest(message);case StatusCodes$1_FORBIDDEN:return new Forbidden(message);case StatusCodes$1_NOT_FOUND:return new NotFound(message);case StatusCodes$1_NOT_IMPLEMENTED:return new NotImplemented(message);case StatusCodes$1_PAYMENT_REQUIRED:return new PaymentRequired(message);case StatusCodes$1_TEAPOT:return new Teapot(message);case StatusCodes$1_UNAUTHORIZED:return new Unauthorized(message);default:return new ServerError(message)}}}const VERSION_EXPRESSION=/^\d+(?:\.\d+){0,2}$/;class VersionParser{parse(number){if(0===number.trim().length)return Version.DEFAULT;if(!1===VERSION_EXPRESSION.test(number))throw new InvalidVersionNumber(number);const parts=number.split(".");switch(parts.length){case 1:return new Version(Number.parseInt(parts[0]));case 2:return new Version(Number.parseInt(parts[0]),Number.parseInt(parts[1]));default:return new Version(Number.parseInt(parts[0]),Number.parseInt(parts[1]),Number.parseInt(parts[2]))}}}class ImplementationNotFound extends NotFound{#fqn;#version;constructor(fqn,version){super(`No implementation found for procedure '${fqn}' with version '${version}'`),this.#fqn=fqn,this.#version=version}get fqn(){return this.#fqn}get version(){return this.#version}}class InvalidSegment extends ServerError{constructor(){super("Invalid segment")}}class Application{#segments=new Map;addSegment(segment){this.#segments.set(segment.id,segment)}getClassNames(){const names=new Set;for(const segment of this.#segments.values()){segment.getClasses().forEach((clazz=>names.add(clazz.fqn)))}return[...names.values()]}hasClass(fqn){return this.getClassNames().includes(fqn)}getClass(fqn){for(const segment of this.#segments.values())if(segment.hasClass(fqn))return segment.getClass(fqn)}getClassByImplementation(implementation){for(const segment of this.#segments.values()){const clazz=segment.getClassByImplementation(implementation);if(void 0!==clazz)return clazz}}getProcedureNames(){const names=new Set;for(const segment of this.#segments.values()){segment.getExposedProcedures().forEach((procedure=>names.add(procedure.fqn)))}return[...names.values()]}hasProcedure(fqn){return this.getProcedureNames().includes(fqn)}getProcedure(fqn){for(const segment of this.#segments.values())if(segment.hasProcedure(fqn))return segment.getProcedure(fqn)}}class ExecutionManager{#argumentConstructor=new ArgumentExtractor;#errorConverter=new ErrorConverter;#application=new Application;async addSegment(segment){if(segment instanceof Segment$1==!1)throw new InvalidSegment;this.#application.addSegment(segment)}getClassNames(){return this.#application.getClassNames()}hasClass(fqn){return this.#application.hasClass(fqn)}getClass(fqn){return this.#application.getClass(fqn)}getClassByImplementation(implementation){return this.#application.getClassByImplementation(implementation)}getProcedureNames(){return this.#application.getProcedureNames()}hasProcedure(fqn){return this.#application.hasProcedure(fqn)}getProcedure(fqn){return this.#application.getProcedure(fqn)}async run(request){const implementation=this.#getImplementation(request.fqn,request.version),args=this.#argumentConstructor.extract(implementation.parameters,request.args);return request.mode===RunModes_DRY?new Response(StatusCodes$1_OK,void 0):this.#runImplementation(request,implementation,args)}#getImplementation(fqn,version){const procedure=this.#application.getProcedure(fqn);if(void 0===procedure)throw new ProcedureNotFound(fqn);const implementation=procedure.getImplementation(version);if(void 0===implementation)throw new ImplementationNotFound(procedure.fqn,version.toString());return implementation}async#runImplementation(request,implementation,args){try{const result=await implementation.executable.call(request,...args);return new Response(StatusCodes$1_OK,result)}catch(error){const status=this.#errorConverter.toStatus(error);return new Response(status,error)}}}class RemoteModuleBuilder{build(implementations){let code="";for(const implementation of implementations)code+=implementation.access===AccessLevels.PRIVATE?this.#createPrivateCode(implementation):this.#createPublicCode(implementation);return code.trim()}#createPrivateCode(implementation){const fqn=implementation.fqn,version=implementation.version,declaration=this.#createDeclaration(implementation),body=`throw new ProcedureNotAccessible('${fqn}', '${version}');`;return this.#createFunction(declaration,body)}#createPublicCode(implementation){const fqn=implementation.fqn,version=implementation.version,args=this.#createArguments(implementation.model.parameters),declaration=this.#createDeclaration(implementation),body=`return __run('${fqn}', '${version}', { ${args} }, this);`;return this.#createFunction(declaration,body)}#createParameters(parameters){const result=[];for(const parameter of parameters)parameter instanceof ESField?result.push(parameter.name):(parameter instanceof ESDestructuredArray||parameter instanceof ESDestructuredObject)&&result.push(parameter.toString());return result.join(", ")}#createArguments(parameters){return this.#extractArguments(parameters).join(", ")}#extractArguments(parameters){const result=[];for(const parameter of parameters)if(parameter instanceof ESDestructuredValue){const argumentz=this.#extractArguments(parameter.members);result.push(...argumentz)}else if(parameter instanceof ESField){const argument=this.#createNamedArgument(parameter);result.push(argument)}return result}#createNamedArgument(parameter){const key=parameter.name,value=key.startsWith("...")?key.substring(3):key;return`'${key}': ${value}`}#createDeclaration(implementation){const name=implementation.model.name,parameters=this.#createParameters(implementation.model.parameters);return`\nexport ${"default"===implementation.importKey?"default ":""}async function ${name}(${parameters})`}#createFunction(declaration,body){return`${declaration} {\n\t${body}\n}\n`}}const IMPORT_PATTERN=/import\s(?:["'\s]*([\w*{}\n, ]+)from\s*)?["'\s]*([@\w/._-]+)["'\s].*/g,APPLICATION_MODULE_INDICATORS$1=[".","/","http:","https:"];class ImportRewriter{#module;#segmentation;#segment;#parser=new Parser;#fileHelper=new FileHelper;constructor(module,segmentation,segment){this.#module=module,this.#segmentation=segmentation,this.#segment=segment}rewrite(code){return code.replaceAll(IMPORT_PATTERN,(statement=>this.#replaceImport(statement)))}#replaceImport(statement){const dependency=this.#parser.parseImport(statement);return this.#isApplicationModule(dependency)?this.#rewriteApplicationImport(dependency):this.#rewriteRuntimeImport(dependency)}#isApplicationModule(dependency){return APPLICATION_MODULE_INDICATORS$1.some((indicator=>dependency.from.startsWith(indicator,1)))}#rewriteApplicationImport(dependency){const targetModuleFilename=this.#getTargetModuleFilename(dependency);if(this.#segmentation.isModuleSegmented(targetModuleFilename)){if(this.#segment?.hasModule(targetModuleFilename)){const from=this.#rewriteApplicationFrom(targetModuleFilename,this.#segment.name);return this.#rewriteToStaticImport(dependency,from)}const from=this.#rewriteApplicationFrom(targetModuleFilename,"remote");return this.#rewriteToStaticImport(dependency,from)}const from=this.#rewriteApplicationFrom(targetModuleFilename,"shared");return void 0===this.#segment?this.#rewriteToStaticImport(dependency,from):this.#rewriteToDynamicImport(dependency,from)}#rewriteRuntimeImport(dependency){const from=this.#rewriteRuntimeFrom(dependency);return this.#rewriteToStaticImport(dependency,from)}#rewriteApplicationFrom(filename,scope){const callingModulePath=this.#fileHelper.extractPath(this.#module.filename),relativeFilename=this.#fileHelper.makePathRelative(filename,callingModulePath);return this.#fileHelper.addSubExtension(relativeFilename,scope)}#rewriteRuntimeFrom(dependency){return this.#stripFrom(dependency.from)}#rewriteToStaticImport(dependency,from){if(0===dependency.members.length)return`import "${from}";`;return`import ${this.#rewriteStaticImportMembers(dependency)} from "${from}";`}#rewriteToDynamicImport(dependency,from){if(0===dependency.members.length)return`await import("${from}");`;return`const ${this.#rewriteDynamicImportMembers(dependency)} = await import("${from}");`}#rewriteStaticImportMembers(dependency){const defaultMember=dependency.members.find((member=>"default"===member.name)),hasDefaultMember=void 0!==defaultMember,defaultMemberImport=hasDefaultMember?defaultMember.as:"",namedMemberImports=dependency.members.filter((member=>"default"!==member.name)).map((member=>member.name!==member.as?`${member.name} as ${member.as}`:member.name)),hasNamedMembers=namedMemberImports.length>0;return`${defaultMemberImport}${hasDefaultMember&&hasNamedMembers?", ":""}${hasNamedMembers?`{ ${namedMemberImports.join(", ")} }`:""}`}#rewriteDynamicImportMembers(dependency){if(this.#doesImportAll(dependency))return dependency.members[0].as;return`{ ${dependency.members.map((member=>member.name!==member.as?`${member.name} : ${member.as}`:member.name)).join(", ")} }`}#getTargetModuleFilename(dependency){const from=this.#stripFrom(dependency.from),callingModulePath=this.#fileHelper.extractPath(this.#module.filename),translated=this.#fileHelper.makePathAbsolute(from,callingModulePath);return this.#fileHelper.assureExtension(translated)}#doesImportAll(dependency){return 1===dependency.members.length&&"*"===dependency.members[0].name}#stripFrom(from){return from.substring(1,from.length-1)}}const EXPORT_PATTERN=/export\s(?:["'\s]*([\w*{}\n, ]+)from\s*)?["'\s]*([@\w/._-]+)["'\s].*/g,APPLICATION_MODULE_INDICATORS=[".","/","http:","https:"];class ExportRewriter{#module;#segmentation;#segment;#parser=new Parser;#fileHelper=new FileHelper;constructor(module,segmentation,segment){this.#module=module,this.#segmentation=segmentation,this.#segment=segment}rewrite(code){return code.replaceAll(EXPORT_PATTERN,(statement=>this.#replaceExport(statement)))}#replaceExport(statement){const dependency=this.#parser.parseExport(statement);return void 0===dependency.from?statement:this.#isApplicationModule(dependency)?this.#rewriteApplicationExport(dependency):this.#rewriteRuntimeExport(dependency)}#isApplicationModule(dependency){return APPLICATION_MODULE_INDICATORS.some((indicator=>dependency.from.startsWith(indicator,1)))}#rewriteApplicationExport(dependency){const targetModuleFilename=this.#getTargetModuleFilename(dependency);if(this.#segmentation.isModuleSegmented(targetModuleFilename)){if(this.#segment?.hasModule(targetModuleFilename)){const from=this.#rewriteApplicationFrom(targetModuleFilename,this.#segment.name);return this.#rewriteToStaticExport(dependency,from)}console.warn("Exporting a module from another segment!");const from=this.#rewriteApplicationFrom(targetModuleFilename,"remote");return this.#rewriteToStaticExport(dependency,from)}void 0!==this.#segment&&console.warn("Exporting shared module from a segmented module!");const from=this.#rewriteApplicationFrom(targetModuleFilename,"shared");return this.#rewriteToStaticExport(dependency,from)}#rewriteRuntimeExport(dependency){const from=this.#rewriteRuntimeFrom(dependency);return this.#rewriteToStaticExport(dependency,from)}#rewriteApplicationFrom(filename,scope){const callingModulePath=this.#fileHelper.extractPath(this.#module.filename),relativeFilename=this.#fileHelper.makePathRelative(filename,callingModulePath);return this.#fileHelper.addSubExtension(relativeFilename,scope)}#rewriteRuntimeFrom(dependency){return this.#stripFrom(dependency.from)}#rewriteToStaticExport(dependency,from){if(0===dependency.members.length)return`export "${from}";`;return`export ${this.#rewriteStaticExportMembers(dependency)} from "${from}";`}#rewriteStaticExportMembers(dependency){const members=dependency.members;if(1===members.length&&""===members[0].name){const member=members[0];return member.name!==member.as?`* as ${member.as}`:"*"}return`{ ${members.map((member=>member.name!==member.as?`${member.name} as ${member.as}`:member.name)).join(", ")} }`}#getTargetModuleFilename(dependency){const from=this.#stripFrom(dependency.from),callingModulePath=this.#fileHelper.extractPath(this.#module.filename),translated=this.#fileHelper.makePathAbsolute(from,callingModulePath);return this.#fileHelper.assureExtension(translated)}#stripFrom(from){return from.substring(1,from.length-1)}}class LocalModuleBuilder{build(module,segmentation,segment){const importRewriter=new ImportRewriter(module,segmentation,segment),exportRewriter=new ExportRewriter(module,segmentation,segment),importCode=importRewriter.rewrite(module.code);return exportRewriter.rewrite(importCode)}}class ModuleBuilder{#fileManager;#localModuleBuilder=new LocalModuleBuilder;#remoteModuleBuilder=new RemoteModuleBuilder;#fileHelper=new FileHelper;constructor(fileManager){this.#fileManager=fileManager}async build(application){const repository=application.repository,segmentation=application.segmentation,builds=repository.modules.map((module=>this.#buildModule(module,segmentation)));await Promise.all(builds)}async#buildModule(module,segmentation){const moduleSegments=segmentation.getSegments(module.filename);if(0===moduleSegments.length)await this.#buildSharedModule(module,segmentation);else{const segmentBuilds=moduleSegments.map((segment=>this.#buildSegmentModule(module,segment,segmentation))),remoteBuild=moduleSegments[0].getModule(module.filename).hasImplementations()?this.#buildRemoteModule(module,moduleSegments):[];await Promise.all([...segmentBuilds,remoteBuild])}this.#fileManager.delete(module.filename)}async#buildSharedModule(module,segmentation){const filename=this.#fileHelper.addSubExtension(module.filename,"shared"),code=this.#localModuleBuilder.build(module,segmentation);return this.#fileManager.write(filename,code)}async#buildSegmentModule(module,segment,segmentation){const filename=this.#fileHelper.addSubExtension(module.filename,segment.name),code=this.#localModuleBuilder.build(module,segmentation,segment);return this.#fileManager.write(filename,code)}async#buildRemoteModule(module,segments){const implementations=this.#getImplementations(module,segments),filename=this.#fileHelper.addSubExtension(module.filename,"remote"),code=this.#remoteModuleBuilder.build(implementations);return this.#fileManager.write(filename,code)}#getImplementations(module,segments){const implementations=segments.map((segment=>segment.getModule(module.filename))).flatMap((segmentModule=>segmentModule.getImplementations())),unique=new Map;for(const implementation of implementations){const key=`${implementation.fqn}:${implementation.version.toString()}`;unique.set(key,implementation)}return[...unique.values()]}}class SegmentBuilder{#fileManager;#logger;#fileHelper=new FileHelper;#versionParser=new VersionParser;constructor(fileManager,logger){this.#fileManager=fileManager,this.#logger=logger}async build(application){const builds=application.segmentation.segments.map((segment=>this.#buildSegment(segment)));await Promise.all(builds)}async#buildSegment(segment){const filename=`${segment.name}.segment.js`,code=this.#createCode(segment);await this.#fileManager.write(filename,code),this.#logger.info(`Built ${segment.name} segment (${segment.modules.length} modules, ${segment.procedures.length} procedures, ${segment.classes.length} classes)`)}#createCode(segment){return`${this.#createImportCode(segment)}\n${this.#createSegmentCode(segment)}`}#createImportCode(segment){return`import { Segment, Class, Procedure, Implementation, Version, NamedParameter, ArrayParameter, ObjectParameter } from "jitar";\n${this.#createModuleImports(segment)}`}#createModuleImports(segment){const imports=[];for(const module of segment.modules){const filename=this.#fileHelper.addSubExtension(module.filename,segment.name),importRule=`import ${this.#createModuleImportMembers(module)} from "./${filename}";`;imports.push(importRule)}return imports.join("\n")}#createModuleImportMembers(module){const members=module.members,defaultImplementation=members.find((member=>"default"===member.importKey)),hasDefaultImplementation=void 0!==defaultImplementation,defaultMemberImport=hasDefaultImplementation?defaultImplementation.id:"",namedImplementations=members.filter((member=>"default"!==member.importKey)),nameImplementationImports=namedImplementations.map((member=>`${member.importKey} as ${member.id}`)),hasNamedImplementations=namedImplementations.length>0;return`${defaultMemberImport}${hasDefaultImplementation&&hasNamedImplementations?", ":""}${hasNamedImplementations?`{ ${nameImplementationImports.join(", ")} }`:""}`}#createSegmentCode(segment){const lines=[];lines.push(`export default new Segment("${segment.name}")`);for(const clazz of segment.classes)lines.push(`\t.addClass(new Class("${clazz.fqn}", ${clazz.id}))`);for(const procedure of segment.procedures){lines.push(`\t.addProcedure(new Procedure("${procedure.fqn}")`);for(const implementation of procedure.implementations){const version=this.#createVersionCode(implementation.version),parameters=this.#createParametersCode(implementation.model);lines.push(`\t\t.addImplementation(new Implementation(${version}, "${implementation.access}", ${parameters}, ${implementation.id}))`)}lines.push("\t)")}return lines.join("\n")}#createVersionCode(versionString){const version=this.#versionParser.parse(versionString);return`new Version(${version.major}, ${version.minor}, ${version.patch})`}#createParametersCode(model){return`[${this.#extractParameters(model.parameters).join(", ")}]`}#extractParameters(parameters){const result=[];for(const parameter of parameters)result.push(this.#extractParameter(parameter));return result}#extractParameter(parameter){return parameter instanceof ESDestructuredArray?this.#createArrayParameter(parameter):parameter instanceof ESDestructuredObject?this.#createObjectParameter(parameter):this.#createNamedParameter(parameter)}#createNamedParameter(parameter){return`new NamedParameter("${parameter.name}", ${void 0!==parameter.value})`}#createArrayParameter(parameter){return`new ArrayParameter([${this.#extractParameters(parameter.members).join(", ")}])`}#createObjectParameter(parameter){return`new ObjectParameter([${this.#extractParameters(parameter.members).join(", ")}])`}}class Builder{#moduleBuilder;#segmentBuilder;constructor(fileManager,logger){this.#moduleBuilder=new ModuleBuilder(fileManager),this.#segmentBuilder=new SegmentBuilder(fileManager,logger)}async build(application){await Promise.all([this.#moduleBuilder.build(application),this.#segmentBuilder.build(application)])}}class BuildManager{#logger;#projectFileManager;#sourceFileManager;#targetFileManager;#applicationReader;#applicationBuilder;constructor(configuration,logLevel){this.#logger=new Logger(logLevel),this.#projectFileManager=new LocalFileManager("./"),this.#sourceFileManager=new LocalFileManager(configuration.source),this.#targetFileManager=new LocalFileManager(configuration.target),this.#applicationReader=new Reader(this.#sourceFileManager),this.#applicationBuilder=new Builder(this.#targetFileManager,this.#logger)}async build(){const moduleFiles=await this.#sourceFileManager.filter(Files_MODULE_PATTERN),segmentFiles=await this.#projectFileManager.filter(Files_SEGMENT_PATTERN),applicationModel=await this.#applicationReader.read(moduleFiles,segmentFiles);return this.#applicationBuilder.build(applicationModel)}}class Validator{#strict;constructor(strict=!0){this.#strict=strict}validate(data,scheme){const errors=[];this.#validateData("",data,scheme,errors);return{valid:0===errors.length,errors:errors}}#validateData(key,data,scheme,errors){this.#strict&&this.#validateKeys(key,data,scheme,errors),this.#validateValues(key,data,scheme,errors)}#validateKeys(key,data,scheme,errors){const dataKeys=Object.keys(data),schemeKeys=Object.keys(scheme);for(const dataKey of dataKeys)if(!1===schemeKeys.includes(dataKey)){const absoluteKey=this.#composeKey(key,dataKey);errors.push(`Unknown field '${absoluteKey}'`)}}#validateValues(key,data,scheme,errors){const valueKeys=Object.keys(scheme);for(const valueKey of valueKeys){const absoluteKey=this.#composeKey(key,valueKey),fieldScheme=scheme[valueKey],value=data[valueKey];this.#validateValue(absoluteKey,value,fieldScheme,errors)}}#validateValue(key,value,scheme,errors){if(void 0!==value)switch(scheme.type){case"string":return this.#validateString(key,value,scheme,errors);case"integer":return this.#validateInteger(key,value,scheme,errors);case"real":return this.#validateReal(key,value,scheme,errors);case"boolean":return this.#validateBoolean(key,value,scheme,errors);case"url":return this.#validateUrl(key,value,scheme,errors);case"group":return this.#validateGroup(key,value,scheme,errors);case"list":return this.#validateList(key,value,scheme,errors)}else!0===scheme.required&&errors.push(`Field '${key}' is required`)}#validateString(key,value,scheme,errors){"string"!=typeof value&&errors.push(`Field '${key}' is not a string`)}#validateInteger(key,value,scheme,errors){"number"==typeof value&&!1!==Number.isInteger(value)||errors.push(`Field '${key}' is not an integer`)}#validateReal(key,value,scheme,errors){"number"!=typeof value&&errors.push(`Field '${key}' is not a real number`)}#validateBoolean(key,value,scheme,errors){"boolean"!=typeof value&&errors.push(`Field '${key}' is not a boolean`)}#validateUrl(key,value,scheme,errors){"string"==typeof value&&!1!==value.startsWith("http")||errors.push(`Field '${key}' is not a valid URL`)}#validateGroup(key,value,scheme,errors){"object"==typeof value?this.#validateData(key,value,scheme.fields,errors):errors.push(`Field '${key}' is not an object`)}#validateList(key,value,scheme,errors){if(!Array.isArray(value))return void errors.push(`Field '${key}' is not a list`);const data=value;for(const itemIndex in data){const itemKey=this.#composeKey(key,itemIndex),itemValue=data[itemIndex];this.#validateValue(itemKey,itemValue,scheme.items,errors)}}#composeKey(parent,key){return""===parent?key:`${parent}.${key}`}}class Configurator{async configure(filename){dotenv.config({path:filename})}}const DefaultValues_FILENAME="./jitar.json",DefaultValues_SOURCE="./src",DefaultValues_TARGET="./dist",validationScheme$6={source:{type:"string",required:!1},target:{type:"string",required:!1}};class RuntimeConfigurationInvalid extends Error{constructor(validation){super(`Runtime configuration is invalid:\n${validation.errors.join("\n")}`)}}let ConfigurationBuilder$1=class{#reader;#validator;constructor(reader,validator){this.#reader=reader,this.#validator=validator}async build(filename=DefaultValues_FILENAME){const configuration=await this.#reader.read(filename),validation=this.#validator.validate(configuration,validationScheme$6);if(!1===validation.valid)throw new RuntimeConfigurationInvalid(validation);return configuration.source??=DefaultValues_SOURCE,configuration.target??=DefaultValues_TARGET,configuration}};const validationScheme={url:{type:"url",required:!0},setUp:{type:"list",required:!1,items:{type:"string"}},tearDown:{type:"list",required:!1,items:{type:"string"}},middleware:{type:"list",required:!1,items:{type:"string"}},healthChecks:{type:"list",required:!1,items:{type:"string"}},gateway:{type:"group",required:!1,fields:{monitor:{type:"integer",required:!1},trustKey:{type:"string",required:!1}}},proxy:{type:"group",required:!1,fields:{gateway:{type:"url",required:!0},repository:{type:"url",required:!0}}},repository:{type:"group",required:!1,fields:{indexFilename:{type:"string",required:!1},serveIndexOnNotFound:{type:"boolean",required:!1},assets:{type:"list",required:!1,items:{type:"string"}}}},standalone:{type:"group",required:!1,fields:{segments:{type:"list",required:!0,items:{type:"string"}},indexFilename:{type:"string",required:!1},serveIndexOnNotFound:{type:"boolean",required:!1},assets:{type:"list",required:!1,items:{type:"string"}}}},worker:{type:"group",required:!1,fields:{gateway:{type:"url",required:!1},segments:{type:"list",required:!0,items:{type:"string"}},trustKey:{type:"string",required:!1}}}};class ServerConfigurationInvalid extends Error{constructor(validation){super(`Invalid server configuration:\n => ${validation.errors.join("\n => ")}`)}}class ConfigurationBuilder{#reader;#validator;constructor(reader,validator){this.#reader=reader,this.#validator=validator}async build(filename){const configuration=await this.#reader.read(filename),validation=this.#validator.validate(configuration,validationScheme);if(!1===validation.valid)throw new ServerConfigurationInvalid(validation);return configuration}}const ENVIRONMENT_VARIABLE_REGEX=/\${([^}]*)}/g;class ConfigurationReader{#fileManager;constructor(rootPath){this.#fileManager=new LocalFileManager(rootPath)}async read(filename){if(!1===await this.#fileManager.exists(filename))return{};const file=await this.#fileManager.read(filename),content=file.content.toString(),configuration=this.#replaceEnvironmentVariables(content);return file.type.includes("json")?this.#parseJson(configuration):this.#parseText(configuration)}#replaceEnvironmentVariables(content){return content.replace(ENVIRONMENT_VARIABLE_REGEX,((match,key)=>process.env[key]??"null"))}#parseJson(configuration){return JSON.parse(configuration)}#parseText(configuration){return{}}}class ConfigurationManager{#environmentConfigurator;#runtimeConfigurationBuilder;#serverConfigurationBuilder;constructor(rootPath="./"){const reader=new ConfigurationReader(rootPath),validator=new Validator;this.#environmentConfigurator=new Configurator,this.#runtimeConfigurationBuilder=new ConfigurationBuilder$1(reader,validator),this.#serverConfigurationBuilder=new ConfigurationBuilder(reader,validator)}configureEnvironment(filename=".env"){return this.#environmentConfigurator.configure(filename)}getRuntimeConfiguration(filename){return this.#runtimeConfigurationBuilder.build(filename)}getServerConfiguration(filename){return this.#serverConfigurationBuilder.build(filename)}}class BuildApp{async execute(args){const environmentFile=args.getOptionalArgument("--env-file",void 0),runtimeConfigFile=args.getOptionalArgument("--config",void 0),logLevelString=args.getOptionalArgument("--log-level",void 0),logLevel=this.#parseLogLevel(logLevelString),configurationManager=new ConfigurationManager;await configurationManager.configureEnvironment(environmentFile);const configuration=await configurationManager.getRuntimeConfiguration(runtimeConfigFile);return new BuildManager(configuration,logLevel).build()}#parseLogLevel(logLevel){if(void 0===logLevel)return;return(new LogLevelParser).parse(logLevel)}}const HeaderKeys_CONTENT_TYPE="content-type",HeaderKeys_CONTENT_TYPE_OPTIONS="x-content-type-options",HeaderKeys_JITAR_CONTENT_TYPE="x-jitar-content-type",HeaderKeys_JITAR_PROCEDURE_VERSION="x-jitar-procedure-version",HeaderKeys_POWERED_BY="x-powered-by",HeaderValues_NO_SNIFF="nosniff",HeaderValues_APPLICATION_JSON="application/json",HeaderValues_APPLICATION_STREAM="application/octet-stream";class HttpRemote{#url;#errorConverter=new ErrorConverter;constructor(url){this.#url=url}connect(){return Promise.resolve()}disconnect(){return Promise.resolve()}async provide(filename){const remoteUrl=`${this.#url}/${filename}`,response=await this.#callRemote(remoteUrl,{method:"GET"}),type=response.headers.get(HeaderKeys_CONTENT_TYPE)??HeaderValues_APPLICATION_STREAM,result=await response.arrayBuffer(),content=Buffer.from(result);return new File(filename,type,content)}async isHealthy(){const remoteUrl=`${this.#url}/health/status`,response=await this.#callRemote(remoteUrl,{method:"GET"}),healthy=await response.text();return Boolean(healthy)}async getHealth(){const remoteUrl=`${this.#url}/health`,response=await this.#callRemote(remoteUrl,{method:"GET"}),health=await response.json();return new Map(Object.entries(health))}async addWorker(url,procedureNames,trustKey){const remoteUrl=`${this.#url}/workers`,body={url:url,procedureNames:procedureNames,trustKey:trustKey},options={method:"POST",headers:{"Content-Type":HeaderValues_APPLICATION_JSON},body:JSON.stringify(body)};await this.#callRemote(remoteUrl,options)}async run(request){request.setHeader(HeaderKeys_CONTENT_TYPE,HeaderValues_APPLICATION_JSON);const argsObject=Object.fromEntries(request.args),headersObject=Object.fromEntries(request.headers),versionString=request.version.toString();headersObject[HeaderKeys_JITAR_PROCEDURE_VERSION]=versionString;const remoteUrl=`${this.#url}/rpc/${request.fqn}`,options={method:"POST",redirect:"manual",headers:headersObject,body:await this.#createRequestBody(argsObject)},response=await this.#callRemote(remoteUrl,options,!1),status=response.status,result=await this.#getResponseResult(response),headers=this.#createResponseHeaders(response);return new Response(status,result,headers)}async#callRemote(remoteUrl,options,throwOnError=!0){const response=await fetch(remoteUrl,options);if(throwOnError&&this.#isErrorResponse(response)){const result=await this.#getResponseResult(response);throw this.#errorConverter.fromStatus(response.status,String(result))}return response}#isErrorResponse(response){return response.status<200||response.status>399}async#createRequestBody(body){return JSON.stringify(body)}async#getResponseResult(response){const contentType=response.headers.get(HeaderKeys_JITAR_CONTENT_TYPE)??response.headers.get(HeaderKeys_CONTENT_TYPE);if(contentType?.includes("undefined"))return;if(contentType?.includes("null"))return null;if(contentType?.includes("json"))return response.json();const content=await response.text();return contentType?.includes("boolean")?"true"===content:contentType?.includes("number")?Number(content):content}#createResponseHeaders(response){const headers=new Map;for(const[name,value]of response.headers)headers.set(name,value);return headers}}class HttpRemoteBuilder{build(url){return new HttpRemote(url)}}class DummyProvider{get url(){throw new NotImplemented}start(){return Promise.resolve()}stop(){return Promise.resolve()}async isHealthy(){return!0}async getHealth(){return new Map}provide(filename){throw new NotImplemented}}class DummyRunner{get url(){throw new NotImplemented}get trustKey(){throw new NotImplemented}start(){return Promise.resolve()}stop(){return Promise.resolve()}async isHealthy(){return!0}async getHealth(){return new Map}getProcedureNames(){throw new NotImplemented}hasProcedure(name){throw new NotImplemented}run(request){throw new NotImplemented}}class NoWorkerAvailable extends ServerError{#name;constructor(name){super(`No worker available for procedure '${name}'`),this.#name=name}get name(){return this.#name}}class WorkerBalancer{#workers=[];#currentIndex=0;get workers(){return this.#workers}addWorker(worker){this.#workers.includes(worker)||this.#workers.push(worker)}removeWorker(worker){const index=this.#workers.indexOf(worker);-1!==index&&this.#workers.splice(index,1)}getNextWorker(){if(0!==this.#workers.length)return this.#currentIndex>=this.#workers.length&&(this.#currentIndex=0),this.#workers[this.#currentIndex++]}async run(request){const worker=this.getNextWorker();if(void 0===worker)throw new NoWorkerAvailable(request.fqn);return worker.run(request)}}class WorkerManager{#workers=new Set;#balancers=new Map;get workers(){return[...this.#workers.values()]}get balancers(){return this.#balancers}getProcedureNames(){const procedureNames=this.workers.map((worker=>worker.getProcedureNames()));return[...new Set(procedureNames.flat()).values()]}hasProcedure(fqn){return this.getProcedureNames().includes(fqn)}async addWorker(worker){this.#workers.add(worker);for(const name of worker.getProcedureNames()){this.#getOrCreateBalancer(name).addWorker(worker)}}removeWorker(worker){this.#workers.delete(worker);for(const name of worker.getProcedureNames()){const balancer=this.#getBalancer(name);void 0!==balancer&&balancer.removeWorker(worker)}}#getBalancer(fqn){return this.#balancers.get(fqn)}#getOrCreateBalancer(fqn){let balancer=this.#getBalancer(fqn);return void 0===balancer&&(balancer=new WorkerBalancer,this.#balancers.set(fqn,balancer)),balancer}async run(request){const balancer=this.#getBalancer(request.fqn);if(void 0===balancer)throw new ProcedureNotFound(request.fqn);return balancer.run(request)}}class WorkerMonitor{#workerManager;#frequency;#interval=null;constructor(workerManager,frequency=5e3){this.#workerManager=workerManager,this.#frequency=frequency}get workerManager(){return this.#workerManager}start(){this.#interval=setInterval((async()=>this.#monitor()),this.#frequency)}stop(){null!==this.#interval&&clearInterval(this.#interval)}async#monitor(){const promises=this.#workerManager.workers.map((worker=>this.#monitorWorker(worker)));await Promise.all(promises)}async#monitorWorker(worker){!1===await this.#checkWorkerAvailable(worker)&&this.#workerManager.removeWorker(worker)}async#checkWorkerAvailable(worker){try{return await worker.isHealthy()}catch(error){return!1}}}class InvalidTrustKey extends Unauthorized{constructor(){super("Invalid trust key")}}class LocalGateway{#url;#trustKey;#workerManager;#workerMonitor;constructor(configuration){this.#url=configuration.url,this.#trustKey=configuration.trustKey,this.#workerManager=new WorkerManager,this.#workerMonitor=new WorkerMonitor(this.#workerManager,configuration.monitorInterval)}get url(){return this.#url}get trustKey(){return this.#trustKey}async start(){return this.#workerMonitor.start()}async stop(){return this.#workerMonitor.stop()}async isHealthy(){return!0}async getHealth(){return new Map}async addWorker(worker,trustKey){if(this.#isInvalidTrustKey(trustKey))throw new InvalidTrustKey;return this.#workerManager.addWorker(worker)}getProcedureNames(){return this.#workerManager.getProcedureNames()}hasProcedure(name){return this.#workerManager.hasProcedure(name)}async run(request){return this.#workerManager.run(request)}#isInvalidTrustKey(trustKey){return void 0!==this.#trustKey&&trustKey!==this.#trustKey}}class RemoteGateway{#url;#remote;constructor(configuration){this.#url=configuration.url,this.#remote=configuration.remote}get url(){return this.#url}get trustKey(){}start(){return this.#remote.connect()}stop(){return this.#remote.disconnect()}isHealthy(){return this.#remote.isHealthy()}getHealth(){return this.#remote.getHealth()}getProcedureNames(){throw new NotImplemented}hasProcedure(name){throw new NotImplemented}addWorker(worker){return this.#remote.addWorker(worker.url,worker.getProcedureNames(),worker.trustKey)}run(request){return this.#remote.run(request)}}class Proxy{#url;#provider;#runner;constructor(configuration){this.#url=configuration.url,this.#provider=configuration.provider,this.#runner=configuration.runner}get url(){return this.#url}get trustKey(){return this.#runner.trustKey}get provider(){return this.#provider}get runner(){return this.#runner}async isHealthy(){const[providerHealthy,runnerHealthy]=await Promise.all([this.#provider.isHealthy(),this.#runner.isHealthy()]);return providerHealthy&&runnerHealthy}async getHealth(){const[providerHealth,runnerHealth]=await Promise.all([this.#provider.getHealth(),this.#runner.getHealth()]);return new Map([...providerHealth,...runnerHealth])}async start(){await Promise.all([this.#provider.start(),this.#runner.start()])}async stop(){await Promise.all([this.#runner.stop(),this.#provider.stop()])}provide(filename){return this.#provider.provide(filename)}getProcedureNames(){return this.#runner.getProcedureNames()}hasProcedure(fqn){return this.#runner.hasProcedure(fqn)}run(request){return this.#runner.run(request)}}class LocalRepository{#url;#sourcingManager;#assets;#indexFilename;#serveIndexOnNotFound;constructor(configuration){this.#url=configuration.url,this.#sourcingManager=configuration.sourcingManager,this.#assets=configuration.assets,this.#indexFilename=configuration.indexFilename??"index.html",this.#serveIndexOnNotFound=configuration.serveIndexOnNotFound??false}get url(){return this.#url}start(){return Promise.resolve()}stop(){return Promise.resolve()}async isHealthy(){return!0}async getHealth(){return new Map}async provide(filename){if(this.#mustProvideIndex(filename))return this.provide(this.#indexFilename);if(!1===this.#assets.has(filename))throw new FileNotFound(filename);return this.#sourcingManager.read(filename)}#mustProvideIndex(filename){return""===filename||filename!==this.#indexFilename&&(this.#serveIndexOnNotFound&&!1===this.#assets.has(filename))}}class RemoteRepository{#url;#remote;constructor(configuration){this.#url=configuration.url,this.#remote=configuration.remote}get url(){return this.#url}start(){return this.#remote.connect()}stop(){return this.#remote.disconnect()}isHealthy(){return this.#remote.isHealthy()}getHealth(){return this.#remote.getHealth()}provide(filename){return this.#remote.provide(filename)}}class ClassNotFound extends Error{constructor(name){super(`The class '${name}' could not be found`)}}class InvalidClass extends Error{constructor(name){super(`The class '${name}' is invalid`)}}class NoDeserializerFound extends Error{constructor(type){super(`No deserializer found for value of type '${type}'`)}}class NoSerializerFound extends Error{constructor(type){super(`No serializer found for value of type '${type}'`)}}class Serializer{#serializers=[];addSerializer(serializer){serializer.parent=this,this.#serializers.unshift(serializer)}async serialize(value){const serializer=this.#serializers.find((serializer=>serializer.canSerialize(value)));if(void 0===serializer)throw new NoSerializerFound(typeof value);return serializer.serialize(value)}async deserialize(value){const serializer=this.#serializers.find((serializer=>serializer.canDeserialize(value)));if(void 0===serializer)throw new NoDeserializerFound(typeof value);return serializer.deserialize(value)}}class ParentSerializerNotSet extends Error{constructor(){super("Parent serializer not set")}}class ValueSerializer{#parent;set parent(parent){this.#parent=parent}serializeOther(value){if(void 0===this.#parent)throw new ParentSerializerNotSet;return this.#parent.serialize(value)}deserializeOther(value){if(void 0===this.#parent)throw new ParentSerializerNotSet;return this.#parent.deserialize(value)}}class ArraySerializer extends ValueSerializer{canSerialize(value){return value instanceof Array}canDeserialize(value){return value instanceof Array}async serialize(array){const values=[];for(const value of array)values.push(await this.serializeOther(value));return values}async deserialize(array){return Promise.all(array.map((async value=>this.deserializeOther(value))))}}class InvalidBigIntString extends Error{constructor(bigIntString){super(`Invalid BigInt string '${bigIntString}'`)}}class BigIntSerializer extends ValueSerializer{canSerialize(value){return"bigint"==typeof value}canDeserialize(value){const bigInt=value;return bigInt instanceof Object&&!0===bigInt.serialized&&"BigInt"===bigInt.name&&"string"==typeof bigInt.value}async serialize(bigInt){return{serialized:!0,name:"BigInt",value:bigInt.toString()}}async deserialize(object){try{return BigInt(object.value)}catch(error){throw new InvalidBigIntString(object.value)}}}const reflector$1=new Reflector;class ClassSerializer extends ValueSerializer{#classResolver;constructor(classResolver){super(),this.#classResolver=classResolver}canSerialize(value){return value instanceof Object&&reflector$1.isClassObject(value)}canDeserialize(value){const object=value;return object instanceof Object&&!0===object.serialized&&"class"===object.name&&"string"==typeof object.key&&object.args instanceof Object&&object.args.constructor===Object&&object.fields instanceof Object&&object.fields.constructor===Object}async serialize(object){const clazz=reflector$1.getClass(object),model=reflector$1.fromClass(clazz,!0),parameterNames=this.#extractConstructorParameters(model),key=this.#classResolver.resolveKey(clazz);if(void 0===key)throw new ClassNotFound(clazz.name);return{serialized:!0,key:key,name:"class",args:await this.#serializeConstructor(model,parameterNames,object),fields:await this.#serializeFields(model,parameterNames,object)}}#extractConstructorParameters(model){const constructor=model.getFunction("constructor");return(constructor?.parameters??[]).map((parameter=>parameter.name))}async#serializeConstructor(model,includeNames,object){const args={};for(const[index,name]of includeNames.entries()){const value=model.canRead(name)?await this.serializeOther(object[name]):void 0;args[index.toString()]=value}return args}async#serializeFields(model,excludeNames,object){const fields={};for(const property of model.writable){const name=property.name;excludeNames.includes(name)||!1===model.canRead(name)||(fields[name]=await this.serializeOther(object[name]))}return fields}async deserialize(object){const clazz=await this.#getClass(object);if(void 0===clazz)throw new ClassNotFound(object.key);if(clazz instanceof Function==!1)throw new InvalidClass(object.key);const args=await this.#deserializeConstructor(clazz,object.args),instance=reflector$1.createInstance(clazz,args);for(const name in object.fields){const fieldValue=object.fields[name];instance[name]=await this.deserializeOther(fieldValue)}return instance}async#deserializeConstructor(clazz,args){const constructor=reflector$1.fromClass(clazz,!0).getFunction("constructor"),values=(constructor?.parameters??[]).map(((_,index)=>{const key=index.toString(),value=args[key];return this.deserializeOther(value)}));return Promise.all(values)}async#getClass(resolvable){return globalThis[resolvable.key]??this.#classResolver.resolveClass(resolvable.key)}}class InvalidDateString extends Error{constructor(dateString){super(`Invalid date string '${dateString}'`)}}class DateSerializer extends ValueSerializer{canSerialize(value){return value instanceof Date}canDeserialize(value){const date=value;return date instanceof Object&&!0===date.serialized&&"Date"===date.name&&"string"==typeof date.value}async serialize(date){return{serialized:!0,name:"Date",value:date.toISOString()}}async deserialize(object){const date=new Date(object.value);if("Invalid Date"===date.toString())throw new InvalidDateString(object.value);return date}}class ErrorSerializer extends ValueSerializer{canSerialize(value){if(value instanceof Object==!1)return!1;const error=value;return error.constructor===Error||error.constructor===EvalError||error.constructor===RangeError||error.constructor===ReferenceError||error.constructor===SyntaxError||error.constructor===TypeError||error.constructor===URIError||error.constructor===AggregateError}canDeserialize(value){const error=value;return error instanceof Object&&!0===error.serialized&&"Error"===error.name&&error.type in globalThis}async serialize(error){return{serialized:!0,name:"Error",type:error.constructor.name,stack:error.stack,message:error.message,cause:error.cause}}async deserialize(object){const error=new(0,globalThis[object.type]);return error.stack=object.stack,error.message=object.message,error.cause=object.cause,error}}class MapSerializer extends ValueSerializer{canSerialize(value){return value instanceof Map}canDeserialize(value){const map=value;return map instanceof Object&&!0===map.serialized&&"Map"===map.name&&map.entries instanceof Object&&map.entries.keys instanceof Array&&map.entries.values instanceof Array}async serialize(map){const keys=[],values=[];for(const[key,value]of map)keys.push(await this.serializeOther(key)),values.push(await this.serializeOther(value));return{serialized:!0,name:"Map",entries:{keys:keys,values:values}}}async deserialize(object){const keys=object.entries.keys,values=object.entries.values,result=new Map;for(let index=0;index<keys.length;index++){const key=await this.deserializeOther(keys[index]),value=await this.deserializeOther(values[index]);result.set(key,value)}return result}}class ObjectSerializer extends ValueSerializer{canSerialize(value){return value instanceof Object&&value.constructor===Object}canDeserialize(value){return value instanceof Object&&value.constructor===Object}async serialize(object){const result={};for(const key in object){const value=object[key];result[key]=await this.serializeOther(value)}return result}async deserialize(object){const result={};for(const key in object){const value=object[key];result[key]=await this.deserializeOther(value)}return result}}class PrimitiveSerializer extends ValueSerializer{canSerialize(value){return value instanceof Object==!1}canDeserialize(value){return value instanceof Object==!1}async serialize(primitive){return primitive}async deserialize(primitive){return primitive}}class InvalidRegExp extends Error{constructor(source,flags){super(`Invalid regular expression '${source}' with flags '${flags}'`)}}class RegExpSerializer extends ValueSerializer{canSerialize(value){return value instanceof RegExp}canDeserialize(value){const regExp=value;return regExp instanceof Object&&!0===regExp.serialized&&"RegExp"===regExp.name&&"string"==typeof regExp.source&&"string"==typeof regExp.flags}async serialize(regExp){return{serialized:!0,name:"RegExp",source:regExp.source,flags:regExp.flags}}async deserialize(object){try{return new RegExp(object.source,object.flags)}catch(error){throw new InvalidRegExp(object.source,object.flags)}}}class SetSerializer extends ValueSerializer{canSerialize(value){return value instanceof Set}canDeserialize(value){const set=value;return set instanceof Object&&!0===set.serialized&&"Set"===set.name&&set.values instanceof Array}async serialize(set){const values=[];for(const value of set.values())values.push(await this.serializeOther(value));return{serialized:!0,name:"Set",values:values}}async deserialize(object){const values=await Promise.all(object.values.map((async value=>this.deserializeOther(value))));return new Set([...values])}}const reflector=new Reflector;class ArrayBufferSerializer extends ValueSerializer{canSerialize(value){return value instanceof Int8Array||value instanceof Uint8Array||value instanceof Uint8ClampedArray||value instanceof Int16Array||value instanceof Uint16Array||value instanceof Int32Array||value instanceof Uint32Array||value instanceof Float32Array||value instanceof Float64Array||value instanceof BigInt64Array||value instanceof BigUint64Array}canDeserialize(value){const array=value;return array instanceof Object&&!0===array.serialized&&"TypedArray"===array.name&&array.type in globalThis&&array.bytes instanceof Array}async serialize(array){const type=array.constructor.name,view=new DataView(array.buffer),bytes=[];for(let index=0;index<view.byteLength;index++)bytes.push(view.getUint8(index));return{serialized:!0,name:"TypedArray",type:type,bytes:bytes}}async deserialize(object){const type=object.type,bytes=object.bytes,buffer=new ArrayBuffer(bytes.length),view=new DataView(buffer);for(let index=0;index<bytes.length;index++)view.setUint8(index,bytes[index]);const clazz=globalThis[type];return reflector.createInstance(clazz,[buffer])}}class InvalidUrlString extends Error{constructor(urlString){super(`Invalid url string '${urlString}'`)}}class UrlSerializer extends ValueSerializer{canSerialize(value){return value instanceof URL}canDeserialize(value){const url=value;return url instanceof Object&&!0===url.serialized&&"Url"===url.name&&"string"==typeof url.value}async serialize(url){return{serialized:!0,name:"Url",value:url.toString()}}async deserialize(object){try{return new URL(object.value)}catch(error){throw new InvalidUrlString(object.value)}}}class SerializerBuilder{static build(classResolver){const serializer=new Serializer;return serializer.addSerializer(new PrimitiveSerializer),serializer.addSerializer(new ObjectSerializer),void 0!==classResolver&&serializer.addSerializer(new ClassSerializer(classResolver)),serializer.addSerializer(new ErrorSerializer),serializer.addSerializer(new RegExpSerializer),serializer.addSerializer(new BigIntSerializer),serializer.addSerializer(new UrlSerializer),serializer.addSerializer(new DateSerializer),serializer.addSerializer(new SetSerializer),serializer.addSerializer(new MapSerializer),serializer.addSerializer(new ArraySerializer),serializer.addSerializer(new ArrayBufferSerializer),serializer}}class ExecutionClassResolver{#executionManager;constructor(executionManager){this.#executionManager=executionManager}resolveKey(clazz){const model=this.#executionManager.getClassByImplementation(clazz);return model?.fqn}resolveClass(key){const model=this.#executionManager.getClass(key);return model?.implementation}}class RequestNotTrusted extends Unauthorized{constructor(){super("Request not trusted")}}class LocalWorker{#url;#trustKey;#gateway;#executionManager;#serializer;constructor(configuration){this.#url=configuration.url,this.#trustKey=configuration.trustKey,this.#gateway=configuration.gateway,this.#executionManager=configuration.executionManager;const classResolver=new ExecutionClassResolver(this.#executionManager);this.#serializer=SerializerBuilder.build(classResolver)}get url(){return this.#url}get trustKey(){return this.#trustKey}async start(){void 0!==this.#gateway&&(await this.#gateway.start(),await this.#gateway.addWorker(this))}async stop(){void 0!==this.#gateway&&await this.#gateway.stop()}getProcedureNames(){return this.#executionManager.getProcedureNames()}hasProcedure(name){return this.#executionManager.hasProcedure(name)}async isHealthy(){return!0}async getHealth(){return new Map}async run(request){return this.#mustRunLocal(request)?this.#runLocal(request):this.#runRemote(request)}#mustRunLocal(request){return void 0===this.#gateway||this.#executionManager.hasProcedure(request.fqn)}async#runLocal(request){const procedure=this.#executionManager.getProcedure(request.fqn),implementation=procedure?.getImplementation(request.version);if(this.#procedureNotFound(implementation))throw new ProcedureNotFound(request.fqn);if(this.#requestNotTrusted(request,implementation))throw new RequestNotTrusted;const dataEncoding=request.getHeader("X-Jitar-Data-Encoding");"serialized"===dataEncoding&&(request=await this.#deserializeRequest(request)),request.removeHeader("X-Jitar-Data-Encoding");const response=await this.#executionManager.run(request);return"serialized"===dataEncoding?this.#serializeResponse(response):response}#procedureNotFound(implementation){return void 0===implementation||implementation.private}#requestNotTrusted(request,implementation){if(implementation.public)return!1;const trustKey=request.getHeader("X-Jitar-Trust-Key");return this.#trustKey!==trustKey}async#runRemote(request){(request=await this.#serializeRequest(request)).setHeader("X-Jitar-Data-Encoding","serialized"),void 0!==this.#trustKey&&request.setHeader("X-Jitar-Trust-Key",this.#trustKey);const response=await this.#gateway.run(request);return this.#deserializeResponse(response)}async#serializeRequest(request){const serializedArgs=new Map;for(const[key,value]of request.args){const serializedValue=await this.#serializer.serialize(value);serializedArgs.set(key,serializedValue)}return new Request(request.fqn,request.version,serializedArgs,request.headers,request.mode)}async#deserializeRequest(request){const deserializedArgs=new Map;for(const[key,value]of request.args){const deserializedValue=await this.#serializer.deserialize(value);deserializedArgs.set(key,deserializedValue)}return new Request(request.fqn,request.version,deserializedArgs,request.headers,request.mode)}async#serializeResponse(response){const serializedResult=await this.#serializer.serialize(response.result);return new Response(response.status,serializedResult,response.headers)}async#deserializeResponse(response){const deserializedResult=await this.#serializer.deserialize(response.result);return new Response(response.status,deserializedResult,response.headers)}}class RemoteWorker{#url;#procedureNames;#remote;constructor(configuration){this.#url=configuration.url,this.#procedureNames=configuration.procedureNames,this.#remote=configuration.remote}get url(){return this.#url}get trustKey(){}start(){return this.#remote.connect()}stop(){return this.#remote.disconnect()}getProcedureNames(){return[...this.#procedureNames.values()]}hasProcedure(name){return this.#procedureNames.has(name)}isHealthy(){return this.#remote.isHealthy()}getHealth(){return this.#remote.getHealth()}run(request){return this.#remote.run(request)}}class ProcedureRunner{#runner;constructor(runner){this.#runner=runner}async handle(request,next){return this.#runner.run(request)}}class Runtime{#versionParser=new VersionParser;constructor(){this.#initGlobals()}#initGlobals(){const globals=globalThis;globals.__run=this.#run.bind(this),globals.ProcedureNotAccessible=ProcedureNotAccessible}async#run(fqn,versionNumber,args,sourceRequest){const version=this.#versionParser.parse(versionNumber),argsMap=new Map(Object.entries(args)),headersMap=sourceRequest instanceof Request?sourceRequest.headers:new Map,targetRequest=new Request(fqn,version,argsMap,headersMap,RunModes_NORMAL),trustKey=this.getTrustKey();void 0!==trustKey&&targetRequest.setHeader("X-Jitar-Trust-Key",trustKey);const targetResponse=await this.runInternal(targetRequest);if(targetResponse.status!==StatusCodes$1_OK)throw targetResponse.result;return targetResponse.result}}class InvalidMiddleware extends ServerError{constructor(){super("Invalid middleware")}}class MiddlewareManager{#middlewares=[];addMiddleware(middleware){if(void 0===middleware?.handle)throw new InvalidMiddleware;this.#middlewares.push(middleware)}getMiddleware(type){return this.#middlewares.find((middleware=>middleware instanceof type))}clearMiddlewares(){this.#middlewares=[]}handle(request){return this.#getNextHandler(request,0)()}#getNextHandler(request,index){const next=this.#middlewares[index];if(void 0===next)return async()=>new Response(StatusCodes$1_OK);const nextHandler=this.#getNextHandler(request,index+1);return async()=>next.handle(request,nextHandler)}}const ContentTypes_NULL="application/null",ContentTypes_UNDEFINED="application/undefined",ContentTypes_BOOLEAN="application/boolean",ContentTypes_NUMBER="application/number",ContentTypes_JSON="application/json",ContentTypes_TEXT="text/plain",StatusCodes_OK=200,StatusCodes_BAD_REQUEST=400,StatusCodes_UNAUTHORIZED=401,StatusCodes_PAYMENT_REQUIRED=402,StatusCodes_FORBIDDEN=403,StatusCodes_NOT_FOUND=404,StatusCodes_TEAPOT=418,StatusCodes_SERVER_ERROR=500,StatusCodes_NOT_IMPLEMENTED=501;class Server extends Runtime{#proxy;#sourcingManager;#remoteBuilder;#middlewareManager;#healthManager;#setUpScripts;#tearDownScripts;#logger;#versionParser=new VersionParser;constructor(configuration){super(),this.#proxy=configuration.proxy,this.#sourcingManager=configuration.sourcingManager,this.#remoteBuilder=configuration.remoteBuilder,this.#middlewareManager=configuration.middlewareManager,this.#healthManager=configuration.healthManager,this.#setUpScripts=configuration.setUpScripts??[],this.#tearDownScripts=configuration.tearDownScripts??[],this.#logger=configuration.logger;const procedureRunner=new ProcedureRunner(this.#proxy);this.#middlewareManager.addMiddleware(procedureRunner)}get proxy(){return this.#proxy}getTrustKey(){return this.#proxy.trustKey}async start(){await this.#setUp(),await this.#proxy.start(),this.#logger.info(`Server started at ${this.#proxy.url}`),this.#proxy.runner instanceof LocalWorker&&this.#logger.info("RPC procedures:",this.#proxy.runner.getProcedureNames())}async stop(){await this.#proxy.stop(),await this.#tearDown(),this.#logger.info("Server stopped")}async getHealth(){try{const internalHealth=await this.#proxy.getHealth(),externalHealth=await this.#healthManager.getHealth(),health=new Map([...internalHealth,...externalHealth]);return this.#logger.debug("Got health"),this.#respondHealth(health)}catch(error){const message=error instanceof Error?error.message:String(error);return this.#logger.error("Failed to get health:",message),this.#respondError(error)}}async isHealthy(){try{const internalsHealthy=await this.#proxy.isHealthy(),externalsHealthy=await this.#healthManager.isHealthy(),healthy=internalsHealthy&&externalsHealthy;return this.#logger.debug("Got health status"),this.#respondHealthy(healthy)}catch(error){const message=error instanceof Error?error.message:String(error);return this.#logger.error("Failed to get health status:",message),this.#respondError(error)}}async provide(provideRequest){try{const file=await this.#proxy.provide(provideRequest.filename);return this.#logger.info("Provided file:",provideRequest.filename),this.#respondFile(file)}catch(error){const message=error instanceof Error?error.message:String(error);return this.#logger.warn("Failed to provide file:",message),this.#respondError(error)}}async run(runRequest){try{const request=this.#transformRunRequest(runRequest),response=await this.#middlewareManager.handle(request);return this.#logger.info("Ran request:",request.fqn),this.#respondResponse(response)}catch(error){const message=error instanceof Error?error.message:String(error);return this.#logger.error("Failed run request:",message),this.#respondError(error)}}async runInternal(request){return this.#proxy.run(request)}async addWorker(addRequest){try{const runner=this.#proxy.runner;if(runner instanceof LocalGateway==!1)throw new BadRequest("Cannot add worker to remote gateway");const worker=this.#buildRemoteWorker(addRequest.url,addRequest.procedureNames);return await runner.addWorker(worker,addRequest.trustKey),this.#logger.info("Added worker:",worker.url),this.#respondSuccess()}catch(error){const message=error instanceof Error?error.message:String(error);return this.#logger.error("Failed to add worker:",message),this.#respondError(error)}}#setUp(){return this.#runScripts(this.#setUpScripts)}#tearDown(){return this.#runScripts(this.#tearDownScripts)}async#runScripts(scripts){await Promise.all(scripts.map((script=>this.#sourcingManager.import(script))))}#transformRunRequest(request){const fqn=this.#processFqn(request.fqn),version=this.#parseVersion(request.version),args=this.#mapArguments(request.args),headers=this.#mapHeaders(request.headers);return new Request(fqn,version,args,headers,request.mode)}#processFqn(fqn){if(0===fqn.length)throw new BadRequest("Missing procedure name");if(fqn.includes(".."))throw new BadRequest("Invalid procedure name");return fqn}#parseVersion(version){return"string"!=typeof version?Version.DEFAULT:this.#versionParser.parse(version)}#mapArguments(args){return new Map(Object.entries(args))}#mapHeaders(headers){const map=new Map;for(const[key,value]of Object.entries(headers)){if(void 0===value)continue;const lowerKey=key.toLowerCase(),stringValue=value.toString();map.set(lowerKey,stringValue)}return map}#respondHealth(health){return{result:Object.fromEntries(health),contentType:ContentTypes_JSON,headers:{},status:StatusCodes_OK}}#respondHealthy(healthy){return{result:healthy,contentType:ContentTypes_BOOLEAN,headers:{},status:StatusCodes_OK}}#respondFile(file){return{result:file.content,contentType:file.type,headers:{},status:StatusCodes_OK}}#respondResponse(response){const result=response.result instanceof Error?response.result.message:response.result;return{result:result,contentType:this.#determineContentType(result),headers:this.#unmapHeaders(response.headers),status:response.status}}#respondError(error){const result=error instanceof Error?error.message:String(error);return{result:result,contentType:this.#determineContentType(result),headers:{},status:this.#determineStatusCode(error)}}#respondSuccess(){return{result:undefined,contentType:ContentTypes_TEXT,headers:{},status:StatusCodes_OK}}#determineContentType(content){if(void 0===content)return ContentTypes_UNDEFINED;if(null===content)return ContentTypes_NULL;switch(typeof content){case"boolean":return ContentTypes_BOOLEAN;case"number":return ContentTypes_NUMBER;case"object":return ContentTypes_JSON;default:return ContentTypes_TEXT}}#unmapHeaders(headers){return Object.fromEntries(headers)}#determineStatusCode(error){return error instanceof BadRequest?StatusCodes_BAD_REQUEST:error instanceof Forbidden?StatusCodes_FORBIDDEN:error instanceof NotFound?StatusCodes_NOT_FOUND:error instanceof NotImplemented?StatusCodes_NOT_IMPLEMENTED:error instanceof PaymentRequired?StatusCodes_PAYMENT_REQUIRED:error instanceof Teapot?StatusCodes_TEAPOT:error instanceof Unauthorized?StatusCodes_UNAUTHORIZED:StatusCodes_SERVER_ERROR}#buildRemoteWorker(url,procedures){const remote=this.#remoteBuilder.build(url),procedureNames=new Set(procedures);return new RemoteWorker({url:url,remote:remote,procedureNames:procedureNames})}}class InvalidHealthCheck extends ServerError{constructor(){super("Invalid health check")}}class HealthManager{#healthChecks=new Map;addHealthCheck(healthCheck){if(void 0===healthCheck.isHealthy)throw new InvalidHealthCheck;this.#healthChecks.set(healthCheck.name,healthCheck)}clearHealthChecks(){this.#healthChecks.clear()}async isHealthy(){const promises=[];for(const healthCheck of this.#healthChecks.values()){const promise=this.#executeHealthCheck(healthCheck);promises.push(promise)}return Promise.all(promises).then((results=>results.every((result=>result)))).catch((()=>!1))}async getHealth(){const promises=[];for(const[name,healthCheck]of this.#healthChecks){const promise=this.#executeHealthCheck(healthCheck).then((result=>({name:name,isHealthy:result}))).catch((()=>({name:name,isHealthy:!1})));promises.push(promise)}const healthChecks=new Map;return Promise.allSettled(promises).then((results=>results.forEach((result=>{"fulfilled"===result.status?healthChecks.set(result.value.name,result.value.isHealthy):healthChecks.set(result.reason.name,!1)})))).then((()=>healthChecks))}async#executeHealthCheck(healthCheck){const health=healthCheck.isHealthy(),milliseconds=healthCheck.timeout;if(void 0===milliseconds)return health;const timeout=new Promise((resolve=>{setTimeout(resolve,milliseconds)})).then((()=>!1));return Promise.race([timeout,health])}}class UnknownServiceConfigured extends Error{constructor(){super("Unknown service configured")}}class RuntimeBuilder{#sourcingManager;#remoteBuilder;constructor(sourcingManager,remoteBuilder){this.#sourcingManager=sourcingManager,this.#remoteBuilder=remoteBuilder}async build(configuration,logLevel){const setUp=configuration.setUp??[],tearDown=configuration.tearDown??[],middleware=configuration.middleware,healthChecks=configuration.healthChecks,proxy=await this.#buildService(configuration),sourcingManager=this.#sourcingManager,remoteBuilder=this.#remoteBuilder,middlewareManager=await this.#buildMiddlewareManager(middleware),healthManager=await this.#buildHealthManager(healthChecks),setUpScripts=setUp.map((filename=>this.#makeSharedFilename(filename))),tearDownScripts=tearDown.map((filename=>this.#makeSharedFilename(filename))),logger=new Logger(logLevel);return new Server({proxy:proxy,sourcingManager:sourcingManager,remoteBuilder:remoteBuilder,middlewareManager:middlewareManager,healthManager:healthManager,setUpScripts:setUpScripts,tearDownScripts:tearDownScripts,logger:logger})}#buildService(configuration){if(void 0!==configuration.gateway)return this.#buildGatewayProxy(configuration.url,configuration.gateway);if(void 0!==configuration.worker)return this.#buildWorkerProxy(configuration.url,configuration.worker);if(void 0!==configuration.repository)return this.#buildRepositoryProxy(configuration.url,configuration.repository);if(void 0!==configuration.proxy)return this.#buildProxy(configuration.url,configuration.proxy);if(void 0!==configuration.standalone)return this.#buildStandalone(configuration.url,configuration.standalone);throw new UnknownServiceConfigured}async#buildGatewayProxy(url,configuration){const provider=new DummyProvider,runner=await this.#buildLocalGateway(url,configuration);return new Proxy({url:url,provider:provider,runner:runner})}async#buildWorkerProxy(url,configuration){const provider=new DummyProvider,runner=await this.#buildLocalWorker(url,configuration);return new Proxy({url:url,provider:provider,runner:runner})}async#buildRepositoryProxy(url,configuration){const provider=await this.#buildLocalRepository(url,configuration),runner=new DummyRunner;return new Proxy({url:url,provider:provider,runner:runner})}async#buildLocalGateway(url,configuration){const trustKey=configuration.trustKey,monitorInterval=configuration.monitor;return new LocalGateway({url:url,trustKey:trustKey,monitorInterval:monitorInterval})}#buildRemoteGateway(url){const remote=this.#remoteBuilder.build(url);return new RemoteGateway({url:url,remote:remote})}async#buildLocalWorker(url,configuration){const trustKey=configuration.trustKey,gateway=configuration.gateway?this.#buildRemoteGateway(configuration.gateway):void 0,executionManager=await this.#buildExecutionManager(configuration.segments);return new LocalWorker({url:url,trustKey:trustKey,gateway:gateway,executionManager:executionManager})}async#buildLocalRepository(url,configuration){const sourcingManager=this.#sourcingManager,assets=await this.#buildAssetSet(configuration.assets),indexFilename=configuration.indexFilename,serveIndexOnNotFound=configuration.serveIndexOnNotFound;return new LocalRepository({url:url,sourcingManager:sourcingManager,assets:assets,indexFilename:indexFilename,serveIndexOnNotFound:serveIndexOnNotFound})}#buildRemoteRepository(url){const remote=this.#remoteBuilder.build(url);return new RemoteRepository({url:url,remote:remote})}async#buildProxy(url,configuration){const provider=this.#buildRemoteRepository(configuration.repository),runner=this.#buildRemoteGateway(configuration.gateway);return new Proxy({url:url,provider:provider,runner:runner})}async#buildStandalone(url,configuration){const provider=await this.#buildLocalRepository(url,configuration),runner=await this.#buildLocalWorker(url,configuration);return new Proxy({url:url,provider:provider,runner:runner})}async#buildHealthManager(filenames){const manager=new HealthManager;if(void 0!==filenames){const sharedFilenames=filenames.map((filename=>this.#makeSharedFilename(filename)));(await Promise.all(sharedFilenames.map((filename=>this.#sourcingManager.import(filename))))).forEach((module=>manager.addHealthCheck(module.default)))}return manager}async#buildMiddlewareManager(filenames){const manager=new MiddlewareManager;if(void 0!==filenames){const sharedFilenames=filenames.map((filename=>this.#makeSharedFilename(filename)));(await Promise.all(sharedFilenames.map((filename=>this.#sourcingManager.import(filename))))).forEach((module=>manager.addMiddleware(module.default)))}return manager}async#buildExecutionManager(segmentNames){const manager=new ExecutionManager,filenames=segmentNames.map((name=>`./${name}.segment.js`));return(await Promise.all(filenames.map((filename=>this.#sourcingManager.import(filename))))).forEach((module=>manager.addSegment(module.default))),manager}async#buildAssetSet(patterns){if(void 0===patterns)return new Set;const filenames=await this.#sourcingManager.filter(...patterns);return new Set(filenames)}#makeSharedFilename(filename){return!1===filename.endsWith(".js")&&(filename+=".js"),filename.replace(".js",".shared.js")}}const Defaults_PORT_NUMBER="3000",Defaults_BODY_LIMIT=204800,IgnoredHeaderKeys=["host","connection","content-length","accept-encoding","user-agent","keep-alive"];class HttpServer{#server;#port;#app;#http;#validator=new Validator;constructor(server,port=Defaults_PORT_NUMBER,bodyLimit=Defaults_BODY_LIMIT){this.#server=server,this.#port=port,this.#app=express(),this.#setupExpress(bodyLimit),this.#setupRoutes()}async start(){return await this.#server.start(),this.#startHttp()}async stop(){return await this.#stopHttp(),this.#server.stop()}#setupExpress(bodyLimit){this.#app.use(express.json({limit:bodyLimit})),this.#app.use(express.urlencoded({extended:!0})),this.#app.use(this.#addDefaultHeaders.bind(this)),this.#app.disable(HeaderKeys_POWERED_BY)}#setupRoutes(){this.#app.get("/health",this.#getHealth.bind(this)),this.#app.get("/health/status",this.#isHealthy.bind(this)),this.#app.get("/rpc/*",this.#runGet.bind(this)),this.#app.post("/rpc/*",this.#runPost.bind(this)),this.#app.options("/rpc/*",this.#runOptions.bind(this)),this.#app.post("/workers",this.#addWorker.bind(this)),this.#app.get("*",this.#provide.bind(this))}#startHttp(){return void 0!==this.#http?Promise.resolve():new Promise(((resolve,reject)=>{this.#http=this.#app.listen(this.#port,resolve),this.#http.on("error",reject)}))}#stopHttp(){return void 0===this.#http?Promise.resolve():new Promise((resolve=>{this.#http.close((()=>resolve()))}))}#addDefaultHeaders(request,response,next){response.setHeader(HeaderKeys_CONTENT_TYPE_OPTIONS,HeaderValues_NO_SNIFF),next()}async#getHealth(request,response){const serverResponse=await this.#server.getHealth();return this.#transformResponse(response,serverResponse)}async#isHealthy(request,response){const serverResponse=await this.#server.isHealthy();return this.#transformResponse(response,serverResponse)}async#runGet(request,response){const fqn=this.#extractFqn(request),version=this.#extractVersion(request),args=this.#extractQueryArguments(request),headers=this.#extractHeaders(request),mode=RunModes_NORMAL,serverResponse=await this.#server.run({fqn:fqn,version:version,args:args,headers:headers,mode:mode});return this.#transformResponse(response,serverResponse)}async#runPost(request,response){const fqn=this.#extractFqn(request),version=this.#extractVersion(request),args=this.#extractBodyArguments(request),headers=this.#extractHeaders(request),mode=RunModes_NORMAL,serverResponse=await this.#server.run({fqn:fqn,version:version,args:args,headers:headers,mode:mode});return this.#transformResponse(response,serverResponse)}async#runOptions(request,response){const fqn=this.#extractFqn(request),version=this.#extractVersion(request),args=this.#extractBodyArguments(request),headers=this.#extractHeaders(request),mode=RunModes_DRY,serverResponse=await this.#server.run({fqn:fqn,version:version,args:args,headers:headers,mode:mode});return this.#transformResponse(response,serverResponse)}async#addWorker(request,response){const args=this.#extractBodyArguments(request),validation=this.#validator.validate(args,{url:{type:"url",required:!0},procedureNames:{type:"list",required:!0,items:{type:"string"}},trustKey:{type:"string",required:!1}});if(!1===validation.valid)return response.status(400).send(validation.errors.join("\n"));const url=args.url,procedureNames=args.procedureNames,trustKey=args.trustKey;try{const serverResponse=await this.#server.addWorker({url:url,procedureNames:procedureNames,trustKey:trustKey});return this.#transformResponse(response,serverResponse)}catch(error){const message=error instanceof Error?error.message:"Server error";return response.status(500).send(message)}}async#provide(request,response){const path=request.path.substring(1).trim(),filename=decodeURIComponent(path),serverResponse=await this.#server.provide({filename:filename});return this.#transformResponse(response,serverResponse)}#extractFqn(request){return decodeURIComponent(request.path.trim()).substring(5).trim()}#extractVersion(request){const versionString=request.headers[HeaderKeys_JITAR_PROCEDURE_VERSION];return Array.isArray(versionString)?versionString[0]:versionString}#extractQueryArguments(request){const args={};for(const[key,value]of Object.entries(request.query))args[key]=value;return args}#extractBodyArguments(request){return request.body}#extractHeaders(request){const headers={};for(const[key,value]of Object.entries(request.headers)){if(void 0===value)continue;const lowerKey=key.toLowerCase(),stringValue=value.toString();IgnoredHeaderKeys.includes(lowerKey)||(headers[lowerKey]=stringValue)}return headers}#transformResponse(response,serverResponse){const status=this.#transformStatus(serverResponse),contentType=this.#transformContentType(serverResponse);response.status(status),response.setHeader(HeaderKeys_CONTENT_TYPE,contentType),response.setHeader(HeaderKeys_JITAR_CONTENT_TYPE,serverResponse.contentType);for(const[name,value]of Object.entries(serverResponse.headers))response.setHeader(name,value);const result=this.#transformResult(serverResponse);return response.send(result)}#transformStatus(serverResponse){return void 0!==serverResponse.headers.location?302:serverResponse.status}#transformContentType(serverResponse){const contentType=serverResponse.contentType.toLowerCase();switch(contentType){case ContentTypes_BOOLEAN:case ContentTypes_NUMBER:case ContentTypes_UNDEFINED:case ContentTypes_NULL:return ContentTypes_TEXT}return contentType}#transformResult(serverResponse){const result=serverResponse.result;return"number"==typeof result||"boolean"==typeof result?String(result):result}}class StartServer{async execute(args){const environmentFile=args.getOptionalArgument("--env-file",void 0),runtimeConfigFile=args.getOptionalArgument("--config",void 0),serviceConfigFile=args.getRequiredArgument("--service"),logLevelString=args.getOptionalArgument("--log-level",void 0),logLevel=this.#parseLogLevel(logLevelString),bodyLimitString=args.getOptionalArgument("--http-body-limit",void 0),bodyLimit=this.#parseBodyLimit(bodyLimitString),configurationManager=new ConfigurationManager;await configurationManager.configureEnvironment(environmentFile);const runtimeConfiguration=await configurationManager.getRuntimeConfiguration(runtimeConfigFile),serverConfiguration=await configurationManager.getServerConfiguration(serviceConfigFile),httpServer=await this.#buildServer(runtimeConfiguration,serverConfiguration,bodyLimit,logLevel);return this.#runServer(httpServer)}async#buildServer(runtimeConfiguration,serverConfiguration,bodyLimit,logLevel){const[protocol,host,port]=serverConfiguration.url.split(":"),fileManager=new LocalFileManager(runtimeConfiguration.target),sourcingManager=new SourceManager(fileManager),remoteBuilder=new HttpRemoteBuilder,serverBuilder=new RuntimeBuilder(sourcingManager,remoteBuilder),server=await serverBuilder.build(serverConfiguration,logLevel);return new HttpServer(server,port,bodyLimit)}#runServer(httpServer){return process.on("SIGINT",(async()=>httpServer.stop())),console.log("\n ██╗██╗████████╗ █████╗ ██████╗ \n ██║██║╚══██╔══╝██╔══██╗██╔══██╗\n ██║██║ ██║ ███████║██████╔╝\n██ ██║██║ ██║ ██╔══██║██╔══██╗\n╚█████╔╝██║ ██║ ██║ ██║██║ ██║\n ╚════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝\n ~ Distributed JavaScript Runtime ~\n____________________________________\n"),httpServer.start()}#parseLogLevel(logLevel){if(void 0===logLevel)return;return(new LogLevelParser).parse(logLevel)}#parseBodyLimit(bodyLimit){if(!1!==Number.isInteger(bodyLimit))return Number.parseInt(bodyLimit)}}class CommandRunner{#commands=new Map;constructor(){this.#commands.set("help",new ShowHelp),this.#commands.set("about",new ShowAbout),this.#commands.set("version",new ShowVersion),this.#commands.set("build",new BuildApp),this.#commands.set("start",new StartServer)}run(name,args){const command=this.#commands.get(name);if(void 0===command)throw new Error(`Command ${name} not found`);return command.execute(args)}}class Cli{#argumentProcessor;#commandRunner;constructor(){this.#argumentProcessor=new ArgumentProcessor(process.argv),this.#commandRunner=new CommandRunner}start(){const commandName=this.#argumentProcessor.getCommand()??"help";return this.#commandRunner.run(commandName,this.#argumentProcessor)}}try{const cli=new Cli;await cli.start()}catch(error){const logger=new Logger,message=error instanceof Error?error.message:String(error);logger.fatal(message)}
2
+ import fs from"fs-extra";import{glob}from"glob";import mime from"mime-types";import path from"path";import dotenv from"dotenv";import{B as BadRequest,N as NotFound,F as Forbidden,a as NamedParameter,A as ArrayParameter,O as ObjectParameter,b as NotImplemented,P as PaymentRequired,T as Teapot,U as Unauthorized,S as ServerError,V as Version,c as Segment$1,R as Response,d as AccessLevels,e as Request}from"./Response-D49TlRAU.js";import express from"express";import crypto from"crypto";class MissingArgument extends Error{constructor(name){super(`Missing argument '${name}'`)}}class ArgumentProcessor{#command;#args;constructor(args){this.#command=args[2],this.#args=this.#parseArguments(args)}getCommand(){return this.#command}getRequiredArgument(name){const value=this.#args.get(name);if(void 0===value)throw new MissingArgument(name);return value}getOptionalArgument(name,defaultValue){return this.#args.get(name)??defaultValue}#parseArguments(args){const commandArgs=args.slice(3),map=new Map;return commandArgs.forEach((arg=>{const[key,value]=arg.split("=");map.set(key.trim(),value?.trim())})),map}}class ShowHelp{async execute(args){console.log("\nUsage: jitar <command> [options]\n\nCommands:\n build Builds the application (creates segment bundles)\n start Starts a server with the configured service\n about Shows information about Jitar\n version Shows the installed version of Jitar\n help Shows help (this message)\n\nOptions:\n --config Path to the configuration file (default: jitar.json)\n --service Path to the service configuration file (required for 'start' command)\n --env-file Path to the environment file (default: none)\n --log-level Optional for 'start' and 'build' commands (default: info, other options: debug, warn, error, fatal)\n --http-body-limit Optional for 'start' command (default: 204,800 bytes)\nMore information can be found at https://docs.jitar.dev\n")}}class ShowAbout{async execute(args){console.log("\nJitar is a JavaScript Distributed Runtime created and maintained by Masking Technology.\n\nMore information can be found at:\n- https://jitar.dev\n- https://masking.tech\n")}}class ShowVersion{async execute(args){console.log("v0.8.0")}}const LogLevels_DEBUG=0,LogLevels_INFO=1,LogLevels_WARN=2,LogLevels_ERROR=3,LogLevels_FATAL=4;class Logger{#logLevel;#writer;constructor(logLevel=LogLevels_INFO,writer=console){this.#logLevel=logLevel,this.#writer=writer}debug(...message){if(this.#logLevel>LogLevels_DEBUG)return;const messageString=this.#createMessage("DEBUG",message);this.#writer.debug(messageString)}info(...message){if(this.#logLevel>LogLevels_INFO)return;const messageString=this.#createMessage("INFO",message);this.#writer.info(messageString)}warn(...message){if(this.#logLevel>LogLevels_WARN)return;const messageString=this.#createMessage("WARN",message);this.#writer.warn(messageString)}error(...message){if(this.#logLevel>LogLevels_ERROR)return;const messageString=this.#createMessage("ERROR",message);this.#writer.error(messageString)}fatal(...message){const messageString=this.#createMessage("FATAL",message);this.#writer.error(messageString)}#createMessage(logLevel,messages){return`[${logLevel}][${(new Date).toISOString()}] ${messages.map((value=>this.#interpretValue(value))).join(" ")}`}#interpretValue(value,level=0){let result;switch(typeof value){case"string":result=value;break;case"object":result=this.#interpretObject(value,level+1);break;case"undefined":result="undefined";break;case"function":result="function";break;default:result=String(value)}return`${this.#indent(level)}${result}`}#interpretObject(object,level){if(null===object)return"null";if(Array.isArray(object)){return`[\n${object.map((value=>this.#interpretValue(value,level))).join(",\n")}\n${this.#indent(level-1)}]`}return object instanceof Error?object.stack??object.message:JSON.stringify(object)}#indent(level){return" ".repeat(level)}}class InvalidLogLevel extends Error{constructor(logLevel){super(`Invalid log level: ${logLevel}`)}}class LogLevelParser{parse(logLevel){switch(logLevel.toUpperCase()){case"DEBUG":return LogLevels_DEBUG;case"INFO":return LogLevels_INFO;case"WARN":return LogLevels_WARN;case"ERROR":return LogLevels_ERROR;case"FATAL":return LogLevels_FATAL;default:throw new InvalidLogLevel(logLevel)}}}const Files$1_MODULE_PATTERN="**/*.js",Files$1_RESOURCE_PATTERN="**/*.json",Files$1_SEGMENT_PATTERN="**/*.json";class InvalidPath extends Error{#location;constructor(location){super(`Invalid location: ${location}`),this.#location=location}get location(){return this.#location}}class FileNotFound extends Error{#filename;constructor(filename){super(`The file '${filename}' could not be found`),this.#filename=filename}get filename(){return this.#filename}}let ModuleNotLoaded$1=class extends Error{#url;#reason;constructor(url,reason){super(`Module '${url}' could not be loaded${void 0!==reason?` | ${reason}`:""}`),this.#url=url,this.#reason=reason}get url(){return this.#url}get reason(){return this.#reason}};class File{#location;#type;#content;constructor(location,type,content){this.#location=location,this.#type=type,this.#content=content}get location(){return this.#location}get type(){return this.#type}get content(){return this.#content}get size(){return this.#content.length}}class LocalFileSystem{copy(source,destination){return fs.copy(source,destination,{overwrite:!0})}delete(location){return fs.remove(location)}exists(location){return fs.exists(location)}isDirectory(location){try{return fs.statSync(location).isDirectory()}catch{return!1}}filter(location,pattern){return glob(`${location}/${pattern}`)}join(...paths){return path.join(...paths)}read(location){return fs.readFile(location)}resolve(location){return path.resolve(location)}relative(from,to){return path.relative(from,to)}async mimeType(location){return mime.lookup(location)||void 0}async write(location,content){const directory=path.dirname(location);return fs.mkdirSync(directory,{recursive:!0}),fs.writeFile(location,content)}}class FileManager{#location;#rootLocation;#fileSystem;constructor(location,fileSystem=new LocalFileSystem){this.#location=location,this.#fileSystem=fileSystem,this.#rootLocation=fileSystem.resolve(location)}getAbsoluteLocation(filename){const location=filename.startsWith("/")?filename:this.#fileSystem.join(this.#location,filename),absolutePath=this.#fileSystem.resolve(location);return this.#validateLocation(absolutePath,filename),absolutePath}getRelativeLocation(filename){return this.#fileSystem.relative(this.#location,filename)}async getType(filename){const location=this.getAbsoluteLocation(filename);return await this.#fileSystem.mimeType(location)??"application/octet-stream"}async getContent(filename){const location=this.getAbsoluteLocation(filename);if(!1===await this.#fileSystem.exists(location))throw new FileNotFound(filename);return this.#fileSystem.read(location)}async exists(filename){const location=this.getAbsoluteLocation(filename);return this.#fileSystem.exists(location)}isDirectory(filename){const location=this.getAbsoluteLocation(filename);return this.#fileSystem.isDirectory(location)}async read(filename){const absoluteFilename=this.getAbsoluteLocation(filename),type=await this.getType(absoluteFilename),content=await this.getContent(absoluteFilename);return new File(filename,type,content)}async write(filename,content){const location=this.getAbsoluteLocation(filename);return this.#fileSystem.write(location,content)}async copy(source,destination){const sourceLocation=this.getAbsoluteLocation(source),destinationLocation=this.getAbsoluteLocation(destination);return this.#fileSystem.copy(sourceLocation,destinationLocation)}async delete(filename){const location=this.getAbsoluteLocation(filename);return this.#fileSystem.delete(location)}async filter(pattern){const location=this.getAbsoluteLocation("./");return this.#fileSystem.filter(location,pattern)}#validateLocation(location,filename){if(!1===location.startsWith(this.#rootLocation))throw new InvalidPath(filename)}}class SourcingManager{#fileManager;constructor(fileManager){this.#fileManager=fileManager}async filter(...patterns){return(await Promise.all(patterns.map((pattern=>this.#fileManager.filter(pattern))))).flat().map((file=>this.#fileManager.getRelativeLocation(file)))}async exists(filename){return this.#fileManager.exists(filename)}async read(filename){return this.#fileManager.read(filename)}async import(filename){const specifier=filename.startsWith("/")?this.#fileManager.getAbsoluteLocation(`.${filename}`):this.#fileManager.getAbsoluteLocation(filename);try{return await import(specifier)}catch(error){const message=error instanceof Error?error.message:String(error);throw new ModuleNotLoaded$1(specifier,message)}}}let Application$1=class{#repository;#resources;#segmentation;constructor(repository,resources,segmentation){this.#repository=repository,this.#resources=resources,this.#segmentation=segmentation}get resources(){return this.#resources}get repository(){return this.#repository}get segmentation(){return this.#segmentation}};class ResourcesList{#resources;constructor(resources){this.#resources=resources}isResourceModule(moduleFilename){return this.#resources.includes(moduleFilename)}}const Defaults$1_ACCESS_LEVEL="private",Defaults$1_VERSION_NUMBER="0.0.0",Files_INDEX="index.js",Files_JSON=".json",Keywords$1_DEFAULT="default",Patterns_IMPORT=/import\s(?:["'\s]*([\w*{}\n, ]+)from\s*)?["'\s]*([@\w/._-]+)["'\s].*/g,Patterns_EXPORT=/export\s(?:["'\s]*([\w*{}\n, ]+)from\s*)?["'\s]*([@\w/._-]+)["'\s].*/g,Values_ASTERISK="*";let IdGenerator$1=class{#id=0;next(){return"$"+ ++this.#id}};const EXTENSION_PATTERN=/\.js$/,APPLICATION_MODULE_INDICATORS=[".","/","http:","https:"];class FileHelper{translatePath(filename){const parts=filename.split("/"),translated=[];for(const part of parts){switch(part.trim()){case"":case".":continue;case"..":translated.pop();continue}translated.push(part)}return translated.join("/")}makePathRelative(absoluteFilename,relativeToPath){if(""===relativeToPath)return`./${absoluteFilename}`;const absoluteFilenameParts=absoluteFilename.split("/"),relativeToParts=relativeToPath.split("/");for(;absoluteFilenameParts[0]===relativeToParts[0];)absoluteFilenameParts.shift(),relativeToParts.shift();const relativePath=relativeToParts.map((()=>"..")).join("/");return`${relativeToParts.length>0?relativePath:"."}/${absoluteFilenameParts.join("/")}`}makePathAbsolute(relativeFilename,relativeToPath){const fullPath=""!==relativeToPath?`${relativeToPath}/${relativeFilename}`:relativeFilename;return this.translatePath(fullPath)}extractPath(filename){return filename.split("/").slice(0,-1).join("/")}stripPath(path){return path.substring(1,path.length-1)}extractFilename(filename){return filename.split("/").pop()}assureExtension(filename){return filename.endsWith(".js")?filename:`${filename}.js`}addSubExtension(filename,subExtension){return filename.replace(EXTENSION_PATTERN,`.${subExtension}.js`)}isApplicationModule(from){return APPLICATION_MODULE_INDICATORS.some((indicator=>from.startsWith(indicator)))}}let FileNotLoaded$2=class extends Error{constructor(filename,message){super(`Failed to load resource file '${filename}' because of: ${message}`)}};class ResourceReader{#resourcesFileManager;#sourceFileManager;#fileHelper=new FileHelper;constructor(resourcesFileManager,sourceFileManager){this.#resourcesFileManager=resourcesFileManager,this.#sourceFileManager=sourceFileManager}async readAll(filenames){const resources=await Promise.all(filenames.map((filename=>this.#loadResourceDefinition(filename))));return new ResourcesList(resources.flat())}async#loadResourceDefinition(filename){try{const content=await this.#resourcesFileManager.getContent(filename);return JSON.parse(content.toString()).map((resource=>this.#makeResourceFilename(resource)))}catch(error){const message=error instanceof Error?error.message:String(error);throw new FileNotLoaded$2(filename,message)}}#makeResourceFilename(filename){const fullFilename=this.#sourceFileManager.isDirectory(filename)?`${filename}/${Files_INDEX}`:this.#fileHelper.assureExtension(filename);return fullFilename.startsWith("./")?fullFilename.substring(2):fullFilename.startsWith("/")?fullFilename.substring(1):fullFilename}}let Module$1=class{#filename;#code;#model;constructor(filename,code,model){this.#code=code,this.#filename=filename,this.#model=model}get filename(){return this.#filename}get code(){return this.#code}get model(){return this.#model}};class Repository{#modules;constructor(modules){this.#modules=modules}get modules(){return this.#modules}get(filename){return this.#modules.find((module=>module.filename===filename))}}class ESAlias{#name;#as;constructor(name,as){this.#name=name,this.#as=as}get name(){return this.#name}get as(){return this.#as}toString(){return`${this.#name} as ${this.#as}`}}class ESValue{#definition;constructor(definition){this.#definition=definition}get definition(){return this.#definition}toString(){return this.#definition}}class ESArray extends ESValue{}class ESMember{#name;#isStatic;#isPrivate;constructor(name,isStatic=!1,isPrivate=!1){this.#name=name,this.#isStatic=isStatic,this.#isPrivate=isPrivate}get name(){return this.#name}get isStatic(){return this.#isStatic}get isPrivate(){return this.#isPrivate}get isPublic(){return!1===this.#isPrivate}}class ESClass extends ESMember{#parentName;#scope;constructor(name,parentName,scope){super(name),this.#parentName=parentName,this.#scope=scope}get parentName(){return this.#parentName}get scope(){return this.#scope}get members(){return this.#scope.members}get declarations(){return this.#scope.declarations}get functions(){return this.#scope.functions}get getters(){return this.#scope.getters}get setters(){return this.#scope.setters}get generators(){return this.#scope.generators}get readable(){const members=new Map;return this.getters.forEach((getter=>{members.set(getter.name,getter)})),this.declarations.forEach((declaration=>{declaration.isPublic&&members.set(declaration.name,declaration)})),[...members.values()]}get writable(){const members=new Map;return this.setters.forEach((setter=>{members.set(setter.name,setter)})),this.declarations.forEach((declaration=>{declaration.isPublic&&members.set(declaration.name,declaration)})),[...members.values()]}get callable(){return this.functions.filter((funktion=>funktion.isPublic))}getMember(name){return this.#scope.getMember(name)}getDeclaration(name){return this.#scope.getDeclaration(name)}getFunction(name){return this.#scope.getFunction(name)}getGetter(name){return this.#scope.getGetter(name)}getSetter(name){return this.#scope.getSetter(name)}getGenerator(name){return this.#scope.getGenerator(name)}hasMember(name){return this.#scope.hasMember(name)}hasDeclaration(name){return this.#scope.hasDeclaration(name)}hasFunction(name){return this.#scope.hasFunction(name)}hasGetter(name){return this.#scope.hasGetter(name)}hasSetter(name){return this.#scope.hasSetter(name)}hasGenerator(name){return this.#scope.hasGenerator(name)}canRead(name){const declaration=this.getDeclaration(name);return declaration?.isPublic||this.hasGetter(name)}canWrite(name){const declaration=this.getDeclaration(name);return declaration?.isPublic||this.hasSetter(name)}canCall(name){const funktion=this.getFunction(name);return funktion?.isPublic??!1}toString(){const infix=void 0!==this.#parentName?` extends ${this.#parentName}`:"";return`class ${this.name}${infix} { ${this.#scope.toString()} }`}}class ESDeclaration extends ESMember{#identifier;#value;constructor(identifier,value,isStatic=!1,isPrivate=!1){super(identifier.toString(),isStatic,isPrivate),this.#identifier=identifier,this.#value=value}get identifier(){return this.#identifier}get value(){return this.#value}toString(){return`${this.name}${this.value?" = "+this.value.toString():""}`}}class ESDestructuredValue{#members;constructor(members){this.#members=members}get members(){return this.#members}toString(){return this.#members.map((member=>member.toString())).join(" , ")}}class ESDestructuredArray extends ESDestructuredValue{toString(){return`[ ${super.toString()} ]`}}class ESDestructuredObject extends ESDestructuredValue{toString(){return`{ ${super.toString()} }`}}class ESExport extends ESMember{#members;#from;constructor(members,from){super(""),this.#members=members,this.#from=from}get members(){return this.#members}get from(){return this.#from}hasMember(name){return this.#members.some((member=>member.as===name))}getMember(name){return this.#members.find((member=>member.as===name))}toString(){const postfix=this.#from?` from '${this.#from}'`:"";return`export { ${this.#members.join(", ")} }${postfix}`}}class ESExpression extends ESValue{}class ESField{#name;#value;constructor(name,value){this.#name=name,this.#value=value}get name(){return this.#name}get value(){return this.#value}toString(){return`${this.name}${this.value?" = "+this.value.toString():""}`}}class ESFunction extends ESMember{#parameters;#body;#isAsync;constructor(name,parameters,body,isStatic=!1,isAsync=!1,isPrivate=!1){super(name,isStatic,isPrivate),this.#parameters=parameters,this.#body=body,this.#isAsync=isAsync}get parameters(){return this.#parameters}get body(){return this.#body}get isAsync(){return this.#isAsync}toString(){const parameters=this.parameters.map((parameter=>parameter.toString()));return`${this.isAsync?"async ":""}${this.name}(${parameters.join(", ")}) { ${this.body} }`}}class ESGenerator extends ESFunction{toString(){const parameters=this.parameters.map((parameter=>parameter.toString()));return`${this.isAsync?"async ":""}${this.name}*(${parameters.join(", ")}) { ${this.body} }`}}class ESGetter extends ESFunction{toString(){return`get ${super.toString()}`}}class ESImport extends ESMember{#members;#from;constructor(members,from){super(""),this.#members=members,this.#from=from}get members(){return this.#members}get from(){return this.#from}hasMember(name){return this.#members.some((member=>member.as===name))}getMember(name){return this.#members.find((member=>member.as===name))}toString(){return`import { ${this.#members.map((member=>member.toString())).join(", ")} } from '${this.#from}';`}}class ESModule{#scope;constructor(scope){this.#scope=scope}get scope(){return this.#scope}get members(){return this.#scope.members}get exportedMembers(){return this.#filterExported(this.#scope.members)}get imports(){return this.#scope.imports}get exports(){return this.#scope.exports}get declarations(){return this.#scope.declarations}get exportedDeclarations(){return this.#filterExported(this.#scope.declarations)}get functions(){return this.#scope.functions}get exportedFunctions(){return this.#filterExported(this.#scope.functions)}get generators(){return this.#scope.generators}get exportedGenerators(){return this.#filterExported(this.#scope.generators)}get classes(){return this.#scope.classes}get exportedClasses(){return this.#filterExported(this.#scope.classes)}get exported(){const exported=new Map;for(const exportItem of this.exports)for(const alias of exportItem.members){const member=this.getMember(alias.name);void 0!==member&&exported.set(alias.as,member)}return exported}getMember(name){return this.#scope.getMember(name)}getDeclaration(name){return this.#scope.getDeclaration(name)}getFunction(name){return this.#scope.getFunction(name)}getGenerator(name){return this.#scope.getGenerator(name)}getClass(name){return this.#scope.getClass(name)}hasMember(name){return this.#scope.hasMember(name)}hasDeclaration(name){return this.#scope.hasDeclaration(name)}hasFunction(name){return this.#scope.hasFunction(name)}hasGenerator(name){return this.#scope.hasGenerator(name)}hasClass(name){return this.#scope.hasClass(name)}getImport(name){return this.imports.find((importItem=>importItem.hasMember(name)))}getImported(name){for(const importItem of this.imports)for(const alias of importItem.members)if(alias.as===name)return this.getMember(alias.name)}isExported(member){for(const exportItem of this.exports)for(const alias of exportItem.members)if(alias.name===member.name)return!0;return!1}getExport(name){return this.exports.find((exportItem=>exportItem.hasMember(name)))}getExported(name){for(const exportItem of this.exports)for(const alias of exportItem.members)if(alias.as===name)return this.getMember(alias.name)}#filterExported(members){return members.filter((member=>this.isExported(member)))}}class ESObject extends ESValue{}class ESSetter extends ESFunction{toString(){return`set ${super.toString()}`}}const IMPORT_NAME=ESImport.name,EXPORT_NAME=ESExport.name,DECLARATION_NAME=ESDeclaration.name,FUNCTION_NAME=ESFunction.name,GETTER_NAME=ESGetter.name,SETTER_NAME=ESSetter.name,GENERATOR_NAME=ESGenerator.name,CLASS_NAME=ESClass.name;class ESScope{#members;constructor(members){this.#members=members}get members(){return this.#members}get imports(){return this.#members.filter((member=>member.constructor.name===IMPORT_NAME))}get exports(){return this.#members.filter((member=>member.constructor.name===EXPORT_NAME))}get declarations(){return this.#members.filter((member=>member.constructor.name===DECLARATION_NAME))}get functions(){return this.#members.filter((member=>member.constructor.name===FUNCTION_NAME))}get getters(){return this.#members.filter((member=>member.constructor.name===GETTER_NAME))}get setters(){return this.#members.filter((member=>member.constructor.name===SETTER_NAME))}get generators(){return this.#members.filter((member=>member.constructor.name===GENERATOR_NAME))}get classes(){return this.#members.filter((member=>member.constructor.name===CLASS_NAME))}getMember(name){return this.#members.find((member=>member.name===name))}getDeclaration(name){return this.declarations.find((member=>member.name===name))}getFunction(name){return this.functions.find((member=>member.name===name))}getGetter(name){return this.getters.find((member=>member.name===name))}getSetter(name){return this.setters.find((member=>member.name===name))}getGenerator(name){return this.generators.find((member=>member.name===name))}getClass(name){return this.classes.find((member=>member.name===name))}hasMember(name){return void 0!==this.getMember(name)}hasDeclaration(name){return void 0!==this.getDeclaration(name)}hasFunction(name){return void 0!==this.getFunction(name)}hasGetter(name){return void 0!==this.getGetter(name)}hasSetter(name){return void 0!==this.getSetter(name)}hasGenerator(name){return void 0!==this.getGenerator(name)}hasClass(name){return void 0!==this.getClass(name)}toString(){return this.#members.map((member=>member.toString())).join("\n")}}const Comment={SINGLE:"//",MULTI_START:"/*",MULTI_END:"*/"},Comments=Object.values(Comment);const Punctuation_DOT=".",Punctuation_LEFT_PARENTHESIS="(",Punctuation_RIGHT_PARENTHESIS=")",Punctuation_LEFT_BRACKET="[",Punctuation_RIGHT_BRACKET="]",Punctuation_LEFT_BRACE="{",Punctuation_RIGHT_BRACE="}",Divider={SCOPE:":",SEPARATOR:",",TERMINATOR:";"},Divisions=Object.values(Divider);function isDivider(value){return Divisions.includes(value)}const Empty={UNDEFINED:void 0,NULL:null,STRING:""},Empties=Object.values(Empty);function isEmpty(value){return Empties.includes(value)}const Group={OPEN:Punctuation_LEFT_PARENTHESIS,CLOSE:Punctuation_RIGHT_PARENTHESIS};function isGroup(value){return value===Group.OPEN||value===Group.CLOSE}const Keyword={EXPORT:"export",DEFAULT:"default",CLASS:"class",FUNCTION:"function",CONST:"const",LET:"let",VAR:"var",AS:"as",FROM:"from",IMPORT:"import",GET:"get",SET:"set",EXTENDS:"extends",STATIC:"static",ASYNC:"async",RETURN:"return"},Keywords=Object.values(Keyword);function isKeyword(value){return Keywords.includes(value)}function isNotReserved(value){return value===Keyword.AS||value===Keyword.ASYNC||value===Keyword.FROM||value===Keyword.GET||value===Keyword.SET}const List={OPEN:Punctuation_LEFT_BRACKET,CLOSE:Punctuation_RIGHT_BRACKET};function isList(value){return value===List.OPEN||value===List.CLOSE}const Literals=Object.values({SINGLE:"'",DOUBLE:'"',BACKTICK:"`"});function isLiteral(value){return Literals.includes(value)}const Operator={ADD:"+",ARROW:"=>",ASSIGN:"=",ASSIGN_ADD:"+=",ASSIGN_BITWISE_AND:"&=",ASSIGN_BITWISE_OR:"|=",ASSIGN_DIVIDE:"/=",ASSIGN_LEFT_SHIFT:"<<=",ASSIGN_LOGICAL_AND:"&&=",ASSIGN_LOGICAL_OR:"||=",ASSIGN_MODULO:"%=",ASSIGN_MULTIPLY:"*=",ASSIGN_RIGHT_SHIFT:">>=",ASSIGN_SUBTRACT:"-=",ASSIGN_XOR:"^=",BITWISE_AND:"&",BITWISE_OR:"|",DECREMENT:"--",DIVIDE:"/",EQUAL:"==",EQUAL_STRICT:"===",GREATER:">",GREATER_EQUAL:">=",INCREMENT:"++",LEFT_SHIFT:"<<",LESS:"<",LESS_EQUAL:"<=",LOGICAL_AND:"&&",LOGICAL_OR:"||",MODULO:"%",MULTIPLY:"*",NOT:"!",NOT_EQUAL:"!=",NOT_EQUAL_STRICT:"!==",RIGHT_SHIFT:">>",SUBTRACT:"-",TERNARY:"?",XOR:"^"},Operators=Object.values(Operator);function isOperator(value){return Operators.includes(value)}const Scope={OPEN:Punctuation_LEFT_BRACE,CLOSE:Punctuation_RIGHT_BRACE};function isScope(value){return value===Scope.OPEN||value===Scope.CLOSE}const TokenType={COMMENT:"comment",DIVIDER:"divider",GROUP:"group",IDENTIFIER:"identifier",KEYWORD:"keyword",LIST:"list",LITERAL:"literal",OPERATOR:"operator",REGEX:"regex",SCOPE:"scope",WHITESPACE:"whitespace"},Whitespace={SPACE:" ",TAB:"\t",NEWLINE:"\n",CARRIAGE_RETURN:"\r"},Whitespaces=Object.values(Whitespace);function isWhitespace(value){return Whitespaces.includes(value)}class ItemList{#items;#position;constructor(items){this.#items=items,this.#position=0}get items(){return this.#items}get position(){return this.#position}get size(){return this.#items.length}get eol(){return this.#position>=this.#items.length}get current(){return this.#items[this.#position]}get next(){return this.#items[this.#position+1]}get previous(){return this.#items[this.#position-1]}notAtEnd(){return!1===this.eol}get(index){return this.#items[index]}step(amount=1){return this.#position+=amount,this.current}stepBack(amount=1){return this.#position-=amount,this.current}hasNext(){return this.#position+1<this.#items.length}}class CharList extends ItemList{constructor(code){super(code.split(""))}}class Token{#type;#value;#start;#end;constructor(type,value,start,end){this.#type=type,this.#value=value,this.#start=start,this.#end=end}get type(){return this.#type}get value(){return this.#value}get start(){return this.#start}get end(){return this.#end}isType(type){return this.#type===type}hasValue(value){return this.#value===value}toString(){return`${this.#value}`}}class TokenList extends ItemList{}class Lexer{tokenize(code){const charList=new CharList(code),tokens=[];let last;for(;charList.notAtEnd();){const token=this.#getNextToken(charList,last);if(void 0===token)break;token.isType(TokenType.WHITESPACE)||token.isType(TokenType.COMMENT)?charList.step():(tokens.push(token),this.#isCodeToken(token)&&(last=token),charList.step())}return new TokenList(tokens)}#isCodeToken(token){return!1===[TokenType.WHITESPACE,TokenType.COMMENT].includes(token.type)}#getNextToken(charList,lastToken){const char=charList.current,start=charList.position;if(isWhitespace(char)){const end=charList.position;return new Token(TokenType.WHITESPACE,char,start,end)}if(function(value){return Comments.includes(value)}(char+charList.next)){const value=this.#readComment(charList),end=charList.position;return new Token(TokenType.COMMENT,value,start,end)}if(this.#startsRegex(char,lastToken)){const value=this.#readRegex(charList),end=charList.position;return new Token(TokenType.REGEX,value,start,end)}if(isLiteral(char)){const value=this.#readLiteral(charList),end=charList.position;return new Token(TokenType.LITERAL,value,start,end)}if(isOperator(char)){const value=this.#readOperation(charList),end=charList.position;return new Token(TokenType.OPERATOR,value,start,end)}if(isDivider(char)){const end=charList.position;return new Token(TokenType.DIVIDER,char,start,end)}if(isGroup(char)){const end=charList.position;return new Token(TokenType.GROUP,char,start,end)}if(isScope(char)){const end=charList.position;return new Token(TokenType.SCOPE,char,start,end)}if(isList(char)){const end=charList.position;return new Token(TokenType.LIST,char,start,end)}if(isEmpty(char))return;const value=this.#readIdentifier(charList),type=isKeyword(value)?TokenType.KEYWORD:TokenType.IDENTIFIER,end=charList.position;return new Token(type,value,start,end)}#readComment(charList){const isMulti=charList.current+charList.next===Comment.MULTI_START,terminator=isMulti?Comment.MULTI_END:Whitespace.NEWLINE;let value=isMulti?Comment.MULTI_START:Comment.SINGLE;for(charList.step(2);charList.notAtEnd();){const char=charList.current;if((isMulti?char+charList.next:char)===terminator){charList.step(terminator.length-1);break}value+=char,charList.step()}return isMulti?value+Comment.MULTI_END:value.trim()}#startsRegex(char,lastToken){return char===Operator.DIVIDE&&(void 0===lastToken||([TokenType.OPERATOR,TokenType.DIVIDER,TokenType.KEYWORD].includes(lastToken.type)||[Group.OPEN,List.OPEN].includes(lastToken.value)))}#endsRegex(char){return isWhitespace(char)||char==Punctuation_DOT||!1===this.#isIdentifier(char)}#readRegex(charList){let value=charList.current,closed=!1;for(charList.step();charList.notAtEnd();){const current=charList.current,previous=charList.previous;if(current===Operator.DIVIDE&&"\\"!==previous)closed=!0;else if(!0===closed&&this.#endsRegex(current)){charList.stepBack();break}value+=current,charList.step()}return value}#readLiteral(charList){const identifier=charList.current;let value=identifier,escaped=!1;for(charList.step();charList.notAtEnd();){const char=charList.current;if(!1===escaped){if(char===identifier){value+=char;break}"\\"===char&&(escaped=!0)}else escaped=!1;value+=char,charList.step()}return value}#isIdentifier(char){return!1===(isEmpty(char)||isWhitespace(char)||isOperator(char)||isLiteral(char)||isDivider(char)||isGroup(char)||isScope(char)||isList(char))}#readIdentifier(charList){let value="";for(;charList.notAtEnd();){const char=charList.current;if(!1===this.#isIdentifier(char)){charList.stepBack();break}value+=char,charList.step()}return value}#readOperation(charList){let value=charList.current;for(charList.step();charList.notAtEnd();){const char=charList.current;if(!1===isOperator(char)||!1===isOperator(value+char)){charList.stepBack();break}value+=char,charList.step()}return value}}class ExpectedKeyword extends Error{constructor(value,position){super(`Expected keyword '${value}' at position ${position}`)}}class ExpectedToken extends Error{constructor(value,position){super(`Expected token '${value}' at position ${position}`)}}class UnexpectedKeyword extends Error{constructor(keyword,position){super(`Unexpected keyword '${keyword}' at position ${position}`)}}class UnexpectedParseResult extends Error{constructor(expected){super(`The given code does not contain ${expected}`)}}class UnexpectedToken extends Error{constructor(value,position){super(`Unexpected token '${value}' at position ${position}`)}}class Parser{#lexer;constructor(lexer=new Lexer){this.#lexer=lexer}parse(code){const tokenList=this.#lexer.tokenize(code),scope=this.#parseScope(tokenList);return new ESModule(scope)}parseFirst(code){const tokenList=this.#lexer.tokenize(code);return this.#parseNext(tokenList)}parseValue(code){const model=this.parseFirst(code);if(model instanceof ESValue==!1)throw new UnexpectedParseResult("a value definition");return model}parseImport(code){const model=this.parseFirst(code);if(model instanceof ESImport==!1)throw new UnexpectedParseResult("an import definition");return model}parseExport(code){const model=this.parseFirst(code);if(model instanceof ESExport==!1)throw new UnexpectedParseResult("an export definition");return model}parseDeclaration(code){const model=this.parseFirst(code);if(model instanceof ESDeclaration==!1)throw new UnexpectedParseResult("a declaration definition");return model}parseFunction(code){const tokenList=this.#lexer.tokenize(code),model=this.#parseMember(tokenList);if(model instanceof ESFunction==!1)throw new UnexpectedParseResult("a function definition");return model}parseClass(code){const tokenList=this.#lexer.tokenize(code),model=this.#parseMember(tokenList);if(model instanceof ESClass==!1)throw new UnexpectedParseResult("a class definition");return model}#parseScope(tokenList){const members=[];for(;tokenList.notAtEnd();){const member=this.#parseNext(tokenList);member instanceof ESMember&&members.push(member)}return new ESScope(members)}#parseNext(tokenList,isAsync=!1){const token=tokenList.current;if(token.isType(TokenType.LITERAL))return this.#parseExpression(tokenList);if(token.isType(TokenType.IDENTIFIER)){const next=tokenList.next;return next?.hasValue(Operator.ARROW)?this.#parseArrowFunction(tokenList,isAsync):this.#parseExpression(tokenList)}if(token.isType(TokenType.KEYWORD)){if(isNotReserved(token.value)){const next=tokenList.next,nextIsFunction=void 0!==next&&(next.hasValue(Keyword.FUNCTION)||next.hasValue(Group.OPEN));if(token.hasValue(Keyword.ASYNC)&&nextIsFunction)return tokenList.step(),this.#parseNext(tokenList,!0);if(void 0===next||this.#atEndOfStatement(next))return this.#parseExpression(tokenList)}return token.hasValue(Keyword.RETURN)?this.#parseExpression(tokenList):this.#parseMember(tokenList,isAsync)}if(token.isType(TokenType.REGEX))return this.#parseExpression(tokenList);if(token.hasValue(Group.OPEN)){const next=this.#peekAfterBlock(tokenList,Group.OPEN,Group.CLOSE);return next?.hasValue(Operator.ARROW)?this.#parseArrowFunction(tokenList,isAsync):this.#parseExpression(tokenList)}if(token.hasValue(Scope.OPEN))return this.#parseObject(tokenList);if(token.hasValue(List.OPEN))return this.#parseArray(tokenList);if(token.hasValue(Operator.NOT)||token.hasValue(Operator.SUBTRACT))return this.#parseExpression(tokenList);if(!isDivider(token.value))throw new UnexpectedToken(token.value,token.start);tokenList.step()}#parseMember(tokenList,isAsync=!1){const token=tokenList.current;switch(tokenList.step(),token.value){case Keyword.IMPORT:return this.#parseImport(tokenList);case Keyword.EXPORT:return this.#parseExport(tokenList);case Keyword.CLASS:return this.#parseClass(tokenList);case Keyword.FUNCTION:return this.#parseFunction(tokenList,isAsync);case Keyword.VAR:case Keyword.LET:case Keyword.CONST:return this.#parseDeclaration(tokenList,!1,!0);case Keyword.ASYNC:return this.#parseMember(tokenList,!0);default:throw new UnexpectedKeyword(token.value,token.start)}}#parseImport(tokenList){const members=[];let token=tokenList.current;if(token.isType(TokenType.LITERAL))return new ESImport(members,token.value);if(token.hasValue(Group.OPEN)){token=tokenList.step();const from=token.value;return tokenList.step(2),new ESImport(members,from)}if(!1===token.hasValue(Scope.OPEN)){const name=token.hasValue(Operator.MULTIPLY)?Operator.MULTIPLY:"default";let as=token.value;token=tokenList.step(),token.hasValue(Keyword.AS)&&(token=tokenList.step(),as=token.value,token=tokenList.step()),members.push(new ESAlias(name,as))}if(token.hasValue(Divider.SEPARATOR)&&(token=tokenList.step()),token.hasValue(Scope.OPEN)){const aliases=this.#parseAliasList(tokenList);members.push(...aliases),token=tokenList.current}if(!1===token.hasValue(Keyword.FROM))throw new ExpectedKeyword(Keyword.FROM,token.start);token=tokenList.step();const from=token.value;return tokenList.step(),new ESImport(members,from)}#parseExport(tokenList){switch(tokenList.current.value){case Keyword.DEFAULT:return tokenList.step(),this.#parseSingleExport(tokenList,!0);case Scope.OPEN:return this.#parseMultiExport(tokenList);default:return this.#parseSingleExport(tokenList,!1)}}#parseSingleExport(tokenList,isDefault){let token=tokenList.current,stepSize=0;var value;token.hasValue(Keyword.ASYNC)&&(token=tokenList.step(),stepSize++),((value=token.value)===Keyword.CLASS||value===Keyword.FUNCTION||value===Keyword.CONST||value===Keyword.LET||value===Keyword.VAR)&&(token=tokenList.step(),stepSize++);const name=this.#isIdentifier(token)?token.value:"",as=isDefault?"default":name;let from;token=tokenList.step(),token?.hasValue(Keyword.FROM)&&(token=tokenList.step(),from=token.value),stepSize>0&&(stepSize++,tokenList.stepBack(stepSize));const alias=new ESAlias(name,as);return new ESExport([alias],from)}#parseMultiExport(tokenList){const members=this.#parseAliasList(tokenList);let from,token=tokenList.current;return token?.hasValue(Keyword.FROM)&&(token=tokenList.step(),from=token.value),tokenList.step(),new ESExport(members,from)}#parseAliasList(tokenList){const aliases=[];let token=tokenList.step();for(;tokenList.notAtEnd();){if(token.hasValue(Scope.CLOSE)){tokenList.step();break}if(token.hasValue(Divider.SEPARATOR)){token=tokenList.step();continue}const alias=this.#parseAlias(tokenList);aliases.push(alias),token=tokenList.step()}return aliases}#parseAlias(tokenList){let token=tokenList.current;const name=token.value;let as=name;return tokenList.next.hasValue(Keyword.AS)&&(token=tokenList.step(2),as=token.value),new ESAlias(name,as)}#parseDeclaration(tokenList,isStatic,parseMultiple=!1){let identifier,value,token=tokenList.current,isPrivate=!1;return token.hasValue(List.OPEN)?(identifier=this.#parseDestructuredArray(tokenList),token=tokenList.current):token.hasValue(Scope.OPEN)?(identifier=this.#parseDestructuredObject(tokenList),token=tokenList.current):(isPrivate=token.value.startsWith("#"),identifier=isPrivate?token.value.substring(1):token.value,token=tokenList.step()),token.hasValue(Operator.ASSIGN)&&(tokenList.step(),value=this.#parseNext(tokenList,!1),token=tokenList.current),void 0!==token&&(token.hasValue(Divider.TERMINATOR)?tokenList.step():!0===parseMultiple&&token.hasValue(Divider.SEPARATOR)&&(tokenList.step(),this.#parseDeclaration(tokenList,isStatic,!0))),value instanceof ESGenerator?new ESGenerator(identifier.toString(),value.parameters,value.body,isStatic,value.isAsync,isPrivate):value instanceof ESFunction?new ESFunction(identifier.toString(),value.parameters,value.body,isStatic,value.isAsync,isPrivate):value instanceof ESClass?new ESClass(identifier.toString(),value.parentName,value.scope):new ESDeclaration(identifier,value,isStatic,isPrivate)}#parseFunction(tokenList,isAsync,isStatic=!1,isGetter=!1,isSetter=!1){let token=tokenList.current,name="",isGenerator=!1,isPrivate=!1;token.hasValue(Operator.MULTIPLY)&&(isGenerator=!0,token=tokenList.step()),this.#isIdentifier(token)&&(isPrivate=token.value.startsWith("#"),name=isPrivate?token.value.substring(1):token.value,token=tokenList.step());const parameters=this.#parseParameters(tokenList,Group.CLOSE);if(token=tokenList.current,!1===token.hasValue(Scope.OPEN))throw new ExpectedToken(Scope.OPEN,token.start);const body=this.#parseBlock(tokenList,Scope.OPEN,Scope.CLOSE);return isGenerator?new ESGenerator(name,parameters,body,isStatic,isAsync,isPrivate):isGetter?new ESGetter(name,parameters,body,isStatic,isAsync,isPrivate):isSetter?new ESSetter(name,parameters,body,isStatic,isAsync,isPrivate):new ESFunction(name,parameters,body,isStatic,isAsync,isPrivate)}#parseArrowFunction(tokenList,isAsync){let parameters,token=tokenList.current;if(token.hasValue(Group.OPEN)?(parameters=this.#parseParameters(tokenList,Group.CLOSE),token=tokenList.current):(parameters=[new ESField(token.value,void 0)],token=tokenList.step()),!1===token.hasValue(Operator.ARROW))throw new ExpectedToken(Operator.ARROW,token.start);token=tokenList.step();const body=token.hasValue(Scope.OPEN)?this.#parseBlock(tokenList,Scope.OPEN,Scope.CLOSE):this.#parseExpression(tokenList).definition;return new ESFunction("",parameters,body,!1,isAsync,!1)}#parseParameters(tokenList,closeId){const parameters=[];for(tokenList.step();tokenList.notAtEnd();){const token=tokenList.current;if(token.hasValue(closeId)){tokenList.step();break}if(token.hasValue(Divider.SEPARATOR)){tokenList.step();continue}let parameter;parameter=token.hasValue(Scope.OPEN)?this.#parseDestructuredObject(tokenList):token.hasValue(List.OPEN)?this.#parseDestructuredArray(tokenList):this.#parseField(tokenList),parameters.push(parameter)}return parameters}#parseClass(tokenList){let parent,token=tokenList.current,name="";if(this.#isIdentifier(token)&&(name=token.value,token=tokenList.step()),token.hasValue(Keyword.EXTENDS)&&(token=tokenList.step(),parent=token.value,token=tokenList.step()),!1===token.hasValue(Scope.OPEN))throw new ExpectedToken(Scope.OPEN,token.start);const scope=this.#parseClassScope(tokenList);return new ESClass(name,parent,scope)}#parseClassScope(tokenList){let token=tokenList.step();const members=[];for(;tokenList.notAtEnd();){if(token.hasValue(Scope.CLOSE)){tokenList.step();break}const member=this.#parseClassMember(tokenList);members.push(member),token=tokenList.current}return new ESScope(members)}#parseClassMember(tokenList){let token=tokenList.current,isAsync=!1,isStatic=!1,isGetter=!1,isSetter=!1;for(;tokenList.notAtEnd();){if(token.hasValue(Keyword.STATIC))isStatic=!0;else if(token.hasValue(Keyword.ASYNC))isAsync=!0;else if(token.hasValue(Keyword.GET))isGetter=!0;else{if(!token.hasValue(Keyword.SET)){if(token.hasValue(Operator.MULTIPLY))return this.#parseFunction(tokenList,isAsync,isStatic,!1,!1);break}isSetter=!0}token=tokenList.step()}return tokenList.next.hasValue(Group.OPEN)?this.#parseFunction(tokenList,isAsync,isStatic,isGetter,isSetter):this.#parseDeclaration(tokenList,isStatic)}#parseArray(tokenList){const items=this.#parseBlock(tokenList,List.OPEN,List.CLOSE);return new ESArray(items)}#parseDestructuredArray(tokenList){const fields=this.#parseParameters(tokenList,List.CLOSE);return new ESDestructuredArray(fields)}#parseObject(tokenList){const fields=this.#parseBlock(tokenList,Scope.OPEN,Scope.CLOSE);return new ESObject(fields)}#parseDestructuredObject(tokenList){const fields=this.#parseParameters(tokenList,Scope.CLOSE);return new ESDestructuredObject(fields)}#parseField(tokenList){let token=tokenList.current;const name=token.value;let value;return token=tokenList.step(),token.hasValue(Operator.ASSIGN)&&(tokenList.step(),value=this.#parseNext(tokenList,!1)),new ESField(name,value)}#parseExpression(tokenList){let token=tokenList.current,code="";for(;tokenList.notAtEnd();){if(token.hasValue(List.OPEN)){code+=this.#parseBlock(tokenList,List.OPEN,List.CLOSE)+" ",token=tokenList.current}else if(token.hasValue(Group.OPEN)){code+=this.#parseBlock(tokenList,Group.OPEN,Group.CLOSE)+" ",token=tokenList.current}else if(token.hasValue(Scope.OPEN)){code+=this.#parseBlock(tokenList,Scope.OPEN,Scope.CLOSE)+" ",token=tokenList.current}else code+=token.toString()+" ",token=tokenList.step();if(void 0===token||this.#atEndOfStatement(token))break}return new ESExpression(code.trim())}#parseBlock(tokenList,openId,closeId){let token=tokenList.step(),code=openId+" ";for(;tokenList.notAtEnd();)if(token.hasValue(openId))code+=this.#parseBlock(tokenList,openId,closeId)+" ",token=tokenList.current;else{if(token.hasValue(closeId))return tokenList.step(),code+=closeId,code;code+=token.toString()+" ",token=tokenList.step()}return code}#peekAfterBlock(tokenList,openId,closeId){const start=tokenList.position;this.#parseBlock(tokenList,openId,closeId);const token=tokenList.current,end=tokenList.position;return tokenList.stepBack(end-start),token}#atEndOfStatement(token){return[Divider.TERMINATOR,Divider.SEPARATOR].includes(token.value)||[List.CLOSE,Group.CLOSE,Scope.CLOSE].includes(token.value)||isKeyword(token.value)}#isIdentifier(token){return token.isType(TokenType.IDENTIFIER)||token.isType(TokenType.KEYWORD)&&isNotReserved(token.value)}}class ClassMerger{merge(model,parent){const declarations=this.#mergeDeclarations(model.declarations,parent.declarations),functions=this.#mergeFunctions(model.functions,parent.functions),getters=this.#mergeFunctions(model.getters,parent.getters),setters=this.#mergeFunctions(model.setters,parent.setters),members=[...declarations.values(),...functions.values(),...getters.values(),...setters.values()];return new ESClass(model.name,parent.name,new ESScope(members))}#mergeDeclarations(model,parent){const declarations=new Map;return parent.forEach((declaration=>declarations.set(declaration.name,declaration))),model.forEach((declaration=>declarations.set(declaration.name,declaration))),[...declarations.values()]}#mergeFunctions(model,parent){const functions=new Map;return parent.forEach((funktion=>functions.set(funktion.name,funktion))),model.forEach((funktion=>functions.set(funktion.name,funktion))),[...functions.values()]}}class Reflector{#parser=new Parser;#merger=new ClassMerger;fromModule(module,inherit=!1){const entries=Object.entries(module),members=[];for(const[key,member]of entries){if("function"!=typeof member.toString)continue;const code=member.toString();if(code.startsWith("class"))members.push(this.fromClass(member,inherit));else if(code.startsWith("function"))members.push(this.fromFunction(member));else{const expression=new ESExpression(code);members.push(new ESDeclaration(key,expression))}}return new ESModule(new ESScope(members))}fromClass(clazz,inherit=!1){const model=this.isClass(clazz)?this.#reflectStatic(clazz):this.#reflectDynamic(clazz);if(!1===inherit)return model;const parentClazz=this.getParentClass(clazz);if(""===parentClazz.name)return model;const parentModel=this.fromClass(parentClazz,!0);return this.#merger.merge(model,parentModel)}fromObject(object,inherit=!0){const clazz=this.getClass(object);return this.fromClass(clazz,inherit)}fromFunction(funktion){const code=funktion.toString();return this.#parser.parseFunction(code)}createInstance(clazz,args=[]){return new clazz(...args)}getClass(object){return object.constructor}getParentClass(clazz){return Object.getPrototypeOf(clazz)}isClassObject(object){return this.isClass(object.constructor)}isFunctionObject(object){return this.isFunction(object.constructor)}isClass(clazz){return clazz.toString().startsWith("class")}isFunction(clazz){return clazz.toString().startsWith("function")||clazz.toString().startsWith("async function")}#reflectStatic(clazz){const code=clazz.toString();return this.#parser.parseClass(code)}#reflectDynamic(clazz){const object=this.createInstance(clazz),members=this.#getMembers(clazz,object),scope=new ESScope(members);return new ESClass(clazz.name,void 0,scope)}#getMembers(clazz,object){return[...this.#getDeclarations(object),...this.#getFunctions(clazz)]}#getDeclarations(object){const fieldNames=Object.getOwnPropertyNames(object),values=object,models=[];for(const fieldName of fieldNames){const content=values[fieldName],value=void 0!==content?new ESValue(String(content)):void 0,model=new ESDeclaration(fieldName,value);models.push(model)}return models}#getFunctions(clazz){const functionDescriptions=Object.getOwnPropertyDescriptors(clazz.prototype),models=[];for(const functionName in functionDescriptions){const description=functionDescriptions[functionName],funktion=description.value;if(funktion instanceof Function==!1)continue;const model=this.fromFunction(funktion);void 0!==description.get?models.push(new ESGetter(model.name,model.parameters,model.body,model.isStatic,model.isAsync,model.isPrivate)):void 0!==description.set?models.push(new ESSetter(model.name,model.parameters,model.body,model.isStatic,model.isAsync,model.isPrivate)):models.push(model)}return models}}let FileNotLoaded$1=class extends Error{constructor(filename,message){super(`Failed to load module file '${filename}' because of: ${message}`)}},LocationRewriter$1=class{#sourceFileManager;#parser=new Parser;#fileHelper=new FileHelper;constructor(sourceFileManager){this.#sourceFileManager=sourceFileManager}rewrite(filename,code){const replacedImports=this.#rewriteImports(filename,code);return this.#rewriteExports(filename,replacedImports)}#rewriteImports(filename,code){return code.replaceAll(Patterns_IMPORT,(statement=>this.#replaceImport(filename,statement)))}#rewriteExports(filename,code){return code.replaceAll(Patterns_EXPORT,(statement=>this.#replaceExport(filename,statement)))}#replaceImport(filename,statement){const dependency=this.#parser.parseImport(statement),from=this.#fileHelper.stripPath(dependency.from);if(!1===this.#fileHelper.isApplicationModule(from))return statement;const rewrittenFrom=this.#rewriteFrom(filename,from);return statement.replace(from,rewrittenFrom)}#replaceExport(filename,statement){const dependency=this.#parser.parseExport(statement);if(void 0===dependency.from)return statement;const from=this.#fileHelper.stripPath(dependency.from);if(!1===this.#fileHelper.isApplicationModule(from))return statement;const rewrittenFrom=this.#rewriteFrom(filename,from);return statement.replace(from,rewrittenFrom)}#rewriteFrom(filename,from){const callingModulePath=this.#fileHelper.extractPath(filename),translated=this.#fileHelper.makePathAbsolute(from,callingModulePath);return this.#sourceFileManager.isDirectory(translated)?`${from}/${Files_INDEX}`:this.#fileHelper.assureExtension(from)}},Reader$1=class{#sourceFileManager;#parser;#locationRewriter;constructor(sourceFileManager,parser=new Parser){this.#sourceFileManager=sourceFileManager,this.#parser=parser,this.#locationRewriter=new LocationRewriter$1(sourceFileManager)}async readAll(filenames){const modules=await Promise.all(filenames.map((filename=>this.read(filename))));return new Repository(modules)}async read(filename){const relativeLocation=this.#sourceFileManager.getRelativeLocation(filename),code=await this.#loadCode(filename),rewrittenCode=this.#locationRewriter.rewrite(relativeLocation,code),module=this.#parser.parse(rewrittenCode);return new Module$1(relativeLocation,rewrittenCode,module)}async#loadCode(filename){try{return(await this.#sourceFileManager.getContent(filename)).toString()}catch(error){const message=error instanceof Error?error.message:String(error);throw new FileNotLoaded$1(filename,message)}}};class Segment{#name;#modules=new Map;#classes=new Map;#procedures=new Map;constructor(name){this.#name=name}get name(){return this.#name}get modules(){return[...this.#modules.values()]}get classes(){return[...this.#classes.values()]}get procedures(){return[...this.#procedures.values()]}hasModule(filename){return this.#modules.has(filename)}getModule(filename){return this.#modules.get(filename)}getSegmentedModules(){return this.modules.filter((module=>module.segmented))}setModule(module){this.#modules.set(module.filename,module)}hasProcedure(fqn){return this.#procedures.has(fqn)}getProcedure(fqn){return this.#procedures.get(fqn)}setProcedure(procedure){this.#procedures.set(procedure.fqn,procedure)}setClass(klass){this.#classes.set(klass.fqn,klass)}}class Member{#id;#importKey;#fqn;constructor(id,importKey,fqn){this.#id=id,this.#importKey=importKey,this.#fqn=fqn}get id(){return this.#id}get importKey(){return this.#importKey}get fqn(){return this.#fqn}}class Class extends Member{#model;constructor(id,importKey,fqn,model){super(id,importKey,fqn),this.#model=model}get model(){return this.#model}}class Implementation extends Member{#access;#version;#model;constructor(id,importKey,fqn,access,version,model){super(id,importKey,fqn),this.#access=access,this.#version=version,this.#model=model}get access(){return this.#access}get version(){return this.#version}get model(){return this.#model}}class Module{#filename;#location;#imports;#members=[];#segmented;constructor(filename,location,imports,segmented){this.#filename=filename,this.#location=location,this.#imports=imports,this.#segmented=segmented}get filename(){return this.#filename}get location(){return this.#location}get imports(){return this.#imports}get members(){return this.#members}get segmented(){return this.#segmented}hasClasses(){return this.#members.some((member=>member instanceof Class))}getClasses(){return this.#members.filter((member=>member instanceof Class))}hasImplementations(){return this.#members.some((member=>member instanceof Implementation))}getImplementations(){return this.#members.filter((member=>member instanceof Implementation))}addMember(members){this.#members.push(members)}addImports(imports){const keys=Object.keys(imports);for(const key of keys)this.#imports[key]=imports[key]}}class Procedure{#fqn;#implementations=[];constructor(fqn,implementations=[]){this.#fqn=fqn,this.#implementations=implementations}get fqn(){return this.#fqn}get implementations(){return this.#implementations}addImplementation(implementation){this.#implementations.push(implementation)}}class Segmentation{#segments;constructor(segments){this.#segments=segments}get segments(){return this.#segments}getSegment(segmentName){return this.#segments.find((segment=>segment.name===segmentName))}isSegmentedModule(moduleFilename){return this.#segments.some((segment=>segment.hasModule(moduleFilename)))}getSegments(moduleFilename){return this.#segments.filter((segment=>segment.hasModule(moduleFilename)))}}class FunctionNotAsync extends Error{constructor(filename,functionName){super(`Function '${functionName}' from file '${filename}' is not async`)}}class InvalidFilename extends Error{constructor(filename){super(`Segment filename '${filename}' is invalid`)}}class FileNotLoaded extends Error{constructor(filename,message){super(`Failed to load segment file '${filename}' because of: ${message}`)}}class InvalidModuleExport extends Error{constructor(filename,exportKey){super(`The export '${exportKey}' from file '${filename}' is not a function or a class.`)}}class MissingModuleExport extends Error{constructor(filename,key){super(`Module '${filename}' does not export '${key}'`)}}class ModuleNotLoaded extends Error{constructor(filename){super(`Segmented module not found '${filename}'`)}}class MemberLocator{#repository;#fileHelper=new FileHelper;constructor(repository){this.#repository=repository}locate(filename,importKey){const trace=[];return{trace:trace,model:this.#locate(filename,importKey,trace)}}#locate(filename,importKey,trace){trace.push({filename:filename,importKey:importKey});const module=this.#getModule(filename);return this.#isReexported(module,importKey)?this.#relocate(module,importKey,trace):this.#extract(module,importKey)}#getModule(filename){const module=this.#repository.get(filename);if(void 0===module)throw new ModuleNotLoaded(filename);return module}#isReexported(module,importKey){const importItem=module.model.getImport(importKey),exportItem=module.model.getExport(importKey);return void 0!==importItem||void 0!==exportItem?.from}#relocate(module,importKey,trace){const relocateInfo=this.#getImportInfo(module,importKey)??this.#getExportInfo(module,importKey),relocatePath=relocateInfo?.from,relocateKey=relocateInfo?.name,callingModulePath=this.#fileHelper.extractPath(module.filename),relativeFrom=this.#fileHelper.stripPath(relocatePath),absoluteFrom=this.#fileHelper.makePathAbsolute(relativeFrom,callingModulePath);return this.#locate(absoluteFrom,relocateKey,trace)}#extract(module,importKey){const exportInfo=this.#getExportInfo(module,importKey);if(void 0===exportInfo)throw new MissingModuleExport(module.filename,importKey);const member=module.model.getMember(exportInfo.name);if(void 0===member)throw new MissingModuleExport(module.filename,exportInfo.name);return member}#getExportInfo(module,importKey){const exportItem=module.model.getExport(importKey),exportAlias=exportItem?.getMember(importKey);if(void 0!==exportAlias)return{from:exportItem?.from,name:exportAlias.name}}#getImportInfo(module,importKey){const importItem=module.model.getImport(importKey),importAlias=importItem?.getMember(importKey);if(void 0!==importItem&&void 0!==importAlias)return{from:importItem.from,name:importAlias.name}}}class SegmentReader{#segmentsFileManager;#sourceFileManager;#memberLocator;#fileHelper=new FileHelper;constructor(segmentsFileManager,sourceFileManager,repository){this.#segmentsFileManager=segmentsFileManager,this.#sourceFileManager=sourceFileManager,this.#memberLocator=new MemberLocator(repository)}async readAll(filenames){const segments=await Promise.all(filenames.map((filename=>this.#read(filename))));return new Segmentation(segments)}async#read(filename){const definition=await this.#loadSegmentDefinition(filename),name=this.#extractSegmentName(filename),segment=new Segment(name);return this.#registerModules(segment,definition),this.#registerMembers(segment),segment}#extractSegmentName(filename){const file=filename.split("/").pop();if(void 0===file||""===file)throw new InvalidFilename(filename);return file.replace(Files_JSON,"")}async#loadSegmentDefinition(filename){try{const content=await this.#segmentsFileManager.getContent(filename);return JSON.parse(content.toString())}catch(error){const message=error instanceof Error?error.message:String(error);throw new FileNotLoaded(filename,message)}}#registerModules(segment,definition){for(const[filename,moduleImports]of Object.entries(definition))this.#createModule(segment,filename,moduleImports,!0)}#createModule(segment,filename,moduleImports,segmented){const moduleFilename=this.#makeModuleFilename(filename),location=this.#fileHelper.extractPath(moduleFilename),module=segment.hasModule(moduleFilename)?segment.getModule(moduleFilename):new Module(moduleFilename,location,{},segmented);module.addImports(moduleImports),segment.setModule(module)}#makeModuleFilename(filename){const fullFilename=this.#sourceFileManager.isDirectory(filename)?`${filename}/${Files_INDEX}`:this.#fileHelper.assureExtension(filename);return fullFilename.startsWith("./")?fullFilename.substring(2):fullFilename.startsWith("/")?fullFilename.substring(1):fullFilename}#registerMembers(segment){const idGenerator=new IdGenerator$1;for(const module of segment.modules)for(const importKey in module.imports)this.#registerModuleMember(segment,module,importKey,idGenerator)}#registerModuleMember(segment,module,importKey,idGenerator){const{model:model,trace:trace}=this.#memberLocator.locate(module.filename,importKey),properties=this.#constructProperties(module,model,importKey,idGenerator);this.#createMember(segment,module,model,properties),trace.shift();for(const entry of trace){const entryImport={[entry.importKey]:{access:properties.access}};this.#createModule(segment,entry.filename,entryImport,!1)}}#constructProperties(module,model,importKey,idGenerator){const configuration=module.imports[importKey],id=idGenerator.next(),name=configuration.as??model.name;return{id:id,importKey:importKey,name:name,access:configuration.access??Defaults$1_ACCESS_LEVEL,version:configuration.version??Defaults$1_VERSION_NUMBER,fqn:this.#constructFqn(module,name,importKey)}}#constructFqn(module,name,importKey){return this.#isRootModule(module)?name:this.#isIndexModule(module)&&this.#isDefaultImport(importKey)?module.location:`${module.location}/${name}`}#isRootModule(module){return""===module.location}#isIndexModule(module){return module.filename.endsWith(Files_INDEX)}#isDefaultImport(importKey){return importKey===Keywords$1_DEFAULT}#createMember(segment,module,model,properties){if(model instanceof ESClass)return this.#createClass(segment,module,model,properties);if(model instanceof ESFunction)return this.#createImplementation(segment,module,model,properties);throw new InvalidModuleExport(module.filename,properties.importKey)}#createClass(segment,module,model,properties){const clazz=new Class(properties.id,properties.importKey,properties.fqn,model);module.addMember(clazz),segment.setClass(clazz)}#createImplementation(segment,module,model,properties){if(!1===model.isAsync)throw new FunctionNotAsync(module.filename,properties.name);const implementation=new Implementation(properties.id,properties.importKey,properties.fqn,properties.access,properties.version,model);this.#createProcedure(segment,module,implementation)}#createProcedure(segment,module,implementation){const procedure=segment.hasProcedure(implementation.fqn)?segment.getProcedure(implementation.fqn):new Procedure(implementation.fqn);procedure.addImplementation(implementation),module.addMember(implementation),segment.setProcedure(procedure)}}class Reader{#projectFileManager;constructor(projectFileManager){this.#projectFileManager=projectFileManager}async read(moduleFiles,resourceFiles,segmentFiles){const sourceFileManager=this.#projectFileManager.source,resourceFileManager=this.#projectFileManager.resource,segmentFileManager=this.#projectFileManager.segment,moduleReader=new Reader$1(sourceFileManager),repository=await moduleReader.readAll(moduleFiles),resourceReader=new ResourceReader(resourceFileManager,sourceFileManager),resources=await resourceReader.readAll(resourceFiles),segmentReader=new SegmentReader(segmentFileManager,sourceFileManager,repository),segmentation=await segmentReader.readAll(segmentFiles);return new Application$1(repository,resources,segmentation)}}class LocationRewriter{#module;#resources;#segmentation;#segment;#parser=new Parser;#fileHelper=new FileHelper;constructor(module,resources,segmentation,segment){this.#module=module,this.#resources=resources,this.#segmentation=segmentation,this.#segment=segment}get parser(){return this.#parser}rewrite(code){return code.replaceAll(this.replacementPattern,(statement=>this.replaceStatement(statement)))}replaceStatement(statement){const dependency=this.parseStatement(statement);return void 0===dependency.from?statement:this.#isApplicationModule(dependency)?this.#rewriteForApplication(dependency):this.#rewriteForRuntime(dependency)}#rewriteForApplication(dependency){const targetModuleFilename=this.#getTargetModuleFilename(dependency);return this.#resources.isResourceModule(targetModuleFilename)?this.#rewriteToResource(targetModuleFilename,dependency):this.#rewriteModule(targetModuleFilename,dependency)}#rewriteForRuntime(dependency){const from=this.#rewriteRuntimeFrom(dependency),keys=dependency.members.map((member=>member.name));return this.includeInBundle(dependency,from,keys)}#rewriteModule(targetModuleFilename,dependency){if(0===dependency.members.length)return this.#rewriteToCommon(targetModuleFilename,dependency,[]);const{segmentKeys:segmentKeys,remoteKeys:remoteKeys,commonKeys:commonKeys}=this.#getModuleImportKeys(targetModuleFilename,dependency),imports=[];return segmentKeys.length>0&&imports.push(this.#rewriteToSegment(targetModuleFilename,dependency,segmentKeys)),remoteKeys.length>0&&imports.push(this.#rewriteToRemote(targetModuleFilename,dependency,remoteKeys)),commonKeys.length>0&&imports.push(this.#rewriteToCommon(targetModuleFilename,dependency,commonKeys)),imports.filter((item=>item.length>0)).join("\n")}#rewriteToResource(targetModuleFilename,dependency){const from=this.#rewriteApplicationFrom(targetModuleFilename);return this.excludeFromBundle(dependency,from)}#rewriteToSegment(targetModuleFilename,dependency,keys){const from=this.#rewriteApplicationFrom(targetModuleFilename,this.#segment.name);return this.includeInBundle(dependency,from,keys)}#rewriteToRemote(targetModuleFilename,dependency,keys){const from=this.#rewriteApplicationFrom(targetModuleFilename,"remote");return this.includeInBundle(dependency,from,keys)}#rewriteToCommon(targetModuleFilename,dependency,keys){const from=this.#rewriteApplicationFrom(targetModuleFilename);return this.includeInBundle(dependency,from,keys)}#isApplicationModule(dependency){const from=this.#fileHelper.stripPath(dependency.from);return this.#fileHelper.isApplicationModule(from)}#getTargetModuleFilename(dependency){const from=this.#fileHelper.stripPath(dependency.from),callingModulePath=this.#fileHelper.extractPath(this.#module.filename);return this.#fileHelper.makePathAbsolute(from,callingModulePath)}#getModuleImportKeys(targetModuleFilename,dependency){const moduleSegmentKeys=this.#getSegmentImportKeys(targetModuleFilename,this.#segment),moduleRemoteKeys=this.#getRemoteImportKeys(targetModuleFilename,moduleSegmentKeys),segmentKeys=this.#filterMemberKeys(dependency,moduleSegmentKeys),remoteKeys=this.#filterMemberKeys(dependency,moduleRemoteKeys);return{segmentKeys:segmentKeys,remoteKeys:remoteKeys,commonKeys:this.#extractUnsegmentedImportKeys(dependency,[...segmentKeys,...remoteKeys])}}#getSegmentImportKeys(targetModuleFilename,segment){if(void 0===segment)return[];const module=segment.getModule(targetModuleFilename);return void 0!==module?Object.keys(module.imports):[]}#getRemoteImportKeys(targetModuleFilename,segmentKeys){const importKeys=this.#segmentation.getSegments(targetModuleFilename).filter((segment=>segment!==this.#segment)).map((segment=>this.#getSegmentImportKeys(targetModuleFilename,segment))).flat();return[...new Set(importKeys)].filter((key=>!1===segmentKeys.includes(key)))}#filterMemberKeys(dependency,keys){return dependency.members.filter((member=>keys.includes(member.name))).map((member=>member.name))}#extractUnsegmentedImportKeys(dependency,segmentedKeys){return dependency.members.filter((member=>!1===segmentedKeys.includes(member.name))).map((member=>member.name))}#rewriteApplicationFrom(filename,scope){const callingModulePath=this.#fileHelper.extractPath(this.#module.filename),relativeFilename=this.#fileHelper.makePathRelative(filename,callingModulePath);return void 0!==scope?this.#fileHelper.addSubExtension(relativeFilename,scope):relativeFilename}#rewriteRuntimeFrom(dependency){return this.#fileHelper.stripPath(dependency.from)}}class ImportRewriter extends LocationRewriter{get replacementPattern(){return Patterns_IMPORT}parseStatement(statement){return this.parser.parseImport(statement)}includeInBundle(dependency,from,keys){if(0===dependency.members.length)return`import "${from}";`;return`import ${this.#rewriteStaticImportMembers(dependency,keys)} from "${from}";`}excludeFromBundle(dependency,from){if(0===dependency.members.length)return`await import("${from}");`;return`const ${this.#rewriteDynamicImportMembers(dependency)} = await import("${from}");`}#rewriteStaticImportMembers(dependency,keys){const members=dependency.members.filter((member=>keys.includes(member.name))),defaultMember=members.find((member=>member.name===Keywords$1_DEFAULT)),hasDefaultMember=void 0!==defaultMember,defaultMemberImport=hasDefaultMember?defaultMember.as:"",namedMemberImports=members.filter((member=>member.name!==Keywords$1_DEFAULT)).map((member=>member.name!==member.as?`${member.name} as ${member.as}`:member.name)),hasNamedMembers=namedMemberImports.length>0;return`${defaultMemberImport}${hasDefaultMember&&hasNamedMembers?", ":""}${hasNamedMembers?`{ ${namedMemberImports.join(", ")} }`:""}`}#rewriteDynamicImportMembers(dependency){if(this.#doesImportAll(dependency))return dependency.members[0].as;return`{ ${dependency.members.map((member=>member.name!==member.as?`${member.name} : ${member.as}`:member.name)).join(", ")} }`}#doesImportAll(dependency){return 1===dependency.members.length&&dependency.members[0].name===Values_ASTERISK}}class ExportRewriter extends LocationRewriter{get replacementPattern(){return Patterns_EXPORT}parseStatement(statement){return this.parser.parseExport(statement)}includeInBundle(dependency,from,keys){if(0===dependency.members.length)return`export "${from}";`;return`export ${this.#rewriteStaticExportMembers(dependency,keys)} from "${from}";`}excludeFromBundle(dependency,from){const keys=dependency.members.map((member=>member.name));return this.includeInBundle(dependency,from,keys)}#rewriteStaticExportMembers(dependency,keys){const members=dependency.members.filter((member=>keys.includes(member.name)));if(1===members.length&&""===members[0].name){const member=members[0];return member.name!==member.as?`${Values_ASTERISK} as ${member.as}`:Values_ASTERISK}return`{ ${members.map((member=>member.name!==member.as?`${member.name} as ${member.as}`:member.name)).join(", ")} }`}}class LocalBuilder{build(module,resources,segmentation,segment){const importRewriter=new ImportRewriter(module,resources,segmentation,segment),exportRewriter=new ExportRewriter(module,resources,segmentation,segment),importCode=importRewriter.rewrite(module.code);return exportRewriter.rewrite(importCode)}}const RunModes_NORMAL="normal",RunModes_DRY="dry",StatusCodes$1_OK=200,StatusCodes$1_BAD_REQUEST=400,StatusCodes$1_UNAUTHORIZED=401,StatusCodes$1_PAYMENT_REQUIRED=402,StatusCodes$1_FORBIDDEN=403,StatusCodes$1_NOT_FOUND=404,StatusCodes$1_TEAPOT=418,StatusCodes$1_SERVER_ERROR=500,StatusCodes$1_NOT_IMPLEMENTED=501;class InvalidVersionNumber extends BadRequest{#number;constructor(number){super(`Invalid version number '${number}'`),this.#number=number}get number(){return this.#number}}class ProcedureNotFound extends NotFound{#fqn;constructor(fqn){super(`Procedure '${fqn}' not found`),this.#fqn=fqn}get fqn(){return this.#fqn}}class ProcedureNotAccessible extends Forbidden{constructor(fqn,versionNumber){super(`Procedure '${fqn}' (v${versionNumber}) is not accessible`)}}class UnknownParameter extends BadRequest{#parameterName;constructor(parameterName){super(`Unknown parameter ${parameterName}`),this.#parameterName=parameterName}get parameterName(){return this.#parameterName}}class MissingParameterValue extends BadRequest{#parameterName;constructor(parameterName){super(`Missing value for parameter '${parameterName}'`),this.#parameterName=parameterName}get parameterName(){return this.#parameterName}}class InvalidParameterValue extends BadRequest{#parameterName;constructor(parameterName){super(`Invalid value for parameter '${parameterName}'`),this.#parameterName=parameterName}get parameterName(){return this.#parameterName}}class ArgumentExtractor{extract(parameters,args){const argsCopy=this.#copyArguments(parameters,args),values=[];for(const parameter of parameters){const value=this.#extractArgumentValue(parameter,argsCopy);values.push(value)}if(argsCopy.size>0){const name=argsCopy.keys().next().value;throw new UnknownParameter(name)}return values}#copyArguments(parameters,args){const copy=new Map;for(const[key,value]of args)if(this.#isOptionalArgument(key)){const name=this.#getParameterName(key);!0===this.#containsParameter(parameters,name)&&copy.set(name,value)}else copy.set(key,value);return copy}#isOptionalArgument(argument){return argument.startsWith("*")}#getParameterName(argument){return argument.substring(1)}#containsParameter(parameters,name){return void 0!==parameters.find((parameter=>parameter.name===name))}#extractArgumentValue(parameter,args,parent){return parameter instanceof NamedParameter?this.#extractNamedArgumentValue(parameter,args,parent):this.#extractDestructedArgumentValue(parameter,args)}#extractNamedArgumentValue(parameter,args,parent){const value=args.get(parameter.name);if(this.#isMissingParameterValue(parameter,value,parent))throw new MissingParameterValue(parameter.name);if(this.#isInvalidRestParameter(parameter,value,parent))throw new InvalidParameterValue(parameter.name);return args.delete(parameter.name),value}#extractDestructedArgumentValue(parameter,args){return parameter instanceof ArrayParameter?this.#extractArrayArgumentValue(parameter,args):this.#extractObjectArgumentValue(parameter,args)}#extractArrayArgumentValue(parameter,args){const values=this.#extractVariableValues(parameter,args);return void 0!==values?Object.values(values):void 0}#extractObjectArgumentValue(parameter,args){return this.#extractVariableValues(parameter,args)}#extractVariableValues(parameter,args){const useIndex=parameter instanceof ArrayParameter,values={},missingValues=[];let containsValues=!1,index=0;for(const variable of parameter.variables){const key=useIndex?index++:variable.name,value=this.#extractArgumentValue(variable,args,parameter);void 0!==value?containsValues=!0:!1===variable.isOptional&&missingValues.push(variable.name),values[key]=value}if(!0===containsValues&&missingValues.length>0)throw new MissingParameterValue(missingValues[0]);return containsValues?values:void 0}#isMissingParameterValue(parameter,value,parent){return void 0===value&&(!0!==parameter.isOptional&&!0!==parent?.isOptional)}#isInvalidRestParameter(parameter,value,parent){return!1!==parameter.name.startsWith("...")&&(void 0===parent&&value instanceof Array==!1||parent instanceof ArrayParameter&&value instanceof Array==!1||parent instanceof ObjectParameter&&value instanceof Object==!1)}}class ErrorConverter{toStatus(error){return error instanceof BadRequest?StatusCodes$1_BAD_REQUEST:error instanceof Forbidden?StatusCodes$1_FORBIDDEN:error instanceof NotFound?StatusCodes$1_NOT_FOUND:error instanceof NotImplemented?StatusCodes$1_NOT_IMPLEMENTED:error instanceof PaymentRequired?StatusCodes$1_PAYMENT_REQUIRED:error instanceof Teapot?StatusCodes$1_TEAPOT:error instanceof Unauthorized?StatusCodes$1_UNAUTHORIZED:StatusCodes$1_SERVER_ERROR}fromStatus(status,message){switch(status){case StatusCodes$1_BAD_REQUEST:return new BadRequest(message);case StatusCodes$1_FORBIDDEN:return new Forbidden(message);case StatusCodes$1_NOT_FOUND:return new NotFound(message);case StatusCodes$1_NOT_IMPLEMENTED:return new NotImplemented(message);case StatusCodes$1_PAYMENT_REQUIRED:return new PaymentRequired(message);case StatusCodes$1_TEAPOT:return new Teapot(message);case StatusCodes$1_UNAUTHORIZED:return new Unauthorized(message);default:return new ServerError(message)}}}const VERSION_EXPRESSION=/^\d+(?:\.\d+){0,2}$/;class VersionParser{parse(number){if(0===number.trim().length)return Version.DEFAULT;if(!1===VERSION_EXPRESSION.test(number))throw new InvalidVersionNumber(number);const parts=number.split(".");switch(parts.length){case 1:return new Version(Number.parseInt(parts[0]));case 2:return new Version(Number.parseInt(parts[0]),Number.parseInt(parts[1]));default:return new Version(Number.parseInt(parts[0]),Number.parseInt(parts[1]),Number.parseInt(parts[2]))}}}class ImplementationNotFound extends NotFound{#fqn;#version;constructor(fqn,version){super(`No implementation found for procedure '${fqn}' with version '${version}'`),this.#fqn=fqn,this.#version=version}get fqn(){return this.#fqn}get version(){return this.#version}}class InvalidSegment extends ServerError{constructor(){super("Invalid segment")}}class Application{#segments=new Map;addSegment(segment){this.#segments.set(segment.id,segment)}getClassNames(){const names=new Set;for(const segment of this.#segments.values()){segment.getClasses().forEach((clazz=>names.add(clazz.fqn)))}return[...names.values()]}hasClass(fqn){return this.getClassNames().includes(fqn)}getClass(fqn){for(const segment of this.#segments.values())if(segment.hasClass(fqn))return segment.getClass(fqn)}getClassByImplementation(implementation){for(const segment of this.#segments.values()){const clazz=segment.getClassByImplementation(implementation);if(void 0!==clazz)return clazz}}getProcedureNames(){const names=new Set;for(const segment of this.#segments.values()){segment.getExposedProcedures().forEach((procedure=>names.add(procedure.fqn)))}return[...names.values()]}hasProcedure(fqn){return this.getProcedureNames().includes(fqn)}getProcedure(fqn){for(const segment of this.#segments.values())if(segment.hasProcedure(fqn))return segment.getProcedure(fqn)}}class ExecutionManager{#argumentConstructor=new ArgumentExtractor;#errorConverter=new ErrorConverter;#application=new Application;async addSegment(segment){if(segment instanceof Segment$1==!1)throw new InvalidSegment;this.#application.addSegment(segment)}getClassNames(){return this.#application.getClassNames()}hasClass(fqn){return this.#application.hasClass(fqn)}getClass(fqn){return this.#application.getClass(fqn)}getClassByImplementation(implementation){return this.#application.getClassByImplementation(implementation)}getProcedureNames(){return this.#application.getProcedureNames()}hasProcedure(fqn){return this.#application.hasProcedure(fqn)}getProcedure(fqn){return this.#application.getProcedure(fqn)}async run(request){const implementation=this.#getImplementation(request.fqn,request.version),args=this.#argumentConstructor.extract(implementation.parameters,request.args);return request.mode===RunModes_DRY?new Response(StatusCodes$1_OK,void 0):this.#runImplementation(request,implementation,args)}#getImplementation(fqn,version){const procedure=this.#application.getProcedure(fqn);if(void 0===procedure)throw new ProcedureNotFound(fqn);const implementation=procedure.getImplementation(version);if(void 0===implementation)throw new ImplementationNotFound(procedure.fqn,version.toString());return implementation}async#runImplementation(request,implementation,args){try{const result=await implementation.executable.call(request,...args);return new Response(StatusCodes$1_OK,result)}catch(error){const status=this.#errorConverter.toStatus(error);return new Response(status,error)}}}class RemoteBuilder{build(implementations){let code="";for(const implementation of implementations)code+=implementation.access===AccessLevels.PRIVATE?this.#createPrivateCode(implementation):this.#createPublicCode(implementation);return code.trim()}#createPrivateCode(implementation){const fqn=implementation.fqn,version=implementation.version,declaration=this.#createDeclaration(implementation),body=`throw new ProcedureNotAccessible('${fqn}', '${version}');`;return this.#createFunction(declaration,body)}#createPublicCode(implementation){const fqn=implementation.fqn,version=implementation.version,args=this.#createArguments(implementation.model.parameters),declaration=this.#createDeclaration(implementation),body=`return __run('${fqn}', '${version}', { ${args} }, this);`;return this.#createFunction(declaration,body)}#createParameters(parameters){const result=[];for(const parameter of parameters)parameter instanceof ESField?result.push(parameter.name):(parameter instanceof ESDestructuredArray||parameter instanceof ESDestructuredObject)&&result.push(parameter.toString());return result.join(", ")}#createArguments(parameters){return this.#extractArguments(parameters).join(", ")}#extractArguments(parameters){const result=[];for(const parameter of parameters)if(parameter instanceof ESDestructuredValue){const argumentz=this.#extractArguments(parameter.members);result.push(...argumentz)}else if(parameter instanceof ESField){const argument=this.#createNamedArgument(parameter);result.push(argument)}return result}#createNamedArgument(parameter){const key=parameter.name,value=key.startsWith("...")?key.substring(3):key;return`'${key}': ${value}`}#createDeclaration(implementation){const name=implementation.model.name,parameters=this.#createParameters(implementation.model.parameters);return`\nexport ${implementation.importKey===Keywords$1_DEFAULT?`${Keywords$1_DEFAULT} `:""}async function ${name}(${parameters})`}#createFunction(declaration,body){return`${declaration} {\n\t${body}\n}\n`}}let Builder$2=class{#targetFileManager;#localBuilder=new LocalBuilder;#remoteBuilder=new RemoteBuilder;#fileHelper=new FileHelper;constructor(targetFileManager){this.#targetFileManager=targetFileManager}async build(application){const repository=application.repository,segmentation=application.segmentation,resources=application.resources,builds=repository.modules.map((module=>this.#buildModule(module,resources,segmentation)));await Promise.all(builds)}async#buildModule(module,resources,segmentation){const moduleSegments=segmentation.getSegments(module.filename);if(0===moduleSegments.length)return this.#buildCommonModule(module,resources,segmentation);const segmentBuilds=moduleSegments.map((segment=>this.#buildSegmentModule(module,resources,segment,segmentation))),remoteBuild=moduleSegments[0].getModule(module.filename).hasImplementations()?this.#buildRemoteModule(module,moduleSegments):Promise.resolve();await Promise.all([...segmentBuilds,remoteBuild]),this.#targetFileManager.delete(module.filename)}async#buildCommonModule(module,resources,segmentation){const filename=module.filename,code=this.#localBuilder.build(module,resources,segmentation);return this.#targetFileManager.write(filename,code)}async#buildSegmentModule(module,resources,segment,segmentation){const filename=this.#fileHelper.addSubExtension(module.filename,segment.name),code=this.#localBuilder.build(module,resources,segmentation,segment);return this.#targetFileManager.write(filename,code)}async#buildRemoteModule(module,segments){const implementations=this.#getImplementations(module,segments),filename=this.#fileHelper.addSubExtension(module.filename,"remote"),code=this.#remoteBuilder.build(implementations);return this.#targetFileManager.write(filename,code)}#getImplementations(module,segments){const implementations=segments.map((segment=>segment.getModule(module.filename))).flatMap((segmentModule=>segmentModule.getImplementations())),unique=new Map;for(const implementation of implementations){const key=`${implementation.fqn}:${implementation.version.toString()}`;unique.set(key,implementation)}return[...unique.values()]}};let Builder$1=class{#targetFileManager;#logger;#fileHelper=new FileHelper;#versionParser=new VersionParser;constructor(targetFileManager,logger){this.#targetFileManager=targetFileManager,this.#logger=logger}async build(application){const builds=application.segmentation.segments.map((segment=>this.#buildSegment(segment)));await Promise.all(builds)}async#buildSegment(segment){const filename=`${segment.name}.segment.js`,code=this.#createCode(segment);await this.#targetFileManager.write(filename,code),this.#logger.info(`Built ${segment.name} segment (${segment.modules.length} modules, ${segment.procedures.length} procedures, ${segment.classes.length} classes)`)}#createCode(segment){return`${this.#createImportCode(segment)}\n${this.#createSegmentCode(segment)}`}#createImportCode(segment){return`import { Segment, Class, Procedure, Implementation, Version, NamedParameter, ArrayParameter, ObjectParameter } from "jitar";\n${this.#createModuleImports(segment)}`}#createModuleImports(segment){const imports=[];for(const module of segment.getSegmentedModules()){if(0===module.members.length)continue;const filename=this.#fileHelper.addSubExtension(module.filename,segment.name),importRule=`import ${this.#createModuleImportMembers(module)} from "./${filename}";`;imports.push(importRule)}return imports.join("\n")}#createModuleImportMembers(module){const members=module.members,defaultImplementation=members.find((member=>member.importKey===Keywords$1_DEFAULT)),hasDefaultImplementation=void 0!==defaultImplementation,defaultMemberImport=hasDefaultImplementation?defaultImplementation.id:"",namedImplementations=members.filter((member=>member.importKey!==Keywords$1_DEFAULT)),nameImplementationImports=namedImplementations.map((member=>`${member.importKey} as ${member.id}`)),hasNamedImplementations=namedImplementations.length>0;return`${defaultMemberImport}${hasDefaultImplementation&&hasNamedImplementations?", ":""}${hasNamedImplementations?`{ ${nameImplementationImports.join(", ")} }`:""}`}#createSegmentCode(segment){const lines=[];lines.push(`export default new Segment("${segment.name}")`);for(const clazz of segment.classes)lines.push(`\t.addClass(new Class("${clazz.fqn}", ${clazz.id}))`);for(const procedure of segment.procedures){lines.push(`\t.addProcedure(new Procedure("${procedure.fqn}")`);for(const implementation of procedure.implementations){const version=this.#createVersionCode(implementation.version),parameters=this.#createParametersCode(implementation.model);lines.push(`\t\t.addImplementation(new Implementation(${version}, "${implementation.access}", ${parameters}, ${implementation.id}))`)}lines.push("\t)")}return lines.join("\n")}#createVersionCode(versionString){const version=this.#versionParser.parse(versionString);return`new Version(${version.major}, ${version.minor}, ${version.patch})`}#createParametersCode(model){return`[${this.#extractParameters(model.parameters).join(", ")}]`}#extractParameters(parameters){const result=[];for(const parameter of parameters)result.push(this.#extractParameter(parameter));return result}#extractParameter(parameter){return parameter instanceof ESDestructuredArray?this.#createArrayParameter(parameter):parameter instanceof ESDestructuredObject?this.#createObjectParameter(parameter):this.#createNamedParameter(parameter)}#createNamedParameter(parameter){return`new NamedParameter("${parameter.name}", ${void 0!==parameter.value})`}#createArrayParameter(parameter){return`new ArrayParameter([${this.#extractParameters(parameter.members).join(", ")}])`}#createObjectParameter(parameter){return`new ObjectParameter([${this.#extractParameters(parameter.members).join(", ")}])`}};class Builder{#moduleBuilder;#segmentBuilder;constructor(projectFileManager,logger){const targetFileManager=projectFileManager.target;this.#moduleBuilder=new Builder$2(targetFileManager),this.#segmentBuilder=new Builder$1(targetFileManager,logger)}async build(application){await Promise.all([this.#moduleBuilder.build(application),this.#segmentBuilder.build(application)])}}class ProjectFileManager{#source;#target;#resource;#segment;constructor(source,target,resource,segment){this.#source=source,this.#target=target,this.#resource=resource,this.#segment=segment}get source(){return this.#source}get target(){return this.#target}get resource(){return this.#resource}get segment(){return this.#segment}}class BuildManager{#logger;#fileManager;#applicationReader;#applicationBuilder;constructor(configuration,logLevel){this.#logger=new Logger(logLevel);const sourceFileManager=new FileManager(configuration.source),targetFileManager=new FileManager(configuration.target),resourceFileManager=new FileManager(configuration.resources),segmentFileManager=new FileManager(configuration.segments);this.#fileManager=new ProjectFileManager(sourceFileManager,targetFileManager,resourceFileManager,segmentFileManager),this.#applicationReader=new Reader(this.#fileManager),this.#applicationBuilder=new Builder(this.#fileManager,this.#logger)}async build(){const sourceFileManager=this.#fileManager.source,resourceFileManager=this.#fileManager.resource,segmentFileManager=this.#fileManager.segment,moduleFiles=await sourceFileManager.filter(Files$1_MODULE_PATTERN),resourceFiles=await resourceFileManager.filter(Files$1_RESOURCE_PATTERN),segmentFiles=await segmentFileManager.filter(Files$1_SEGMENT_PATTERN),applicationModel=await this.#applicationReader.read(moduleFiles,resourceFiles,segmentFiles);return this.#applicationBuilder.build(applicationModel)}}class Validator{#strict;constructor(strict=!0){this.#strict=strict}validate(data,scheme){const errors=[];this.#validateData("",data,scheme,errors);return{valid:0===errors.length,errors:errors}}#validateData(key,data,scheme,errors){this.#strict&&this.#validateKeys(key,data,scheme,errors),this.#validateValues(key,data,scheme,errors)}#validateKeys(key,data,scheme,errors){const dataKeys=Object.keys(data),schemeKeys=Object.keys(scheme);for(const dataKey of dataKeys)if(!1===schemeKeys.includes(dataKey)){const absoluteKey=this.#composeKey(key,dataKey);errors.push(`Unknown field '${absoluteKey}'`)}}#validateValues(key,data,scheme,errors){const valueKeys=Object.keys(scheme);for(const valueKey of valueKeys){const absoluteKey=this.#composeKey(key,valueKey),fieldScheme=scheme[valueKey],value=data[valueKey];this.#validateValue(absoluteKey,value,fieldScheme,errors)}}#validateValue(key,value,scheme,errors){if(void 0!==value)switch(scheme.type){case"string":return this.#validateString(key,value,scheme,errors);case"integer":return this.#validateInteger(key,value,scheme,errors);case"real":return this.#validateReal(key,value,scheme,errors);case"boolean":return this.#validateBoolean(key,value,scheme,errors);case"url":return this.#validateUrl(key,value,scheme,errors);case"group":return this.#validateGroup(key,value,scheme,errors);case"list":return this.#validateList(key,value,scheme,errors)}else!0===scheme.required&&errors.push(`Field '${key}' is required`)}#validateString(key,value,scheme,errors){"string"!=typeof value&&errors.push(`Field '${key}' is not a string`)}#validateInteger(key,value,scheme,errors){"number"==typeof value&&!1!==Number.isInteger(value)||errors.push(`Field '${key}' is not an integer`)}#validateReal(key,value,scheme,errors){"number"!=typeof value&&errors.push(`Field '${key}' is not a real number`)}#validateBoolean(key,value,scheme,errors){"boolean"!=typeof value&&errors.push(`Field '${key}' is not a boolean`)}#validateUrl(key,value,scheme,errors){"string"==typeof value&&!1!==value.startsWith("http")||errors.push(`Field '${key}' is not a valid URL`)}#validateGroup(key,value,scheme,errors){"object"==typeof value?this.#validateData(key,value,scheme.fields,errors):errors.push(`Field '${key}' is not an object`)}#validateList(key,value,scheme,errors){if(!Array.isArray(value))return void errors.push(`Field '${key}' is not a list`);const data=value;for(const itemIndex in data){const itemKey=this.#composeKey(key,itemIndex),itemValue=data[itemIndex];this.#validateValue(itemKey,itemValue,scheme.items,errors)}}#composeKey(parent,key){return""===parent?key:`${parent}.${key}`}}class Configurator{async configure(filename){dotenv.config({path:filename})}}class RuntimeConfigurationInvalid extends Error{constructor(validation){super(`Runtime configuration is invalid:\n${validation.errors.join("\n")}`)}}const DefaultValues_FILENAME="./jitar.json",DefaultValues_SOURCE="./src",DefaultValues_TARGET="./dist",DefaultValues_SEGMENTS="./segments",DefaultValues_RESOURCES="./resources",validationScheme$6={source:{type:"string",required:!1},target:{type:"string",required:!1},segments:{type:"string",required:!1},resources:{type:"string",required:!1}};let ConfigurationBuilder$1=class{#reader;#validator;constructor(reader,validator){this.#reader=reader,this.#validator=validator}async build(filename=DefaultValues_FILENAME){const configuration=await this.#reader.read(filename),validation=this.#validator.validate(configuration,validationScheme$6);if(!1===validation.valid)throw new RuntimeConfigurationInvalid(validation);return configuration.source??=DefaultValues_SOURCE,configuration.target??=DefaultValues_TARGET,configuration.segments??=DefaultValues_SEGMENTS,configuration.resources??=DefaultValues_RESOURCES,configuration}};class ServerConfigurationInvalid extends Error{constructor(validation){super(`Invalid server configuration:\n => ${validation.errors.join("\n => ")}`)}}const validationScheme={url:{type:"url",required:!0},setUp:{type:"list",required:!1,items:{type:"string"}},tearDown:{type:"list",required:!1,items:{type:"string"}},middleware:{type:"list",required:!1,items:{type:"string"}},healthChecks:{type:"list",required:!1,items:{type:"string"}},gateway:{type:"group",required:!1,fields:{monitor:{type:"integer",required:!1},trustKey:{type:"string",required:!1}}},proxy:{type:"group",required:!1,fields:{gateway:{type:"url",required:!0},repository:{type:"url",required:!0}}},repository:{type:"group",required:!1,fields:{indexFilename:{type:"string",required:!1},serveIndexOnNotFound:{type:"boolean",required:!1},assets:{type:"list",required:!1,items:{type:"string"}}}},standalone:{type:"group",required:!1,fields:{segments:{type:"list",required:!0,items:{type:"string"}},indexFilename:{type:"string",required:!1},serveIndexOnNotFound:{type:"boolean",required:!1},assets:{type:"list",required:!1,items:{type:"string"}}}},worker:{type:"group",required:!1,fields:{gateway:{type:"url",required:!1},segments:{type:"list",required:!0,items:{type:"string"}},trustKey:{type:"string",required:!1}}}};class ConfigurationBuilder{#reader;#validator;constructor(reader,validator){this.#reader=reader,this.#validator=validator}async build(filename){const configuration=await this.#reader.read(filename),validation=this.#validator.validate(configuration,validationScheme);if(!1===validation.valid)throw new ServerConfigurationInvalid(validation);return configuration}}class InvalidConfigurationFile extends Error{constructor(filename){super(`${filename} is not a valid configuration file.`)}}const ENVIRONMENT_VARIABLE_REGEX=/\${([^}]*)}/g;class ConfigurationReader{#fileManager;constructor(fileManager){this.#fileManager=fileManager}async read(filename){if(!1===await this.#fileManager.exists(filename))return{};const file=await this.#fileManager.read(filename);if(!1===file.type.includes("json"))throw new InvalidConfigurationFile(filename);const content=file.content.toString(),configuration=this.#replaceEnvironmentVariables(content);return this.#parseJson(configuration)}#replaceEnvironmentVariables(content){return content.replace(ENVIRONMENT_VARIABLE_REGEX,((match,key)=>process.env[key]??"null"))}#parseJson(configuration){return JSON.parse(configuration)}}class ConfigurationManager{#environmentConfigurator;#runtimeConfigurationBuilder;#serverConfigurationBuilder;constructor(rootPath="./"){const fileManager=new FileManager(rootPath),reader=new ConfigurationReader(fileManager),validator=new Validator;this.#environmentConfigurator=new Configurator,this.#runtimeConfigurationBuilder=new ConfigurationBuilder$1(reader,validator),this.#serverConfigurationBuilder=new ConfigurationBuilder(reader,validator)}configureEnvironment(filename=".env"){return this.#environmentConfigurator.configure(filename)}getRuntimeConfiguration(filename){return this.#runtimeConfigurationBuilder.build(filename)}getServerConfiguration(filename){return this.#serverConfigurationBuilder.build(filename)}}class BuildApp{async execute(args){const environmentFile=args.getOptionalArgument("--env-file",void 0),runtimeConfigFile=args.getOptionalArgument("--config",void 0),logLevelString=args.getOptionalArgument("--log-level",void 0),logLevel=this.#parseLogLevel(logLevelString),configurationManager=new ConfigurationManager;await configurationManager.configureEnvironment(environmentFile);const configuration=await configurationManager.getRuntimeConfiguration(runtimeConfigFile);return new BuildManager(configuration,logLevel).build()}#parseLogLevel(logLevel){if(void 0===logLevel)return;return(new LogLevelParser).parse(logLevel)}}const HeaderKeys_CONTENT_TYPE="content-type",HeaderKeys_CONTENT_TYPE_OPTIONS="x-content-type-options",HeaderKeys_JITAR_CONTENT_TYPE="x-jitar-content-type",HeaderKeys_JITAR_PROCEDURE_VERSION="x-jitar-procedure-version",HeaderKeys_POWERED_BY="x-powered-by",HeaderValues_NO_SNIFF="nosniff",HeaderValues_APPLICATION_JSON="application/json",HeaderValues_APPLICATION_STREAM="application/octet-stream";class InvalidWorkerId extends Error{constructor(){super("Invalid worker id")}}class HttpRemote{#url;#httpClient;#errorConverter=new ErrorConverter;#validator=new Validator;constructor(url,httpClient){this.#url=url,this.#httpClient=httpClient}connect(){return Promise.resolve()}disconnect(){return Promise.resolve()}async provide(filename){const remoteUrl=`${this.#url}/${filename}`,response=await this.#callRemote(remoteUrl,{method:"GET"}),type=response.headers.get(HeaderKeys_CONTENT_TYPE)??HeaderValues_APPLICATION_STREAM,result=await response.arrayBuffer(),content=Buffer.from(result);return new File(filename,type,content)}async isHealthy(){const remoteUrl=`${this.#url}/health/status`,response=await this.#callRemote(remoteUrl,{method:"GET"});return"true"===await response.text()}async getHealth(){const remoteUrl=`${this.#url}/health`,response=await this.#callRemote(remoteUrl,{method:"GET"}),health=await response.json();return new Map(Object.entries(health))}async addWorker(url,procedureNames,trustKey){const remoteUrl=`${this.#url}/workers`,body={url:url,procedureNames:procedureNames,trustKey:trustKey},options={method:"POST",headers:{"Content-Type":HeaderValues_APPLICATION_JSON},body:JSON.stringify(body)},response=await this.#callRemote(remoteUrl,options),contentType=response.headers.get(HeaderKeys_CONTENT_TYPE);if(null===contentType||!1===contentType.includes(HeaderValues_APPLICATION_JSON))throw new InvalidWorkerId;const result=await response.json();if(!1===this.#validator.validate(result,{id:{type:"string",required:!0}}).valid)throw new InvalidWorkerId;return result.id}async removeWorker(id){const remoteUrl=`${this.#url}/workers/${id}`,options={method:"DELETE",headers:{"Content-Type":HeaderValues_APPLICATION_JSON}};await this.#callRemote(remoteUrl,options)}async run(request){request.setHeader(HeaderKeys_CONTENT_TYPE,HeaderValues_APPLICATION_JSON);const argsObject=Object.fromEntries(request.args),headersObject=Object.fromEntries(request.headers),versionString=request.version.toString();headersObject[HeaderKeys_JITAR_PROCEDURE_VERSION]=versionString;const remoteUrl=`${this.#url}/rpc/${request.fqn}`,options={method:"POST",redirect:"manual",headers:headersObject,body:await this.#createRequestBody(argsObject)},response=await this.#callRemote(remoteUrl,options,!1),status=response.status,result=await this.#getResponseResult(response),headers=this.#createResponseHeaders(response);return new Response(status,result,headers)}async#callRemote(remoteUrl,options,throwOnError=!0){const response=await this.#httpClient.execute(remoteUrl,options);if(throwOnError&&this.#isErrorResponse(response)){const result=await this.#getResponseResult(response);throw this.#errorConverter.fromStatus(response.status,String(result))}return response}#isErrorResponse(response){return response.status<200||response.status>399}async#createRequestBody(body){return JSON.stringify(body)}async#getResponseResult(response){const contentType=response.headers.get(HeaderKeys_JITAR_CONTENT_TYPE)??response.headers.get(HeaderKeys_CONTENT_TYPE);if(contentType?.includes("undefined"))return;if(contentType?.includes("null"))return null;if(contentType?.includes("json"))return response.json();const content=await response.text();return contentType?.includes("boolean")?"true"===content:contentType?.includes("number")?Number(content):content}#createResponseHeaders(response){const headers=new Map;for(const[name,value]of response.headers)headers.set(name,value);return headers}}class FetchHttpClient{async execute(url,options){return fetch(url,options)}}class HttpRemoteBuilder{#httpClient;constructor(httpClient=new FetchHttpClient){this.#httpClient=httpClient}build(url){return new HttpRemote(url,this.#httpClient)}}class DummyProvider{get url(){throw new NotImplemented}start(){return Promise.resolve()}stop(){return Promise.resolve()}async isHealthy(){return!0}async getHealth(){return new Map}provide(filename){throw new NotImplemented}}class DummyRunner{get url(){throw new NotImplemented}get trustKey(){throw new NotImplemented}start(){return Promise.resolve()}stop(){return Promise.resolve()}async isHealthy(){return!0}async getHealth(){return new Map}getProcedureNames(){throw new NotImplemented}hasProcedure(name){throw new NotImplemented}run(request){throw new NotImplemented}}class NoWorkerAvailable extends ServerError{#name;constructor(name){super(`No worker available for procedure '${name}'`),this.#name=name}get name(){return this.#name}}class WorkerBalancer{#workers=[];#currentIndex=0;get workers(){return this.#workers}addWorker(worker){this.#workers.includes(worker)||this.#workers.push(worker)}removeWorker(worker){const index=this.#workers.indexOf(worker);-1!==index&&this.#workers.splice(index,1)}getNextWorker(){if(0!==this.#workers.length)return this.#currentIndex>=this.#workers.length&&(this.#currentIndex=0),this.#workers[this.#currentIndex++]}async run(request){const worker=this.getNextWorker();if(void 0===worker)throw new NoWorkerAvailable(request.fqn);return worker.run(request)}}class IdGenerator{generate(){return crypto.randomUUID()}}class UnknownWorker extends ServerError{#id;constructor(id){super(`Unknown worker id '${id}'`),this.#id=id}get id(){return this.#id}}class WorkerManager{#workers=new Map;#balancers=new Map;#idGenerator=new IdGenerator;get workers(){return[...this.#workers.values()]}get balancers(){return this.#balancers}getProcedureNames(){const procedureNames=this.workers.map((worker=>worker.getProcedureNames()));return[...new Set(procedureNames.flat()).values()]}hasProcedure(fqn){return this.getProcedureNames().includes(fqn)}addWorker(worker){worker.id=this.#idGenerator.generate(),this.#workers.set(worker.id,worker);for(const name of worker.getProcedureNames()){this.#getOrCreateBalancer(name).addWorker(worker)}return worker.id}getWorker(id){const worker=this.#workers.get(id);if(void 0===worker)throw new UnknownWorker(id);return worker}removeWorker(worker){this.#workers.delete(worker.id);for(const name of worker.getProcedureNames()){const balancer=this.#getBalancer(name);void 0!==balancer&&balancer.removeWorker(worker)}}#getBalancer(fqn){return this.#balancers.get(fqn)}#getOrCreateBalancer(fqn){let balancer=this.#getBalancer(fqn);return void 0===balancer&&(balancer=new WorkerBalancer,this.#balancers.set(fqn,balancer)),balancer}async run(request){const balancer=this.#getBalancer(request.fqn);if(void 0===balancer)throw new ProcedureNotFound(request.fqn);return balancer.run(request)}}class WorkerMonitor{#workerManager;#frequency;#interval=null;constructor(workerManager,frequency=5e3){this.#workerManager=workerManager,this.#frequency=frequency}get workerManager(){return this.#workerManager}start(){this.#interval=setInterval((async()=>this.#monitor()),this.#frequency)}stop(){null!==this.#interval&&clearInterval(this.#interval)}async#monitor(){const promises=this.#workerManager.workers.map((worker=>this.#monitorWorker(worker)));await Promise.all(promises)}async#monitorWorker(worker){!1===await this.#checkWorkerAvailable(worker)&&this.#workerManager.removeWorker(worker)}async#checkWorkerAvailable(worker){try{return await worker.isHealthy()}catch{return!1}}}class InvalidTrustKey extends Unauthorized{constructor(){super("Invalid trust key")}}class LocalGateway{#url;#trustKey;#workerManager;#workerMonitor;constructor(configuration){this.#url=configuration.url,this.#trustKey=configuration.trustKey,this.#workerManager=new WorkerManager,this.#workerMonitor=new WorkerMonitor(this.#workerManager,configuration.monitorInterval)}get url(){return this.#url}get trustKey(){return this.#trustKey}async start(){return this.#workerMonitor.start()}async stop(){return this.#workerMonitor.stop()}async isHealthy(){return!0}async getHealth(){return new Map}async addWorker(worker){if(this.#isInvalidTrustKey(worker.trustKey))throw new InvalidTrustKey;return this.#workerManager.addWorker(worker)}getWorker(id){return this.#workerManager.getWorker(id)}async removeWorker(worker){return this.#workerManager.removeWorker(worker)}getProcedureNames(){return this.#workerManager.getProcedureNames()}hasProcedure(name){return this.#workerManager.hasProcedure(name)}async run(request){return this.#workerManager.run(request)}#isInvalidTrustKey(trustKey){return void 0!==this.#trustKey&&trustKey!==this.#trustKey}}class RemoteGateway{#url;#remote;constructor(configuration){this.#url=configuration.url,this.#remote=configuration.remote}get url(){return this.#url}get trustKey(){}start(){return this.#remote.connect()}stop(){return this.#remote.disconnect()}isHealthy(){return this.#remote.isHealthy()}getHealth(){return this.#remote.getHealth()}getProcedureNames(){throw new NotImplemented}hasProcedure(name){throw new NotImplemented}addWorker(worker){return this.#remote.addWorker(worker.url,worker.getProcedureNames(),worker.trustKey)}removeWorker(worker){return this.#remote.removeWorker(worker.id)}run(request){return this.#remote.run(request)}}class Proxy{#url;#provider;#runner;constructor(configuration){this.#url=configuration.url,this.#provider=configuration.provider,this.#runner=configuration.runner}get url(){return this.#url}get trustKey(){return this.#runner.trustKey}get provider(){return this.#provider}get runner(){return this.#runner}async isHealthy(){const[providerHealthy,runnerHealthy]=await Promise.all([this.#provider.isHealthy(),this.#runner.isHealthy()]);return providerHealthy&&runnerHealthy}async getHealth(){const[providerHealth,runnerHealth]=await Promise.all([this.#provider.getHealth(),this.#runner.getHealth()]);return new Map([...providerHealth,...runnerHealth])}async start(){await Promise.all([this.#provider.start(),this.#runner.start()])}async stop(){await Promise.all([this.#runner.stop(),this.#provider.stop()])}provide(filename){return this.#provider.provide(filename)}getProcedureNames(){return this.#runner.getProcedureNames()}hasProcedure(fqn){return this.#runner.hasProcedure(fqn)}run(request){return this.#runner.run(request)}}class LocalRepository{#url;#sourcingManager;#assets;#indexFilename;#serveIndexOnNotFound;constructor(configuration){this.#url=configuration.url,this.#sourcingManager=configuration.sourcingManager,this.#assets=configuration.assets,this.#indexFilename=configuration.indexFilename??"index.html",this.#serveIndexOnNotFound=configuration.serveIndexOnNotFound??false}get url(){return this.#url}start(){return Promise.resolve()}stop(){return Promise.resolve()}async isHealthy(){return!0}async getHealth(){return new Map}async provide(filename){if(this.#mustProvideIndex(filename))return this.provide(this.#indexFilename);if(!1===this.#assets.has(filename))throw new FileNotFound(filename);return this.#sourcingManager.read(filename)}#mustProvideIndex(filename){return""===filename||filename!==this.#indexFilename&&(this.#serveIndexOnNotFound&&!1===this.#assets.has(filename))}}class RemoteRepository{#url;#remote;constructor(configuration){this.#url=configuration.url,this.#remote=configuration.remote}get url(){return this.#url}start(){return this.#remote.connect()}stop(){return this.#remote.disconnect()}isHealthy(){return this.#remote.isHealthy()}getHealth(){return this.#remote.getHealth()}provide(filename){return this.#remote.provide(filename)}}class ClassNotFound extends Error{constructor(name){super(`The class '${name}' could not be found`)}}class InvalidClass extends Error{constructor(name){super(`The class '${name}' is invalid`)}}class NoDeserializerFound extends Error{constructor(type){super(`No deserializer found for value of type '${type}'`)}}class NoSerializerFound extends Error{constructor(type){super(`No serializer found for value of type '${type}'`)}}class Serializer{#serializers=[];addSerializer(serializer){serializer.parent=this,this.#serializers.unshift(serializer)}async serialize(value){const serializer=this.#serializers.find((serializer=>serializer.canSerialize(value)));if(void 0===serializer)throw new NoSerializerFound(typeof value);return serializer.serialize(value)}async deserialize(value){const serializer=this.#serializers.find((serializer=>serializer.canDeserialize(value)));if(void 0===serializer)throw new NoDeserializerFound(typeof value);return serializer.deserialize(value)}}class ParentSerializerNotSet extends Error{constructor(){super("Parent serializer not set")}}class ValueSerializer{#parent;set parent(parent){this.#parent=parent}serializeOther(value){if(void 0===this.#parent)throw new ParentSerializerNotSet;return this.#parent.serialize(value)}deserializeOther(value){if(void 0===this.#parent)throw new ParentSerializerNotSet;return this.#parent.deserialize(value)}}class ArraySerializer extends ValueSerializer{canSerialize(value){return value instanceof Array}canDeserialize(value){return value instanceof Array}async serialize(array){const values=[];for(const value of array)values.push(await this.serializeOther(value));return values}async deserialize(array){return Promise.all(array.map((async value=>this.deserializeOther(value))))}}class InvalidBigIntString extends Error{constructor(bigIntString){super(`Invalid BigInt string '${bigIntString}'`)}}class BigIntSerializer extends ValueSerializer{canSerialize(value){return"bigint"==typeof value}canDeserialize(value){const bigInt=value;return bigInt instanceof Object&&!0===bigInt.serialized&&"BigInt"===bigInt.name&&"string"==typeof bigInt.value}async serialize(bigInt){return{serialized:!0,name:"BigInt",value:bigInt.toString()}}async deserialize(object){try{return BigInt(object.value)}catch{throw new InvalidBigIntString(object.value)}}}class InvalidBufferString extends Error{constructor(bufferString){super(`Invalid Buffer string '${bufferString}'`)}}class BufferSerializer extends ValueSerializer{canSerialize(value){return value instanceof Buffer}canDeserialize(value){const buffer=value;return buffer instanceof Object&&!0===buffer.serialized&&"Buffer"===buffer.name&&"string"==typeof buffer.base64}async serialize(buffer){return{serialized:!0,name:"Buffer",base64:buffer.toString("base64")}}async deserialize(object){try{return Buffer.from(object.base64,"base64")}catch{throw new InvalidBufferString(object.base64)}}}const reflector$1=new Reflector;class ClassSerializer extends ValueSerializer{#classResolver;constructor(classResolver){super(),this.#classResolver=classResolver}canSerialize(value){return value instanceof Object&&reflector$1.isClassObject(value)}canDeserialize(value){const object=value;return object instanceof Object&&!0===object.serialized&&"class"===object.name&&"string"==typeof object.key&&object.args instanceof Object&&object.args.constructor===Object&&object.fields instanceof Object&&object.fields.constructor===Object}async serialize(object){const clazz=reflector$1.getClass(object),model=reflector$1.fromClass(clazz,!0),parameterNames=this.#extractConstructorParameters(model),key=this.#classResolver.resolveKey(clazz);if(void 0===key)throw new ClassNotFound(clazz.name);return{serialized:!0,key:key,name:"class",args:await this.#serializeConstructor(model,parameterNames,object),fields:await this.#serializeFields(model,parameterNames,object)}}#extractConstructorParameters(model){const constructor=model.getFunction("constructor");return(constructor?.parameters??[]).map((parameter=>parameter.name))}async#serializeConstructor(model,includeNames,object){const args={};for(const[index,name]of includeNames.entries()){const value=model.canRead(name)?await this.serializeOther(object[name]):void 0;args[index.toString()]=value}return args}async#serializeFields(model,excludeNames,object){const fields={};for(const property of model.writable){const name=property.name;excludeNames.includes(name)||!1===model.canRead(name)||(fields[name]=await this.serializeOther(object[name]))}return fields}async deserialize(object){const clazz=await this.#getClass(object);if(void 0===clazz)throw new ClassNotFound(object.key);if(clazz instanceof Function==!1)throw new InvalidClass(object.key);const args=await this.#deserializeConstructor(clazz,object.args),instance=reflector$1.createInstance(clazz,args);for(const name in object.fields){const fieldValue=object.fields[name];instance[name]=await this.deserializeOther(fieldValue)}return instance}async#deserializeConstructor(clazz,args){const constructor=reflector$1.fromClass(clazz,!0).getFunction("constructor"),values=(constructor?.parameters??[]).map(((_,index)=>{const key=index.toString(),value=args[key];return this.deserializeOther(value)}));return Promise.all(values)}async#getClass(resolvable){return globalThis[resolvable.key]??this.#classResolver.resolveClass(resolvable.key)}}class InvalidDateString extends Error{constructor(dateString){super(`Invalid date string '${dateString}'`)}}class DateSerializer extends ValueSerializer{canSerialize(value){return value instanceof Date}canDeserialize(value){const date=value;return date instanceof Object&&!0===date.serialized&&"Date"===date.name&&"string"==typeof date.value}async serialize(date){return{serialized:!0,name:"Date",value:date.toISOString()}}async deserialize(object){const date=new Date(object.value);if("Invalid Date"===date.toString())throw new InvalidDateString(object.value);return date}}class ErrorSerializer extends ValueSerializer{canSerialize(value){if(value instanceof Object==!1)return!1;const error=value;return error.constructor===Error||error.constructor===EvalError||error.constructor===RangeError||error.constructor===ReferenceError||error.constructor===SyntaxError||error.constructor===TypeError||error.constructor===URIError||error.constructor===AggregateError}canDeserialize(value){const error=value;return error instanceof Object&&!0===error.serialized&&"Error"===error.name&&error.type in globalThis}async serialize(error){return{serialized:!0,name:"Error",type:error.constructor.name,stack:error.stack,message:error.message,cause:error.cause}}async deserialize(object){const error=new(0,globalThis[object.type])(object.message,{cause:object.cause});return error.stack=object.stack,error}}class MapSerializer extends ValueSerializer{canSerialize(value){return value instanceof Map}canDeserialize(value){const map=value;return map instanceof Object&&!0===map.serialized&&"Map"===map.name&&map.entries instanceof Object&&map.entries.keys instanceof Array&&map.entries.values instanceof Array}async serialize(map){const keys=[],values=[];for(const[key,value]of map)keys.push(await this.serializeOther(key)),values.push(await this.serializeOther(value));return{serialized:!0,name:"Map",entries:{keys:keys,values:values}}}async deserialize(object){const keys=object.entries.keys,values=object.entries.values,result=new Map;for(let index=0;index<keys.length;index++){const key=await this.deserializeOther(keys[index]),value=await this.deserializeOther(values[index]);result.set(key,value)}return result}}class ObjectSerializer extends ValueSerializer{canSerialize(value){return value instanceof Object&&value.constructor===Object}canDeserialize(value){return value instanceof Object&&value.constructor===Object}async serialize(object){const result={};for(const key in object){const value=object[key];result[key]=await this.serializeOther(value)}return result}async deserialize(object){const result={};for(const key in object){const value=object[key];result[key]=await this.deserializeOther(value)}return result}}class PrimitiveSerializer extends ValueSerializer{canSerialize(value){return value instanceof Object==!1}canDeserialize(value){return value instanceof Object==!1}async serialize(primitive){return primitive}async deserialize(primitive){return primitive}}class InvalidRegExp extends Error{constructor(source,flags){super(`Invalid regular expression '${source}' with flags '${flags}'`)}}class RegExpSerializer extends ValueSerializer{canSerialize(value){return value instanceof RegExp}canDeserialize(value){const regExp=value;return regExp instanceof Object&&!0===regExp.serialized&&"RegExp"===regExp.name&&"string"==typeof regExp.source&&"string"==typeof regExp.flags}async serialize(regExp){return{serialized:!0,name:"RegExp",source:regExp.source,flags:regExp.flags}}async deserialize(object){try{return new RegExp(object.source,object.flags)}catch{throw new InvalidRegExp(object.source,object.flags)}}}class SetSerializer extends ValueSerializer{canSerialize(value){return value instanceof Set}canDeserialize(value){const set=value;return set instanceof Object&&!0===set.serialized&&"Set"===set.name&&set.values instanceof Array}async serialize(set){const values=[];for(const value of set.values())values.push(await this.serializeOther(value));return{serialized:!0,name:"Set",values:values}}async deserialize(object){const values=await Promise.all(object.values.map((async value=>this.deserializeOther(value))));return new Set([...values])}}const reflector=new Reflector;class ArrayBufferSerializer extends ValueSerializer{canSerialize(value){return value instanceof Int8Array||value instanceof Uint8Array||value instanceof Uint8ClampedArray||value instanceof Int16Array||value instanceof Uint16Array||value instanceof Int32Array||value instanceof Uint32Array||value instanceof Float32Array||value instanceof Float64Array||value instanceof BigInt64Array||value instanceof BigUint64Array}canDeserialize(value){const array=value;return array instanceof Object&&!0===array.serialized&&"TypedArray"===array.name&&array.type in globalThis&&array.bytes instanceof Array}async serialize(array){const type=array.constructor.name,view=new DataView(array.buffer),bytes=[];for(let index=0;index<view.byteLength;index++)bytes.push(view.getUint8(index));return{serialized:!0,name:"TypedArray",type:type,bytes:bytes}}async deserialize(object){const type=object.type,bytes=object.bytes,buffer=new ArrayBuffer(bytes.length),view=new DataView(buffer);for(let index=0;index<bytes.length;index++)view.setUint8(index,bytes[index]);const clazz=globalThis[type];return reflector.createInstance(clazz,[buffer])}}class InvalidUrlString extends Error{constructor(urlString){super(`Invalid url string '${urlString}'`)}}class UrlSerializer extends ValueSerializer{canSerialize(value){return value instanceof URL}canDeserialize(value){const url=value;return url instanceof Object&&!0===url.serialized&&"Url"===url.name&&"string"==typeof url.value}async serialize(url){return{serialized:!0,name:"Url",value:url.toString()}}async deserialize(object){try{return new URL(object.value)}catch{throw new InvalidUrlString(object.value)}}}class SerializerBuilder{static build(classResolver){const serializer=new Serializer;return serializer.addSerializer(new PrimitiveSerializer),serializer.addSerializer(new ObjectSerializer),void 0!==classResolver&&serializer.addSerializer(new ClassSerializer(classResolver)),serializer.addSerializer(new ErrorSerializer),serializer.addSerializer(new RegExpSerializer),serializer.addSerializer(new BigIntSerializer),serializer.addSerializer(new UrlSerializer),serializer.addSerializer(new DateSerializer),serializer.addSerializer(new SetSerializer),serializer.addSerializer(new MapSerializer),serializer.addSerializer(new ArraySerializer),serializer.addSerializer(new ArrayBufferSerializer),"undefined"!=typeof Buffer&&serializer.addSerializer(new BufferSerializer),serializer}}class ExecutionClassResolver{#executionManager;constructor(executionManager){this.#executionManager=executionManager}resolveKey(clazz){const model=this.#executionManager.getClassByImplementation(clazz);return model?.fqn}resolveClass(key){const model=this.#executionManager.getClass(key);return model?.implementation}}class RequestNotTrusted extends Unauthorized{constructor(){super("Request not trusted")}}class LocalWorker{#id;#url;#trustKey;#gateway;#executionManager;#serializer;constructor(configuration){this.#url=configuration.url,this.#trustKey=configuration.trustKey,this.#gateway=configuration.gateway,this.#executionManager=configuration.executionManager;const classResolver=new ExecutionClassResolver(this.#executionManager);this.#serializer=SerializerBuilder.build(classResolver)}get id(){return this.#id}set id(id){this.#id=id}get url(){return this.#url}get trustKey(){return this.#trustKey}async start(){void 0!==this.#gateway&&(await this.#gateway.start(),this.#id=await this.#gateway.addWorker(this))}async stop(){void 0!==this.#gateway&&void 0!==this.#id&&(await this.#gateway.removeWorker(this),await this.#gateway.stop())}getProcedureNames(){return this.#executionManager.getProcedureNames()}hasProcedure(name){return this.#executionManager.hasProcedure(name)}async isHealthy(){return!0}async getHealth(){return new Map}async run(request){return this.#mustRunLocal(request)?this.#runLocal(request):this.#runRemote(request)}#mustRunLocal(request){return void 0===this.#gateway||this.#executionManager.hasProcedure(request.fqn)}async#runLocal(request){const procedure=this.#executionManager.getProcedure(request.fqn),implementation=procedure?.getImplementation(request.version);if(this.#procedureNotFound(implementation))throw new ProcedureNotFound(request.fqn);if(this.#requestNotTrusted(request,implementation))throw new RequestNotTrusted;const dataEncoding=request.getHeader("X-Jitar-Data-Encoding");"serialized"===dataEncoding&&(request=await this.#deserializeRequest(request)),request.removeHeader("X-Jitar-Data-Encoding");const response=await this.#executionManager.run(request);return"serialized"===dataEncoding?this.#serializeResponse(response):response}#procedureNotFound(implementation){return void 0===implementation||implementation.private}#requestNotTrusted(request,implementation){if(implementation.public)return!1;const trustKey=request.getHeader("X-Jitar-Trust-Key");return this.#trustKey!==trustKey}async#runRemote(request){(request=await this.#serializeRequest(request)).setHeader("X-Jitar-Data-Encoding","serialized"),void 0!==this.#trustKey&&request.setHeader("X-Jitar-Trust-Key",this.#trustKey);const response=await this.#gateway.run(request);return this.#deserializeResponse(response)}async#serializeRequest(request){const serializedArgs=new Map;for(const[key,value]of request.args){const serializedValue=await this.#serializer.serialize(value);serializedArgs.set(key,serializedValue)}return new Request(request.fqn,request.version,serializedArgs,request.headers,request.mode)}async#deserializeRequest(request){const deserializedArgs=new Map;for(const[key,value]of request.args){const deserializedValue=await this.#serializer.deserialize(value);deserializedArgs.set(key,deserializedValue)}return new Request(request.fqn,request.version,deserializedArgs,request.headers,request.mode)}async#serializeResponse(response){const serializedResult=await this.#serializer.serialize(response.result);return new Response(response.status,serializedResult,response.headers)}async#deserializeResponse(response){const deserializedResult=await this.#serializer.deserialize(response.result);return new Response(response.status,deserializedResult,response.headers)}}class RemoteWorker{#id;#url;#trustKey;#procedureNames;#remote;constructor(configuration){this.#url=configuration.url,this.#trustKey=configuration.trustKey,this.#procedureNames=configuration.procedureNames,this.#remote=configuration.remote}get id(){return this.#id}set id(id){this.#id=id}get url(){return this.#url}get trustKey(){return this.#trustKey}start(){return this.#remote.connect()}stop(){return this.#remote.disconnect()}getProcedureNames(){return[...this.#procedureNames.values()]}hasProcedure(name){return this.#procedureNames.has(name)}isHealthy(){return this.#remote.isHealthy()}getHealth(){return this.#remote.getHealth()}run(request){return this.#remote.run(request)}}class ProcedureRunner{#runner;constructor(runner){this.#runner=runner}async handle(request,next){return this.#runner.run(request)}}class Runtime{#versionParser=new VersionParser;constructor(){this.#initGlobals()}#initGlobals(){const globals=globalThis;globals.__run=this.#run.bind(this),globals.ProcedureNotAccessible=ProcedureNotAccessible}async#run(fqn,versionNumber,args,sourceRequest){const version=this.#versionParser.parse(versionNumber),argsMap=new Map(Object.entries(args)),headersMap=sourceRequest instanceof Request?sourceRequest.headers:new Map,targetRequest=new Request(fqn,version,argsMap,headersMap,RunModes_NORMAL),trustKey=this.getTrustKey();void 0!==trustKey&&targetRequest.setHeader("X-Jitar-Trust-Key",trustKey);const targetResponse=await this.runInternal(targetRequest);if(targetResponse.status!==StatusCodes$1_OK)throw targetResponse.result;return targetResponse.result}}class InvalidMiddleware extends ServerError{constructor(){super("Invalid middleware")}}class MiddlewareManager{#middlewares=[];addMiddleware(middleware){if(void 0===middleware?.handle)throw new InvalidMiddleware;this.#middlewares.push(middleware)}getMiddleware(type){return this.#middlewares.find((middleware=>middleware instanceof type))}clearMiddlewares(){this.#middlewares=[]}handle(request){return this.#getNextHandler(request,0)()}#getNextHandler(request,index){const next=this.#middlewares[index];if(void 0===next)return async()=>new Response(StatusCodes$1_OK);const nextHandler=this.#getNextHandler(request,index+1);return async()=>next.handle(request,nextHandler)}}const ContentTypes_NULL="application/null",ContentTypes_UNDEFINED="application/undefined",ContentTypes_BOOLEAN="application/boolean",ContentTypes_NUMBER="application/number",ContentTypes_JSON="application/json",ContentTypes_TEXT="text/plain",StatusCodes_OK=200,StatusCodes_BAD_REQUEST=400,StatusCodes_UNAUTHORIZED=401,StatusCodes_PAYMENT_REQUIRED=402,StatusCodes_FORBIDDEN=403,StatusCodes_NOT_FOUND=404,StatusCodes_TEAPOT=418,StatusCodes_SERVER_ERROR=500,StatusCodes_NOT_IMPLEMENTED=501;class Server extends Runtime{#proxy;#sourcingManager;#remoteBuilder;#middlewareManager;#healthManager;#setUpScripts;#tearDownScripts;#logger;#versionParser=new VersionParser;constructor(configuration){super(),this.#proxy=configuration.proxy,this.#sourcingManager=configuration.sourcingManager,this.#remoteBuilder=configuration.remoteBuilder,this.#middlewareManager=configuration.middlewareManager,this.#healthManager=configuration.healthManager,this.#setUpScripts=configuration.setUpScripts??[],this.#tearDownScripts=configuration.tearDownScripts??[],this.#logger=configuration.logger;const procedureRunner=new ProcedureRunner(this.#proxy);this.#middlewareManager.addMiddleware(procedureRunner)}get proxy(){return this.#proxy}getTrustKey(){return this.#proxy.trustKey}async start(){await this.#setUp(),await this.#proxy.start(),this.#logger.info(`Server started at ${this.#proxy.url}`),this.#proxy.runner instanceof LocalWorker&&this.#logger.info("RPC procedures:",this.#proxy.runner.getProcedureNames())}async stop(){await this.#proxy.stop(),await this.#tearDown(),this.#logger.info("Server stopped")}async getHealth(){try{const internalHealth=await this.#proxy.getHealth(),externalHealth=await this.#healthManager.getHealth(),health=new Map([...internalHealth,...externalHealth]);return this.#logger.debug("Got health"),this.#respondHealth(health)}catch(error){const message=error instanceof Error?error.message:String(error);return this.#logger.error("Failed to get health:",message),this.#respondError(error)}}async isHealthy(){try{const internalsHealthy=await this.#proxy.isHealthy(),externalsHealthy=await this.#healthManager.isHealthy(),healthy=internalsHealthy&&externalsHealthy;return this.#logger.debug("Got health status"),this.#respondHealthy(healthy)}catch(error){const message=error instanceof Error?error.message:String(error);return this.#logger.error("Failed to get health status:",message),this.#respondError(error)}}async provide(provideRequest){try{const file=await this.#proxy.provide(provideRequest.filename);return this.#logger.info("Provided file:",provideRequest.filename),this.#respondFile(file)}catch(error){const message=error instanceof Error?error.message:String(error);return this.#logger.warn("Failed to provide file:",message),this.#respondError(error)}}async run(runRequest){try{const request=this.#transformRunRequest(runRequest),response=await this.#middlewareManager.handle(request);return this.#logger.info("Ran request:",request.fqn),this.#respondResponse(response)}catch(error){const message=error instanceof Error?error.message:String(error);return this.#logger.error("Failed run request:",message),this.#respondError(error)}}async runInternal(request){return this.#proxy.run(request)}async addWorker(addRequest){try{const runner=this.#proxy.runner;if(runner instanceof LocalGateway==!1)throw new BadRequest("Cannot add worker to remote gateway");const worker=this.#buildRemoteWorker(addRequest.url,addRequest.procedureNames,addRequest.trustKey),id=await runner.addWorker(worker);return this.#logger.info("Added worker:",worker.url),this.#respondSuccess({id:id})}catch(error){const message=error instanceof Error?error.message:String(error);return this.#logger.error("Failed to add worker:",message),this.#respondError(error)}}async removeWorker(removeRequest){try{const runner=this.#proxy.runner;if(runner instanceof LocalGateway==!1)throw new BadRequest("Cannot remove worker from remote gateway");const worker=runner.getWorker(removeRequest.id);return await runner.removeWorker(worker),this.#logger.info("Removed worker:",worker.url),this.#respondSuccess()}catch(error){const message=error instanceof Error?error.message:String(error);return this.#logger.error("Failed to remove worker:",message),this.#respondError(error)}}#setUp(){return this.#runScripts(this.#setUpScripts)}#tearDown(){return this.#runScripts(this.#tearDownScripts)}async#runScripts(scripts){await Promise.all(scripts.map((script=>this.#sourcingManager.import(script))))}#transformRunRequest(request){const fqn=this.#processFqn(request.fqn),version=this.#parseVersion(request.version),args=this.#mapArguments(request.args),headers=this.#mapHeaders(request.headers);return new Request(fqn,version,args,headers,request.mode)}#processFqn(fqn){if(0===fqn.length)throw new BadRequest("Missing procedure name");if(fqn.includes(".."))throw new BadRequest("Invalid procedure name");return fqn}#parseVersion(version){return"string"!=typeof version?Version.DEFAULT:this.#versionParser.parse(version)}#mapArguments(args){return new Map(Object.entries(args))}#mapHeaders(headers){const map=new Map;for(const[key,value]of Object.entries(headers)){if(void 0===value)continue;const lowerKey=key.toLowerCase(),stringValue=value.toString();map.set(lowerKey,stringValue)}return map}#respondHealth(health){return{result:Object.fromEntries(health),contentType:ContentTypes_JSON,headers:{},status:StatusCodes_OK}}#respondHealthy(healthy){return{result:healthy,contentType:ContentTypes_BOOLEAN,headers:{},status:StatusCodes_OK}}#respondFile(file){return{result:file.content,contentType:file.type,headers:{},status:StatusCodes_OK}}#respondResponse(response){const result=response.result instanceof Error?response.result.message:response.result;return{result:result,contentType:this.#determineContentType(result),headers:this.#unmapHeaders(response.headers),status:response.status}}#respondError(error){const result=error instanceof Error?error.message:String(error);return{result:result,contentType:this.#determineContentType(result),headers:{},status:this.#determineStatusCode(error)}}#respondSuccess(result){return{result:result,contentType:this.#determineContentType(result),headers:{},status:StatusCodes_OK}}#determineContentType(content){if(void 0===content)return ContentTypes_UNDEFINED;if(null===content)return ContentTypes_NULL;switch(typeof content){case"boolean":return ContentTypes_BOOLEAN;case"number":return ContentTypes_NUMBER;case"object":return ContentTypes_JSON;default:return ContentTypes_TEXT}}#unmapHeaders(headers){return Object.fromEntries(headers)}#determineStatusCode(error){return error instanceof BadRequest?StatusCodes_BAD_REQUEST:error instanceof Forbidden?StatusCodes_FORBIDDEN:error instanceof NotFound?StatusCodes_NOT_FOUND:error instanceof NotImplemented?StatusCodes_NOT_IMPLEMENTED:error instanceof PaymentRequired?StatusCodes_PAYMENT_REQUIRED:error instanceof Teapot?StatusCodes_TEAPOT:error instanceof Unauthorized?StatusCodes_UNAUTHORIZED:StatusCodes_SERVER_ERROR}#buildRemoteWorker(url,procedures,trustKey){const remote=this.#remoteBuilder.build(url),procedureNames=new Set(procedures);return new RemoteWorker({url:url,trustKey:trustKey,remote:remote,procedureNames:procedureNames})}}class InvalidHealthCheck extends ServerError{constructor(){super("Invalid health check")}}class HealthManager{#healthChecks=new Map;addHealthCheck(healthCheck){if(void 0===healthCheck.isHealthy)throw new InvalidHealthCheck;this.#healthChecks.set(healthCheck.name,healthCheck)}clearHealthChecks(){this.#healthChecks.clear()}async isHealthy(){const promises=[];for(const healthCheck of this.#healthChecks.values()){const promise=this.#executeHealthCheck(healthCheck);promises.push(promise)}return Promise.all(promises).then((results=>results.every((result=>result)))).catch((()=>!1))}async getHealth(){const promises=[];for(const[name,healthCheck]of this.#healthChecks){const promise=this.#executeHealthCheck(healthCheck).then((result=>({name:name,isHealthy:result}))).catch((()=>({name:name,isHealthy:!1})));promises.push(promise)}const healthChecks=new Map;return Promise.allSettled(promises).then((results=>results.forEach((result=>this.#handleHealthCheckResult(result,healthChecks))))).then((()=>healthChecks))}#handleHealthCheckResult(result,healthChecks){"fulfilled"===result.status?healthChecks.set(result.value.name,result.value.isHealthy):healthChecks.set(result.reason.name,!1)}async#executeHealthCheck(healthCheck){const health=healthCheck.isHealthy(),milliseconds=healthCheck.timeout;if(void 0===milliseconds)return health;const timeout=new Promise((resolve=>{setTimeout(resolve,milliseconds)})).then((()=>!1));return Promise.race([timeout,health])}}class UnknownServiceConfigured extends Error{constructor(){super("Unknown service configured")}}class RuntimeBuilder{#sourcingManager;#remoteBuilder;constructor(sourcingManager,remoteBuilder){this.#sourcingManager=sourcingManager,this.#remoteBuilder=remoteBuilder}async build(configuration,logLevel){const setUp=configuration.setUp??[],tearDown=configuration.tearDown??[],middleware=configuration.middleware,healthChecks=configuration.healthChecks,proxy=await this.#buildService(configuration),sourcingManager=this.#sourcingManager,remoteBuilder=this.#remoteBuilder,middlewareManager=await this.#buildMiddlewareManager(middleware),healthManager=await this.#buildHealthManager(healthChecks),setUpScripts=setUp.map((filename=>this.#assureExtension(filename))),tearDownScripts=tearDown.map((filename=>this.#assureExtension(filename))),logger=new Logger(logLevel);return new Server({proxy:proxy,sourcingManager:sourcingManager,remoteBuilder:remoteBuilder,middlewareManager:middlewareManager,healthManager:healthManager,setUpScripts:setUpScripts,tearDownScripts:tearDownScripts,logger:logger})}#buildService(configuration){if(void 0!==configuration.gateway)return this.#buildGatewayProxy(configuration.url,configuration.gateway);if(void 0!==configuration.worker)return this.#buildWorkerProxy(configuration.url,configuration.worker);if(void 0!==configuration.repository)return this.#buildRepositoryProxy(configuration.url,configuration.repository);if(void 0!==configuration.proxy)return this.#buildProxy(configuration.url,configuration.proxy);if(void 0!==configuration.standalone)return this.#buildStandalone(configuration.url,configuration.standalone);throw new UnknownServiceConfigured}async#buildGatewayProxy(url,configuration){const provider=new DummyProvider,runner=await this.#buildLocalGateway(url,configuration);return new Proxy({url:url,provider:provider,runner:runner})}async#buildWorkerProxy(url,configuration){const provider=new DummyProvider,runner=await this.#buildLocalWorker(url,configuration);return new Proxy({url:url,provider:provider,runner:runner})}async#buildRepositoryProxy(url,configuration){const provider=await this.#buildLocalRepository(url,configuration),runner=new DummyRunner;return new Proxy({url:url,provider:provider,runner:runner})}async#buildLocalGateway(url,configuration){const trustKey=configuration.trustKey,monitorInterval=configuration.monitor;return new LocalGateway({url:url,trustKey:trustKey,monitorInterval:monitorInterval})}#buildRemoteGateway(url){const remote=this.#remoteBuilder.build(url);return new RemoteGateway({url:url,remote:remote})}async#buildLocalWorker(url,configuration){const trustKey=configuration.trustKey,gateway=configuration.gateway?this.#buildRemoteGateway(configuration.gateway):void 0,executionManager=await this.#buildExecutionManager(configuration.segments);return new LocalWorker({url:url,trustKey:trustKey,gateway:gateway,executionManager:executionManager})}async#buildLocalRepository(url,configuration){const sourcingManager=this.#sourcingManager,assets=await this.#buildAssetSet(configuration.assets),indexFilename=configuration.indexFilename,serveIndexOnNotFound=configuration.serveIndexOnNotFound;return new LocalRepository({url:url,sourcingManager:sourcingManager,assets:assets,indexFilename:indexFilename,serveIndexOnNotFound:serveIndexOnNotFound})}#buildRemoteRepository(url){const remote=this.#remoteBuilder.build(url);return new RemoteRepository({url:url,remote:remote})}async#buildProxy(url,configuration){const provider=this.#buildRemoteRepository(configuration.repository),runner=this.#buildRemoteGateway(configuration.gateway);return new Proxy({url:url,provider:provider,runner:runner})}async#buildStandalone(url,configuration){const provider=await this.#buildLocalRepository(url,configuration),runner=await this.#buildLocalWorker(url,configuration);return new Proxy({url:url,provider:provider,runner:runner})}async#buildHealthManager(filenames){const manager=new HealthManager;if(void 0!==filenames){const translatedFilenames=filenames.map((filename=>this.#assureExtension(filename)));(await Promise.all(translatedFilenames.map((filename=>this.#sourcingManager.import(filename))))).forEach((module=>manager.addHealthCheck(module.default)))}return manager}async#buildMiddlewareManager(filenames){const manager=new MiddlewareManager;if(void 0!==filenames){const translatedFilenames=filenames.map((filename=>this.#assureExtension(filename)));(await Promise.all(translatedFilenames.map((filename=>this.#sourcingManager.import(filename))))).forEach((module=>manager.addMiddleware(module.default)))}return manager}async#buildExecutionManager(segmentNames){const manager=new ExecutionManager,filenames=segmentNames.map((name=>`./${name}.segment.js`));return(await Promise.all(filenames.map((filename=>this.#sourcingManager.import(filename))))).forEach((module=>manager.addSegment(module.default))),manager}async#buildAssetSet(patterns){if(void 0===patterns)return new Set;const filenames=await this.#sourcingManager.filter(...patterns);return new Set(filenames)}#assureExtension(filename){return filename.endsWith(".js")?filename:filename+".js"}}const Defaults_PORT_NUMBER="3000",Defaults_BODY_LIMIT=204800,IgnoredHeaderKeys=["host","connection","content-length","accept-encoding","user-agent","keep-alive"];class HttpServer{#server;#port;#app;#http;#validator=new Validator;constructor(server,port=Defaults_PORT_NUMBER,bodyLimit=Defaults_BODY_LIMIT){this.#server=server,this.#port=port,this.#app=express(),this.#setupExpress(bodyLimit),this.#setupRoutes()}async start(){return await this.#server.start(),this.#startHttp()}async stop(){return await this.#stopHttp(),this.#server.stop()}#setupExpress(bodyLimit){this.#app.use(express.json({limit:bodyLimit})),this.#app.use(express.urlencoded({extended:!0})),this.#app.use(this.#addDefaultHeaders.bind(this)),this.#app.disable(HeaderKeys_POWERED_BY)}#setupRoutes(){this.#app.get("/health",((request,response)=>{this.#getHealth(request,response)})),this.#app.get("/health/status",((request,response)=>{this.#isHealthy(request,response)})),this.#app.get("/rpc/*procedure",((request,response)=>{this.#runGet(request,response)})),this.#app.post("/rpc/*procedure",((request,response)=>{this.#runPost(request,response)})),this.#app.options("/rpc/*procedure",((request,response)=>{this.#runOptions(request,response)})),this.#app.post("/workers",((request,response)=>{this.#addWorker(request,response)})),this.#app.delete("/workers/:id",((request,response)=>{this.#removeWorker(request,response)})),this.#app.use(((request,response)=>{this.#provide(request,response)}))}#startHttp(){return void 0!==this.#http?Promise.resolve():new Promise(((resolve,reject)=>{this.#http=this.#app.listen(this.#port,reject),resolve()}))}#stopHttp(){return void 0===this.#http?Promise.resolve():new Promise((resolve=>{this.#http.close((()=>resolve()))}))}#addDefaultHeaders(request,response,next){response.setHeader(HeaderKeys_CONTENT_TYPE_OPTIONS,HeaderValues_NO_SNIFF),next()}async#getHealth(request,response){const serverResponse=await this.#server.getHealth();return this.#transformResponse(response,serverResponse)}async#isHealthy(request,response){const serverResponse=await this.#server.isHealthy();return this.#transformResponse(response,serverResponse)}async#runGet(request,response){const fqn=this.#extractFqn(request),version=this.#extractVersion(request),args=this.#extractQueryArguments(request),headers=this.#extractHeaders(request),mode=RunModes_NORMAL,serverResponse=await this.#server.run({fqn:fqn,version:version,args:args,headers:headers,mode:mode});return this.#transformResponse(response,serverResponse)}async#runPost(request,response){const fqn=this.#extractFqn(request),version=this.#extractVersion(request),args=this.#extractBodyArguments(request),headers=this.#extractHeaders(request),mode=RunModes_NORMAL,serverResponse=await this.#server.run({fqn:fqn,version:version,args:args,headers:headers,mode:mode});return this.#transformResponse(response,serverResponse)}async#runOptions(request,response){const fqn=this.#extractFqn(request),version=this.#extractVersion(request),args=this.#extractBodyArguments(request),headers=this.#extractHeaders(request),mode=RunModes_DRY,serverResponse=await this.#server.run({fqn:fqn,version:version,args:args,headers:headers,mode:mode});return this.#transformResponse(response,serverResponse)}async#addWorker(request,response){const args=this.#extractBodyArguments(request),validation=this.#validator.validate(args,{url:{type:"url",required:!0},procedureNames:{type:"list",required:!0,items:{type:"string"}},trustKey:{type:"string",required:!1}});if(!1===validation.valid)return response.status(400).send(validation.errors.join("\n"));const url=args.url,procedureNames=args.procedureNames,trustKey=args.trustKey;try{const serverResponse=await this.#server.addWorker({url:url,procedureNames:procedureNames,trustKey:trustKey});return this.#transformResponse(response,serverResponse)}catch(error){const message=error instanceof Error?error.message:"Server error";return response.status(500).send(message)}}async#removeWorker(request,response){const args={id:request.params.id},validation=this.#validator.validate(args,{id:{type:"string",required:!0}});if(!1===validation.valid)return response.status(400).send(validation.errors.join("\n"));const id=args.id;try{const serverResponse=await this.#server.removeWorker({id:id});return this.#transformResponse(response,serverResponse)}catch(error){const message=error instanceof Error?error.message:"Server error";return response.status(500).send(message)}}async#provide(request,response){const path=request.path.substring(1).trim(),filename=decodeURIComponent(path),serverResponse=await this.#server.provide({filename:filename});return this.#transformResponse(response,serverResponse)}#extractFqn(request){return decodeURIComponent(request.path.trim()).substring(5).trim()}#extractVersion(request){const versionString=request.headers[HeaderKeys_JITAR_PROCEDURE_VERSION];return Array.isArray(versionString)?versionString[0]:versionString}#extractQueryArguments(request){const args={};for(const[key,value]of Object.entries(request.query))args[key]=value;return args}#extractBodyArguments(request){return request.body}#extractHeaders(request){const headers={};for(const[key,value]of Object.entries(request.headers)){if(void 0===value)continue;const lowerKey=key.toLowerCase(),stringValue=value.toString();IgnoredHeaderKeys.includes(lowerKey)||(headers[lowerKey]=stringValue)}return headers}#transformResponse(response,serverResponse){const status=this.#transformStatus(serverResponse),contentType=this.#transformContentType(serverResponse);response.status(status),response.setHeader(HeaderKeys_CONTENT_TYPE,contentType),response.setHeader(HeaderKeys_JITAR_CONTENT_TYPE,serverResponse.contentType);for(const[name,value]of Object.entries(serverResponse.headers))response.setHeader(name,value);const result=this.#transformResult(serverResponse);return response.send(result)}#transformStatus(serverResponse){return void 0!==serverResponse.headers.location?302:serverResponse.status}#transformContentType(serverResponse){const contentType=serverResponse.contentType.toLowerCase();switch(contentType){case ContentTypes_BOOLEAN:case ContentTypes_NUMBER:case ContentTypes_UNDEFINED:case ContentTypes_NULL:return ContentTypes_TEXT}return contentType}#transformResult(serverResponse){const result=serverResponse.result;return"number"==typeof result||"boolean"==typeof result?String(result):result}}class StartServer{async execute(args){const environmentFile=args.getOptionalArgument("--env-file",void 0),runtimeConfigFile=args.getOptionalArgument("--config",void 0),serviceConfigFile=args.getRequiredArgument("--service"),logLevelString=args.getOptionalArgument("--log-level",void 0),logLevel=this.#parseLogLevel(logLevelString),bodyLimitString=args.getOptionalArgument("--http-body-limit",void 0),bodyLimit=this.#parseBodyLimit(bodyLimitString),configurationManager=new ConfigurationManager;await configurationManager.configureEnvironment(environmentFile);const runtimeConfiguration=await configurationManager.getRuntimeConfiguration(runtimeConfigFile),serverConfiguration=await configurationManager.getServerConfiguration(serviceConfigFile),httpServer=await this.#buildServer(runtimeConfiguration,serverConfiguration,bodyLimit,logLevel);return this.#runServer(httpServer)}async#buildServer(runtimeConfiguration,serverConfiguration,bodyLimit,logLevel){const[,,port]=serverConfiguration.url.split(":"),fileManager=new FileManager(runtimeConfiguration.target),sourcingManager=new SourcingManager(fileManager),remoteBuilder=new HttpRemoteBuilder,serverBuilder=new RuntimeBuilder(sourcingManager,remoteBuilder),server=await serverBuilder.build(serverConfiguration,logLevel);return new HttpServer(server,port,bodyLimit)}#runServer(httpServer){let isShuttingDown=!1;return process.on("SIGINT",(async()=>{isShuttingDown||(isShuttingDown=!0,httpServer.stop())})),console.log("\n ██╗██╗████████╗ █████╗ ██████╗ \n ██║██║╚══██╔══╝██╔══██╗██╔══██╗\n ██║██║ ██║ ███████║██████╔╝\n██ ██║██║ ██║ ██╔══██║██╔══██╗\n╚█████╔╝██║ ██║ ██║ ██║██║ ██║\n ╚════╝ ╚═╝ ╚═╝ ╚═╝ ╚═╝╚═╝ ╚═╝\n ~ Distributed JavaScript Runtime ~\n____________________________________\n"),httpServer.start()}#parseLogLevel(logLevel){if(void 0===logLevel)return;return(new LogLevelParser).parse(logLevel)}#parseBodyLimit(bodyLimitString){const bodyLimit=Number.parseInt(bodyLimitString);return Number.isNaN(bodyLimit)?void 0:bodyLimit}}class CommandRunner{#commands=new Map;constructor(){this.#commands.set("help",new ShowHelp),this.#commands.set("about",new ShowAbout),this.#commands.set("version",new ShowVersion),this.#commands.set("build",new BuildApp),this.#commands.set("start",new StartServer)}run(name,args){const command=this.#commands.get(name);if(void 0===command)throw new Error(`Command ${name} not found`);return command.execute(args)}}class Cli{#argumentProcessor;#commandRunner;constructor(){this.#argumentProcessor=new ArgumentProcessor(process.argv),this.#commandRunner=new CommandRunner}start(){const commandName=this.#argumentProcessor.getCommand()??"help";return this.#commandRunner.run(commandName,this.#argumentProcessor)}}try{const cli=new Cli;await cli.start()}catch(error){const logger=new Logger,message=error instanceof Error?error.message:String(error);logger.fatal(message)}
package/dist/client.js CHANGED
@@ -1 +1 @@
1
- class BadRequest extends Error{constructor(message="Invalid request"){super(message)}}class Forbidden extends Error{constructor(message="Forbidden"){super(message)}}class NotFound extends Error{constructor(message="Not found"){super(message)}}class NotImplemented extends Error{constructor(message="Not implemented"){super(message)}}class PaymentRequired extends Error{constructor(message="Payment required"){super(message)}}class ServerError extends Error{constructor(message="Server error"){super(message)}}class Teapot extends Error{constructor(message="I'm a teapot"){super(message)}}class Unauthorized extends Error{constructor(message="Unauthorized"){super(message)}}const AccessLevels_PRIVATE="private",AccessLevels_PROTECTED="protected",AccessLevels_PUBLIC="public",RunModes_NORMAL="normal",RunModes_DRY="dry",StatusCodes_OK=200,StatusCodes_BAD_REQUEST=400,StatusCodes_UNAUTHORIZED=401,StatusCodes_PAYMENT_REQUIRED=402,StatusCodes_FORBIDDEN=403,StatusCodes_NOT_FOUND=404,StatusCodes_TEAPOT=418,StatusCodes_SERVER_ERROR=500,StatusCodes_NOT_IMPLEMENTED=501;class InvalidVersionNumber extends BadRequest{#number;constructor(number){super(`Invalid version number '${number}'`),this.#number=number}get number(){return this.#number}}class ProcedureNotFound extends NotFound{#fqn;constructor(fqn){super(`Procedure '${fqn}' not found`),this.#fqn=fqn}get fqn(){return this.#fqn}}class ProcedureNotAccessible extends Forbidden{constructor(fqn,versionNumber){super(`Procedure '${fqn}' (v${versionNumber}) is not accessible`)}}class Segment{#id;#classes=new Map;#procedures=new Map;constructor(id){this.#id=id}get id(){return this.#id}addClass(clazz){return this.#classes.set(clazz.fqn,clazz),this}hasClass(fqn){return void 0!==this.getClass(fqn)}getClass(fqn){return this.#classes.get(fqn)}getClassByImplementation(implementation){return this.getClasses().find((clazz=>clazz.implementation===implementation))}getClasses(){return[...this.#classes.values()]}addProcedure(procedure){return this.#procedures.set(procedure.fqn,procedure),this}hasProcedure(fqn){return this.#procedures.has(fqn)}getProcedure(fqn){return this.#procedures.get(fqn)}getExposedProcedures(){return[...this.#procedures.values()].filter((procedure=>procedure.public||procedure.protected))}}class Class{#fqn;#implementation;constructor(fqn,implementation){this.#fqn=fqn,this.#implementation=implementation}get fqn(){return this.#fqn}get implementation(){return this.#implementation}}class Version{static get DEFAULT(){return new Version(0,0,0)}#major;#minor;#patch;constructor(major=0,minor=0,patch=0){this.#major=major,this.#minor=minor,this.#patch=patch}get major(){return this.#major}get minor(){return this.#minor}get patch(){return this.#patch}equals(version){return this.#major===version.major&&this.#minor===version.minor&&this.#patch===version.patch}greater(version){return this.#major!==version.major?this.#major>version.major:this.#minor!==version.minor?this.#minor>version.minor:this.#patch!==version.patch&&this.#patch>version.patch}less(version){return this.#major!==version.major?this.#major<version.major:this.#minor!==version.minor?this.#minor<version.minor:this.#patch!==version.patch&&this.#patch<version.patch}toString(){return`${this.#major}.${this.#minor}.${this.#patch}`}}class Procedure{#fqn;#implementations=new Map;#latestImplementation;constructor(fqn){this.#fqn=fqn}get fqn(){return this.#fqn}get public(){return[...this.#implementations.values()].some((implementation=>implementation.public))}get protected(){return[...this.#implementations.values()].some((implementation=>implementation.protected))}addImplementation(implementation){return this.#implementations.set(implementation.version,implementation),this.#isNewLatestImplementation(implementation)&&(this.#latestImplementation=implementation),this}#isNewLatestImplementation(implementation){return void 0===this.#latestImplementation||implementation.version.greater(this.#latestImplementation.version)}getImplementation(version){const selectedVersion=this.#selectAvailableVersion(version);return this.#implementations.get(selectedVersion)}#selectAvailableVersion(version){let selectedVersion=Version.DEFAULT;for(const implementationVersion of this.#implementations.keys()){if(implementationVersion.equals(version))return implementationVersion;implementationVersion.greater(version)||selectedVersion.less(implementationVersion)&&(selectedVersion=implementationVersion)}return selectedVersion}}class Implementation{#version;#access;#parameters;#executable;constructor(version,access,parameters,executable){this.#version=version,this.#access=access,this.#parameters=parameters,this.#executable=executable}get version(){return this.#version}get public(){return this.#access===AccessLevels_PUBLIC}get protected(){return this.#access===AccessLevels_PROTECTED}get private(){return this.#access===AccessLevels_PRIVATE}get parameters(){return this.#parameters}get executable(){return this.#executable}}class Parameter{#name;#isOptional;constructor(name,isOptional=!1){this.#name=name,this.#isOptional=isOptional}get name(){return this.#name}get isOptional(){return this.#isOptional}}class NamedParameter extends Parameter{}class DestructuredParameter extends Parameter{#variables;constructor(variables,name,isOptional){super(name??"(anonymous)",isOptional),this.#variables=variables}get variables(){return this.#variables}}class ArrayParameter extends DestructuredParameter{}class ObjectParameter extends DestructuredParameter{}class Request{#fqn;#version;#args;#headers=new Map;#mode;constructor(fqn,version,args,headers,mode){this.#fqn=fqn,this.#version=version,this.#args=args,this.#headers=headers,this.#mode=mode}get fqn(){return this.#fqn}get version(){return this.#version}get args(){return this.#args}get headers(){return this.#headers}get mode(){return this.#mode}clearArguments(){this.#args.clear()}setArgument(name,value){this.#args.set(name,value)}getArgument(name){return this.#args.get(name)}hasArgument(name){return this.#args.has(name)}removeArgument(name){this.#args.delete(name)}clearHeaders(){this.#headers.clear()}setHeader(name,value){this.#headers.set(name.toLowerCase(),value)}getHeader(name){return this.#headers.get(name.toLowerCase())}hasHeader(name){return this.#headers.has(name.toLowerCase())}removeHeader(name){this.#headers.delete(name.toLowerCase())}}class Response{#status;#result;#headers;constructor(status,result=void 0,headers=new Map){this.#status=status,this.#result=result,this.#headers=headers}get status(){return this.#status}get result(){return this.#result}set result(value){this.#result=value}get headers(){return this.#headers}clearHeaders(){this.#headers.clear()}setHeader(name,value){this.#headers.set(name.toLowerCase(),value)}getHeader(name){return this.#headers.get(name.toLowerCase())}hasHeader(name){return this.#headers.has(name.toLowerCase())}removeHeader(name){this.#headers.delete(name.toLowerCase())}}class UnknownParameter extends BadRequest{#parameterName;constructor(parameterName){super(`Unknown parameter ${parameterName}`),this.#parameterName=parameterName}get parameterName(){return this.#parameterName}}class MissingParameterValue extends BadRequest{#parameterName;constructor(parameterName){super(`Missing value for parameter '${parameterName}'`),this.#parameterName=parameterName}get parameterName(){return this.#parameterName}}class InvalidParameterValue extends BadRequest{#parameterName;constructor(parameterName){super(`Invalid value for parameter '${parameterName}'`),this.#parameterName=parameterName}get parameterName(){return this.#parameterName}}class ArgumentExtractor{extract(parameters,args){const argsCopy=this.#copyArguments(parameters,args),values=[];for(const parameter of parameters){const value=this.#extractArgumentValue(parameter,argsCopy);values.push(value)}if(argsCopy.size>0){const name=argsCopy.keys().next().value;throw new UnknownParameter(name)}return values}#copyArguments(parameters,args){const copy=new Map;for(const[key,value]of args)if(this.#isOptionalArgument(key)){const name=this.#getParameterName(key);!0===this.#containsParameter(parameters,name)&&copy.set(name,value)}else copy.set(key,value);return copy}#isOptionalArgument(argument){return argument.startsWith("*")}#getParameterName(argument){return argument.substring(1)}#containsParameter(parameters,name){return void 0!==parameters.find((parameter=>parameter.name===name))}#extractArgumentValue(parameter,args,parent){return parameter instanceof NamedParameter?this.#extractNamedArgumentValue(parameter,args,parent):this.#extractDestructedArgumentValue(parameter,args)}#extractNamedArgumentValue(parameter,args,parent){const value=args.get(parameter.name);if(this.#isMissingParameterValue(parameter,value,parent))throw new MissingParameterValue(parameter.name);if(this.#isInvalidRestParameter(parameter,value,parent))throw new InvalidParameterValue(parameter.name);return args.delete(parameter.name),value}#extractDestructedArgumentValue(parameter,args){return parameter instanceof ArrayParameter?this.#extractArrayArgumentValue(parameter,args):this.#extractObjectArgumentValue(parameter,args)}#extractArrayArgumentValue(parameter,args){const values=this.#extractVariableValues(parameter,args);return void 0!==values?Object.values(values):void 0}#extractObjectArgumentValue(parameter,args){return this.#extractVariableValues(parameter,args)}#extractVariableValues(parameter,args){const useIndex=parameter instanceof ArrayParameter,values={},missingValues=[];let containsValues=!1,index=0;for(const variable of parameter.variables){const key=useIndex?index++:variable.name,value=this.#extractArgumentValue(variable,args,parameter);void 0!==value?containsValues=!0:!1===variable.isOptional&&missingValues.push(variable.name),values[key]=value}if(!0===containsValues&&missingValues.length>0)throw new MissingParameterValue(missingValues[0]);return containsValues?values:void 0}#isMissingParameterValue(parameter,value,parent){return void 0===value&&(!0!==parameter.isOptional&&!0!==parent?.isOptional)}#isInvalidRestParameter(parameter,value,parent){return!1!==parameter.name.startsWith("...")&&(void 0===parent&&value instanceof Array==!1||parent instanceof ArrayParameter&&value instanceof Array==!1||parent instanceof ObjectParameter&&value instanceof Object==!1)}}class ErrorConverter{toStatus(error){return error instanceof BadRequest?StatusCodes_BAD_REQUEST:error instanceof Forbidden?StatusCodes_FORBIDDEN:error instanceof NotFound?StatusCodes_NOT_FOUND:error instanceof NotImplemented?StatusCodes_NOT_IMPLEMENTED:error instanceof PaymentRequired?StatusCodes_PAYMENT_REQUIRED:error instanceof Teapot?StatusCodes_TEAPOT:error instanceof Unauthorized?StatusCodes_UNAUTHORIZED:StatusCodes_SERVER_ERROR}fromStatus(status,message){switch(status){case StatusCodes_BAD_REQUEST:return new BadRequest(message);case StatusCodes_FORBIDDEN:return new Forbidden(message);case StatusCodes_NOT_FOUND:return new NotFound(message);case StatusCodes_NOT_IMPLEMENTED:return new NotImplemented(message);case StatusCodes_PAYMENT_REQUIRED:return new PaymentRequired(message);case StatusCodes_TEAPOT:return new Teapot(message);case StatusCodes_UNAUTHORIZED:return new Unauthorized(message);default:return new ServerError(message)}}}const VERSION_EXPRESSION=/^\d+(?:\.\d+){0,2}$/;class VersionParser{parse(number){if(0===number.trim().length)return Version.DEFAULT;if(!1===VERSION_EXPRESSION.test(number))throw new InvalidVersionNumber(number);const parts=number.split(".");switch(parts.length){case 1:return new Version(Number.parseInt(parts[0]));case 2:return new Version(Number.parseInt(parts[0]),Number.parseInt(parts[1]));default:return new Version(Number.parseInt(parts[0]),Number.parseInt(parts[1]),Number.parseInt(parts[2]))}}}class ImplementationNotFound extends NotFound{#fqn;#version;constructor(fqn,version){super(`No implementation found for procedure '${fqn}' with version '${version}'`),this.#fqn=fqn,this.#version=version}get fqn(){return this.#fqn}get version(){return this.#version}}class InvalidSegment extends ServerError{constructor(){super("Invalid segment")}}class Application{#segments=new Map;addSegment(segment){this.#segments.set(segment.id,segment)}getClassNames(){const names=new Set;for(const segment of this.#segments.values()){segment.getClasses().forEach((clazz=>names.add(clazz.fqn)))}return[...names.values()]}hasClass(fqn){return this.getClassNames().includes(fqn)}getClass(fqn){for(const segment of this.#segments.values())if(segment.hasClass(fqn))return segment.getClass(fqn)}getClassByImplementation(implementation){for(const segment of this.#segments.values()){const clazz=segment.getClassByImplementation(implementation);if(void 0!==clazz)return clazz}}getProcedureNames(){const names=new Set;for(const segment of this.#segments.values()){segment.getExposedProcedures().forEach((procedure=>names.add(procedure.fqn)))}return[...names.values()]}hasProcedure(fqn){return this.getProcedureNames().includes(fqn)}getProcedure(fqn){for(const segment of this.#segments.values())if(segment.hasProcedure(fqn))return segment.getProcedure(fqn)}}class ExecutionManager{#argumentConstructor=new ArgumentExtractor;#errorConverter=new ErrorConverter;#application=new Application;async addSegment(segment){if(segment instanceof Segment==!1)throw new InvalidSegment;this.#application.addSegment(segment)}getClassNames(){return this.#application.getClassNames()}hasClass(fqn){return this.#application.hasClass(fqn)}getClass(fqn){return this.#application.getClass(fqn)}getClassByImplementation(implementation){return this.#application.getClassByImplementation(implementation)}getProcedureNames(){return this.#application.getProcedureNames()}hasProcedure(fqn){return this.#application.hasProcedure(fqn)}getProcedure(fqn){return this.#application.getProcedure(fqn)}async run(request){const implementation=this.#getImplementation(request.fqn,request.version),args=this.#argumentConstructor.extract(implementation.parameters,request.args);return request.mode===RunModes_DRY?new Response(StatusCodes_OK,void 0):this.#runImplementation(request,implementation,args)}#getImplementation(fqn,version){const procedure=this.#application.getProcedure(fqn);if(void 0===procedure)throw new ProcedureNotFound(fqn);const implementation=procedure.getImplementation(version);if(void 0===implementation)throw new ImplementationNotFound(procedure.fqn,version.toString());return implementation}async#runImplementation(request,implementation,args){try{const result=await implementation.executable.call(request,...args);return new Response(StatusCodes_OK,result)}catch(error){const status=this.#errorConverter.toStatus(error);return new Response(status,error)}}}class RemoteGateway{#url;#remote;constructor(configuration){this.#url=configuration.url,this.#remote=configuration.remote}get url(){return this.#url}get trustKey(){}start(){return this.#remote.connect()}stop(){return this.#remote.disconnect()}isHealthy(){return this.#remote.isHealthy()}getHealth(){return this.#remote.getHealth()}getProcedureNames(){throw new NotImplemented}hasProcedure(name){throw new NotImplemented}addWorker(worker){return this.#remote.addWorker(worker.url,worker.getProcedureNames(),worker.trustKey)}run(request){return this.#remote.run(request)}}class File{#location;#type;#content;constructor(location,type,content){this.#location=location,this.#type=type,this.#content=content}get location(){return this.#location}get type(){return this.#type}get content(){return this.#content}get size(){return this.#content.length}}class ClassNotFound extends Error{constructor(name){super(`The class '${name}' could not be found`)}}class InvalidClass extends Error{constructor(name){super(`The class '${name}' is invalid`)}}class NoDeserializerFound extends Error{constructor(type){super(`No deserializer found for value of type '${type}'`)}}class NoSerializerFound extends Error{constructor(type){super(`No serializer found for value of type '${type}'`)}}class Serializer{#serializers=[];addSerializer(serializer){serializer.parent=this,this.#serializers.unshift(serializer)}async serialize(value){const serializer=this.#serializers.find((serializer=>serializer.canSerialize(value)));if(void 0===serializer)throw new NoSerializerFound(typeof value);return serializer.serialize(value)}async deserialize(value){const serializer=this.#serializers.find((serializer=>serializer.canDeserialize(value)));if(void 0===serializer)throw new NoDeserializerFound(typeof value);return serializer.deserialize(value)}}class ParentSerializerNotSet extends Error{constructor(){super("Parent serializer not set")}}class ValueSerializer{#parent;set parent(parent){this.#parent=parent}serializeOther(value){if(void 0===this.#parent)throw new ParentSerializerNotSet;return this.#parent.serialize(value)}deserializeOther(value){if(void 0===this.#parent)throw new ParentSerializerNotSet;return this.#parent.deserialize(value)}}class ArraySerializer extends ValueSerializer{canSerialize(value){return value instanceof Array}canDeserialize(value){return value instanceof Array}async serialize(array){const values=[];for(const value of array)values.push(await this.serializeOther(value));return values}async deserialize(array){return Promise.all(array.map((async value=>this.deserializeOther(value))))}}class InvalidBigIntString extends Error{constructor(bigIntString){super(`Invalid BigInt string '${bigIntString}'`)}}class BigIntSerializer extends ValueSerializer{canSerialize(value){return"bigint"==typeof value}canDeserialize(value){const bigInt=value;return bigInt instanceof Object&&!0===bigInt.serialized&&"BigInt"===bigInt.name&&"string"==typeof bigInt.value}async serialize(bigInt){return{serialized:!0,name:"BigInt",value:bigInt.toString()}}async deserialize(object){try{return BigInt(object.value)}catch(error){throw new InvalidBigIntString(object.value)}}}class ESAlias{#name;#as;constructor(name,as){this.#name=name,this.#as=as}get name(){return this.#name}get as(){return this.#as}toString(){return`${this.#name} as ${this.#as}`}}class ESValue{#definition;constructor(definition){this.#definition=definition}get definition(){return this.#definition}toString(){return this.#definition}}class ESArray extends ESValue{}class ESMember{#name;#isStatic;#isPrivate;constructor(name,isStatic=!1,isPrivate=!1){this.#name=name,this.#isStatic=isStatic,this.#isPrivate=isPrivate}get name(){return this.#name}get isStatic(){return this.#isStatic}get isPrivate(){return this.#isPrivate}get isPublic(){return!1===this.#isPrivate}}class ESClass extends ESMember{#parentName;#scope;constructor(name,parentName,scope){super(name),this.#parentName=parentName,this.#scope=scope}get parentName(){return this.#parentName}get scope(){return this.#scope}get members(){return this.#scope.members}get declarations(){return this.#scope.declarations}get functions(){return this.#scope.functions}get getters(){return this.#scope.getters}get setters(){return this.#scope.setters}get generators(){return this.#scope.generators}get readable(){const members=new Map;return this.getters.forEach((getter=>{members.set(getter.name,getter)})),this.declarations.forEach((declaration=>{declaration.isPublic&&members.set(declaration.name,declaration)})),[...members.values()]}get writable(){const members=new Map;return this.setters.forEach((setter=>{members.set(setter.name,setter)})),this.declarations.forEach((declaration=>{declaration.isPublic&&members.set(declaration.name,declaration)})),[...members.values()]}get callable(){return this.functions.filter((funktion=>funktion.isPublic))}getMember(name){return this.#scope.getMember(name)}getDeclaration(name){return this.#scope.getDeclaration(name)}getFunction(name){return this.#scope.getFunction(name)}getGetter(name){return this.#scope.getGetter(name)}getSetter(name){return this.#scope.getSetter(name)}getGenerator(name){return this.#scope.getGenerator(name)}hasMember(name){return this.#scope.hasMember(name)}hasDeclaration(name){return this.#scope.hasDeclaration(name)}hasFunction(name){return this.#scope.hasFunction(name)}hasGetter(name){return this.#scope.hasGetter(name)}hasSetter(name){return this.#scope.hasSetter(name)}hasGenerator(name){return this.#scope.hasGenerator(name)}canRead(name){const declaration=this.getDeclaration(name);return declaration?.isPublic||this.hasGetter(name)}canWrite(name){const declaration=this.getDeclaration(name);return declaration?.isPublic||this.hasSetter(name)}canCall(name){const funktion=this.getFunction(name);return funktion?.isPublic??!1}toString(){const infix=void 0!==this.#parentName?` extends ${this.#parentName}`:"";return`class ${this.name}${infix} { ${this.#scope.toString()} }`}}class ESDeclaration extends ESMember{#identifier;#value;constructor(identifier,value,isStatic=!1,isPrivate=!1){super(identifier.toString(),isStatic,isPrivate),this.#identifier=identifier,this.#value=value}get identifier(){return this.#identifier}get value(){return this.#value}toString(){return`${this.name}${this.value?" = "+this.value.toString():""}`}}class ESDestructuredValue{#members;constructor(members){this.#members=members}get members(){return this.#members}toString(){return this.#members.map((member=>member.toString())).join(" , ")}}class ESDestructuredArray extends ESDestructuredValue{toString(){return`[ ${super.toString()} ]`}}class ESDestructuredObject extends ESDestructuredValue{toString(){return`{ ${super.toString()} }`}}class ESExport extends ESMember{#members;#from;constructor(members,from){super(""),this.#members=members,this.#from=from}get members(){return this.#members}get from(){return this.#from}toString(){const postfix=this.#from?` from '${this.#from}'`:"";return`export { ${this.#members.join(", ")} }${postfix}`}}class ESExpression extends ESValue{}class ESField{#name;#value;constructor(name,value){this.#name=name,this.#value=value}get name(){return this.#name}get value(){return this.#value}toString(){return`${this.name}${this.value?" = "+this.value.toString():""}`}}class ESFunction extends ESMember{#parameters;#body;#isAsync;constructor(name,parameters,body,isStatic=!1,isAsync=!1,isPrivate=!1){super(name,isStatic,isPrivate),this.#parameters=parameters,this.#body=body,this.#isAsync=isAsync}get parameters(){return this.#parameters}get body(){return this.#body}get isAsync(){return this.#isAsync}toString(){const parameters=this.parameters.map((parameter=>parameter.toString()));return`${this.isAsync?"async ":""}${this.name}(${parameters.join(", ")}) { ${this.body} }`}}class ESGenerator extends ESFunction{toString(){const parameters=this.parameters.map((parameter=>parameter.toString()));return`${this.isAsync?"async ":""}${this.name}*(${parameters.join(", ")}) { ${this.body} }`}}class ESGetter extends ESFunction{toString(){return`get ${super.toString()}`}}class ESImport extends ESMember{#members;#from;constructor(members,from){super(""),this.#members=members,this.#from=from}get members(){return this.#members}get from(){return this.#from}toString(){return`import { ${this.#members.map((member=>member.toString())).join(", ")} } from '${this.#from}';`}}class ESModule{#scope;constructor(scope){this.#scope=scope}get scope(){return this.#scope}get members(){return this.#scope.members}get exportedMembers(){return this.#filterExported(this.#scope.members)}get imports(){return this.#scope.imports}get exports(){return this.#scope.exports}get declarations(){return this.#scope.declarations}get exportedDeclarations(){return this.#filterExported(this.#scope.declarations)}get functions(){return this.#scope.functions}get exportedFunctions(){return this.#filterExported(this.#scope.functions)}get generators(){return this.#scope.generators}get exportedGenerators(){return this.#filterExported(this.#scope.generators)}get classes(){return this.#scope.classes}get exportedClasses(){return this.#filterExported(this.#scope.classes)}get exported(){const exported=new Map;for(const exportItem of this.exports)for(const alias of exportItem.members){const member=this.getMember(alias.name);void 0!==member&&exported.set(alias.as,member)}return exported}getMember(name){return this.#scope.getMember(name)}getDeclaration(name){return this.#scope.getDeclaration(name)}getFunction(name){return this.#scope.getFunction(name)}getGenerator(name){return this.#scope.getGenerator(name)}getClass(name){return this.#scope.getClass(name)}hasMember(name){return this.#scope.hasMember(name)}hasDeclaration(name){return this.#scope.hasDeclaration(name)}hasFunction(name){return this.#scope.hasFunction(name)}hasGenerator(name){return this.#scope.hasGenerator(name)}hasClass(name){return this.#scope.hasClass(name)}isExported(member){for(const exportItem of this.exports)for(const alias of exportItem.members)if(alias.name===member.name)return!0;return!1}getExported(name){for(const exportItem of this.exports)for(const alias of exportItem.members)if(alias.as===name)return this.getMember(alias.name)}#filterExported(members){return members.filter((member=>this.isExported(member)))}}class ESObject extends ESValue{}class ESSetter extends ESFunction{toString(){return`set ${super.toString()}`}}const IMPORT_NAME=ESImport.name,EXPORT_NAME=ESExport.name,DECLARATION_NAME=ESDeclaration.name,FUNCTION_NAME=ESFunction.name,GETTER_NAME=ESGetter.name,SETTER_NAME=ESSetter.name,GENERATOR_NAME=ESGenerator.name,CLASS_NAME=ESClass.name;class ESScope{#members;constructor(members){this.#members=members}get members(){return this.#members}get imports(){return this.#members.filter((member=>member.constructor.name===IMPORT_NAME))}get exports(){return this.#members.filter((member=>member.constructor.name===EXPORT_NAME))}get declarations(){return this.#members.filter((member=>member.constructor.name===DECLARATION_NAME))}get functions(){return this.#members.filter((member=>member.constructor.name===FUNCTION_NAME))}get getters(){return this.#members.filter((member=>member.constructor.name===GETTER_NAME))}get setters(){return this.#members.filter((member=>member.constructor.name===SETTER_NAME))}get generators(){return this.#members.filter((member=>member.constructor.name===GENERATOR_NAME))}get classes(){return this.#members.filter((member=>member.constructor.name===CLASS_NAME))}getMember(name){return this.#members.find((member=>member.name===name))}getDeclaration(name){return this.declarations.find((member=>member.name===name))}getFunction(name){return this.functions.find((member=>member.name===name))}getGetter(name){return this.getters.find((member=>member.name===name))}getSetter(name){return this.setters.find((member=>member.name===name))}getGenerator(name){return this.generators.find((member=>member.name===name))}getClass(name){return this.classes.find((member=>member.name===name))}hasMember(name){return void 0!==this.getMember(name)}hasDeclaration(name){return void 0!==this.getDeclaration(name)}hasFunction(name){return void 0!==this.getFunction(name)}hasGetter(name){return void 0!==this.getGetter(name)}hasSetter(name){return void 0!==this.getSetter(name)}hasGenerator(name){return void 0!==this.getGenerator(name)}hasClass(name){return void 0!==this.getClass(name)}toString(){return this.#members.map((member=>member.toString())).join("\n")}}const Comment={SINGLE:"//",MULTI_START:"/*",MULTI_END:"*/"},Comments=Object.values(Comment);const Punctuation_DOT=".",Punctuation_LEFT_PARENTHESIS="(",Punctuation_RIGHT_PARENTHESIS=")",Punctuation_LEFT_BRACKET="[",Punctuation_RIGHT_BRACKET="]",Punctuation_LEFT_BRACE="{",Punctuation_RIGHT_BRACE="}",Divider={SCOPE:":",SEPARATOR:",",TERMINATOR:";"},Divisions=Object.values(Divider);function isDivider(value){return Divisions.includes(value)}const Empty={UNDEFINED:void 0,NULL:null,STRING:""},Empties=Object.values(Empty);function isEmpty(value){return Empties.includes(value)}const Group={OPEN:Punctuation_LEFT_PARENTHESIS,CLOSE:Punctuation_RIGHT_PARENTHESIS};function isGroup(value){return value===Group.OPEN||value===Group.CLOSE}const Keyword={EXPORT:"export",DEFAULT:"default",CLASS:"class",FUNCTION:"function",CONST:"const",LET:"let",VAR:"var",AS:"as",FROM:"from",IMPORT:"import",GET:"get",SET:"set",EXTENDS:"extends",STATIC:"static",ASYNC:"async",RETURN:"return"},Keywords=Object.values(Keyword);function isKeyword(value){return Keywords.includes(value)}function isNotReserved(value){return value===Keyword.AS||value===Keyword.ASYNC||value===Keyword.FROM||value===Keyword.GET||value===Keyword.SET}const List={OPEN:Punctuation_LEFT_BRACKET,CLOSE:Punctuation_RIGHT_BRACKET};function isList(value){return value===List.OPEN||value===List.CLOSE}const Literals=Object.values({SINGLE:"'",DOUBLE:'"',BACKTICK:"`"});function isLiteral(value){return Literals.includes(value)}const Operator={ADD:"+",ARROW:"=>",ASSIGN:"=",ASSIGN_ADD:"+=",ASSIGN_BITWISE_AND:"&=",ASSIGN_BITWISE_OR:"|=",ASSIGN_DIVIDE:"/=",ASSIGN_LEFT_SHIFT:"<<=",ASSIGN_LOGICAL_AND:"&&=",ASSIGN_LOGICAL_OR:"||=",ASSIGN_MODULO:"%=",ASSIGN_MULTIPLY:"*=",ASSIGN_RIGHT_SHIFT:">>=",ASSIGN_SUBTRACT:"-=",ASSIGN_XOR:"^=",BITWISE_AND:"&",BITWISE_OR:"|",DECREMENT:"--",DIVIDE:"/",EQUAL:"==",EQUAL_STRICT:"===",GREATER:">",GREATER_EQUAL:">=",INCREMENT:"++",LEFT_SHIFT:"<<",LESS:"<",LESS_EQUAL:"<=",LOGICAL_AND:"&&",LOGICAL_OR:"||",MODULO:"%",MULTIPLY:"*",NOT:"!",NOT_EQUAL:"!=",NOT_EQUAL_STRICT:"!==",RIGHT_SHIFT:">>",SUBTRACT:"-",TERNARY:"?",XOR:"^"},Operators=Object.values(Operator);function isOperator(value){return Operators.includes(value)}const Scope={OPEN:Punctuation_LEFT_BRACE,CLOSE:Punctuation_RIGHT_BRACE};function isScope(value){return value===Scope.OPEN||value===Scope.CLOSE}const TokenType={COMMENT:"comment",DIVIDER:"divider",GROUP:"group",IDENTIFIER:"identifier",KEYWORD:"keyword",LIST:"list",LITERAL:"literal",OPERATOR:"operator",REGEX:"regex",SCOPE:"scope",WHITESPACE:"whitespace"},Whitespace={SPACE:" ",TAB:"\t",NEWLINE:"\n",CARRIAGE_RETURN:"\r"},Whitespaces=Object.values(Whitespace);function isWhitespace(value){return Whitespaces.includes(value)}class ItemList{#items;#position;constructor(items){this.#items=items,this.#position=0}get items(){return this.#items}get position(){return this.#position}get size(){return this.#items.length}get eol(){return this.#position>=this.#items.length}get current(){return this.#items[this.#position]}get next(){return this.#items[this.#position+1]}get previous(){return this.#items[this.#position-1]}notAtEnd(){return!1===this.eol}get(index){return this.#items[index]}step(amount=1){return this.#position+=amount,this.current}stepBack(amount=1){return this.#position-=amount,this.current}hasNext(){return this.#position+1<this.#items.length}}class CharList extends ItemList{constructor(code){super(code.split(""))}}class Token{#type;#value;#start;#end;constructor(type,value,start,end){this.#type=type,this.#value=value,this.#start=start,this.#end=end}get type(){return this.#type}get value(){return this.#value}get start(){return this.#start}get end(){return this.#end}isType(type){return this.#type===type}hasValue(value){return this.#value===value}toString(){return`${this.#value}`}}class TokenList extends ItemList{}class Lexer{tokenize(code){const charList=new CharList(code),tokens=[];let last;for(;charList.notAtEnd();){const token=this.#getNextToken(charList,last);if(void 0===token)break;token.isType(TokenType.WHITESPACE)||token.isType(TokenType.COMMENT)?charList.step():(tokens.push(token),this.#isCodeToken(token)&&(last=token),charList.step())}return new TokenList(tokens)}#isCodeToken(token){return!1===[TokenType.WHITESPACE,TokenType.COMMENT].includes(token.type)}#getNextToken(charList,lastToken){const char=charList.current,start=charList.position;if(isWhitespace(char)){const end=charList.position;return new Token(TokenType.WHITESPACE,char,start,end)}if(function(value){return Comments.includes(value)}(char+charList.next)){const value=this.#readComment(charList),end=charList.position;return new Token(TokenType.COMMENT,value,start,end)}if(this.#startsRegex(char,lastToken)){const value=this.#readRegex(charList),end=charList.position;return new Token(TokenType.REGEX,value,start,end)}if(isLiteral(char)){const value=this.#readLiteral(charList),end=charList.position;return new Token(TokenType.LITERAL,value,start,end)}if(isOperator(char)){const value=this.#readOperation(charList),end=charList.position;return new Token(TokenType.OPERATOR,value,start,end)}if(isDivider(char)){const end=charList.position;return new Token(TokenType.DIVIDER,char,start,end)}if(isGroup(char)){const end=charList.position;return new Token(TokenType.GROUP,char,start,end)}if(isScope(char)){const end=charList.position;return new Token(TokenType.SCOPE,char,start,end)}if(isList(char)){const end=charList.position;return new Token(TokenType.LIST,char,start,end)}if(isEmpty(char))return;const value=this.#readIdentifier(charList),type=isKeyword(value)?TokenType.KEYWORD:TokenType.IDENTIFIER,end=charList.position;return new Token(type,value,start,end)}#readComment(charList){const isMulti=charList.current+charList.next===Comment.MULTI_START,terminator=isMulti?Comment.MULTI_END:Whitespace.NEWLINE;let value=isMulti?Comment.MULTI_START:Comment.SINGLE;for(charList.step(2);charList.notAtEnd();){const char=charList.current;if((isMulti?char+charList.next:char)===terminator){charList.step(terminator.length-1);break}value+=char,charList.step()}return isMulti?value+Comment.MULTI_END:value.trim()}#startsRegex(char,lastToken){return char===Operator.DIVIDE&&(void 0===lastToken||([TokenType.OPERATOR,TokenType.DIVIDER,TokenType.KEYWORD].includes(lastToken.type)||[Group.OPEN,List.OPEN].includes(lastToken.value)))}#endsRegex(char){return isWhitespace(char)||char==Punctuation_DOT||!1===this.#isIdentifier(char)}#readRegex(charList){let value=charList.current,closed=!1;for(charList.step();charList.notAtEnd();){const current=charList.current,previous=charList.previous;if(current===Operator.DIVIDE&&"\\"!==previous)closed=!0;else if(!0===closed&&this.#endsRegex(current)){charList.stepBack();break}value+=current,charList.step()}return value}#readLiteral(charList){const identifier=charList.current;let value=identifier,escaped=!1;for(charList.step();charList.notAtEnd();){const char=charList.current;if(!1===escaped){if(char===identifier){value+=char;break}"\\"===char&&(escaped=!0)}else escaped=!1;value+=char,charList.step()}return value}#isIdentifier(char){return!1===(isEmpty(char)||isWhitespace(char)||isOperator(char)||isLiteral(char)||isDivider(char)||isGroup(char)||isScope(char)||isList(char))}#readIdentifier(charList){let value="";for(;charList.notAtEnd();){const char=charList.current;if(!1===this.#isIdentifier(char)){charList.stepBack();break}value+=char,charList.step()}return value}#readOperation(charList){let value=charList.current;for(charList.step();charList.notAtEnd();){const char=charList.current;if(!1===isOperator(char)||!1===isOperator(value+char)){charList.stepBack();break}value+=char,charList.step()}return value}}class ExpectedKeyword extends Error{constructor(value,position){super(`Expected keyword '${value}' at position ${position}`)}}class ExpectedToken extends Error{constructor(value,position){super(`Expected token '${value}' at position ${position}`)}}class UnexpectedKeyword extends Error{constructor(keyword,position){super(`Unexpected keyword '${keyword}' at position ${position}`)}}class UnexpectedParseResult extends Error{constructor(expected){super(`The given code does not contain ${expected}`)}}class UnexpectedToken extends Error{constructor(value,position){super(`Unexpected token '${value}' at position ${position}`)}}class Parser{#lexer;constructor(lexer=new Lexer){this.#lexer=lexer}parse(code){const tokenList=this.#lexer.tokenize(code),scope=this.#parseScope(tokenList);return new ESModule(scope)}parseFirst(code){const tokenList=this.#lexer.tokenize(code);return this.#parseNext(tokenList)}parseValue(code){const model=this.parseFirst(code);if(model instanceof ESValue==!1)throw new UnexpectedParseResult("a value definition");return model}parseImport(code){const model=this.parseFirst(code);if(model instanceof ESImport==!1)throw new UnexpectedParseResult("an import definition");return model}parseExport(code){const model=this.parseFirst(code);if(model instanceof ESExport==!1)throw new UnexpectedParseResult("an export definition");return model}parseDeclaration(code){const model=this.parseFirst(code);if(model instanceof ESDeclaration==!1)throw new UnexpectedParseResult("a declaration definition");return model}parseFunction(code){const tokenList=this.#lexer.tokenize(code),model=this.#parseMember(tokenList);if(model instanceof ESFunction==!1)throw new UnexpectedParseResult("a function definition");return model}parseClass(code){const tokenList=this.#lexer.tokenize(code),model=this.#parseMember(tokenList);if(model instanceof ESClass==!1)throw new UnexpectedParseResult("a class definition");return model}#parseScope(tokenList){const members=[];for(;tokenList.notAtEnd();){const member=this.#parseNext(tokenList);member instanceof ESMember&&members.push(member)}return new ESScope(members)}#parseNext(tokenList,isAsync=!1){const token=tokenList.current;if(token.isType(TokenType.LITERAL))return this.#parseExpression(tokenList);if(token.isType(TokenType.IDENTIFIER)){const next=tokenList.next;return next?.hasValue(Operator.ARROW)?this.#parseArrowFunction(tokenList,isAsync):this.#parseExpression(tokenList)}if(token.isType(TokenType.KEYWORD)){if(isNotReserved(token.value)){const next=tokenList.next,nextIsFunction=void 0!==next&&(next.hasValue(Keyword.FUNCTION)||next.hasValue(Group.OPEN));if(token.hasValue(Keyword.ASYNC)&&nextIsFunction)return tokenList.step(),this.#parseNext(tokenList,!0);if(void 0===next||this.#atEndOfStatement(next))return this.#parseExpression(tokenList)}return token.hasValue(Keyword.RETURN)?this.#parseExpression(tokenList):this.#parseMember(tokenList,isAsync)}if(token.isType(TokenType.REGEX))return this.#parseExpression(tokenList);if(token.hasValue(Group.OPEN)){const next=this.#peekAfterBlock(tokenList,Group.OPEN,Group.CLOSE);return next?.hasValue(Operator.ARROW)?this.#parseArrowFunction(tokenList,isAsync):this.#parseExpression(tokenList)}if(token.hasValue(Scope.OPEN))return this.#parseObject(tokenList);if(token.hasValue(List.OPEN))return this.#parseArray(tokenList);if(token.hasValue(Operator.NOT)||token.hasValue(Operator.SUBTRACT))return this.#parseExpression(tokenList);if(!isDivider(token.value))throw new UnexpectedToken(token.value,token.start);tokenList.step()}#parseMember(tokenList,isAsync=!1){const token=tokenList.current;switch(tokenList.step(),token.value){case Keyword.IMPORT:return this.#parseImport(tokenList);case Keyword.EXPORT:return this.#parseExport(tokenList);case Keyword.CLASS:return this.#parseClass(tokenList);case Keyword.FUNCTION:return this.#parseFunction(tokenList,isAsync);case Keyword.VAR:case Keyword.LET:case Keyword.CONST:return this.#parseDeclaration(tokenList,!1,!0);case Keyword.ASYNC:return this.#parseMember(tokenList,!0);default:throw new UnexpectedKeyword(token.value,token.start)}}#parseImport(tokenList){const members=[];let token=tokenList.current;if(token.isType(TokenType.LITERAL))return new ESImport(members,token.value);if(token.hasValue(Group.OPEN)){token=tokenList.step();const from=token.value;return tokenList.step(2),new ESImport(members,from)}if(!1===token.hasValue(Scope.OPEN)){const name=token.hasValue(Operator.MULTIPLY)?Operator.MULTIPLY:"default";let as=token.value;token=tokenList.step(),token.hasValue(Keyword.AS)&&(token=tokenList.step(),as=token.value,token=tokenList.step()),members.push(new ESAlias(name,as))}if(token.hasValue(Divider.SEPARATOR)&&(token=tokenList.step()),token.hasValue(Scope.OPEN)){const aliases=this.#parseAliasList(tokenList);members.push(...aliases),token=tokenList.current}if(!1===token.hasValue(Keyword.FROM))throw new ExpectedKeyword(Keyword.FROM,token.start);token=tokenList.step();const from=token.value;return tokenList.step(),new ESImport(members,from)}#parseExport(tokenList){switch(tokenList.current.value){case Keyword.DEFAULT:return tokenList.step(),this.#parseSingleExport(tokenList,!0);case Scope.OPEN:return this.#parseMultiExport(tokenList);default:return this.#parseSingleExport(tokenList,!1)}}#parseSingleExport(tokenList,isDefault){let token=tokenList.current,stepSize=0;var value;token.hasValue(Keyword.ASYNC)&&(token=tokenList.step(),stepSize++),((value=token.value)===Keyword.CLASS||value===Keyword.FUNCTION||value===Keyword.CONST||value===Keyword.LET||value===Keyword.VAR)&&(token=tokenList.step(),stepSize++);const name=this.#isIdentifier(token)?token.value:"",as=isDefault?"default":name;let from;token=tokenList.step(),token?.hasValue(Keyword.FROM)&&(token=tokenList.step(),from=token.value),stepSize>0&&(stepSize++,tokenList.stepBack(stepSize));const alias=new ESAlias(name,as);return new ESExport([alias],from)}#parseMultiExport(tokenList){const members=this.#parseAliasList(tokenList);let from,token=tokenList.current;return token?.hasValue(Keyword.FROM)&&(token=tokenList.step(),from=token.value),tokenList.step(),new ESExport(members,from)}#parseAliasList(tokenList){const aliases=[];let token=tokenList.step();for(;tokenList.notAtEnd();){if(token.hasValue(Scope.CLOSE)){tokenList.step();break}if(token.hasValue(Divider.SEPARATOR)){token=tokenList.step();continue}const alias=this.#parseAlias(tokenList);aliases.push(alias),token=tokenList.step()}return aliases}#parseAlias(tokenList){let token=tokenList.current;const name=token.value;let as=name;return tokenList.next.hasValue(Keyword.AS)&&(token=tokenList.step(2),as=token.value),new ESAlias(name,as)}#parseDeclaration(tokenList,isStatic,parseMultiple=!1){let value,token=tokenList.current,identifier="",isPrivate=!1;return token.hasValue(List.OPEN)?(identifier=this.#parseDestructuredArray(tokenList),token=tokenList.current):token.hasValue(Scope.OPEN)?(identifier=this.#parseDestructuredObject(tokenList),token=tokenList.current):(isPrivate=token.value.startsWith("#"),identifier=isPrivate?token.value.substring(1):token.value,token=tokenList.step()),token.hasValue(Operator.ASSIGN)&&(tokenList.step(),value=this.#parseNext(tokenList,!1),token=tokenList.current),void 0!==token&&(token.hasValue(Divider.TERMINATOR)?tokenList.step():!0===parseMultiple&&token.hasValue(Divider.SEPARATOR)&&(tokenList.step(),this.#parseDeclaration(tokenList,isStatic,!0))),value instanceof ESGenerator?new ESGenerator(identifier.toString(),value.parameters,value.body,isStatic,value.isAsync,isPrivate):value instanceof ESFunction?new ESFunction(identifier.toString(),value.parameters,value.body,isStatic,value.isAsync,isPrivate):value instanceof ESClass?new ESClass(identifier.toString(),value.parentName,value.scope):new ESDeclaration(identifier,value,isStatic,isPrivate)}#parseFunction(tokenList,isAsync,isStatic=!1,isGetter=!1,isSetter=!1){let token=tokenList.current,name="",isGenerator=!1,isPrivate=!1;token.hasValue(Operator.MULTIPLY)&&(isGenerator=!0,token=tokenList.step()),this.#isIdentifier(token)&&(isPrivate=token.value.startsWith("#"),name=isPrivate?token.value.substring(1):token.value,token=tokenList.step());const parameters=this.#parseParameters(tokenList,Group.CLOSE);if(token=tokenList.current,!1===token.hasValue(Scope.OPEN))throw new ExpectedToken(Scope.OPEN,token.start);const body=this.#parseBlock(tokenList,Scope.OPEN,Scope.CLOSE);return isGenerator?new ESGenerator(name,parameters,body,isStatic,isAsync,isPrivate):isGetter?new ESGetter(name,parameters,body,isStatic,isAsync,isPrivate):isSetter?new ESSetter(name,parameters,body,isStatic,isAsync,isPrivate):new ESFunction(name,parameters,body,isStatic,isAsync,isPrivate)}#parseArrowFunction(tokenList,isAsync){let parameters,token=tokenList.current;if(token.hasValue(Group.OPEN)?(parameters=this.#parseParameters(tokenList,Group.CLOSE),token=tokenList.current):(parameters=[new ESField(token.value,void 0)],token=tokenList.step()),!1===token.hasValue(Operator.ARROW))throw new ExpectedToken(Operator.ARROW,token.start);token=tokenList.step();const body=token.hasValue(Scope.OPEN)?this.#parseBlock(tokenList,Scope.OPEN,Scope.CLOSE):this.#parseExpression(tokenList).definition;return new ESFunction("",parameters,body,!1,isAsync,!1)}#parseParameters(tokenList,closeId){const parameters=[];for(tokenList.step();tokenList.notAtEnd();){const token=tokenList.current;if(token.hasValue(closeId)){tokenList.step();break}if(token.hasValue(Divider.SEPARATOR)){tokenList.step();continue}let parameter;parameter=token.hasValue(Scope.OPEN)?this.#parseDestructuredObject(tokenList):token.hasValue(List.OPEN)?this.#parseDestructuredArray(tokenList):this.#parseField(tokenList),parameters.push(parameter)}return parameters}#parseClass(tokenList){let parent,token=tokenList.current,name="";if(this.#isIdentifier(token)&&(name=token.value,token=tokenList.step()),token.hasValue(Keyword.EXTENDS)&&(token=tokenList.step(),parent=token.value,token=tokenList.step()),!1===token.hasValue(Scope.OPEN))throw new ExpectedToken(Scope.OPEN,token.start);const scope=this.#parseClassScope(tokenList);return new ESClass(name,parent,scope)}#parseClassScope(tokenList){let token=tokenList.step();const members=[];for(;tokenList.notAtEnd();){if(token.hasValue(Scope.CLOSE)){tokenList.step();break}const member=this.#parseClassMember(tokenList);members.push(member),token=tokenList.current}return new ESScope(members)}#parseClassMember(tokenList){let token=tokenList.current,isAsync=!1,isStatic=!1,isGetter=!1,isSetter=!1;for(;tokenList.notAtEnd();){if(token.hasValue(Keyword.STATIC))isStatic=!0;else if(token.hasValue(Keyword.ASYNC))isAsync=!0;else if(token.hasValue(Keyword.GET))isGetter=!0;else{if(!token.hasValue(Keyword.SET)){if(token.hasValue(Operator.MULTIPLY))return this.#parseFunction(tokenList,isAsync,isStatic,!1,!1);break}isSetter=!0}token=tokenList.step()}return tokenList.next.hasValue(Group.OPEN)?this.#parseFunction(tokenList,isAsync,isStatic,isGetter,isSetter):this.#parseDeclaration(tokenList,isStatic)}#parseArray(tokenList){const items=this.#parseBlock(tokenList,List.OPEN,List.CLOSE);return new ESArray(items)}#parseDestructuredArray(tokenList){const fields=this.#parseParameters(tokenList,List.CLOSE);return new ESDestructuredArray(fields)}#parseObject(tokenList){const fields=this.#parseBlock(tokenList,Scope.OPEN,Scope.CLOSE);return new ESObject(fields)}#parseDestructuredObject(tokenList){const fields=this.#parseParameters(tokenList,Scope.CLOSE);return new ESDestructuredObject(fields)}#parseField(tokenList){let token=tokenList.current;const name=token.value;let value;return token=tokenList.step(),token.hasValue(Operator.ASSIGN)&&(tokenList.step(),value=this.#parseNext(tokenList,!1)),new ESField(name,value)}#parseExpression(tokenList){let token=tokenList.current,code="";for(;tokenList.notAtEnd();){if(token.hasValue(List.OPEN)){code+=this.#parseBlock(tokenList,List.OPEN,List.CLOSE)+" ",token=tokenList.current}else if(token.hasValue(Group.OPEN)){code+=this.#parseBlock(tokenList,Group.OPEN,Group.CLOSE)+" ",token=tokenList.current}else if(token.hasValue(Scope.OPEN)){code+=this.#parseBlock(tokenList,Scope.OPEN,Scope.CLOSE)+" ",token=tokenList.current}else code+=token.toString()+" ",token=tokenList.step();if(void 0===token||this.#atEndOfStatement(token))break}return new ESExpression(code.trim())}#parseBlock(tokenList,openId,closeId){let token=tokenList.step(),code=openId+" ";for(;tokenList.notAtEnd();)if(token.hasValue(openId))code+=this.#parseBlock(tokenList,openId,closeId)+" ",token=tokenList.current;else{if(token.hasValue(closeId))return tokenList.step(),code+=closeId,code;code+=token.toString()+" ",token=tokenList.step()}return code}#peekAfterBlock(tokenList,openId,closeId){const start=tokenList.position;this.#parseBlock(tokenList,openId,closeId);const token=tokenList.current,end=tokenList.position;return tokenList.stepBack(end-start),token}#atEndOfStatement(token){return[Divider.TERMINATOR,Divider.SEPARATOR].includes(token.value)||[List.CLOSE,Group.CLOSE,Scope.CLOSE].includes(token.value)||isKeyword(token.value)}#isIdentifier(token){return token.isType(TokenType.IDENTIFIER)||token.isType(TokenType.KEYWORD)&&isNotReserved(token.value)}}class ClassMerger{merge(model,parent){const declarations=this.#mergeDeclarations(model.declarations,parent.declarations),functions=this.#mergeFunctions(model.functions,parent.functions),getters=this.#mergeFunctions(model.getters,parent.getters),setters=this.#mergeFunctions(model.setters,parent.setters),members=[...declarations.values(),...functions.values(),...getters.values(),...setters.values()];return new ESClass(model.name,parent.name,new ESScope(members))}#mergeDeclarations(model,parent){const declarations=new Map;return parent.forEach((declaration=>declarations.set(declaration.name,declaration))),model.forEach((declaration=>declarations.set(declaration.name,declaration))),[...declarations.values()]}#mergeFunctions(model,parent){const functions=new Map;return parent.forEach((funktion=>functions.set(funktion.name,funktion))),model.forEach((funktion=>functions.set(funktion.name,funktion))),[...functions.values()]}}class Reflector{#parser=new Parser;#merger=new ClassMerger;fromModule(module,inherit=!1){const entries=Object.entries(module),members=[];for(const[key,member]of entries){if("function"!=typeof member.toString)continue;const code=member.toString();if(code.startsWith("class"))members.push(this.fromClass(member,inherit));else if(code.startsWith("function"))members.push(this.fromFunction(member));else{const expression=new ESExpression(code);members.push(new ESDeclaration(key,expression))}}return new ESModule(new ESScope(members))}fromClass(clazz,inherit=!1){const model=this.isClass(clazz)?this.#reflectStatic(clazz):this.#reflectDynamic(clazz);if(!1===inherit)return model;const parentClazz=this.getParentClass(clazz);if(""===parentClazz.name)return model;const parentModel=this.fromClass(parentClazz,!0);return this.#merger.merge(model,parentModel)}fromObject(object,inherit=!0){const clazz=this.getClass(object);return this.fromClass(clazz,inherit)}fromFunction(funktion){const code=funktion.toString();return this.#parser.parseFunction(code)}createInstance(clazz,args=[]){return new clazz(...args)}getClass(object){return object.constructor}getParentClass(clazz){return Object.getPrototypeOf(clazz)}isClassObject(object){return this.isClass(object.constructor)}isFunctionObject(object){return this.isFunction(object.constructor)}isClass(clazz){return clazz.toString().startsWith("class")}isFunction(clazz){return clazz.toString().startsWith("function")||clazz.toString().startsWith("async function")}#reflectStatic(clazz){const code=clazz.toString();return this.#parser.parseClass(code)}#reflectDynamic(clazz){const object=this.createInstance(clazz),members=this.#getMembers(clazz,object),scope=new ESScope(members);return new ESClass(clazz.name,void 0,scope)}#getMembers(clazz,object){return[...this.#getDeclarations(object),...this.#getFunctions(clazz)]}#getDeclarations(object){const fieldNames=Object.getOwnPropertyNames(object),values=object,models=[];for(const fieldName of fieldNames){const content=values[fieldName],value=void 0!==content?new ESValue(String(content)):void 0,model=new ESDeclaration(fieldName,value);models.push(model)}return models}#getFunctions(clazz){const functionDescriptions=Object.getOwnPropertyDescriptors(clazz.prototype),models=[];for(const functionName in functionDescriptions){const description=functionDescriptions[functionName],funktion=description.value;if(funktion instanceof Function==!1)continue;const model=this.fromFunction(funktion);void 0!==description.get?models.push(new ESGetter(model.name,model.parameters,model.body,model.isStatic,model.isAsync,model.isPrivate)):void 0!==description.set?models.push(new ESSetter(model.name,model.parameters,model.body,model.isStatic,model.isAsync,model.isPrivate)):models.push(model)}return models}}const reflector$1=new Reflector;class ClassSerializer extends ValueSerializer{#classResolver;constructor(classResolver){super(),this.#classResolver=classResolver}canSerialize(value){return value instanceof Object&&reflector$1.isClassObject(value)}canDeserialize(value){const object=value;return object instanceof Object&&!0===object.serialized&&"class"===object.name&&"string"==typeof object.key&&object.args instanceof Object&&object.args.constructor===Object&&object.fields instanceof Object&&object.fields.constructor===Object}async serialize(object){const clazz=reflector$1.getClass(object),model=reflector$1.fromClass(clazz,!0),parameterNames=this.#extractConstructorParameters(model),key=this.#classResolver.resolveKey(clazz);if(void 0===key)throw new ClassNotFound(clazz.name);return{serialized:!0,key:key,name:"class",args:await this.#serializeConstructor(model,parameterNames,object),fields:await this.#serializeFields(model,parameterNames,object)}}#extractConstructorParameters(model){const constructor=model.getFunction("constructor");return(constructor?.parameters??[]).map((parameter=>parameter.name))}async#serializeConstructor(model,includeNames,object){const args={};for(const[index,name]of includeNames.entries()){const value=model.canRead(name)?await this.serializeOther(object[name]):void 0;args[index.toString()]=value}return args}async#serializeFields(model,excludeNames,object){const fields={};for(const property of model.writable){const name=property.name;excludeNames.includes(name)||!1===model.canRead(name)||(fields[name]=await this.serializeOther(object[name]))}return fields}async deserialize(object){const clazz=await this.#getClass(object);if(void 0===clazz)throw new ClassNotFound(object.key);if(clazz instanceof Function==!1)throw new InvalidClass(object.key);const args=await this.#deserializeConstructor(clazz,object.args),instance=reflector$1.createInstance(clazz,args);for(const name in object.fields){const fieldValue=object.fields[name];instance[name]=await this.deserializeOther(fieldValue)}return instance}async#deserializeConstructor(clazz,args){const constructor=reflector$1.fromClass(clazz,!0).getFunction("constructor"),values=(constructor?.parameters??[]).map(((_,index)=>{const key=index.toString(),value=args[key];return this.deserializeOther(value)}));return Promise.all(values)}async#getClass(resolvable){return globalThis[resolvable.key]??this.#classResolver.resolveClass(resolvable.key)}}class InvalidDateString extends Error{constructor(dateString){super(`Invalid date string '${dateString}'`)}}class DateSerializer extends ValueSerializer{canSerialize(value){return value instanceof Date}canDeserialize(value){const date=value;return date instanceof Object&&!0===date.serialized&&"Date"===date.name&&"string"==typeof date.value}async serialize(date){return{serialized:!0,name:"Date",value:date.toISOString()}}async deserialize(object){const date=new Date(object.value);if("Invalid Date"===date.toString())throw new InvalidDateString(object.value);return date}}class ErrorSerializer extends ValueSerializer{canSerialize(value){if(value instanceof Object==!1)return!1;const error=value;return error.constructor===Error||error.constructor===EvalError||error.constructor===RangeError||error.constructor===ReferenceError||error.constructor===SyntaxError||error.constructor===TypeError||error.constructor===URIError||error.constructor===AggregateError}canDeserialize(value){const error=value;return error instanceof Object&&!0===error.serialized&&"Error"===error.name&&error.type in globalThis}async serialize(error){return{serialized:!0,name:"Error",type:error.constructor.name,stack:error.stack,message:error.message,cause:error.cause}}async deserialize(object){const error=new(0,globalThis[object.type]);return error.stack=object.stack,error.message=object.message,error.cause=object.cause,error}}class MapSerializer extends ValueSerializer{canSerialize(value){return value instanceof Map}canDeserialize(value){const map=value;return map instanceof Object&&!0===map.serialized&&"Map"===map.name&&map.entries instanceof Object&&map.entries.keys instanceof Array&&map.entries.values instanceof Array}async serialize(map){const keys=[],values=[];for(const[key,value]of map)keys.push(await this.serializeOther(key)),values.push(await this.serializeOther(value));return{serialized:!0,name:"Map",entries:{keys:keys,values:values}}}async deserialize(object){const keys=object.entries.keys,values=object.entries.values,result=new Map;for(let index=0;index<keys.length;index++){const key=await this.deserializeOther(keys[index]),value=await this.deserializeOther(values[index]);result.set(key,value)}return result}}class ObjectSerializer extends ValueSerializer{canSerialize(value){return value instanceof Object&&value.constructor===Object}canDeserialize(value){return value instanceof Object&&value.constructor===Object}async serialize(object){const result={};for(const key in object){const value=object[key];result[key]=await this.serializeOther(value)}return result}async deserialize(object){const result={};for(const key in object){const value=object[key];result[key]=await this.deserializeOther(value)}return result}}class PrimitiveSerializer extends ValueSerializer{canSerialize(value){return value instanceof Object==!1}canDeserialize(value){return value instanceof Object==!1}async serialize(primitive){return primitive}async deserialize(primitive){return primitive}}class InvalidRegExp extends Error{constructor(source,flags){super(`Invalid regular expression '${source}' with flags '${flags}'`)}}class RegExpSerializer extends ValueSerializer{canSerialize(value){return value instanceof RegExp}canDeserialize(value){const regExp=value;return regExp instanceof Object&&!0===regExp.serialized&&"RegExp"===regExp.name&&"string"==typeof regExp.source&&"string"==typeof regExp.flags}async serialize(regExp){return{serialized:!0,name:"RegExp",source:regExp.source,flags:regExp.flags}}async deserialize(object){try{return new RegExp(object.source,object.flags)}catch(error){throw new InvalidRegExp(object.source,object.flags)}}}class SetSerializer extends ValueSerializer{canSerialize(value){return value instanceof Set}canDeserialize(value){const set=value;return set instanceof Object&&!0===set.serialized&&"Set"===set.name&&set.values instanceof Array}async serialize(set){const values=[];for(const value of set.values())values.push(await this.serializeOther(value));return{serialized:!0,name:"Set",values:values}}async deserialize(object){const values=await Promise.all(object.values.map((async value=>this.deserializeOther(value))));return new Set([...values])}}const reflector=new Reflector;class ArrayBufferSerializer extends ValueSerializer{canSerialize(value){return value instanceof Int8Array||value instanceof Uint8Array||value instanceof Uint8ClampedArray||value instanceof Int16Array||value instanceof Uint16Array||value instanceof Int32Array||value instanceof Uint32Array||value instanceof Float32Array||value instanceof Float64Array||value instanceof BigInt64Array||value instanceof BigUint64Array}canDeserialize(value){const array=value;return array instanceof Object&&!0===array.serialized&&"TypedArray"===array.name&&array.type in globalThis&&array.bytes instanceof Array}async serialize(array){const type=array.constructor.name,view=new DataView(array.buffer),bytes=[];for(let index=0;index<view.byteLength;index++)bytes.push(view.getUint8(index));return{serialized:!0,name:"TypedArray",type:type,bytes:bytes}}async deserialize(object){const type=object.type,bytes=object.bytes,buffer=new ArrayBuffer(bytes.length),view=new DataView(buffer);for(let index=0;index<bytes.length;index++)view.setUint8(index,bytes[index]);const clazz=globalThis[type];return reflector.createInstance(clazz,[buffer])}}class InvalidUrlString extends Error{constructor(urlString){super(`Invalid url string '${urlString}'`)}}class UrlSerializer extends ValueSerializer{canSerialize(value){return value instanceof URL}canDeserialize(value){const url=value;return url instanceof Object&&!0===url.serialized&&"Url"===url.name&&"string"==typeof url.value}async serialize(url){return{serialized:!0,name:"Url",value:url.toString()}}async deserialize(object){try{return new URL(object.value)}catch(error){throw new InvalidUrlString(object.value)}}}class SerializerBuilder{static build(classResolver){const serializer=new Serializer;return serializer.addSerializer(new PrimitiveSerializer),serializer.addSerializer(new ObjectSerializer),void 0!==classResolver&&serializer.addSerializer(new ClassSerializer(classResolver)),serializer.addSerializer(new ErrorSerializer),serializer.addSerializer(new RegExpSerializer),serializer.addSerializer(new BigIntSerializer),serializer.addSerializer(new UrlSerializer),serializer.addSerializer(new DateSerializer),serializer.addSerializer(new SetSerializer),serializer.addSerializer(new MapSerializer),serializer.addSerializer(new ArraySerializer),serializer.addSerializer(new ArrayBufferSerializer),serializer}}class ExecutionClassResolver{#executionManager;constructor(executionManager){this.#executionManager=executionManager}resolveKey(clazz){const model=this.#executionManager.getClassByImplementation(clazz);return model?.fqn}resolveClass(key){const model=this.#executionManager.getClass(key);return model?.implementation}}class RequestNotTrusted extends Unauthorized{constructor(){super("Request not trusted")}}class LocalWorker{#url;#trustKey;#gateway;#executionManager;#serializer;constructor(configuration){this.#url=configuration.url,this.#trustKey=configuration.trustKey,this.#gateway=configuration.gateway,this.#executionManager=configuration.executionManager;const classResolver=new ExecutionClassResolver(this.#executionManager);this.#serializer=SerializerBuilder.build(classResolver)}get url(){return this.#url}get trustKey(){return this.#trustKey}async start(){void 0!==this.#gateway&&(await this.#gateway.start(),await this.#gateway.addWorker(this))}async stop(){void 0!==this.#gateway&&await this.#gateway.stop()}getProcedureNames(){return this.#executionManager.getProcedureNames()}hasProcedure(name){return this.#executionManager.hasProcedure(name)}async isHealthy(){return!0}async getHealth(){return new Map}async run(request){return this.#mustRunLocal(request)?this.#runLocal(request):this.#runRemote(request)}#mustRunLocal(request){return void 0===this.#gateway||this.#executionManager.hasProcedure(request.fqn)}async#runLocal(request){const procedure=this.#executionManager.getProcedure(request.fqn),implementation=procedure?.getImplementation(request.version);if(this.#procedureNotFound(implementation))throw new ProcedureNotFound(request.fqn);if(this.#requestNotTrusted(request,implementation))throw new RequestNotTrusted;const dataEncoding=request.getHeader("X-Jitar-Data-Encoding");"serialized"===dataEncoding&&(request=await this.#deserializeRequest(request)),request.removeHeader("X-Jitar-Data-Encoding");const response=await this.#executionManager.run(request);return"serialized"===dataEncoding?this.#serializeResponse(response):response}#procedureNotFound(implementation){return void 0===implementation||implementation.private}#requestNotTrusted(request,implementation){if(implementation.public)return!1;const trustKey=request.getHeader("X-Jitar-Trust-Key");return this.#trustKey!==trustKey}async#runRemote(request){(request=await this.#serializeRequest(request)).setHeader("X-Jitar-Data-Encoding","serialized"),void 0!==this.#trustKey&&request.setHeader("X-Jitar-Trust-Key",this.#trustKey);const response=await this.#gateway.run(request);return this.#deserializeResponse(response)}async#serializeRequest(request){const serializedArgs=new Map;for(const[key,value]of request.args){const serializedValue=await this.#serializer.serialize(value);serializedArgs.set(key,serializedValue)}return new Request(request.fqn,request.version,serializedArgs,request.headers,request.mode)}async#deserializeRequest(request){const deserializedArgs=new Map;for(const[key,value]of request.args){const deserializedValue=await this.#serializer.deserialize(value);deserializedArgs.set(key,deserializedValue)}return new Request(request.fqn,request.version,deserializedArgs,request.headers,request.mode)}async#serializeResponse(response){const serializedResult=await this.#serializer.serialize(response.result);return new Response(response.status,serializedResult,response.headers)}async#deserializeResponse(response){const deserializedResult=await this.#serializer.deserialize(response.result);return new Response(response.status,deserializedResult,response.headers)}}class ProcedureRunner{#runner;constructor(runner){this.#runner=runner}async handle(request,next){return this.#runner.run(request)}}class Runtime{#versionParser=new VersionParser;constructor(){this.#initGlobals()}#initGlobals(){const globals=globalThis;globals.__run=this.#run.bind(this),globals.ProcedureNotAccessible=ProcedureNotAccessible}async#run(fqn,versionNumber,args,sourceRequest){const version=this.#versionParser.parse(versionNumber),argsMap=new Map(Object.entries(args)),headersMap=sourceRequest instanceof Request?sourceRequest.headers:new Map,targetRequest=new Request(fqn,version,argsMap,headersMap,RunModes_NORMAL),trustKey=this.getTrustKey();void 0!==trustKey&&targetRequest.setHeader("X-Jitar-Trust-Key",trustKey);const targetResponse=await this.runInternal(targetRequest);if(targetResponse.status!==StatusCodes_OK)throw targetResponse.result;return targetResponse.result}}class Client extends Runtime{#worker;#middlewareManager;constructor(configuration){super(),this.#worker=new LocalWorker({url:configuration.remoteUrl,gateway:new RemoteGateway({url:configuration.remoteUrl,remote:configuration.remote}),executionManager:configuration.executionManager}),this.#middlewareManager=configuration.middlewareManager;const procedureRunner=new ProcedureRunner(this.#worker);this.#middlewareManager.addMiddleware(procedureRunner)}get worker(){return this.#worker}start(){return this.#worker.start()}stop(){return this.#worker.stop()}getTrustKey(){}run(request){return this.runInternal(request)}runInternal(request){return this.#middlewareManager.handle(request)}}class InvalidMiddleware extends ServerError{constructor(){super("Invalid middleware")}}class MiddlewareManager{#middlewares=[];addMiddleware(middleware){if(void 0===middleware?.handle)throw new InvalidMiddleware;this.#middlewares.push(middleware)}getMiddleware(type){return this.#middlewares.find((middleware=>middleware instanceof type))}clearMiddlewares(){this.#middlewares=[]}handle(request){return this.#getNextHandler(request,0)()}#getNextHandler(request,index){const next=this.#middlewares[index];if(void 0===next)return async()=>new Response(StatusCodes_OK);const nextHandler=this.#getNextHandler(request,index+1);return async()=>next.handle(request,nextHandler)}}class ClientBuilder{#remoteBuilder;constructor(remoteBuilder){this.#remoteBuilder=remoteBuilder}build(configuration){const remoteUrl=configuration.remoteUrl,remote=this.#remoteBuilder.build(remoteUrl),middlewareManager=this.#buildMiddlewareManager(configuration.middleware??[]),executionManager=this.#buildExecutionManager(configuration.segments??[]);return new Client({remoteUrl:remoteUrl,remote:remote,middlewareManager:middlewareManager,executionManager:executionManager})}#buildMiddlewareManager(middleware){const manager=new MiddlewareManager;return middleware.forEach((middleware=>manager.addMiddleware(middleware))),manager}#buildExecutionManager(segments){const manager=new ExecutionManager;return segments.forEach((segment=>manager.addSegment(segment))),manager}}const HeaderKeys_CONTENT_TYPE="content-type",HeaderKeys_JITAR_CONTENT_TYPE="x-jitar-content-type",HeaderKeys_JITAR_PROCEDURE_VERSION="x-jitar-procedure-version",HeaderValues_APPLICATION_JSON="application/json",HeaderValues_APPLICATION_STREAM="application/octet-stream";class HttpRemote{#url;#errorConverter=new ErrorConverter;constructor(url){this.#url=url}connect(){return Promise.resolve()}disconnect(){return Promise.resolve()}async provide(filename){const remoteUrl=`${this.#url}/${filename}`,response=await this.#callRemote(remoteUrl,{method:"GET"}),type=response.headers.get(HeaderKeys_CONTENT_TYPE)??HeaderValues_APPLICATION_STREAM,result=await response.arrayBuffer(),content=Buffer.from(result);return new File(filename,type,content)}async isHealthy(){const remoteUrl=`${this.#url}/health/status`,response=await this.#callRemote(remoteUrl,{method:"GET"}),healthy=await response.text();return Boolean(healthy)}async getHealth(){const remoteUrl=`${this.#url}/health`,response=await this.#callRemote(remoteUrl,{method:"GET"}),health=await response.json();return new Map(Object.entries(health))}async addWorker(url,procedureNames,trustKey){const remoteUrl=`${this.#url}/workers`,body={url:url,procedureNames:procedureNames,trustKey:trustKey},options={method:"POST",headers:{"Content-Type":HeaderValues_APPLICATION_JSON},body:JSON.stringify(body)};await this.#callRemote(remoteUrl,options)}async run(request){request.setHeader(HeaderKeys_CONTENT_TYPE,HeaderValues_APPLICATION_JSON);const argsObject=Object.fromEntries(request.args),headersObject=Object.fromEntries(request.headers),versionString=request.version.toString();headersObject[HeaderKeys_JITAR_PROCEDURE_VERSION]=versionString;const remoteUrl=`${this.#url}/rpc/${request.fqn}`,options={method:"POST",redirect:"manual",headers:headersObject,body:await this.#createRequestBody(argsObject)},response=await this.#callRemote(remoteUrl,options,!1),status=response.status,result=await this.#getResponseResult(response),headers=this.#createResponseHeaders(response);return new Response(status,result,headers)}async#callRemote(remoteUrl,options,throwOnError=!0){const response=await fetch(remoteUrl,options);if(throwOnError&&this.#isErrorResponse(response)){const result=await this.#getResponseResult(response);throw this.#errorConverter.fromStatus(response.status,String(result))}return response}#isErrorResponse(response){return response.status<200||response.status>399}async#createRequestBody(body){return JSON.stringify(body)}async#getResponseResult(response){const contentType=response.headers.get(HeaderKeys_JITAR_CONTENT_TYPE)??response.headers.get(HeaderKeys_CONTENT_TYPE);if(contentType?.includes("undefined"))return;if(contentType?.includes("null"))return null;if(contentType?.includes("json"))return response.json();const content=await response.text();return contentType?.includes("boolean")?"true"===content:contentType?.includes("number")?Number(content):content}#createResponseHeaders(response){const headers=new Map;for(const[name,value]of response.headers)headers.set(name,value);return headers}}class HttpRemoteBuilder{build(url){return new HttpRemote(url)}}export{ArrayParameter,BadRequest,Class,ClientBuilder,Forbidden,HttpRemoteBuilder,Implementation,NamedParameter,NotFound,NotImplemented,ObjectParameter,PaymentRequired,Procedure,Request,Response,Segment,ServerError,Teapot,Unauthorized,Version};
1
+ class BadRequest extends Error{constructor(message="Invalid request"){super(message)}}class Forbidden extends Error{constructor(message="Forbidden"){super(message)}}class NotFound extends Error{constructor(message="Not found"){super(message)}}class NotImplemented extends Error{constructor(message="Not implemented"){super(message)}}class PaymentRequired extends Error{constructor(message="Payment required"){super(message)}}class ServerError extends Error{constructor(message="Server error"){super(message)}}class Teapot extends Error{constructor(message="I'm a teapot"){super(message)}}class Unauthorized extends Error{constructor(message="Unauthorized"){super(message)}}const AccessLevels_PRIVATE="private",AccessLevels_PROTECTED="protected",AccessLevels_PUBLIC="public",RunModes_NORMAL="normal",RunModes_DRY="dry",StatusCodes_OK=200,StatusCodes_BAD_REQUEST=400,StatusCodes_UNAUTHORIZED=401,StatusCodes_PAYMENT_REQUIRED=402,StatusCodes_FORBIDDEN=403,StatusCodes_NOT_FOUND=404,StatusCodes_TEAPOT=418,StatusCodes_SERVER_ERROR=500,StatusCodes_NOT_IMPLEMENTED=501;class InvalidVersionNumber extends BadRequest{#number;constructor(number){super(`Invalid version number '${number}'`),this.#number=number}get number(){return this.#number}}class ProcedureNotFound extends NotFound{#fqn;constructor(fqn){super(`Procedure '${fqn}' not found`),this.#fqn=fqn}get fqn(){return this.#fqn}}class ProcedureNotAccessible extends Forbidden{constructor(fqn,versionNumber){super(`Procedure '${fqn}' (v${versionNumber}) is not accessible`)}}class Segment{#id;#classes=new Map;#procedures=new Map;constructor(id){this.#id=id}get id(){return this.#id}addClass(clazz){return this.#classes.set(clazz.fqn,clazz),this}hasClass(fqn){return void 0!==this.getClass(fqn)}getClass(fqn){return this.#classes.get(fqn)}getClassByImplementation(implementation){return this.getClasses().find((clazz=>clazz.implementation===implementation))}getClasses(){return[...this.#classes.values()]}addProcedure(procedure){return this.#procedures.set(procedure.fqn,procedure),this}hasProcedure(fqn){return this.#procedures.has(fqn)}getProcedure(fqn){return this.#procedures.get(fqn)}getExposedProcedures(){return[...this.#procedures.values()].filter((procedure=>procedure.public||procedure.protected))}}class Class{#fqn;#implementation;constructor(fqn,implementation){this.#fqn=fqn,this.#implementation=implementation}get fqn(){return this.#fqn}get implementation(){return this.#implementation}}class Version{static get DEFAULT(){return new Version(0,0,0)}#major;#minor;#patch;constructor(major=0,minor=0,patch=0){this.#major=major,this.#minor=minor,this.#patch=patch}get major(){return this.#major}get minor(){return this.#minor}get patch(){return this.#patch}equals(version){return this.#major===version.major&&this.#minor===version.minor&&this.#patch===version.patch}greater(version){return this.#major!==version.major?this.#major>version.major:this.#minor!==version.minor?this.#minor>version.minor:this.#patch!==version.patch&&this.#patch>version.patch}less(version){return this.#major!==version.major?this.#major<version.major:this.#minor!==version.minor?this.#minor<version.minor:this.#patch!==version.patch&&this.#patch<version.patch}toString(){return`${this.#major}.${this.#minor}.${this.#patch}`}}class Procedure{#fqn;#implementations=new Map;#latestImplementation;constructor(fqn){this.#fqn=fqn}get fqn(){return this.#fqn}get public(){return[...this.#implementations.values()].some((implementation=>implementation.public))}get protected(){return[...this.#implementations.values()].some((implementation=>implementation.protected))}addImplementation(implementation){return this.#implementations.set(implementation.version,implementation),this.#isNewLatestImplementation(implementation)&&(this.#latestImplementation=implementation),this}#isNewLatestImplementation(implementation){return void 0===this.#latestImplementation||implementation.version.greater(this.#latestImplementation.version)}getImplementation(version){const selectedVersion=this.#selectAvailableVersion(version);return this.#implementations.get(selectedVersion)}#selectAvailableVersion(version){let selectedVersion=Version.DEFAULT;for(const implementationVersion of this.#implementations.keys()){if(implementationVersion.equals(version))return implementationVersion;implementationVersion.greater(version)||selectedVersion.less(implementationVersion)&&(selectedVersion=implementationVersion)}return selectedVersion}}class Implementation{#version;#access;#parameters;#executable;constructor(version,access,parameters,executable){this.#version=version,this.#access=access,this.#parameters=parameters,this.#executable=executable}get version(){return this.#version}get public(){return this.#access===AccessLevels_PUBLIC}get protected(){return this.#access===AccessLevels_PROTECTED}get private(){return this.#access===AccessLevels_PRIVATE}get parameters(){return this.#parameters}get executable(){return this.#executable}}class Parameter{#name;#isOptional;constructor(name,isOptional=!1){this.#name=name,this.#isOptional=isOptional}get name(){return this.#name}get isOptional(){return this.#isOptional}}class NamedParameter extends Parameter{}class DestructuredParameter extends Parameter{#variables;constructor(variables,name,isOptional){super(name??"(anonymous)",isOptional),this.#variables=variables}get variables(){return this.#variables}}class ArrayParameter extends DestructuredParameter{}class ObjectParameter extends DestructuredParameter{}class Request{#fqn;#version;#args;#headers=new Map;#mode;constructor(fqn,version,args,headers,mode){this.#fqn=fqn,this.#version=version,this.#args=args,this.#headers=headers,this.#mode=mode}get fqn(){return this.#fqn}get version(){return this.#version}get args(){return this.#args}get headers(){return this.#headers}get mode(){return this.#mode}clearArguments(){this.#args.clear()}setArgument(name,value){this.#args.set(name,value)}getArgument(name){return this.#args.get(name)}hasArgument(name){return this.#args.has(name)}removeArgument(name){this.#args.delete(name)}clearHeaders(){this.#headers.clear()}setHeader(name,value){this.#headers.set(name.toLowerCase(),value)}getHeader(name){return this.#headers.get(name.toLowerCase())}hasHeader(name){return this.#headers.has(name.toLowerCase())}removeHeader(name){this.#headers.delete(name.toLowerCase())}}class Response{#status;#result;#headers;constructor(status,result=void 0,headers=new Map){this.#status=status,this.#result=result,this.#headers=headers}get status(){return this.#status}get result(){return this.#result}set result(value){this.#result=value}get headers(){return this.#headers}clearHeaders(){this.#headers.clear()}setHeader(name,value){this.#headers.set(name.toLowerCase(),value)}getHeader(name){return this.#headers.get(name.toLowerCase())}hasHeader(name){return this.#headers.has(name.toLowerCase())}removeHeader(name){this.#headers.delete(name.toLowerCase())}}class UnknownParameter extends BadRequest{#parameterName;constructor(parameterName){super(`Unknown parameter ${parameterName}`),this.#parameterName=parameterName}get parameterName(){return this.#parameterName}}class MissingParameterValue extends BadRequest{#parameterName;constructor(parameterName){super(`Missing value for parameter '${parameterName}'`),this.#parameterName=parameterName}get parameterName(){return this.#parameterName}}class InvalidParameterValue extends BadRequest{#parameterName;constructor(parameterName){super(`Invalid value for parameter '${parameterName}'`),this.#parameterName=parameterName}get parameterName(){return this.#parameterName}}class ArgumentExtractor{extract(parameters,args){const argsCopy=this.#copyArguments(parameters,args),values=[];for(const parameter of parameters){const value=this.#extractArgumentValue(parameter,argsCopy);values.push(value)}if(argsCopy.size>0){const name=argsCopy.keys().next().value;throw new UnknownParameter(name)}return values}#copyArguments(parameters,args){const copy=new Map;for(const[key,value]of args)if(this.#isOptionalArgument(key)){const name=this.#getParameterName(key);!0===this.#containsParameter(parameters,name)&&copy.set(name,value)}else copy.set(key,value);return copy}#isOptionalArgument(argument){return argument.startsWith("*")}#getParameterName(argument){return argument.substring(1)}#containsParameter(parameters,name){return void 0!==parameters.find((parameter=>parameter.name===name))}#extractArgumentValue(parameter,args,parent){return parameter instanceof NamedParameter?this.#extractNamedArgumentValue(parameter,args,parent):this.#extractDestructedArgumentValue(parameter,args)}#extractNamedArgumentValue(parameter,args,parent){const value=args.get(parameter.name);if(this.#isMissingParameterValue(parameter,value,parent))throw new MissingParameterValue(parameter.name);if(this.#isInvalidRestParameter(parameter,value,parent))throw new InvalidParameterValue(parameter.name);return args.delete(parameter.name),value}#extractDestructedArgumentValue(parameter,args){return parameter instanceof ArrayParameter?this.#extractArrayArgumentValue(parameter,args):this.#extractObjectArgumentValue(parameter,args)}#extractArrayArgumentValue(parameter,args){const values=this.#extractVariableValues(parameter,args);return void 0!==values?Object.values(values):void 0}#extractObjectArgumentValue(parameter,args){return this.#extractVariableValues(parameter,args)}#extractVariableValues(parameter,args){const useIndex=parameter instanceof ArrayParameter,values={},missingValues=[];let containsValues=!1,index=0;for(const variable of parameter.variables){const key=useIndex?index++:variable.name,value=this.#extractArgumentValue(variable,args,parameter);void 0!==value?containsValues=!0:!1===variable.isOptional&&missingValues.push(variable.name),values[key]=value}if(!0===containsValues&&missingValues.length>0)throw new MissingParameterValue(missingValues[0]);return containsValues?values:void 0}#isMissingParameterValue(parameter,value,parent){return void 0===value&&(!0!==parameter.isOptional&&!0!==parent?.isOptional)}#isInvalidRestParameter(parameter,value,parent){return!1!==parameter.name.startsWith("...")&&(void 0===parent&&value instanceof Array==!1||parent instanceof ArrayParameter&&value instanceof Array==!1||parent instanceof ObjectParameter&&value instanceof Object==!1)}}class ErrorConverter{toStatus(error){return error instanceof BadRequest?StatusCodes_BAD_REQUEST:error instanceof Forbidden?StatusCodes_FORBIDDEN:error instanceof NotFound?StatusCodes_NOT_FOUND:error instanceof NotImplemented?StatusCodes_NOT_IMPLEMENTED:error instanceof PaymentRequired?StatusCodes_PAYMENT_REQUIRED:error instanceof Teapot?StatusCodes_TEAPOT:error instanceof Unauthorized?StatusCodes_UNAUTHORIZED:StatusCodes_SERVER_ERROR}fromStatus(status,message){switch(status){case StatusCodes_BAD_REQUEST:return new BadRequest(message);case StatusCodes_FORBIDDEN:return new Forbidden(message);case StatusCodes_NOT_FOUND:return new NotFound(message);case StatusCodes_NOT_IMPLEMENTED:return new NotImplemented(message);case StatusCodes_PAYMENT_REQUIRED:return new PaymentRequired(message);case StatusCodes_TEAPOT:return new Teapot(message);case StatusCodes_UNAUTHORIZED:return new Unauthorized(message);default:return new ServerError(message)}}}const VERSION_EXPRESSION=/^\d+(?:\.\d+){0,2}$/;class VersionParser{parse(number){if(0===number.trim().length)return Version.DEFAULT;if(!1===VERSION_EXPRESSION.test(number))throw new InvalidVersionNumber(number);const parts=number.split(".");switch(parts.length){case 1:return new Version(Number.parseInt(parts[0]));case 2:return new Version(Number.parseInt(parts[0]),Number.parseInt(parts[1]));default:return new Version(Number.parseInt(parts[0]),Number.parseInt(parts[1]),Number.parseInt(parts[2]))}}}class ImplementationNotFound extends NotFound{#fqn;#version;constructor(fqn,version){super(`No implementation found for procedure '${fqn}' with version '${version}'`),this.#fqn=fqn,this.#version=version}get fqn(){return this.#fqn}get version(){return this.#version}}class InvalidSegment extends ServerError{constructor(){super("Invalid segment")}}class Application{#segments=new Map;addSegment(segment){this.#segments.set(segment.id,segment)}getClassNames(){const names=new Set;for(const segment of this.#segments.values()){segment.getClasses().forEach((clazz=>names.add(clazz.fqn)))}return[...names.values()]}hasClass(fqn){return this.getClassNames().includes(fqn)}getClass(fqn){for(const segment of this.#segments.values())if(segment.hasClass(fqn))return segment.getClass(fqn)}getClassByImplementation(implementation){for(const segment of this.#segments.values()){const clazz=segment.getClassByImplementation(implementation);if(void 0!==clazz)return clazz}}getProcedureNames(){const names=new Set;for(const segment of this.#segments.values()){segment.getExposedProcedures().forEach((procedure=>names.add(procedure.fqn)))}return[...names.values()]}hasProcedure(fqn){return this.getProcedureNames().includes(fqn)}getProcedure(fqn){for(const segment of this.#segments.values())if(segment.hasProcedure(fqn))return segment.getProcedure(fqn)}}class ExecutionManager{#argumentConstructor=new ArgumentExtractor;#errorConverter=new ErrorConverter;#application=new Application;async addSegment(segment){if(segment instanceof Segment==!1)throw new InvalidSegment;this.#application.addSegment(segment)}getClassNames(){return this.#application.getClassNames()}hasClass(fqn){return this.#application.hasClass(fqn)}getClass(fqn){return this.#application.getClass(fqn)}getClassByImplementation(implementation){return this.#application.getClassByImplementation(implementation)}getProcedureNames(){return this.#application.getProcedureNames()}hasProcedure(fqn){return this.#application.hasProcedure(fqn)}getProcedure(fqn){return this.#application.getProcedure(fqn)}async run(request){const implementation=this.#getImplementation(request.fqn,request.version),args=this.#argumentConstructor.extract(implementation.parameters,request.args);return request.mode===RunModes_DRY?new Response(StatusCodes_OK,void 0):this.#runImplementation(request,implementation,args)}#getImplementation(fqn,version){const procedure=this.#application.getProcedure(fqn);if(void 0===procedure)throw new ProcedureNotFound(fqn);const implementation=procedure.getImplementation(version);if(void 0===implementation)throw new ImplementationNotFound(procedure.fqn,version.toString());return implementation}async#runImplementation(request,implementation,args){try{const result=await implementation.executable.call(request,...args);return new Response(StatusCodes_OK,result)}catch(error){const status=this.#errorConverter.toStatus(error);return new Response(status,error)}}}class RemoteGateway{#url;#remote;constructor(configuration){this.#url=configuration.url,this.#remote=configuration.remote}get url(){return this.#url}get trustKey(){}start(){return this.#remote.connect()}stop(){return this.#remote.disconnect()}isHealthy(){return this.#remote.isHealthy()}getHealth(){return this.#remote.getHealth()}getProcedureNames(){throw new NotImplemented}hasProcedure(name){throw new NotImplemented}addWorker(worker){return this.#remote.addWorker(worker.url,worker.getProcedureNames(),worker.trustKey)}removeWorker(worker){return this.#remote.removeWorker(worker.id)}run(request){return this.#remote.run(request)}}class File{#location;#type;#content;constructor(location,type,content){this.#location=location,this.#type=type,this.#content=content}get location(){return this.#location}get type(){return this.#type}get content(){return this.#content}get size(){return this.#content.length}}class ClassNotFound extends Error{constructor(name){super(`The class '${name}' could not be found`)}}class InvalidClass extends Error{constructor(name){super(`The class '${name}' is invalid`)}}class NoDeserializerFound extends Error{constructor(type){super(`No deserializer found for value of type '${type}'`)}}class NoSerializerFound extends Error{constructor(type){super(`No serializer found for value of type '${type}'`)}}class Serializer{#serializers=[];addSerializer(serializer){serializer.parent=this,this.#serializers.unshift(serializer)}async serialize(value){const serializer=this.#serializers.find((serializer=>serializer.canSerialize(value)));if(void 0===serializer)throw new NoSerializerFound(typeof value);return serializer.serialize(value)}async deserialize(value){const serializer=this.#serializers.find((serializer=>serializer.canDeserialize(value)));if(void 0===serializer)throw new NoDeserializerFound(typeof value);return serializer.deserialize(value)}}class ParentSerializerNotSet extends Error{constructor(){super("Parent serializer not set")}}class ValueSerializer{#parent;set parent(parent){this.#parent=parent}serializeOther(value){if(void 0===this.#parent)throw new ParentSerializerNotSet;return this.#parent.serialize(value)}deserializeOther(value){if(void 0===this.#parent)throw new ParentSerializerNotSet;return this.#parent.deserialize(value)}}class ArraySerializer extends ValueSerializer{canSerialize(value){return value instanceof Array}canDeserialize(value){return value instanceof Array}async serialize(array){const values=[];for(const value of array)values.push(await this.serializeOther(value));return values}async deserialize(array){return Promise.all(array.map((async value=>this.deserializeOther(value))))}}class InvalidBigIntString extends Error{constructor(bigIntString){super(`Invalid BigInt string '${bigIntString}'`)}}class BigIntSerializer extends ValueSerializer{canSerialize(value){return"bigint"==typeof value}canDeserialize(value){const bigInt=value;return bigInt instanceof Object&&!0===bigInt.serialized&&"BigInt"===bigInt.name&&"string"==typeof bigInt.value}async serialize(bigInt){return{serialized:!0,name:"BigInt",value:bigInt.toString()}}async deserialize(object){try{return BigInt(object.value)}catch{throw new InvalidBigIntString(object.value)}}}class InvalidBufferString extends Error{constructor(bufferString){super(`Invalid Buffer string '${bufferString}'`)}}class BufferSerializer extends ValueSerializer{canSerialize(value){return value instanceof Buffer}canDeserialize(value){const buffer=value;return buffer instanceof Object&&!0===buffer.serialized&&"Buffer"===buffer.name&&"string"==typeof buffer.base64}async serialize(buffer){return{serialized:!0,name:"Buffer",base64:buffer.toString("base64")}}async deserialize(object){try{return Buffer.from(object.base64,"base64")}catch{throw new InvalidBufferString(object.base64)}}}class ESAlias{#name;#as;constructor(name,as){this.#name=name,this.#as=as}get name(){return this.#name}get as(){return this.#as}toString(){return`${this.#name} as ${this.#as}`}}class ESValue{#definition;constructor(definition){this.#definition=definition}get definition(){return this.#definition}toString(){return this.#definition}}class ESArray extends ESValue{}class ESMember{#name;#isStatic;#isPrivate;constructor(name,isStatic=!1,isPrivate=!1){this.#name=name,this.#isStatic=isStatic,this.#isPrivate=isPrivate}get name(){return this.#name}get isStatic(){return this.#isStatic}get isPrivate(){return this.#isPrivate}get isPublic(){return!1===this.#isPrivate}}class ESClass extends ESMember{#parentName;#scope;constructor(name,parentName,scope){super(name),this.#parentName=parentName,this.#scope=scope}get parentName(){return this.#parentName}get scope(){return this.#scope}get members(){return this.#scope.members}get declarations(){return this.#scope.declarations}get functions(){return this.#scope.functions}get getters(){return this.#scope.getters}get setters(){return this.#scope.setters}get generators(){return this.#scope.generators}get readable(){const members=new Map;return this.getters.forEach((getter=>{members.set(getter.name,getter)})),this.declarations.forEach((declaration=>{declaration.isPublic&&members.set(declaration.name,declaration)})),[...members.values()]}get writable(){const members=new Map;return this.setters.forEach((setter=>{members.set(setter.name,setter)})),this.declarations.forEach((declaration=>{declaration.isPublic&&members.set(declaration.name,declaration)})),[...members.values()]}get callable(){return this.functions.filter((funktion=>funktion.isPublic))}getMember(name){return this.#scope.getMember(name)}getDeclaration(name){return this.#scope.getDeclaration(name)}getFunction(name){return this.#scope.getFunction(name)}getGetter(name){return this.#scope.getGetter(name)}getSetter(name){return this.#scope.getSetter(name)}getGenerator(name){return this.#scope.getGenerator(name)}hasMember(name){return this.#scope.hasMember(name)}hasDeclaration(name){return this.#scope.hasDeclaration(name)}hasFunction(name){return this.#scope.hasFunction(name)}hasGetter(name){return this.#scope.hasGetter(name)}hasSetter(name){return this.#scope.hasSetter(name)}hasGenerator(name){return this.#scope.hasGenerator(name)}canRead(name){const declaration=this.getDeclaration(name);return declaration?.isPublic||this.hasGetter(name)}canWrite(name){const declaration=this.getDeclaration(name);return declaration?.isPublic||this.hasSetter(name)}canCall(name){const funktion=this.getFunction(name);return funktion?.isPublic??!1}toString(){const infix=void 0!==this.#parentName?` extends ${this.#parentName}`:"";return`class ${this.name}${infix} { ${this.#scope.toString()} }`}}class ESDeclaration extends ESMember{#identifier;#value;constructor(identifier,value,isStatic=!1,isPrivate=!1){super(identifier.toString(),isStatic,isPrivate),this.#identifier=identifier,this.#value=value}get identifier(){return this.#identifier}get value(){return this.#value}toString(){return`${this.name}${this.value?" = "+this.value.toString():""}`}}class ESDestructuredValue{#members;constructor(members){this.#members=members}get members(){return this.#members}toString(){return this.#members.map((member=>member.toString())).join(" , ")}}class ESDestructuredArray extends ESDestructuredValue{toString(){return`[ ${super.toString()} ]`}}class ESDestructuredObject extends ESDestructuredValue{toString(){return`{ ${super.toString()} }`}}class ESExport extends ESMember{#members;#from;constructor(members,from){super(""),this.#members=members,this.#from=from}get members(){return this.#members}get from(){return this.#from}hasMember(name){return this.#members.some((member=>member.as===name))}getMember(name){return this.#members.find((member=>member.as===name))}toString(){const postfix=this.#from?` from '${this.#from}'`:"";return`export { ${this.#members.join(", ")} }${postfix}`}}class ESExpression extends ESValue{}class ESField{#name;#value;constructor(name,value){this.#name=name,this.#value=value}get name(){return this.#name}get value(){return this.#value}toString(){return`${this.name}${this.value?" = "+this.value.toString():""}`}}class ESFunction extends ESMember{#parameters;#body;#isAsync;constructor(name,parameters,body,isStatic=!1,isAsync=!1,isPrivate=!1){super(name,isStatic,isPrivate),this.#parameters=parameters,this.#body=body,this.#isAsync=isAsync}get parameters(){return this.#parameters}get body(){return this.#body}get isAsync(){return this.#isAsync}toString(){const parameters=this.parameters.map((parameter=>parameter.toString()));return`${this.isAsync?"async ":""}${this.name}(${parameters.join(", ")}) { ${this.body} }`}}class ESGenerator extends ESFunction{toString(){const parameters=this.parameters.map((parameter=>parameter.toString()));return`${this.isAsync?"async ":""}${this.name}*(${parameters.join(", ")}) { ${this.body} }`}}class ESGetter extends ESFunction{toString(){return`get ${super.toString()}`}}class ESImport extends ESMember{#members;#from;constructor(members,from){super(""),this.#members=members,this.#from=from}get members(){return this.#members}get from(){return this.#from}hasMember(name){return this.#members.some((member=>member.as===name))}getMember(name){return this.#members.find((member=>member.as===name))}toString(){return`import { ${this.#members.map((member=>member.toString())).join(", ")} } from '${this.#from}';`}}class ESModule{#scope;constructor(scope){this.#scope=scope}get scope(){return this.#scope}get members(){return this.#scope.members}get exportedMembers(){return this.#filterExported(this.#scope.members)}get imports(){return this.#scope.imports}get exports(){return this.#scope.exports}get declarations(){return this.#scope.declarations}get exportedDeclarations(){return this.#filterExported(this.#scope.declarations)}get functions(){return this.#scope.functions}get exportedFunctions(){return this.#filterExported(this.#scope.functions)}get generators(){return this.#scope.generators}get exportedGenerators(){return this.#filterExported(this.#scope.generators)}get classes(){return this.#scope.classes}get exportedClasses(){return this.#filterExported(this.#scope.classes)}get exported(){const exported=new Map;for(const exportItem of this.exports)for(const alias of exportItem.members){const member=this.getMember(alias.name);void 0!==member&&exported.set(alias.as,member)}return exported}getMember(name){return this.#scope.getMember(name)}getDeclaration(name){return this.#scope.getDeclaration(name)}getFunction(name){return this.#scope.getFunction(name)}getGenerator(name){return this.#scope.getGenerator(name)}getClass(name){return this.#scope.getClass(name)}hasMember(name){return this.#scope.hasMember(name)}hasDeclaration(name){return this.#scope.hasDeclaration(name)}hasFunction(name){return this.#scope.hasFunction(name)}hasGenerator(name){return this.#scope.hasGenerator(name)}hasClass(name){return this.#scope.hasClass(name)}getImport(name){return this.imports.find((importItem=>importItem.hasMember(name)))}getImported(name){for(const importItem of this.imports)for(const alias of importItem.members)if(alias.as===name)return this.getMember(alias.name)}isExported(member){for(const exportItem of this.exports)for(const alias of exportItem.members)if(alias.name===member.name)return!0;return!1}getExport(name){return this.exports.find((exportItem=>exportItem.hasMember(name)))}getExported(name){for(const exportItem of this.exports)for(const alias of exportItem.members)if(alias.as===name)return this.getMember(alias.name)}#filterExported(members){return members.filter((member=>this.isExported(member)))}}class ESObject extends ESValue{}class ESSetter extends ESFunction{toString(){return`set ${super.toString()}`}}const IMPORT_NAME=ESImport.name,EXPORT_NAME=ESExport.name,DECLARATION_NAME=ESDeclaration.name,FUNCTION_NAME=ESFunction.name,GETTER_NAME=ESGetter.name,SETTER_NAME=ESSetter.name,GENERATOR_NAME=ESGenerator.name,CLASS_NAME=ESClass.name;class ESScope{#members;constructor(members){this.#members=members}get members(){return this.#members}get imports(){return this.#members.filter((member=>member.constructor.name===IMPORT_NAME))}get exports(){return this.#members.filter((member=>member.constructor.name===EXPORT_NAME))}get declarations(){return this.#members.filter((member=>member.constructor.name===DECLARATION_NAME))}get functions(){return this.#members.filter((member=>member.constructor.name===FUNCTION_NAME))}get getters(){return this.#members.filter((member=>member.constructor.name===GETTER_NAME))}get setters(){return this.#members.filter((member=>member.constructor.name===SETTER_NAME))}get generators(){return this.#members.filter((member=>member.constructor.name===GENERATOR_NAME))}get classes(){return this.#members.filter((member=>member.constructor.name===CLASS_NAME))}getMember(name){return this.#members.find((member=>member.name===name))}getDeclaration(name){return this.declarations.find((member=>member.name===name))}getFunction(name){return this.functions.find((member=>member.name===name))}getGetter(name){return this.getters.find((member=>member.name===name))}getSetter(name){return this.setters.find((member=>member.name===name))}getGenerator(name){return this.generators.find((member=>member.name===name))}getClass(name){return this.classes.find((member=>member.name===name))}hasMember(name){return void 0!==this.getMember(name)}hasDeclaration(name){return void 0!==this.getDeclaration(name)}hasFunction(name){return void 0!==this.getFunction(name)}hasGetter(name){return void 0!==this.getGetter(name)}hasSetter(name){return void 0!==this.getSetter(name)}hasGenerator(name){return void 0!==this.getGenerator(name)}hasClass(name){return void 0!==this.getClass(name)}toString(){return this.#members.map((member=>member.toString())).join("\n")}}const Comment={SINGLE:"//",MULTI_START:"/*",MULTI_END:"*/"},Comments=Object.values(Comment);const Punctuation_DOT=".",Punctuation_LEFT_PARENTHESIS="(",Punctuation_RIGHT_PARENTHESIS=")",Punctuation_LEFT_BRACKET="[",Punctuation_RIGHT_BRACKET="]",Punctuation_LEFT_BRACE="{",Punctuation_RIGHT_BRACE="}",Divider={SCOPE:":",SEPARATOR:",",TERMINATOR:";"},Divisions=Object.values(Divider);function isDivider(value){return Divisions.includes(value)}const Empty={UNDEFINED:void 0,NULL:null,STRING:""},Empties=Object.values(Empty);function isEmpty(value){return Empties.includes(value)}const Group={OPEN:Punctuation_LEFT_PARENTHESIS,CLOSE:Punctuation_RIGHT_PARENTHESIS};function isGroup(value){return value===Group.OPEN||value===Group.CLOSE}const Keyword={EXPORT:"export",DEFAULT:"default",CLASS:"class",FUNCTION:"function",CONST:"const",LET:"let",VAR:"var",AS:"as",FROM:"from",IMPORT:"import",GET:"get",SET:"set",EXTENDS:"extends",STATIC:"static",ASYNC:"async",RETURN:"return"},Keywords=Object.values(Keyword);function isKeyword(value){return Keywords.includes(value)}function isNotReserved(value){return value===Keyword.AS||value===Keyword.ASYNC||value===Keyword.FROM||value===Keyword.GET||value===Keyword.SET}const List={OPEN:Punctuation_LEFT_BRACKET,CLOSE:Punctuation_RIGHT_BRACKET};function isList(value){return value===List.OPEN||value===List.CLOSE}const Literals=Object.values({SINGLE:"'",DOUBLE:'"',BACKTICK:"`"});function isLiteral(value){return Literals.includes(value)}const Operator={ADD:"+",ARROW:"=>",ASSIGN:"=",ASSIGN_ADD:"+=",ASSIGN_BITWISE_AND:"&=",ASSIGN_BITWISE_OR:"|=",ASSIGN_DIVIDE:"/=",ASSIGN_LEFT_SHIFT:"<<=",ASSIGN_LOGICAL_AND:"&&=",ASSIGN_LOGICAL_OR:"||=",ASSIGN_MODULO:"%=",ASSIGN_MULTIPLY:"*=",ASSIGN_RIGHT_SHIFT:">>=",ASSIGN_SUBTRACT:"-=",ASSIGN_XOR:"^=",BITWISE_AND:"&",BITWISE_OR:"|",DECREMENT:"--",DIVIDE:"/",EQUAL:"==",EQUAL_STRICT:"===",GREATER:">",GREATER_EQUAL:">=",INCREMENT:"++",LEFT_SHIFT:"<<",LESS:"<",LESS_EQUAL:"<=",LOGICAL_AND:"&&",LOGICAL_OR:"||",MODULO:"%",MULTIPLY:"*",NOT:"!",NOT_EQUAL:"!=",NOT_EQUAL_STRICT:"!==",RIGHT_SHIFT:">>",SUBTRACT:"-",TERNARY:"?",XOR:"^"},Operators=Object.values(Operator);function isOperator(value){return Operators.includes(value)}const Scope={OPEN:Punctuation_LEFT_BRACE,CLOSE:Punctuation_RIGHT_BRACE};function isScope(value){return value===Scope.OPEN||value===Scope.CLOSE}const TokenType={COMMENT:"comment",DIVIDER:"divider",GROUP:"group",IDENTIFIER:"identifier",KEYWORD:"keyword",LIST:"list",LITERAL:"literal",OPERATOR:"operator",REGEX:"regex",SCOPE:"scope",WHITESPACE:"whitespace"},Whitespace={SPACE:" ",TAB:"\t",NEWLINE:"\n",CARRIAGE_RETURN:"\r"},Whitespaces=Object.values(Whitespace);function isWhitespace(value){return Whitespaces.includes(value)}class ItemList{#items;#position;constructor(items){this.#items=items,this.#position=0}get items(){return this.#items}get position(){return this.#position}get size(){return this.#items.length}get eol(){return this.#position>=this.#items.length}get current(){return this.#items[this.#position]}get next(){return this.#items[this.#position+1]}get previous(){return this.#items[this.#position-1]}notAtEnd(){return!1===this.eol}get(index){return this.#items[index]}step(amount=1){return this.#position+=amount,this.current}stepBack(amount=1){return this.#position-=amount,this.current}hasNext(){return this.#position+1<this.#items.length}}class CharList extends ItemList{constructor(code){super(code.split(""))}}class Token{#type;#value;#start;#end;constructor(type,value,start,end){this.#type=type,this.#value=value,this.#start=start,this.#end=end}get type(){return this.#type}get value(){return this.#value}get start(){return this.#start}get end(){return this.#end}isType(type){return this.#type===type}hasValue(value){return this.#value===value}toString(){return`${this.#value}`}}class TokenList extends ItemList{}class Lexer{tokenize(code){const charList=new CharList(code),tokens=[];let last;for(;charList.notAtEnd();){const token=this.#getNextToken(charList,last);if(void 0===token)break;token.isType(TokenType.WHITESPACE)||token.isType(TokenType.COMMENT)?charList.step():(tokens.push(token),this.#isCodeToken(token)&&(last=token),charList.step())}return new TokenList(tokens)}#isCodeToken(token){return!1===[TokenType.WHITESPACE,TokenType.COMMENT].includes(token.type)}#getNextToken(charList,lastToken){const char=charList.current,start=charList.position;if(isWhitespace(char)){const end=charList.position;return new Token(TokenType.WHITESPACE,char,start,end)}if(function(value){return Comments.includes(value)}(char+charList.next)){const value=this.#readComment(charList),end=charList.position;return new Token(TokenType.COMMENT,value,start,end)}if(this.#startsRegex(char,lastToken)){const value=this.#readRegex(charList),end=charList.position;return new Token(TokenType.REGEX,value,start,end)}if(isLiteral(char)){const value=this.#readLiteral(charList),end=charList.position;return new Token(TokenType.LITERAL,value,start,end)}if(isOperator(char)){const value=this.#readOperation(charList),end=charList.position;return new Token(TokenType.OPERATOR,value,start,end)}if(isDivider(char)){const end=charList.position;return new Token(TokenType.DIVIDER,char,start,end)}if(isGroup(char)){const end=charList.position;return new Token(TokenType.GROUP,char,start,end)}if(isScope(char)){const end=charList.position;return new Token(TokenType.SCOPE,char,start,end)}if(isList(char)){const end=charList.position;return new Token(TokenType.LIST,char,start,end)}if(isEmpty(char))return;const value=this.#readIdentifier(charList),type=isKeyword(value)?TokenType.KEYWORD:TokenType.IDENTIFIER,end=charList.position;return new Token(type,value,start,end)}#readComment(charList){const isMulti=charList.current+charList.next===Comment.MULTI_START,terminator=isMulti?Comment.MULTI_END:Whitespace.NEWLINE;let value=isMulti?Comment.MULTI_START:Comment.SINGLE;for(charList.step(2);charList.notAtEnd();){const char=charList.current;if((isMulti?char+charList.next:char)===terminator){charList.step(terminator.length-1);break}value+=char,charList.step()}return isMulti?value+Comment.MULTI_END:value.trim()}#startsRegex(char,lastToken){return char===Operator.DIVIDE&&(void 0===lastToken||([TokenType.OPERATOR,TokenType.DIVIDER,TokenType.KEYWORD].includes(lastToken.type)||[Group.OPEN,List.OPEN].includes(lastToken.value)))}#endsRegex(char){return isWhitespace(char)||char==Punctuation_DOT||!1===this.#isIdentifier(char)}#readRegex(charList){let value=charList.current,closed=!1;for(charList.step();charList.notAtEnd();){const current=charList.current,previous=charList.previous;if(current===Operator.DIVIDE&&"\\"!==previous)closed=!0;else if(!0===closed&&this.#endsRegex(current)){charList.stepBack();break}value+=current,charList.step()}return value}#readLiteral(charList){const identifier=charList.current;let value=identifier,escaped=!1;for(charList.step();charList.notAtEnd();){const char=charList.current;if(!1===escaped){if(char===identifier){value+=char;break}"\\"===char&&(escaped=!0)}else escaped=!1;value+=char,charList.step()}return value}#isIdentifier(char){return!1===(isEmpty(char)||isWhitespace(char)||isOperator(char)||isLiteral(char)||isDivider(char)||isGroup(char)||isScope(char)||isList(char))}#readIdentifier(charList){let value="";for(;charList.notAtEnd();){const char=charList.current;if(!1===this.#isIdentifier(char)){charList.stepBack();break}value+=char,charList.step()}return value}#readOperation(charList){let value=charList.current;for(charList.step();charList.notAtEnd();){const char=charList.current;if(!1===isOperator(char)||!1===isOperator(value+char)){charList.stepBack();break}value+=char,charList.step()}return value}}class ExpectedKeyword extends Error{constructor(value,position){super(`Expected keyword '${value}' at position ${position}`)}}class ExpectedToken extends Error{constructor(value,position){super(`Expected token '${value}' at position ${position}`)}}class UnexpectedKeyword extends Error{constructor(keyword,position){super(`Unexpected keyword '${keyword}' at position ${position}`)}}class UnexpectedParseResult extends Error{constructor(expected){super(`The given code does not contain ${expected}`)}}class UnexpectedToken extends Error{constructor(value,position){super(`Unexpected token '${value}' at position ${position}`)}}class Parser{#lexer;constructor(lexer=new Lexer){this.#lexer=lexer}parse(code){const tokenList=this.#lexer.tokenize(code),scope=this.#parseScope(tokenList);return new ESModule(scope)}parseFirst(code){const tokenList=this.#lexer.tokenize(code);return this.#parseNext(tokenList)}parseValue(code){const model=this.parseFirst(code);if(model instanceof ESValue==!1)throw new UnexpectedParseResult("a value definition");return model}parseImport(code){const model=this.parseFirst(code);if(model instanceof ESImport==!1)throw new UnexpectedParseResult("an import definition");return model}parseExport(code){const model=this.parseFirst(code);if(model instanceof ESExport==!1)throw new UnexpectedParseResult("an export definition");return model}parseDeclaration(code){const model=this.parseFirst(code);if(model instanceof ESDeclaration==!1)throw new UnexpectedParseResult("a declaration definition");return model}parseFunction(code){const tokenList=this.#lexer.tokenize(code),model=this.#parseMember(tokenList);if(model instanceof ESFunction==!1)throw new UnexpectedParseResult("a function definition");return model}parseClass(code){const tokenList=this.#lexer.tokenize(code),model=this.#parseMember(tokenList);if(model instanceof ESClass==!1)throw new UnexpectedParseResult("a class definition");return model}#parseScope(tokenList){const members=[];for(;tokenList.notAtEnd();){const member=this.#parseNext(tokenList);member instanceof ESMember&&members.push(member)}return new ESScope(members)}#parseNext(tokenList,isAsync=!1){const token=tokenList.current;if(token.isType(TokenType.LITERAL))return this.#parseExpression(tokenList);if(token.isType(TokenType.IDENTIFIER)){const next=tokenList.next;return next?.hasValue(Operator.ARROW)?this.#parseArrowFunction(tokenList,isAsync):this.#parseExpression(tokenList)}if(token.isType(TokenType.KEYWORD)){if(isNotReserved(token.value)){const next=tokenList.next,nextIsFunction=void 0!==next&&(next.hasValue(Keyword.FUNCTION)||next.hasValue(Group.OPEN));if(token.hasValue(Keyword.ASYNC)&&nextIsFunction)return tokenList.step(),this.#parseNext(tokenList,!0);if(void 0===next||this.#atEndOfStatement(next))return this.#parseExpression(tokenList)}return token.hasValue(Keyword.RETURN)?this.#parseExpression(tokenList):this.#parseMember(tokenList,isAsync)}if(token.isType(TokenType.REGEX))return this.#parseExpression(tokenList);if(token.hasValue(Group.OPEN)){const next=this.#peekAfterBlock(tokenList,Group.OPEN,Group.CLOSE);return next?.hasValue(Operator.ARROW)?this.#parseArrowFunction(tokenList,isAsync):this.#parseExpression(tokenList)}if(token.hasValue(Scope.OPEN))return this.#parseObject(tokenList);if(token.hasValue(List.OPEN))return this.#parseArray(tokenList);if(token.hasValue(Operator.NOT)||token.hasValue(Operator.SUBTRACT))return this.#parseExpression(tokenList);if(!isDivider(token.value))throw new UnexpectedToken(token.value,token.start);tokenList.step()}#parseMember(tokenList,isAsync=!1){const token=tokenList.current;switch(tokenList.step(),token.value){case Keyword.IMPORT:return this.#parseImport(tokenList);case Keyword.EXPORT:return this.#parseExport(tokenList);case Keyword.CLASS:return this.#parseClass(tokenList);case Keyword.FUNCTION:return this.#parseFunction(tokenList,isAsync);case Keyword.VAR:case Keyword.LET:case Keyword.CONST:return this.#parseDeclaration(tokenList,!1,!0);case Keyword.ASYNC:return this.#parseMember(tokenList,!0);default:throw new UnexpectedKeyword(token.value,token.start)}}#parseImport(tokenList){const members=[];let token=tokenList.current;if(token.isType(TokenType.LITERAL))return new ESImport(members,token.value);if(token.hasValue(Group.OPEN)){token=tokenList.step();const from=token.value;return tokenList.step(2),new ESImport(members,from)}if(!1===token.hasValue(Scope.OPEN)){const name=token.hasValue(Operator.MULTIPLY)?Operator.MULTIPLY:"default";let as=token.value;token=tokenList.step(),token.hasValue(Keyword.AS)&&(token=tokenList.step(),as=token.value,token=tokenList.step()),members.push(new ESAlias(name,as))}if(token.hasValue(Divider.SEPARATOR)&&(token=tokenList.step()),token.hasValue(Scope.OPEN)){const aliases=this.#parseAliasList(tokenList);members.push(...aliases),token=tokenList.current}if(!1===token.hasValue(Keyword.FROM))throw new ExpectedKeyword(Keyword.FROM,token.start);token=tokenList.step();const from=token.value;return tokenList.step(),new ESImport(members,from)}#parseExport(tokenList){switch(tokenList.current.value){case Keyword.DEFAULT:return tokenList.step(),this.#parseSingleExport(tokenList,!0);case Scope.OPEN:return this.#parseMultiExport(tokenList);default:return this.#parseSingleExport(tokenList,!1)}}#parseSingleExport(tokenList,isDefault){let token=tokenList.current,stepSize=0;var value;token.hasValue(Keyword.ASYNC)&&(token=tokenList.step(),stepSize++),((value=token.value)===Keyword.CLASS||value===Keyword.FUNCTION||value===Keyword.CONST||value===Keyword.LET||value===Keyword.VAR)&&(token=tokenList.step(),stepSize++);const name=this.#isIdentifier(token)?token.value:"",as=isDefault?"default":name;let from;token=tokenList.step(),token?.hasValue(Keyword.FROM)&&(token=tokenList.step(),from=token.value),stepSize>0&&(stepSize++,tokenList.stepBack(stepSize));const alias=new ESAlias(name,as);return new ESExport([alias],from)}#parseMultiExport(tokenList){const members=this.#parseAliasList(tokenList);let from,token=tokenList.current;return token?.hasValue(Keyword.FROM)&&(token=tokenList.step(),from=token.value),tokenList.step(),new ESExport(members,from)}#parseAliasList(tokenList){const aliases=[];let token=tokenList.step();for(;tokenList.notAtEnd();){if(token.hasValue(Scope.CLOSE)){tokenList.step();break}if(token.hasValue(Divider.SEPARATOR)){token=tokenList.step();continue}const alias=this.#parseAlias(tokenList);aliases.push(alias),token=tokenList.step()}return aliases}#parseAlias(tokenList){let token=tokenList.current;const name=token.value;let as=name;return tokenList.next.hasValue(Keyword.AS)&&(token=tokenList.step(2),as=token.value),new ESAlias(name,as)}#parseDeclaration(tokenList,isStatic,parseMultiple=!1){let identifier,value,token=tokenList.current,isPrivate=!1;return token.hasValue(List.OPEN)?(identifier=this.#parseDestructuredArray(tokenList),token=tokenList.current):token.hasValue(Scope.OPEN)?(identifier=this.#parseDestructuredObject(tokenList),token=tokenList.current):(isPrivate=token.value.startsWith("#"),identifier=isPrivate?token.value.substring(1):token.value,token=tokenList.step()),token.hasValue(Operator.ASSIGN)&&(tokenList.step(),value=this.#parseNext(tokenList,!1),token=tokenList.current),void 0!==token&&(token.hasValue(Divider.TERMINATOR)?tokenList.step():!0===parseMultiple&&token.hasValue(Divider.SEPARATOR)&&(tokenList.step(),this.#parseDeclaration(tokenList,isStatic,!0))),value instanceof ESGenerator?new ESGenerator(identifier.toString(),value.parameters,value.body,isStatic,value.isAsync,isPrivate):value instanceof ESFunction?new ESFunction(identifier.toString(),value.parameters,value.body,isStatic,value.isAsync,isPrivate):value instanceof ESClass?new ESClass(identifier.toString(),value.parentName,value.scope):new ESDeclaration(identifier,value,isStatic,isPrivate)}#parseFunction(tokenList,isAsync,isStatic=!1,isGetter=!1,isSetter=!1){let token=tokenList.current,name="",isGenerator=!1,isPrivate=!1;token.hasValue(Operator.MULTIPLY)&&(isGenerator=!0,token=tokenList.step()),this.#isIdentifier(token)&&(isPrivate=token.value.startsWith("#"),name=isPrivate?token.value.substring(1):token.value,token=tokenList.step());const parameters=this.#parseParameters(tokenList,Group.CLOSE);if(token=tokenList.current,!1===token.hasValue(Scope.OPEN))throw new ExpectedToken(Scope.OPEN,token.start);const body=this.#parseBlock(tokenList,Scope.OPEN,Scope.CLOSE);return isGenerator?new ESGenerator(name,parameters,body,isStatic,isAsync,isPrivate):isGetter?new ESGetter(name,parameters,body,isStatic,isAsync,isPrivate):isSetter?new ESSetter(name,parameters,body,isStatic,isAsync,isPrivate):new ESFunction(name,parameters,body,isStatic,isAsync,isPrivate)}#parseArrowFunction(tokenList,isAsync){let parameters,token=tokenList.current;if(token.hasValue(Group.OPEN)?(parameters=this.#parseParameters(tokenList,Group.CLOSE),token=tokenList.current):(parameters=[new ESField(token.value,void 0)],token=tokenList.step()),!1===token.hasValue(Operator.ARROW))throw new ExpectedToken(Operator.ARROW,token.start);token=tokenList.step();const body=token.hasValue(Scope.OPEN)?this.#parseBlock(tokenList,Scope.OPEN,Scope.CLOSE):this.#parseExpression(tokenList).definition;return new ESFunction("",parameters,body,!1,isAsync,!1)}#parseParameters(tokenList,closeId){const parameters=[];for(tokenList.step();tokenList.notAtEnd();){const token=tokenList.current;if(token.hasValue(closeId)){tokenList.step();break}if(token.hasValue(Divider.SEPARATOR)){tokenList.step();continue}let parameter;parameter=token.hasValue(Scope.OPEN)?this.#parseDestructuredObject(tokenList):token.hasValue(List.OPEN)?this.#parseDestructuredArray(tokenList):this.#parseField(tokenList),parameters.push(parameter)}return parameters}#parseClass(tokenList){let parent,token=tokenList.current,name="";if(this.#isIdentifier(token)&&(name=token.value,token=tokenList.step()),token.hasValue(Keyword.EXTENDS)&&(token=tokenList.step(),parent=token.value,token=tokenList.step()),!1===token.hasValue(Scope.OPEN))throw new ExpectedToken(Scope.OPEN,token.start);const scope=this.#parseClassScope(tokenList);return new ESClass(name,parent,scope)}#parseClassScope(tokenList){let token=tokenList.step();const members=[];for(;tokenList.notAtEnd();){if(token.hasValue(Scope.CLOSE)){tokenList.step();break}const member=this.#parseClassMember(tokenList);members.push(member),token=tokenList.current}return new ESScope(members)}#parseClassMember(tokenList){let token=tokenList.current,isAsync=!1,isStatic=!1,isGetter=!1,isSetter=!1;for(;tokenList.notAtEnd();){if(token.hasValue(Keyword.STATIC))isStatic=!0;else if(token.hasValue(Keyword.ASYNC))isAsync=!0;else if(token.hasValue(Keyword.GET))isGetter=!0;else{if(!token.hasValue(Keyword.SET)){if(token.hasValue(Operator.MULTIPLY))return this.#parseFunction(tokenList,isAsync,isStatic,!1,!1);break}isSetter=!0}token=tokenList.step()}return tokenList.next.hasValue(Group.OPEN)?this.#parseFunction(tokenList,isAsync,isStatic,isGetter,isSetter):this.#parseDeclaration(tokenList,isStatic)}#parseArray(tokenList){const items=this.#parseBlock(tokenList,List.OPEN,List.CLOSE);return new ESArray(items)}#parseDestructuredArray(tokenList){const fields=this.#parseParameters(tokenList,List.CLOSE);return new ESDestructuredArray(fields)}#parseObject(tokenList){const fields=this.#parseBlock(tokenList,Scope.OPEN,Scope.CLOSE);return new ESObject(fields)}#parseDestructuredObject(tokenList){const fields=this.#parseParameters(tokenList,Scope.CLOSE);return new ESDestructuredObject(fields)}#parseField(tokenList){let token=tokenList.current;const name=token.value;let value;return token=tokenList.step(),token.hasValue(Operator.ASSIGN)&&(tokenList.step(),value=this.#parseNext(tokenList,!1)),new ESField(name,value)}#parseExpression(tokenList){let token=tokenList.current,code="";for(;tokenList.notAtEnd();){if(token.hasValue(List.OPEN)){code+=this.#parseBlock(tokenList,List.OPEN,List.CLOSE)+" ",token=tokenList.current}else if(token.hasValue(Group.OPEN)){code+=this.#parseBlock(tokenList,Group.OPEN,Group.CLOSE)+" ",token=tokenList.current}else if(token.hasValue(Scope.OPEN)){code+=this.#parseBlock(tokenList,Scope.OPEN,Scope.CLOSE)+" ",token=tokenList.current}else code+=token.toString()+" ",token=tokenList.step();if(void 0===token||this.#atEndOfStatement(token))break}return new ESExpression(code.trim())}#parseBlock(tokenList,openId,closeId){let token=tokenList.step(),code=openId+" ";for(;tokenList.notAtEnd();)if(token.hasValue(openId))code+=this.#parseBlock(tokenList,openId,closeId)+" ",token=tokenList.current;else{if(token.hasValue(closeId))return tokenList.step(),code+=closeId,code;code+=token.toString()+" ",token=tokenList.step()}return code}#peekAfterBlock(tokenList,openId,closeId){const start=tokenList.position;this.#parseBlock(tokenList,openId,closeId);const token=tokenList.current,end=tokenList.position;return tokenList.stepBack(end-start),token}#atEndOfStatement(token){return[Divider.TERMINATOR,Divider.SEPARATOR].includes(token.value)||[List.CLOSE,Group.CLOSE,Scope.CLOSE].includes(token.value)||isKeyword(token.value)}#isIdentifier(token){return token.isType(TokenType.IDENTIFIER)||token.isType(TokenType.KEYWORD)&&isNotReserved(token.value)}}class ClassMerger{merge(model,parent){const declarations=this.#mergeDeclarations(model.declarations,parent.declarations),functions=this.#mergeFunctions(model.functions,parent.functions),getters=this.#mergeFunctions(model.getters,parent.getters),setters=this.#mergeFunctions(model.setters,parent.setters),members=[...declarations.values(),...functions.values(),...getters.values(),...setters.values()];return new ESClass(model.name,parent.name,new ESScope(members))}#mergeDeclarations(model,parent){const declarations=new Map;return parent.forEach((declaration=>declarations.set(declaration.name,declaration))),model.forEach((declaration=>declarations.set(declaration.name,declaration))),[...declarations.values()]}#mergeFunctions(model,parent){const functions=new Map;return parent.forEach((funktion=>functions.set(funktion.name,funktion))),model.forEach((funktion=>functions.set(funktion.name,funktion))),[...functions.values()]}}class Reflector{#parser=new Parser;#merger=new ClassMerger;fromModule(module,inherit=!1){const entries=Object.entries(module),members=[];for(const[key,member]of entries){if("function"!=typeof member.toString)continue;const code=member.toString();if(code.startsWith("class"))members.push(this.fromClass(member,inherit));else if(code.startsWith("function"))members.push(this.fromFunction(member));else{const expression=new ESExpression(code);members.push(new ESDeclaration(key,expression))}}return new ESModule(new ESScope(members))}fromClass(clazz,inherit=!1){const model=this.isClass(clazz)?this.#reflectStatic(clazz):this.#reflectDynamic(clazz);if(!1===inherit)return model;const parentClazz=this.getParentClass(clazz);if(""===parentClazz.name)return model;const parentModel=this.fromClass(parentClazz,!0);return this.#merger.merge(model,parentModel)}fromObject(object,inherit=!0){const clazz=this.getClass(object);return this.fromClass(clazz,inherit)}fromFunction(funktion){const code=funktion.toString();return this.#parser.parseFunction(code)}createInstance(clazz,args=[]){return new clazz(...args)}getClass(object){return object.constructor}getParentClass(clazz){return Object.getPrototypeOf(clazz)}isClassObject(object){return this.isClass(object.constructor)}isFunctionObject(object){return this.isFunction(object.constructor)}isClass(clazz){return clazz.toString().startsWith("class")}isFunction(clazz){return clazz.toString().startsWith("function")||clazz.toString().startsWith("async function")}#reflectStatic(clazz){const code=clazz.toString();return this.#parser.parseClass(code)}#reflectDynamic(clazz){const object=this.createInstance(clazz),members=this.#getMembers(clazz,object),scope=new ESScope(members);return new ESClass(clazz.name,void 0,scope)}#getMembers(clazz,object){return[...this.#getDeclarations(object),...this.#getFunctions(clazz)]}#getDeclarations(object){const fieldNames=Object.getOwnPropertyNames(object),values=object,models=[];for(const fieldName of fieldNames){const content=values[fieldName],value=void 0!==content?new ESValue(String(content)):void 0,model=new ESDeclaration(fieldName,value);models.push(model)}return models}#getFunctions(clazz){const functionDescriptions=Object.getOwnPropertyDescriptors(clazz.prototype),models=[];for(const functionName in functionDescriptions){const description=functionDescriptions[functionName],funktion=description.value;if(funktion instanceof Function==!1)continue;const model=this.fromFunction(funktion);void 0!==description.get?models.push(new ESGetter(model.name,model.parameters,model.body,model.isStatic,model.isAsync,model.isPrivate)):void 0!==description.set?models.push(new ESSetter(model.name,model.parameters,model.body,model.isStatic,model.isAsync,model.isPrivate)):models.push(model)}return models}}const reflector$1=new Reflector;class ClassSerializer extends ValueSerializer{#classResolver;constructor(classResolver){super(),this.#classResolver=classResolver}canSerialize(value){return value instanceof Object&&reflector$1.isClassObject(value)}canDeserialize(value){const object=value;return object instanceof Object&&!0===object.serialized&&"class"===object.name&&"string"==typeof object.key&&object.args instanceof Object&&object.args.constructor===Object&&object.fields instanceof Object&&object.fields.constructor===Object}async serialize(object){const clazz=reflector$1.getClass(object),model=reflector$1.fromClass(clazz,!0),parameterNames=this.#extractConstructorParameters(model),key=this.#classResolver.resolveKey(clazz);if(void 0===key)throw new ClassNotFound(clazz.name);return{serialized:!0,key:key,name:"class",args:await this.#serializeConstructor(model,parameterNames,object),fields:await this.#serializeFields(model,parameterNames,object)}}#extractConstructorParameters(model){const constructor=model.getFunction("constructor");return(constructor?.parameters??[]).map((parameter=>parameter.name))}async#serializeConstructor(model,includeNames,object){const args={};for(const[index,name]of includeNames.entries()){const value=model.canRead(name)?await this.serializeOther(object[name]):void 0;args[index.toString()]=value}return args}async#serializeFields(model,excludeNames,object){const fields={};for(const property of model.writable){const name=property.name;excludeNames.includes(name)||!1===model.canRead(name)||(fields[name]=await this.serializeOther(object[name]))}return fields}async deserialize(object){const clazz=await this.#getClass(object);if(void 0===clazz)throw new ClassNotFound(object.key);if(clazz instanceof Function==!1)throw new InvalidClass(object.key);const args=await this.#deserializeConstructor(clazz,object.args),instance=reflector$1.createInstance(clazz,args);for(const name in object.fields){const fieldValue=object.fields[name];instance[name]=await this.deserializeOther(fieldValue)}return instance}async#deserializeConstructor(clazz,args){const constructor=reflector$1.fromClass(clazz,!0).getFunction("constructor"),values=(constructor?.parameters??[]).map(((_,index)=>{const key=index.toString(),value=args[key];return this.deserializeOther(value)}));return Promise.all(values)}async#getClass(resolvable){return globalThis[resolvable.key]??this.#classResolver.resolveClass(resolvable.key)}}class InvalidDateString extends Error{constructor(dateString){super(`Invalid date string '${dateString}'`)}}class DateSerializer extends ValueSerializer{canSerialize(value){return value instanceof Date}canDeserialize(value){const date=value;return date instanceof Object&&!0===date.serialized&&"Date"===date.name&&"string"==typeof date.value}async serialize(date){return{serialized:!0,name:"Date",value:date.toISOString()}}async deserialize(object){const date=new Date(object.value);if("Invalid Date"===date.toString())throw new InvalidDateString(object.value);return date}}class ErrorSerializer extends ValueSerializer{canSerialize(value){if(value instanceof Object==!1)return!1;const error=value;return error.constructor===Error||error.constructor===EvalError||error.constructor===RangeError||error.constructor===ReferenceError||error.constructor===SyntaxError||error.constructor===TypeError||error.constructor===URIError||error.constructor===AggregateError}canDeserialize(value){const error=value;return error instanceof Object&&!0===error.serialized&&"Error"===error.name&&error.type in globalThis}async serialize(error){return{serialized:!0,name:"Error",type:error.constructor.name,stack:error.stack,message:error.message,cause:error.cause}}async deserialize(object){const error=new(0,globalThis[object.type])(object.message,{cause:object.cause});return error.stack=object.stack,error}}class MapSerializer extends ValueSerializer{canSerialize(value){return value instanceof Map}canDeserialize(value){const map=value;return map instanceof Object&&!0===map.serialized&&"Map"===map.name&&map.entries instanceof Object&&map.entries.keys instanceof Array&&map.entries.values instanceof Array}async serialize(map){const keys=[],values=[];for(const[key,value]of map)keys.push(await this.serializeOther(key)),values.push(await this.serializeOther(value));return{serialized:!0,name:"Map",entries:{keys:keys,values:values}}}async deserialize(object){const keys=object.entries.keys,values=object.entries.values,result=new Map;for(let index=0;index<keys.length;index++){const key=await this.deserializeOther(keys[index]),value=await this.deserializeOther(values[index]);result.set(key,value)}return result}}class ObjectSerializer extends ValueSerializer{canSerialize(value){return value instanceof Object&&value.constructor===Object}canDeserialize(value){return value instanceof Object&&value.constructor===Object}async serialize(object){const result={};for(const key in object){const value=object[key];result[key]=await this.serializeOther(value)}return result}async deserialize(object){const result={};for(const key in object){const value=object[key];result[key]=await this.deserializeOther(value)}return result}}class PrimitiveSerializer extends ValueSerializer{canSerialize(value){return value instanceof Object==!1}canDeserialize(value){return value instanceof Object==!1}async serialize(primitive){return primitive}async deserialize(primitive){return primitive}}class InvalidRegExp extends Error{constructor(source,flags){super(`Invalid regular expression '${source}' with flags '${flags}'`)}}class RegExpSerializer extends ValueSerializer{canSerialize(value){return value instanceof RegExp}canDeserialize(value){const regExp=value;return regExp instanceof Object&&!0===regExp.serialized&&"RegExp"===regExp.name&&"string"==typeof regExp.source&&"string"==typeof regExp.flags}async serialize(regExp){return{serialized:!0,name:"RegExp",source:regExp.source,flags:regExp.flags}}async deserialize(object){try{return new RegExp(object.source,object.flags)}catch{throw new InvalidRegExp(object.source,object.flags)}}}class SetSerializer extends ValueSerializer{canSerialize(value){return value instanceof Set}canDeserialize(value){const set=value;return set instanceof Object&&!0===set.serialized&&"Set"===set.name&&set.values instanceof Array}async serialize(set){const values=[];for(const value of set.values())values.push(await this.serializeOther(value));return{serialized:!0,name:"Set",values:values}}async deserialize(object){const values=await Promise.all(object.values.map((async value=>this.deserializeOther(value))));return new Set([...values])}}const reflector=new Reflector;class ArrayBufferSerializer extends ValueSerializer{canSerialize(value){return value instanceof Int8Array||value instanceof Uint8Array||value instanceof Uint8ClampedArray||value instanceof Int16Array||value instanceof Uint16Array||value instanceof Int32Array||value instanceof Uint32Array||value instanceof Float32Array||value instanceof Float64Array||value instanceof BigInt64Array||value instanceof BigUint64Array}canDeserialize(value){const array=value;return array instanceof Object&&!0===array.serialized&&"TypedArray"===array.name&&array.type in globalThis&&array.bytes instanceof Array}async serialize(array){const type=array.constructor.name,view=new DataView(array.buffer),bytes=[];for(let index=0;index<view.byteLength;index++)bytes.push(view.getUint8(index));return{serialized:!0,name:"TypedArray",type:type,bytes:bytes}}async deserialize(object){const type=object.type,bytes=object.bytes,buffer=new ArrayBuffer(bytes.length),view=new DataView(buffer);for(let index=0;index<bytes.length;index++)view.setUint8(index,bytes[index]);const clazz=globalThis[type];return reflector.createInstance(clazz,[buffer])}}class InvalidUrlString extends Error{constructor(urlString){super(`Invalid url string '${urlString}'`)}}class UrlSerializer extends ValueSerializer{canSerialize(value){return value instanceof URL}canDeserialize(value){const url=value;return url instanceof Object&&!0===url.serialized&&"Url"===url.name&&"string"==typeof url.value}async serialize(url){return{serialized:!0,name:"Url",value:url.toString()}}async deserialize(object){try{return new URL(object.value)}catch{throw new InvalidUrlString(object.value)}}}class SerializerBuilder{static build(classResolver){const serializer=new Serializer;return serializer.addSerializer(new PrimitiveSerializer),serializer.addSerializer(new ObjectSerializer),void 0!==classResolver&&serializer.addSerializer(new ClassSerializer(classResolver)),serializer.addSerializer(new ErrorSerializer),serializer.addSerializer(new RegExpSerializer),serializer.addSerializer(new BigIntSerializer),serializer.addSerializer(new UrlSerializer),serializer.addSerializer(new DateSerializer),serializer.addSerializer(new SetSerializer),serializer.addSerializer(new MapSerializer),serializer.addSerializer(new ArraySerializer),serializer.addSerializer(new ArrayBufferSerializer),"undefined"!=typeof Buffer&&serializer.addSerializer(new BufferSerializer),serializer}}class ExecutionClassResolver{#executionManager;constructor(executionManager){this.#executionManager=executionManager}resolveKey(clazz){const model=this.#executionManager.getClassByImplementation(clazz);return model?.fqn}resolveClass(key){const model=this.#executionManager.getClass(key);return model?.implementation}}class RequestNotTrusted extends Unauthorized{constructor(){super("Request not trusted")}}class LocalWorker{#id;#url;#trustKey;#gateway;#executionManager;#serializer;constructor(configuration){this.#url=configuration.url,this.#trustKey=configuration.trustKey,this.#gateway=configuration.gateway,this.#executionManager=configuration.executionManager;const classResolver=new ExecutionClassResolver(this.#executionManager);this.#serializer=SerializerBuilder.build(classResolver)}get id(){return this.#id}set id(id){this.#id=id}get url(){return this.#url}get trustKey(){return this.#trustKey}async start(){void 0!==this.#gateway&&(await this.#gateway.start(),this.#id=await this.#gateway.addWorker(this))}async stop(){void 0!==this.#gateway&&void 0!==this.#id&&(await this.#gateway.removeWorker(this),await this.#gateway.stop())}getProcedureNames(){return this.#executionManager.getProcedureNames()}hasProcedure(name){return this.#executionManager.hasProcedure(name)}async isHealthy(){return!0}async getHealth(){return new Map}async run(request){return this.#mustRunLocal(request)?this.#runLocal(request):this.#runRemote(request)}#mustRunLocal(request){return void 0===this.#gateway||this.#executionManager.hasProcedure(request.fqn)}async#runLocal(request){const procedure=this.#executionManager.getProcedure(request.fqn),implementation=procedure?.getImplementation(request.version);if(this.#procedureNotFound(implementation))throw new ProcedureNotFound(request.fqn);if(this.#requestNotTrusted(request,implementation))throw new RequestNotTrusted;const dataEncoding=request.getHeader("X-Jitar-Data-Encoding");"serialized"===dataEncoding&&(request=await this.#deserializeRequest(request)),request.removeHeader("X-Jitar-Data-Encoding");const response=await this.#executionManager.run(request);return"serialized"===dataEncoding?this.#serializeResponse(response):response}#procedureNotFound(implementation){return void 0===implementation||implementation.private}#requestNotTrusted(request,implementation){if(implementation.public)return!1;const trustKey=request.getHeader("X-Jitar-Trust-Key");return this.#trustKey!==trustKey}async#runRemote(request){(request=await this.#serializeRequest(request)).setHeader("X-Jitar-Data-Encoding","serialized"),void 0!==this.#trustKey&&request.setHeader("X-Jitar-Trust-Key",this.#trustKey);const response=await this.#gateway.run(request);return this.#deserializeResponse(response)}async#serializeRequest(request){const serializedArgs=new Map;for(const[key,value]of request.args){const serializedValue=await this.#serializer.serialize(value);serializedArgs.set(key,serializedValue)}return new Request(request.fqn,request.version,serializedArgs,request.headers,request.mode)}async#deserializeRequest(request){const deserializedArgs=new Map;for(const[key,value]of request.args){const deserializedValue=await this.#serializer.deserialize(value);deserializedArgs.set(key,deserializedValue)}return new Request(request.fqn,request.version,deserializedArgs,request.headers,request.mode)}async#serializeResponse(response){const serializedResult=await this.#serializer.serialize(response.result);return new Response(response.status,serializedResult,response.headers)}async#deserializeResponse(response){const deserializedResult=await this.#serializer.deserialize(response.result);return new Response(response.status,deserializedResult,response.headers)}}class ProcedureRunner{#runner;constructor(runner){this.#runner=runner}async handle(request,next){return this.#runner.run(request)}}class Runtime{#versionParser=new VersionParser;constructor(){this.#initGlobals()}#initGlobals(){const globals=globalThis;globals.__run=this.#run.bind(this),globals.ProcedureNotAccessible=ProcedureNotAccessible}async#run(fqn,versionNumber,args,sourceRequest){const version=this.#versionParser.parse(versionNumber),argsMap=new Map(Object.entries(args)),headersMap=sourceRequest instanceof Request?sourceRequest.headers:new Map,targetRequest=new Request(fqn,version,argsMap,headersMap,RunModes_NORMAL),trustKey=this.getTrustKey();void 0!==trustKey&&targetRequest.setHeader("X-Jitar-Trust-Key",trustKey);const targetResponse=await this.runInternal(targetRequest);if(targetResponse.status!==StatusCodes_OK)throw targetResponse.result;return targetResponse.result}}class Client extends Runtime{#worker;#middlewareManager;constructor(configuration){super(),this.#worker=new LocalWorker({url:configuration.remoteUrl,gateway:new RemoteGateway({url:configuration.remoteUrl,remote:configuration.remote}),executionManager:configuration.executionManager}),this.#middlewareManager=configuration.middlewareManager;const procedureRunner=new ProcedureRunner(this.#worker);this.#middlewareManager.addMiddleware(procedureRunner)}get worker(){return this.#worker}start(){return this.#worker.start()}stop(){return this.#worker.stop()}getTrustKey(){}run(request){return this.runInternal(request)}runInternal(request){return this.#middlewareManager.handle(request)}}class InvalidMiddleware extends ServerError{constructor(){super("Invalid middleware")}}class MiddlewareManager{#middlewares=[];addMiddleware(middleware){if(void 0===middleware?.handle)throw new InvalidMiddleware;this.#middlewares.push(middleware)}getMiddleware(type){return this.#middlewares.find((middleware=>middleware instanceof type))}clearMiddlewares(){this.#middlewares=[]}handle(request){return this.#getNextHandler(request,0)()}#getNextHandler(request,index){const next=this.#middlewares[index];if(void 0===next)return async()=>new Response(StatusCodes_OK);const nextHandler=this.#getNextHandler(request,index+1);return async()=>next.handle(request,nextHandler)}}class ClientBuilder{#remoteBuilder;constructor(remoteBuilder){this.#remoteBuilder=remoteBuilder}build(configuration){const remoteUrl=configuration.remoteUrl,remote=this.#remoteBuilder.build(remoteUrl),middlewareManager=this.#buildMiddlewareManager(configuration.middleware??[]),executionManager=this.#buildExecutionManager(configuration.segments??[]);return new Client({remoteUrl:remoteUrl,remote:remote,middlewareManager:middlewareManager,executionManager:executionManager})}#buildMiddlewareManager(middleware){const manager=new MiddlewareManager;return middleware.forEach((middleware=>manager.addMiddleware(middleware))),manager}#buildExecutionManager(segments){const manager=new ExecutionManager;return segments.forEach((segment=>manager.addSegment(segment))),manager}}class Validator{#strict;constructor(strict=!0){this.#strict=strict}validate(data,scheme){const errors=[];this.#validateData("",data,scheme,errors);return{valid:0===errors.length,errors:errors}}#validateData(key,data,scheme,errors){this.#strict&&this.#validateKeys(key,data,scheme,errors),this.#validateValues(key,data,scheme,errors)}#validateKeys(key,data,scheme,errors){const dataKeys=Object.keys(data),schemeKeys=Object.keys(scheme);for(const dataKey of dataKeys)if(!1===schemeKeys.includes(dataKey)){const absoluteKey=this.#composeKey(key,dataKey);errors.push(`Unknown field '${absoluteKey}'`)}}#validateValues(key,data,scheme,errors){const valueKeys=Object.keys(scheme);for(const valueKey of valueKeys){const absoluteKey=this.#composeKey(key,valueKey),fieldScheme=scheme[valueKey],value=data[valueKey];this.#validateValue(absoluteKey,value,fieldScheme,errors)}}#validateValue(key,value,scheme,errors){if(void 0!==value)switch(scheme.type){case"string":return this.#validateString(key,value,scheme,errors);case"integer":return this.#validateInteger(key,value,scheme,errors);case"real":return this.#validateReal(key,value,scheme,errors);case"boolean":return this.#validateBoolean(key,value,scheme,errors);case"url":return this.#validateUrl(key,value,scheme,errors);case"group":return this.#validateGroup(key,value,scheme,errors);case"list":return this.#validateList(key,value,scheme,errors)}else!0===scheme.required&&errors.push(`Field '${key}' is required`)}#validateString(key,value,scheme,errors){"string"!=typeof value&&errors.push(`Field '${key}' is not a string`)}#validateInteger(key,value,scheme,errors){"number"==typeof value&&!1!==Number.isInteger(value)||errors.push(`Field '${key}' is not an integer`)}#validateReal(key,value,scheme,errors){"number"!=typeof value&&errors.push(`Field '${key}' is not a real number`)}#validateBoolean(key,value,scheme,errors){"boolean"!=typeof value&&errors.push(`Field '${key}' is not a boolean`)}#validateUrl(key,value,scheme,errors){"string"==typeof value&&!1!==value.startsWith("http")||errors.push(`Field '${key}' is not a valid URL`)}#validateGroup(key,value,scheme,errors){"object"==typeof value?this.#validateData(key,value,scheme.fields,errors):errors.push(`Field '${key}' is not an object`)}#validateList(key,value,scheme,errors){if(!Array.isArray(value))return void errors.push(`Field '${key}' is not a list`);const data=value;for(const itemIndex in data){const itemKey=this.#composeKey(key,itemIndex),itemValue=data[itemIndex];this.#validateValue(itemKey,itemValue,scheme.items,errors)}}#composeKey(parent,key){return""===parent?key:`${parent}.${key}`}}const HeaderKeys_CONTENT_TYPE="content-type",HeaderKeys_JITAR_CONTENT_TYPE="x-jitar-content-type",HeaderKeys_JITAR_PROCEDURE_VERSION="x-jitar-procedure-version",HeaderValues_APPLICATION_JSON="application/json",HeaderValues_APPLICATION_STREAM="application/octet-stream";class InvalidWorkerId extends Error{constructor(){super("Invalid worker id")}}class HttpRemote{#url;#httpClient;#errorConverter=new ErrorConverter;#validator=new Validator;constructor(url,httpClient){this.#url=url,this.#httpClient=httpClient}connect(){return Promise.resolve()}disconnect(){return Promise.resolve()}async provide(filename){const remoteUrl=`${this.#url}/${filename}`,response=await this.#callRemote(remoteUrl,{method:"GET"}),type=response.headers.get(HeaderKeys_CONTENT_TYPE)??HeaderValues_APPLICATION_STREAM,result=await response.arrayBuffer(),content=Buffer.from(result);return new File(filename,type,content)}async isHealthy(){const remoteUrl=`${this.#url}/health/status`,response=await this.#callRemote(remoteUrl,{method:"GET"});return"true"===await response.text()}async getHealth(){const remoteUrl=`${this.#url}/health`,response=await this.#callRemote(remoteUrl,{method:"GET"}),health=await response.json();return new Map(Object.entries(health))}async addWorker(url,procedureNames,trustKey){const remoteUrl=`${this.#url}/workers`,body={url:url,procedureNames:procedureNames,trustKey:trustKey},options={method:"POST",headers:{"Content-Type":HeaderValues_APPLICATION_JSON},body:JSON.stringify(body)},response=await this.#callRemote(remoteUrl,options),contentType=response.headers.get(HeaderKeys_CONTENT_TYPE);if(null===contentType||!1===contentType.includes(HeaderValues_APPLICATION_JSON))throw new InvalidWorkerId;const result=await response.json();if(!1===this.#validator.validate(result,{id:{type:"string",required:!0}}).valid)throw new InvalidWorkerId;return result.id}async removeWorker(id){const remoteUrl=`${this.#url}/workers/${id}`,options={method:"DELETE",headers:{"Content-Type":HeaderValues_APPLICATION_JSON}};await this.#callRemote(remoteUrl,options)}async run(request){request.setHeader(HeaderKeys_CONTENT_TYPE,HeaderValues_APPLICATION_JSON);const argsObject=Object.fromEntries(request.args),headersObject=Object.fromEntries(request.headers),versionString=request.version.toString();headersObject[HeaderKeys_JITAR_PROCEDURE_VERSION]=versionString;const remoteUrl=`${this.#url}/rpc/${request.fqn}`,options={method:"POST",redirect:"manual",headers:headersObject,body:await this.#createRequestBody(argsObject)},response=await this.#callRemote(remoteUrl,options,!1),status=response.status,result=await this.#getResponseResult(response),headers=this.#createResponseHeaders(response);return new Response(status,result,headers)}async#callRemote(remoteUrl,options,throwOnError=!0){const response=await this.#httpClient.execute(remoteUrl,options);if(throwOnError&&this.#isErrorResponse(response)){const result=await this.#getResponseResult(response);throw this.#errorConverter.fromStatus(response.status,String(result))}return response}#isErrorResponse(response){return response.status<200||response.status>399}async#createRequestBody(body){return JSON.stringify(body)}async#getResponseResult(response){const contentType=response.headers.get(HeaderKeys_JITAR_CONTENT_TYPE)??response.headers.get(HeaderKeys_CONTENT_TYPE);if(contentType?.includes("undefined"))return;if(contentType?.includes("null"))return null;if(contentType?.includes("json"))return response.json();const content=await response.text();return contentType?.includes("boolean")?"true"===content:contentType?.includes("number")?Number(content):content}#createResponseHeaders(response){const headers=new Map;for(const[name,value]of response.headers)headers.set(name,value);return headers}}class FetchHttpClient{async execute(url,options){return fetch(url,options)}}class HttpRemoteBuilder{#httpClient;constructor(httpClient=new FetchHttpClient){this.#httpClient=httpClient}build(url){return new HttpRemote(url,this.#httpClient)}}export{ArrayParameter,BadRequest,Class,ClientBuilder,Forbidden,HttpRemoteBuilder,Implementation,NamedParameter,NotFound,NotImplemented,ObjectParameter,PaymentRequired,Procedure,Request,Response,Segment,ServerError,Teapot,Unauthorized,Version};
package/dist/lib.d.ts CHANGED
@@ -122,7 +122,7 @@ declare class Procedure {
122
122
  get fqn(): string;
123
123
  get public(): boolean;
124
124
  get protected(): boolean;
125
- addImplementation(implementation: Implementation): Procedure;
125
+ addImplementation(implementation: Implementation): this;
126
126
  getImplementation(version: Version): Implementation | undefined;
127
127
  }
128
128
 
@@ -130,12 +130,12 @@ declare class Segment {
130
130
  #private;
131
131
  constructor(id: string);
132
132
  get id(): string;
133
- addClass(clazz: Class): Segment;
133
+ addClass(clazz: Class): this;
134
134
  hasClass(fqn: string): boolean;
135
135
  getClass(fqn: string): Class | undefined;
136
136
  getClassByImplementation(implementation: Function): Class | undefined;
137
137
  getClasses(): Class[];
138
- addProcedure(procedure: Procedure): Segment;
138
+ addProcedure(procedure: Procedure): this;
139
139
  hasProcedure(fqn: string): boolean;
140
140
  getProcedure(fqn: string): Procedure | undefined;
141
141
  getExposedProcedures(): Procedure[];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jitar",
3
- "version": "0.8.2",
3
+ "version": "0.9.1",
4
4
  "description": "Distributed runtime for JavaScript and TypeScript to chop monolithic applications into micros.",
5
5
  "author": "Masking Technology <info@masking.tech> (https://jitar.dev)",
6
6
  "license": "MIT",
@@ -19,17 +19,17 @@
19
19
  ],
20
20
  "bin": "./dist/cli.js",
21
21
  "scripts": {
22
- "lint": "eslint . --ext .ts",
22
+ "lint": "eslint",
23
23
  "validate": "tsc -p tsconfig.json --noEmit",
24
24
  "build": "npm run clean && rollup -c && chmod +x dist/cli.js",
25
25
  "clean": "rm -rf dist",
26
26
  "prepublishOnly": "npm run clean && npm run build"
27
27
  },
28
28
  "dependencies": {
29
- "dotenv": "^16.4.5",
30
- "express": "^4.19.2",
31
- "fs-extra": "^11.2.0",
32
- "glob": "11.0.0",
29
+ "dotenv": "^16.4.7",
30
+ "express": "^5.0.1",
31
+ "fs-extra": "^11.3.0",
32
+ "glob": "11.0.1",
33
33
  "mime-types": "^2.1.35"
34
34
  },
35
35
  "devDependencies": {
@@ -39,7 +39,8 @@
39
39
  "@jitar/health": "*",
40
40
  "@jitar/http": "*",
41
41
  "@jitar/logging": "*",
42
- "@jitar/middleware": "*"
42
+ "@jitar/middleware": "*",
43
+ "@jitar/runtime": "*"
43
44
  },
44
45
  "engines": {
45
46
  "node": ">=20.0"
@@ -62,5 +63,5 @@
62
63
  "full stack",
63
64
  "web applications"
64
65
  ],
65
- "gitHead": "0bff066d2b51e97e910486e72b9f6b089bae96b1"
66
+ "gitHead": "3e4dcf529f258336521b4ce3a4db2faa94d67ea1"
66
67
  }