jitar 0.4.2 → 0.5.0
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/client.js +1 -1
- package/dist/globals-e6900615.js +1 -0
- package/dist/lib.d.ts +82 -33
- package/dist/server.js +1 -1
- package/package.json +4 -5
- package/LICENCE +0 -23
- package/dist/globals-a24096f0.js +0 -1
package/dist/client.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{A as
|
|
1
|
+
import{A as AccessLevels,y as Version,j as RemoteRepository,k as RemoteGateway,L as LocalNode}from"./globals-e6900615.js";export{O as ArrayParameter,B as BadRequest,C as ClientNotFound,F as FileNotFound,v as Forbidden,X as ImplementationNotFound,a as InvalidClientId,Y as InvalidParameterValue,I as InvalidSegmentFile,Z as InvalidVersionNumber,_ as MissingParameterValue,$ as ModuleNotAccessible,a0 as ModuleNotLoaded,K as NamedParameter,N as NoNodeAvailable,w as NotFound,x as NotImplemented,Q as ObjectParameter,u as PaymentRequired,a1 as ProcedureNotAccessible,P as ProcedureNotFound,a2 as RepositoryNotAvailable,z as Request,J as Response,a3 as RuntimeNotAvailable,a4 as SegmentNotFound,W as ServerError,T as Teapot,U as Unauthorized,a5 as UnknownParameter}from"./globals-e6900615.js";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 parameters(){return this.#parameters}get executable(){return this.#executable}}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))}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 Segment{#id;#procedures=new Map;constructor(id){this.#id=id}get id(){return this.#id}addProcedure(procedure){return this.#procedures.set(procedure.fqn,procedure),this}hasProcedure(fqn){return void 0!==this.getProcedure(fqn)}getProcedure(fqn){return this.#procedures.get(fqn)}getPublicProcedures(){return[...this.#procedures.values()].filter((procedure=>procedure.public))}}let client;const resolvers=[];async function startClient(remoteUrl,segmentNames=[]){const repository=new RemoteRepository(remoteUrl),gateway=new RemoteGateway(remoteUrl),node=new LocalNode(repository,gateway);return node.segmentNames=new Set(segmentNames),await node.start(),client=node,resolvers.forEach((resolve=>resolve(node))),resolvers.length=0,node}async function getClient(){return void 0===client?new Promise((resolve=>{resolvers.push(resolve)})):client}export{Implementation,Procedure,Segment,Version,getClient,startClient};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
const AccessLevels={PRIVATE:"private",PUBLIC:"public"};Object.freeze(AccessLevels);const Files={MODULE_PATTERN:"**/*.js",SEGMENT_PATTERN:"**/*.segment.json",NODE_SEGMENT_PATTERN:"**/*.segment.node.js",REPOSITORY_SEGMENT_PATTERN:"**/*.segment.repository.js"};function convertToLocalFilename(filename){return filename.replace(".js",".local.js")}function convertToRemoteFilename(filename){return filename.replace(".js",".remote.js")}function createNodeFilename(name){return`./${name}.segment.node.js`}function createRepositoryFilename(name){return`./${name}.segment.repository.js`}function isSegmentFilename(filename){return filename.includes(".segment.")}Object.freeze(Files);const ExecutionScopes={APPLICATION:"application",RUNTIME:"runtime"};Object.freeze(ExecutionScopes);class BadRequest extends Error{constructor(message="Invalid request"){super(message)}}BadRequest.source="/jitar/client.js";class Forbidden extends Error{constructor(message="Forbidden"){super(message)}}Forbidden.source="/jitar/client.js";class NotFound extends Error{constructor(message="Not found"){super(message)}}NotFound.source="/jitar/client.js";class NotImplemented extends Error{constructor(message="Not implemented"){super(message)}}NotImplemented.source="/jitar/client.js";class PaymentRequired extends Error{constructor(message="Payment required"){super(message)}}PaymentRequired.source="/jitar/client.js";class ServerError extends Error{constructor(message="Server error"){super(message)}}ServerError.source="/jitar/client.js";class Teapot extends Error{constructor(){super("I'm a teapot")}}Teapot.source="/jitar/client.js";class Unauthorized extends Error{constructor(message="Unauthorized"){super(message)}}Unauthorized.source="/jitar/client.js";class ClientNotFound extends BadRequest{#clientId;constructor(clientId){super(`Client not found for id '${clientId}'`),this.#clientId=clientId}get clientId(){return this.#clientId}}ClientNotFound.source="/jitar/client.js";class FileNotFound extends NotFound{#filename;constructor(filename){super(`The file '${filename} could not be found'`),this.#filename=filename}get filename(){return this.#filename}}FileNotFound.source="/jitar/client.js";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}}ImplementationNotFound.source="/jitar/client.js";class InvalidClientId extends BadRequest{#clientId;constructor(clientId){super(`Invalid client id '${clientId}'`),this.#clientId=clientId}get clientId(){return this.#clientId}}InvalidClientId.source="/jitar/client.js";class InvalidParameterValue extends BadRequest{#parameterName;constructor(parameterName){super(`Invalid value for parameter '${parameterName}'`),this.#parameterName=parameterName}get parameterName(){return this.#parameterName}}InvalidParameterValue.source="/jitar/client.js";class InvalidSegmentFile extends ServerError{#filename;constructor(filename){super(`Missing files array in segment file '${filename}'`),this.#filename=filename}get filename(){return this.#filename}}InvalidSegmentFile.source="/jitar/client.js";class InvalidVersionNumber extends BadRequest{#number;constructor(number){super(`Invalid version number '${number}'`),this.#number=number}get number(){return this.#number}}InvalidVersionNumber.source="/jitar/client.js";class MissingParameterValue extends BadRequest{#parameterName;constructor(parameterName){super(`Missing value for parameter '${parameterName}'`),this.#parameterName=parameterName}get parameterName(){return this.#parameterName}}MissingParameterValue.source="/jitar/client.js";class ModuleNotAccessible extends Forbidden{#url;constructor(url){super(`Module '${url}' is not accessible`),this.#url=url}get url(){return this.#url}}ModuleNotAccessible.source="/jitar/client.js";class ModuleNotLoaded extends ServerError{#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}}ModuleNotLoaded.source="/jitar/client.js";class NoNodeAvailable extends ServerError{#name;constructor(name){super(`No node available for procedure '${name}'`),this.#name=name}get name(){return this.#name}}NoNodeAvailable.source="/jitar/client.js";class ProcedureNotAccessible extends Forbidden{#fqn;#versionNumber;constructor(fqn,versionNumber){super(`Procedure '${fqn}' (v${versionNumber}) is not accessible`),this.#fqn=fqn,this.#versionNumber=versionNumber}get fqn(){return this.#fqn}get versionNumber(){return this.#versionNumber}}ProcedureNotAccessible.source="/jitar/client.js";class ProcedureNotFound extends NotFound{#fqn;constructor(fqn){super(`Procedure '${fqn}' not found`),this.#fqn=fqn}get fqn(){return this.#fqn}}ProcedureNotFound.source="/jitar/client.js";class RepositoryNotAvailable extends ServerError{constructor(){super("Repository not available")}}RepositoryNotAvailable.source="/jitar/client.js";class RuntimeNotAvailable extends ServerError{constructor(){super("Runtime not available")}}RuntimeNotAvailable.source="/jitar/client.js";class SegmentNotFound extends ServerError{#source;constructor(source){super(`Segment found for '${source}'`),this.#source=source}get source(){return this.#source}}SegmentNotFound.source="/jitar/client.js";class UnknownParameter extends BadRequest{#parameterName;constructor(parameterName){super(`Unknown parameter ${parameterName}`),this.#parameterName=parameterName}get parameterName(){return this.#parameterName}}UnknownParameter.source="/jitar/client.js";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 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 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 NamedParameter extends Parameter{}class ObjectParameter extends DestructuredParameter{}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 Request{#fqn;#version;#args;#headers=new Map;constructor(fqn,version,args,headers){this.#fqn=fqn,this.#version=version,this.#args=args,this.#headers=headers}get fqn(){return this.#fqn}get version(){return this.#version}get args(){return this.#args}get headers(){return this.#headers}setArgument(name,value){this.#args.set(name,value)}getArgument(name){return this.#args.get(name)}removeArgument(name){this.#args.delete(name)}clearHeaders(){this.#headers.clear()}setHeader(name,value){this.#headers.set(name,value)}getHeader(name){return this.#headers.get(name)}removeHeader(name){this.#headers.delete(name)}}class Response{#result;#headers;constructor(result=void 0,headers=new Map){this.#result=result,this.#headers=headers}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,value)}getHeader(name){return this.#headers.get(name)}removeHeader(name){this.#headers.delete(name)}}class InvalidMiddleware extends ServerError{#url;constructor(url){super(`Module '${url}' does not export valid middleware`),this.#url=url}get url(){return this.#url}}InvalidMiddleware.source="/jitar/client.js";class ProcedureRunner{#runner;constructor(runner){this.#runner=runner}async handle(request,next){return this.#runner.run(request)}}class InvalidHealthCheck extends ServerError{#url;constructor(url){super(`Module '${url}' does not export a valid health check`),this.#url=url}get url(){return this.#url}}InvalidHealthCheck.source="/jitar/client.js";class Runtime{#url;#healthCheckFiles=new Set;#healthChecks=new Map;constructor(url){this.#url=url}get url(){return this.#url}set healthCheckFiles(filenames){this.#healthCheckFiles=filenames}start(){return this.#importHealthChecks()}async stop(){this.#clearHealthChecks()}addHealthCheck(healthCheck){this.#healthChecks.set(healthCheck.name,healthCheck)}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#importHealthChecks(){for(const filename of this.#healthCheckFiles)await this.#importHealthCheck(filename)}async#importHealthCheck(url){const healthCheck=(await this.import(url,ExecutionScopes.APPLICATION)).default;if(void 0===healthCheck?.isHealthy)throw new InvalidHealthCheck(url);this.addHealthCheck(healthCheck)}#clearHealthChecks(){this.#healthChecks.clear()}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 ProcedureRuntime extends Runtime{#repository;#middlewareFiles=new Set;#middlewares=[];constructor(repository,url){super(url),this.#repository=repository,this.#middlewares.push(new ProcedureRunner(this))}get repository(){return this.#repository}set middlewareFiles(filenames){this.#middlewareFiles=filenames}async start(){await this.#repository.start(),await super.start(),await this.#importMiddlewares()}async stop(){this.#clearMiddlewares(),await this.#repository.stop(),await super.stop()}import(url,scope){return this.#repository.import(url,scope)}addMiddleware(middleware){const index=this.#middlewares.length-1;this.#middlewares.splice(index,0,middleware)}getMiddleware(type){return this.#middlewares.find((middleware=>middleware instanceof type))}handle(request){return this.#getNextHandler(request,0)()}#getNextHandler(request,index){const next=this.#middlewares[index];if(void 0===next)return async()=>new Response;const nextHandler=this.#getNextHandler(request,index+1);return async()=>next.handle(request,nextHandler)}async#importMiddlewares(){for(const url of this.#middlewareFiles)await this.#importMiddleware(url)}async#importMiddleware(url){const middleware=(await this.import(url,ExecutionScopes.APPLICATION)).default;if(void 0===middleware?.handle)throw new InvalidMiddleware(url);this.addMiddleware(middleware)}#clearMiddlewares(){this.#middlewares=[]}}class Gateway extends ProcedureRuntime{}class ArgumentExtractor{extract(parameters,args){const argsCopy=new Map(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}#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 Node extends ProcedureRuntime{}class VersionParser{static parse(number){if(0===number.trim().length)return Version.DEFAULT;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]));case 3:return new Version(Number.parseInt(parts[0]),Number.parseInt(parts[1]),Number.parseInt(parts[2]));default:throw new InvalidVersionNumber(number)}}}const RUNS_IN_BROWSER="undefined"!=typeof window;let _runtime;function getRuntime(){if(void 0===_runtime)throw new RuntimeNotAvailable;return _runtime}class LocalNode extends Node{#gateway;#argumentConstructor;#segmentNames=new Set;#segments=new Map;constructor(repository,gateway,url,argumentConstructor=new ArgumentExtractor){super(repository,url),this.#gateway=gateway,this.#argumentConstructor=argumentConstructor,_runtime=this}set segmentNames(names){this.#segmentNames=names}async start(){await super.start(),await this.#loadSegments(),void 0!==this.#gateway&&await this.#gateway.start()}async stop(){this.#unloadSegments(),void 0!==this.#gateway&&await this.#gateway.stop(),await super.stop()}getProcedureNames(){const names=new Set;for(const segment of this.#segments.values()){segment.getPublicProcedures().forEach((procedure=>names.add(procedure.fqn)))}return[...names.values()]}addSegment(segment){this.#segments.set(segment.id,segment)}hasProcedure(fqn){return this.getProcedureNames().includes(fqn)}run(request){const procedure=this.#getProcedure(request.fqn);return void 0===procedure?this.#useGateway(request):this.#runProcedure(procedure,request)}async#loadSegments(){for(const segmentName of this.#segmentNames)await this.#loadSegment(segmentName)}async#loadSegment(name){const filename=createNodeFilename(name),segment=(await this.import(filename,ExecutionScopes.APPLICATION)).segment;this.addSegment(segment)}#unloadSegments(){this.#segments.clear()}#useGateway(request){if(void 0===this.#gateway)throw new ProcedureNotFound(request.fqn);return this.#gateway.run(request)}async#runProcedure(procedure,request){const implementation=procedure.getImplementation(request.version);if(void 0===implementation)throw new ImplementationNotFound(procedure.fqn,request.version.toString());const values=this.#argumentConstructor.extract(implementation.parameters,request.args),result=await implementation.executable.call(request,...values);return new Response(result)}#getProcedure(fqn){for(const segment of this.#segments.values())if(segment.hasProcedure(fqn))return segment.getProcedure(fqn)}}class UrlRewriter{static addBase(url,base){if(url.startsWith(base))return url;const parts=`${base}/${url}`.split("://"),protocol=parts.length>1?`${parts[0]}://`:"",address=parts.length>1?parts[1]:parts[0];return`${protocol}${this.#translateAddress(address)}`}static removeBase(url,base){return!1===url.startsWith(base)?url:url.substring(base.length)}static#translateAddress(address){const parts=address.split("/"),translated=[];translated.push(parts[0]);for(let index=1;index<parts.length;index++){const part=parts[index].trim();switch(part){case"":case".":continue;case"..":translated.pop();continue}translated.push(part)}return translated.join("/")}}const APPLICATION_MODULE_INDICATORS=[".","/","http:","https:"];let _baseUrl="",_import=async name=>import(name);class ModuleLoader{static setBaseUrl(baseUrl){_baseUrl=baseUrl}static setImporter(importer){_import=importer}static async load(specifier){if(this.#isSystemModule(specifier))return this.#import(specifier);if(specifier.startsWith("/jitar"))return this.#import("jitar");const filename=this.assureExtension(specifier),url=UrlRewriter.addBase(filename,_baseUrl);if(!1===url.startsWith(_baseUrl))throw new ModuleNotAccessible(specifier);return this.#import(url)}static assureExtension(specifier){return specifier.endsWith(".js")?specifier:`${specifier}.js`}static#isSystemModule(specifier){return!1===APPLICATION_MODULE_INDICATORS.some((indicator=>specifier.startsWith(indicator)))}static async#import(specifier){try{return await _import(specifier)}catch(error){const safeUrl=UrlRewriter.removeBase(specifier,_baseUrl),message=error instanceof Error?error.message:String(error);throw new ModuleNotLoaded(safeUrl,message)}}}class Repository extends Runtime{async import(url,scope){return scope===ExecutionScopes.RUNTIME?ModuleLoader.load(url):this.loadModule(url)}}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 ReflectionAlias{#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 ReflectionValue{#definition;constructor(definition){this.#definition=definition}get definition(){return this.#definition}toString(){return this.#definition}}class ReflectionArray extends ReflectionValue{}class ReflectionMember{#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 ReflectionClass extends ReflectionMember{#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 void 0!==declaration&&declaration.isPublic||this.hasGetter(name)}canWrite(name){const declaration=this.getDeclaration(name);return void 0!==declaration&&declaration.isPublic||this.hasSetter(name)}canCall(name){const funktion=this.getFunction(name);return void 0!==funktion&&funktion.isPublic}toString(){const infix=void 0!==this.#parentName?` extends ${this.#parentName}`:"";return`class ${this.name}${infix} { ${this.#scope.toString()} }`}}class ReflectionDeclaration extends ReflectionMember{#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 ReflectionDestructuredValue{#members;constructor(members){this.#members=members}get members(){return this.#members}toString(){return this.#members.map((member=>member.toString())).join(" , ")}}class ReflectionDestructuredArray extends ReflectionDestructuredValue{toString(){return`[ ${super.toString()} ]`}}class ReflectionDestructuredObject extends ReflectionDestructuredValue{toString(){return`{ ${super.toString()} }`}}class ReflectionExport extends ReflectionMember{#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 ReflectionExpression extends ReflectionValue{}class ReflectionField{#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 ReflectionFunction extends ReflectionMember{#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 ReflectionGenerator extends ReflectionFunction{toString(){const parameters=this.parameters.map((parameter=>parameter.toString()));return`${this.isAsync?"async ":""}${this.name}*(${parameters.join(", ")}) { ${this.body} }`}}class ReflectionGetter extends ReflectionFunction{toString(){return`get ${super.toString()}`}}class ReflectionImport extends ReflectionMember{#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 ReflectionModule{#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 ReflectionObject extends ReflectionValue{}class ReflectionSetter extends ReflectionFunction{toString(){return`set ${super.toString()}`}}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{}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)}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 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}`)}}const IMPORT_NAME=ReflectionImport.name,EXPORT_NAME=ReflectionExport.name,DECLARATION_NAME=ReflectionDeclaration.name,FUNCTION_NAME=ReflectionFunction.name,GETTER_NAME=ReflectionGetter.name,SETTER_NAME=ReflectionSetter.name,GENERATOR_NAME=ReflectionGenerator.name,CLASS_NAME=ReflectionClass.name;class ReflectionScope{#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")}}class Parser{#lexer;constructor(lexer=new Lexer){this.#lexer=lexer}parse(code){const tokenList=this.#lexer.tokenize(code),scope=this.#parseScope(tokenList);return new ReflectionModule(scope)}parseFirst(code){const tokenList=this.#lexer.tokenize(code);return this.#parseNext(tokenList)}parseValue(code){const model=this.parseFirst(code);if(model instanceof ReflectionValue==!1)throw new UnexpectedParseResult("a value definition");return model}parseImport(code){const model=this.parseFirst(code);if(model instanceof ReflectionImport==!1)throw new UnexpectedParseResult("an import definition");return model}parseExport(code){const model=this.parseFirst(code);if(model instanceof ReflectionExport==!1)throw new UnexpectedParseResult("an export definition");return model}parseDeclaration(code){const model=this.parseFirst(code);if(model instanceof ReflectionDeclaration==!1)throw new UnexpectedParseResult("a declaration definition");return model}parseFunction(code){const tokenList=this.#lexer.tokenize(code),model=this.#parseMember(tokenList);if(model instanceof ReflectionFunction==!1)throw new UnexpectedParseResult("a function definition");return model}parseClass(code){const tokenList=this.#lexer.tokenize(code),model=this.#parseMember(tokenList);if(model instanceof ReflectionClass==!1)throw new UnexpectedParseResult("a class definition");return model}#parseScope(tokenList){const members=[];for(;tokenList.notAtEnd();){const member=this.#parseNext(tokenList);member instanceof ReflectionMember&&members.push(member)}return new ReflectionScope(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 void 0!==next&&next.hasValue(Operator.ARROW)?this.#parseArrowFunction(tokenList,isAsync):this.#parseExpression(tokenList)}if(token.isType(TokenType.KEYWORD))return token.hasValue(Keyword.ASYNC)?(tokenList.step(),this.#parseNext(tokenList,!0)):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 void 0!==next&&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 ReflectionImport(members,token.value);if(token.hasValue(Group.OPEN)){token=tokenList.step();const from=token.value;return tokenList.step(2),new ReflectionImport(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 ReflectionAlias(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 ReflectionImport(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=token.isType(TokenType.IDENTIFIER)?token.value:"",as=isDefault?"default":name;let from;token=tokenList.step(),void 0!==token&&token.hasValue(Keyword.FROM)&&(token=tokenList.step(),from=token.value),stepSize>0&&(stepSize++,tokenList.stepBack(stepSize));const alias=new ReflectionAlias(name,as);return new ReflectionExport([alias],from)}#parseMultiExport(tokenList){const members=this.#parseAliasList(tokenList);let from,token=tokenList.current;return void 0!==token&&token.hasValue(Keyword.FROM)&&(token=tokenList.step(),from=token.value),tokenList.step(),new ReflectionExport(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 ReflectionAlias(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 ReflectionGenerator?new ReflectionGenerator(identifier.toString(),value.parameters,value.body,isStatic,value.isAsync,isPrivate):value instanceof ReflectionFunction?new ReflectionFunction(identifier.toString(),value.parameters,value.body,isStatic,value.isAsync,isPrivate):value instanceof ReflectionClass?new ReflectionClass(identifier.toString(),value.parentName,value.scope):new ReflectionDeclaration(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()),token.isType(TokenType.IDENTIFIER)&&(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 ReflectionGenerator(name,parameters,body,isStatic,isAsync,isPrivate):isGetter?new ReflectionGetter(name,parameters,body,isStatic,isAsync,isPrivate):isSetter?new ReflectionSetter(name,parameters,body,isStatic,isAsync,isPrivate):new ReflectionFunction(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 ReflectionField(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 ReflectionFunction("",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(token.isType(TokenType.IDENTIFIER)&&(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 ReflectionClass(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 ReflectionScope(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 ReflectionArray(items)}#parseDestructuredArray(tokenList){const fields=this.#parseParameters(tokenList,List.CLOSE);return new ReflectionDestructuredArray(fields)}#parseObject(tokenList){const fields=this.#parseBlock(tokenList,Scope.OPEN,Scope.CLOSE);return new ReflectionObject(fields)}#parseDestructuredObject(tokenList){const fields=this.#parseParameters(tokenList,Scope.CLOSE);return new ReflectionDestructuredObject(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 ReflectionField(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 ReflectionExpression(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)}}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 ReflectionClass(model.name,parent.name,new ReflectionScope(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;#merger;constructor(parser=new Parser,merger=new ClassMerger){this.#parser=parser,this.#merger=merger}parse(code){return this.#parser.parse(code)}parseClass(code){return this.#parser.parseClass(code)}parseFunction(code){return this.#parser.parseFunction(code)}parseDeclaration(code){return this.#parser.parseDeclaration(code)}parseImport(code){return this.#parser.parseImport(code)}parseExport(code){return this.#parser.parseExport(code)}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 ReflectionExpression(code);members.push(new ReflectionDeclaration(key,expression))}}return new ReflectionModule(new ReflectionScope(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.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.parseClass(code)}#reflectDynamic(clazz){const object=this.createInstance(clazz),members=this.#getMembers(clazz,object),scope=new ReflectionScope(members);return new ReflectionClass(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 ReflectionValue(String(content)):void 0,model=new ReflectionDeclaration(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 ReflectionGetter(model.name,model.parameters,model.body,model.isStatic,model.isAsync,model.isPrivate)):void 0!==description.set?models.push(new ReflectionSetter(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{#classLoader;constructor(classLoader){super(),this.#classLoader=classLoader}canSerialize(value){return value instanceof Object&&reflector$1.isClassObject(value)}canDeserialize(value){const object=value;return object instanceof Object&&!0===object.serialized&&"string"==typeof object.name&&object.args instanceof Array&&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.#extractParameterNames(model);return{serialized:!0,name:clazz.name,source:clazz.source,args:await this.#extractArguments(model,parameterNames,object),fields:await this.#extractFields(model,parameterNames,object)}}#extractParameterNames(model){const constructor=model.getFunction("constructor");return(constructor?.parameters??[]).map((parameter=>parameter.name))}async#extractArguments(model,includeNames,object){const args=[];for(const name of includeNames){const objectValue=model.canRead(name)?await this.serializeOther(object[name]):void 0;args.push(objectValue)}return args}async#extractFields(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.name);if(clazz instanceof Function==!1)throw new InvalidClass(object.name);const args=await Promise.all(object.args.map((async value=>this.deserializeOther(value)))),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#getClass(clazz){return void 0===clazz.source?globalThis[clazz.name]:this.#classLoader.loadClass(clazz)}}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)}}}const defaultClassLoader=new class{async loadClass(loadable){if("string"!=typeof loadable.source)throw new ClassNotFound(loadable.name);const module=await import(loadable.source),clazz=module[loadable.name]??module.default;if(void 0===clazz)throw new ClassNotFound(loadable.name);if(clazz instanceof Function==!1)throw new InvalidClass(loadable.name);return clazz}};class SerializerBuilder{static build(loader=defaultClassLoader){const serializer=new Serializer;return serializer.addSerializer(new PrimitiveSerializer),serializer.addSerializer(new ObjectSerializer),serializer.addSerializer(new ClassSerializer(loader)),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 RemoteClassLoader{async loadClass(loadable){if("string"!=typeof loadable.source)throw new ClassNotFound(loadable.name);const module=await ModuleLoader.load(loadable.source),clazz=module[loadable.name]??module.default;if(void 0===clazz)throw new ClassNotFound(loadable.name);if(clazz instanceof Function==!1)throw new InvalidClass(loadable.name);return clazz}}const remoteClassLoader=new RemoteClassLoader,defaultSerializer=SerializerBuilder.build(remoteClassLoader);class Remote{#url;#serializer;constructor(url,serializer=defaultSerializer){this.#url=url,this.#serializer=serializer}async registerClient(segmentFiles){const url=`${this.#url}/modules`,options={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(segmentFiles)};return(await this.#callRemote(url,options,200)).text()}async loadFile(filename){const url=`${this.#url}/${filename}`,response=await this.#callRemote(url,{method:"GET"},200),type=response.headers.get("Content-Type")||"application/octet-stream",content=await response.text();return new File(filename,type,content)}async isHealthy(){const url=`${this.#url}/health/status`,response=await this.#callRemote(url,{method:"GET"},200),healthy=await response.text();return Boolean(healthy)}async getHealth(){const url=`${this.#url}/health`,response=await this.#callRemote(url,{method:"GET"},200),health=await response.json();return new Map(Object.entries(health))}async addNode(node){const url=`${this.#url}/nodes`,body={url:node.url,procedureNames:node.getProcedureNames()},options={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(body)};await this.#callRemote(url,options,201)}async run(request){request.setHeader("content-type","application/json");const versionString=request.version.toString(),argsObject=Object.fromEntries(request.args),headersObject=Object.fromEntries(request.headers),url=`${this.#url}/rpc/${request.fqn}?version=${versionString}&serialize=true`,options={method:"POST",headers:headersObject,body:await this.#createRequestBody(argsObject)},response=await this.#callRemote(url,options,200),result=await this.#createResponseResult(response);return new Response(result)}async#callRemote(url,options,expectedStatus){const response=await fetch(url,options);if(response.status!==expectedStatus)throw await this.#createResponseResult(response);return response}async#createRequestBody(body){const data=await this.#serializer.serialize(body);return JSON.stringify(data)}async#createResponseResult(response){const result=await this.#getResponseResult(response);return this.#serializer.deserialize(result)}#getResponseResult(response){const contentType=response.headers.get("Content-Type");return null!==contentType&&contentType.includes("json")?response.json():response.text()}}class DummyRepository extends Repository{async start(){}async stop(){}async registerClient(segmentFiles){throw new RepositoryNotAvailable}async readAsset(filename){throw new RepositoryNotAvailable}async readModule(filename,clientId){throw new RepositoryNotAvailable}async loadModule(filename){throw new RepositoryNotAvailable}}class RemoteGateway extends Gateway{#remote;#node;constructor(url){super(new DummyRepository,url),this.#remote=new Remote(url)}get node(){return this.#node}set node(node){this.#node=node}async start(){await super.start(),void 0!==this.#node&&await this.addNode(this.#node)}getProcedureNames(){throw new NotImplemented}hasProcedure(name){throw new NotImplemented}addNode(node){return this.#remote.addNode(node)}run(request){return this.#remote.run(request)}}class RemoteRepository extends Repository{#remote;#segmentNames=new Set;constructor(url){super(url),this.#remote=new Remote(url)}get segmentNames(){return[...this.#segmentNames.values()]}set segmentNames(segmentNames){this.#segmentNames=segmentNames}async start(){const clientId=await this.registerClient(this.segmentNames),baseUrl=this.#getModuleBaseUrl(clientId);ModuleLoader.setBaseUrl(baseUrl),await super.start()}registerClient(segmentFiles){return this.#remote.registerClient(segmentFiles)}readAsset(filename){return this.#remote.loadFile(filename)}readModule(filename,clientId){return this.#remote.loadFile(`modules/${clientId}/${filename}`)}loadModule(filename){return ModuleLoader.load(filename)}#getModuleBaseUrl(clientId){return`${this.url}/modules/${clientId}`}}class RuntimeNotBuilt extends ServerError{constructor(reason){super(`Building the runtime failed: ${reason}`)}}RuntimeNotBuilt.source="/jitar/client.js";const globals=globalThis;globals.__import=async function(name,scope,extractDefault=!0){const runtime=getRuntime();RUNS_IN_BROWSER&&"jitar"===name&&(name="/jitar/client.js");const module=await runtime.import(name,scope);return extractDefault&&void 0!==module.default?module.default:module},globals.__run=async function(fqn,versionNumber,args,sourceRequest){const runtime=getRuntime(),version=VersionParser.parse(versionNumber),argsMap=new Map(Object.entries(args)),headersMap=sourceRequest instanceof Request?sourceRequest.headers:new Map,targetRequest=new Request(fqn,version,argsMap,headersMap);return(await runtime.run(targetRequest)).result},globals.ProcedureNotAccessible=ProcedureNotAccessible;export{ModuleNotAccessible as $,AccessLevels as A,BadRequest as B,ClientNotFound as C,DummyRepository as D,RemoteClassLoader as E,FileNotFound as F,Gateway as G,ExecutionScopes as H,InvalidSegmentFile as I,Response as J,NamedParameter as K,LocalNode as L,ModuleLoader as M,NoNodeAvailable as N,ArrayParameter as O,ProcedureNotFound as P,ObjectParameter as Q,Repository as R,SerializerBuilder as S,Teapot as T,Unauthorized as U,VersionParser as V,ServerError as W,ImplementationNotFound as X,InvalidParameterValue as Y,InvalidVersionNumber as Z,MissingParameterValue as _,InvalidClientId as a,ModuleNotLoaded as a0,ProcedureNotAccessible as a1,RepositoryNotAvailable as a2,RuntimeNotAvailable as a3,SegmentNotFound as a4,UnknownParameter as a5,File as b,convertToRemoteFilename as c,convertToLocalFilename as d,createRepositoryFilename as e,ProcedureRuntime as f,Node as g,Remote as h,isSegmentFilename as i,RemoteRepository as j,RemoteGateway as k,RuntimeNotBuilt as l,Reflector as m,ReflectionField as n,ReflectionDestructuredArray as o,ReflectionDestructuredObject as p,ReflectionDestructuredValue as q,createNodeFilename as r,ReflectionFunction as s,Files as t,PaymentRequired as u,Forbidden as v,NotFound as w,NotImplemented as x,Version as y,Request as z};
|
package/dist/lib.d.ts
CHANGED
|
@@ -1,4 +1,18 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
|
+
declare const AccessLevels: {
|
|
3
|
+
readonly PRIVATE: "private";
|
|
4
|
+
readonly PUBLIC: "public";
|
|
5
|
+
};
|
|
6
|
+
type Keys$1 = keyof typeof AccessLevels;
|
|
7
|
+
type AccessLevel = typeof AccessLevels[Keys$1];
|
|
8
|
+
|
|
9
|
+
declare const ExecutionScopes: {
|
|
10
|
+
readonly APPLICATION: "application";
|
|
11
|
+
readonly RUNTIME: "runtime";
|
|
12
|
+
};
|
|
13
|
+
type Keys = keyof typeof ExecutionScopes;
|
|
14
|
+
type ExecutionScope = typeof ExecutionScopes[Keys];
|
|
15
|
+
|
|
2
16
|
declare class BadRequest extends Error {
|
|
3
17
|
constructor(message?: string);
|
|
4
18
|
}
|
|
@@ -142,6 +156,7 @@ declare class File {
|
|
|
142
156
|
}
|
|
143
157
|
|
|
144
158
|
interface HealthCheck {
|
|
159
|
+
get name(): string;
|
|
145
160
|
get timeout(): number | undefined;
|
|
146
161
|
isHealthy(): Promise<boolean>;
|
|
147
162
|
}
|
|
@@ -159,10 +174,38 @@ declare class Version {
|
|
|
159
174
|
toString(): string;
|
|
160
175
|
}
|
|
161
176
|
|
|
162
|
-
|
|
177
|
+
declare class Request {
|
|
178
|
+
#private;
|
|
179
|
+
constructor(fqn: string, version: Version, args: Map<string, unknown>, headers: Map<string, string>);
|
|
180
|
+
get fqn(): string;
|
|
181
|
+
get version(): Version;
|
|
182
|
+
get args(): Map<string, unknown>;
|
|
183
|
+
get headers(): Map<string, string>;
|
|
184
|
+
setArgument(name: string, value: unknown): void;
|
|
185
|
+
getArgument(name: string): unknown;
|
|
186
|
+
removeArgument(name: string): void;
|
|
187
|
+
clearHeaders(): void;
|
|
188
|
+
setHeader(name: string, value: string): void;
|
|
189
|
+
getHeader(name: string): string | undefined;
|
|
190
|
+
removeHeader(name: string): void;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
declare class Response {
|
|
194
|
+
#private;
|
|
195
|
+
constructor(result?: unknown, headers?: Map<any, any>);
|
|
196
|
+
get result(): unknown;
|
|
197
|
+
set result(value: unknown);
|
|
198
|
+
get headers(): Map<string, string>;
|
|
199
|
+
clearHeaders(): void;
|
|
200
|
+
setHeader(name: string, value: string): void;
|
|
201
|
+
getHeader(name: string): string | undefined;
|
|
202
|
+
removeHeader(name: string): void;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
type NextHandler = () => Promise<Response>;
|
|
163
206
|
|
|
164
207
|
interface Middleware {
|
|
165
|
-
handle(
|
|
208
|
+
handle(request: Request, next: NextHandler): Promise<Response>;
|
|
166
209
|
}
|
|
167
210
|
|
|
168
211
|
declare class Parameter {
|
|
@@ -183,7 +226,7 @@ declare class ArrayParameter extends DestructuredParameter {
|
|
|
183
226
|
|
|
184
227
|
declare class Implementation {
|
|
185
228
|
#private;
|
|
186
|
-
constructor(version: Version, access:
|
|
229
|
+
constructor(version: Version, access: AccessLevel, parameters: Parameter[], executable: Function);
|
|
187
230
|
get version(): Version;
|
|
188
231
|
get public(): boolean;
|
|
189
232
|
get parameters(): Parameter[];
|
|
@@ -216,27 +259,46 @@ declare class Segment {
|
|
|
216
259
|
}
|
|
217
260
|
|
|
218
261
|
interface Runner {
|
|
219
|
-
run(
|
|
262
|
+
run(request: Request): Promise<Response>;
|
|
220
263
|
}
|
|
221
264
|
|
|
265
|
+
type Module = Record<string, unknown>;
|
|
266
|
+
|
|
222
267
|
declare abstract class Runtime {
|
|
223
268
|
#private;
|
|
224
269
|
constructor(url?: string);
|
|
225
270
|
get url(): string | undefined;
|
|
226
|
-
|
|
271
|
+
set healthCheckFiles(filenames: Set<string>);
|
|
272
|
+
abstract import(url: string, scope: ExecutionScope): Promise<Module>;
|
|
273
|
+
start(): Promise<void>;
|
|
274
|
+
stop(): Promise<void>;
|
|
275
|
+
addHealthCheck(healthCheck: HealthCheck): void;
|
|
227
276
|
isHealthy(): Promise<boolean>;
|
|
228
277
|
getHealth(): Promise<Map<string, boolean>>;
|
|
229
278
|
}
|
|
230
279
|
|
|
280
|
+
declare abstract class Repository extends Runtime {
|
|
281
|
+
import(url: string, scope: ExecutionScope): Promise<Module>;
|
|
282
|
+
abstract registerClient(segmentFiles: string[]): Promise<string>;
|
|
283
|
+
abstract readAsset(filename: string): Promise<File>;
|
|
284
|
+
abstract readModule(name: string, clientId: string): Promise<File>;
|
|
285
|
+
abstract loadModule(name: string): Promise<Module>;
|
|
286
|
+
}
|
|
287
|
+
|
|
231
288
|
declare abstract class ProcedureRuntime extends Runtime implements Runner {
|
|
232
289
|
#private;
|
|
233
|
-
constructor(url?: string);
|
|
290
|
+
constructor(repository: Repository, url?: string);
|
|
291
|
+
get repository(): Repository;
|
|
292
|
+
set middlewareFiles(filenames: Set<string>);
|
|
293
|
+
start(): Promise<void>;
|
|
294
|
+
stop(): Promise<void>;
|
|
234
295
|
abstract getProcedureNames(): string[];
|
|
235
296
|
abstract hasProcedure(name: string): boolean;
|
|
236
|
-
abstract run(
|
|
297
|
+
abstract run(request: Request): Promise<Response>;
|
|
298
|
+
import(url: string, scope: ExecutionScope): Promise<Module>;
|
|
237
299
|
addMiddleware(middleware: Middleware): void;
|
|
238
300
|
getMiddleware(type: Function): Middleware | undefined;
|
|
239
|
-
handle(
|
|
301
|
+
handle(request: Request): Promise<Response>;
|
|
240
302
|
}
|
|
241
303
|
|
|
242
304
|
declare abstract class Node extends ProcedureRuntime {
|
|
@@ -246,16 +308,6 @@ declare abstract class Gateway extends ProcedureRuntime {
|
|
|
246
308
|
abstract addNode(node: Node): Promise<void>;
|
|
247
309
|
}
|
|
248
310
|
|
|
249
|
-
type Module = Record<string, unknown>;
|
|
250
|
-
|
|
251
|
-
declare abstract class Repository extends Runtime {
|
|
252
|
-
abstract registerClient(segmentFiles: string[]): Promise<string>;
|
|
253
|
-
abstract loadAsset(filename: string): Promise<File>;
|
|
254
|
-
abstract getModuleLocation(clientId: string): Promise<string>;
|
|
255
|
-
abstract loadModule(clientId: string, filename: string): Promise<File>;
|
|
256
|
-
abstract importModule(clientId: string, filename: string): Promise<Module>;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
311
|
declare class ArgumentExtractor {
|
|
260
312
|
#private;
|
|
261
313
|
extract(parameters: Parameter[], args: Map<string, unknown>): unknown[];
|
|
@@ -263,15 +315,14 @@ declare class ArgumentExtractor {
|
|
|
263
315
|
|
|
264
316
|
declare class LocalNode extends Node {
|
|
265
317
|
#private;
|
|
266
|
-
constructor(url?: string, argumentConstructor?: ArgumentExtractor);
|
|
318
|
+
constructor(repository: Repository, gateway?: Gateway, url?: string, argumentConstructor?: ArgumentExtractor);
|
|
319
|
+
set segmentNames(names: Set<string>);
|
|
320
|
+
start(): Promise<void>;
|
|
321
|
+
stop(): Promise<void>;
|
|
267
322
|
getProcedureNames(): string[];
|
|
268
|
-
loadSegment(name: string): Promise<void>;
|
|
269
323
|
addSegment(segment: Segment): void;
|
|
270
324
|
hasProcedure(fqn: string): boolean;
|
|
271
|
-
|
|
272
|
-
setRepository(repository: Repository, segmentNames: string[]): Promise<void>;
|
|
273
|
-
import(url: string, base?: string): Promise<Module>;
|
|
274
|
-
run(fqn: string, version: Version, args: Map<string, unknown>, headers: Map<string, string>): Promise<unknown>;
|
|
325
|
+
run(request: Request): Promise<Response>;
|
|
275
326
|
}
|
|
276
327
|
|
|
277
328
|
type Loadable = {
|
|
@@ -306,13 +357,12 @@ type ModuleImporter = (name: string) => Promise<Module>;
|
|
|
306
357
|
declare function startClient(remoteUrl: string, segmentNames?: string[]): Promise<LocalNode>;
|
|
307
358
|
declare function getClient(): Promise<LocalNode>;
|
|
308
359
|
|
|
309
|
-
declare function
|
|
310
|
-
|
|
311
|
-
declare function runProcedure(fqn: string, versionNumber: string, args: object, context?: object): Promise<unknown>;
|
|
360
|
+
declare function importModule(name: string, scope: ExecutionScope, extractDefault?: boolean): Promise<unknown>;
|
|
361
|
+
declare function runProcedure(fqn: string, versionNumber: string, args: object, sourceRequest?: Request): Promise<unknown>;
|
|
312
362
|
|
|
313
363
|
declare global {
|
|
314
|
-
const
|
|
315
|
-
const
|
|
364
|
+
const __import: typeof importModule;
|
|
365
|
+
const __run: typeof runProcedure;
|
|
316
366
|
}
|
|
317
367
|
|
|
318
368
|
declare class CorsMiddleware implements Middleware {
|
|
@@ -321,7 +371,7 @@ declare class CorsMiddleware implements Middleware {
|
|
|
321
371
|
get allowOrigin(): string;
|
|
322
372
|
get allowMethods(): string;
|
|
323
373
|
get allowHeaders(): string;
|
|
324
|
-
handle(
|
|
374
|
+
handle(request: Request, next: NextHandler): Promise<Response>;
|
|
325
375
|
}
|
|
326
376
|
|
|
327
377
|
declare class JitarServer {
|
|
@@ -330,11 +380,10 @@ declare class JitarServer {
|
|
|
330
380
|
get classLoader(): ClassLoader;
|
|
331
381
|
build(): Promise<void>;
|
|
332
382
|
start(): Promise<void>;
|
|
333
|
-
|
|
383
|
+
stop(): Promise<void>;
|
|
334
384
|
addSerializer(serializer: ValueSerializer): void;
|
|
335
|
-
addMiddleware(middleware: Middleware): void;
|
|
336
385
|
}
|
|
337
386
|
|
|
338
387
|
declare function buildServer(moduleImporter: ModuleImporter): Promise<JitarServer>;
|
|
339
388
|
|
|
340
|
-
export { ArrayParameter, BadRequest, ClientNotFound, CorsMiddleware, FileNotFound, Forbidden, type HealthCheck, Implementation, ImplementationNotFound, InvalidClientId, InvalidParameterValue, InvalidSegmentFile, InvalidVersionNumber, type Middleware, MissingParameterValue, ModuleNotAccessible, ModuleNotLoaded, NamedParameter, type NextHandler, NoNodeAvailable, NotFound, NotImplemented, ObjectParameter, PaymentRequired, Procedure, ProcedureNotAccessible, ProcedureNotFound, RepositoryNotAvailable, RuntimeNotAvailable, Segment, SegmentNotFound, ServerError, Teapot, Unauthorized, UnknownParameter, Version, buildServer, getClient, startClient };
|
|
389
|
+
export { ArrayParameter, BadRequest, ClientNotFound, CorsMiddleware, FileNotFound, Forbidden, type HealthCheck, Implementation, ImplementationNotFound, InvalidClientId, InvalidParameterValue, InvalidSegmentFile, InvalidVersionNumber, type Middleware, MissingParameterValue, ModuleNotAccessible, ModuleNotLoaded, NamedParameter, type NextHandler, NoNodeAvailable, NotFound, NotImplemented, ObjectParameter, PaymentRequired, Procedure, ProcedureNotAccessible, ProcedureNotFound, RepositoryNotAvailable, Request, Response, RuntimeNotAvailable, Segment, SegmentNotFound, ServerError, Teapot, Unauthorized, UnknownParameter, Version, buildServer, getClient, startClient };
|
package/dist/server.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{R as Repository,M as ModuleLoader,I as InvalidSegmentFile,F as FileNotFound,a as InvalidClientId,C as ClientNotFound,i as isSegmentFilename,c as convertToLocalFilename,b as File,d as convertToRemoteFilename,e as createRepositoryFilename,P as ProcedureRuntime,N as Node,f as Remote,g as Reflector,A as AccessLevel,h as ReflectionField,j as ReflectionDestructuredArray,k as ReflectionDestructuredObject,l as ReflectionDestructuredValue,m as createNodeFilename,V as VersionParser,n as ReflectionFunction,o as Files,L as LocalGateway,p as LocalNode,q as RemoteRepository,r as RemoteGateway,B as BadRequest,U as Unauthorized,s as PaymentRequired,t as Forbidden,u as NotFound,T as Teapot,v as NotImplemented,w as Version,x as RemoteClassLoader,S as SerializerBuilder}from"./globals-a24096f0.js";import express from"express";import{readFileSync}from"fs";import{z}from"zod";import fs from"fs-extra";import glob from"glob-promise";import mime from"mime-types";import path from"path";import yargs from"yargs";import{Logger}from"tslog";import{fileURLToPath}from"url";import expressProxy from"express-http-proxy";class CorsMiddleware{#allowOrigin;#allowMethods="GET, POST";#allowHeaders;constructor(origin="*",headers="*"){this.#allowOrigin=origin,this.#allowHeaders=headers}get allowOrigin(){return this.#allowOrigin}get allowMethods(){return this.#allowMethods}get allowHeaders(){return this.#allowHeaders}async handle(fqn,version,args,headers,next){const result=await next();return this.#setHeaders(headers),result}#setHeaders(headers){headers.set("Access-Control-Allow-Origin",this.#allowOrigin),headers.set("Access-Control-Allow-Methods",this.#allowMethods),headers.set("Access-Control-Allow-Headers",this.#allowHeaders)}}const CLIENT_ID_REGEX=/^CLIENT_\d+$/;let lastClientId=0;class ClientIdHelper{generate(){return"CLIENT_"+lastClientId++}validate(clientId){return CLIENT_ID_REGEX.test(clientId)}}const clientIdHelper$1=new ClientIdHelper;class LocalRepository extends Repository{#fileManager;#segments=new Map;#clients=new Map;#assets;constructor(fileManager,assets,url){super(url),this.#fileManager=fileManager,this.#assets=assets}async loadSegment(name){const filename=`./${createRepositoryFilename(name)}`,location=this.#fileManager.getAbsoluteLocation(filename),files=(await ModuleLoader.load(location)).files;if(void 0===files)throw new InvalidSegmentFile(location);this.registerSegment(name,files)}async registerSegment(name,files){files.forEach((file=>this.#segments.set(file,name)))}async registerClient(segmentFilenames){const clientId=clientIdHelper$1.generate();return this.#clients.set(clientId,segmentFilenames),clientId}loadAsset(filename){if(!1===this.#assets.includes(filename))throw new FileNotFound(filename);return this.#readFile(filename)}async getModuleLocation(clientId){return this.#fileManager.getRootLocation()}loadModule(clientId,filename){this.#validateClientId(clientId);const segmentFilename=this.#segments.get(filename);return void 0===segmentFilename||this.#hasClientSegmentFile(clientId,segmentFilename)?this.#getNodeModule(filename):this.#getRemoteModule(filename)}importModule(clientId,filename){filename=ModuleLoader.assureExtension(filename);const location=this.#fileManager.getAbsoluteLocation(filename);return ModuleLoader.import(location)}#validateClientId(clientId){if(!1===clientIdHelper$1.validate(clientId))throw new InvalidClientId(clientId);if(!1===this.#clients.has(clientId))throw new ClientNotFound(clientId)}#hasClientSegmentFile(clientId,segmentFilename){const clientSegmentFiles=this.#clients.get(clientId);if(void 0===clientSegmentFiles)throw new ClientNotFound(clientId);return clientSegmentFiles.some((clientSegmentFilename=>segmentFilename.endsWith(clientSegmentFilename)))}async#getNodeModule(filename){const localFilename=isSegmentFilename(filename)?filename:convertToLocalFilename(filename),code=(await this.#readFile(localFilename)).content.toString();return new File(filename,"application/javascript",code)}#getRemoteModule(filename){const remoteFilename=convertToRemoteFilename(filename);return this.#readFile(remoteFilename)}#readFile(filename){return this.#fileManager.read(filename)}}class NodeMonitor{#gateway;#frequency;#interval=null;constructor(gateway,frequency=5e3){this.#gateway=gateway,this.#frequency=frequency}start(){this.#interval=setInterval((async()=>this.#monitor()),this.#frequency)}stop(){null!==this.#interval&&clearInterval(this.#interval)}async#monitor(){const promises=this.#gateway.nodes.map((async node=>this.#monitorNode(node)));await Promise.all(promises)}async#monitorNode(node){!1===await this.#checkNodeAvailable(node)&&this.#gateway.removeNode(node)}async#checkNodeAvailable(node){try{return await node.isHealthy()}catch(error){return!1}}}class Proxy extends ProcedureRuntime{#repository;#runner;constructor(repository,runner,url){super(url),this.#repository=repository,this.#runner=runner}get repository(){return this.#repository}get runner(){return this.#runner}getProcedureNames(){return this.#runner.getProcedureNames()}hasProcedure(fqn){return this.getProcedureNames().includes(fqn)}loadAsset(filename){return this.#repository.loadAsset(filename)}registerClient(segmentFiles){return this.#repository.registerClient(segmentFiles)}loadModule(clientId,filename){return this.#repository.loadModule(clientId,filename)}run(name,version,args,headers){return this.#runner.run(name,version,args,headers)}}class RemoteNode extends Node{#remote;#procedureNames=new Set;constructor(url,procedureNames){super(url),this.#remote=new Remote(url),this.registerProcedures(procedureNames)}getProcedureNames(){return[...this.#procedureNames.values()]}registerProcedures(procedureNames){procedureNames.forEach((procedureName=>this.#procedureNames.add(procedureName)))}hasProcedure(name){return this.#procedureNames.has(name)}isHealthy(){return this.#remote.isHealthy()}getHealth(){return this.#remote.getHealth()}run(fqn,version,args,headers){return this.#remote.run(fqn,version,args,headers)}}const gatewaySchema=z.object({monitor:z.number().optional(),repository:z.string().url().optional()}).strict().transform((value=>new GatewayConfiguration(value.monitor,value.repository)));class GatewayConfiguration{#monitor;#repository;constructor(monitor,repository){this.#monitor=monitor,this.#repository=repository}get monitor(){return this.#monitor}get repository(){return this.#repository}}const nodeSchema=z.object({gateway:z.string().url().optional(),repository:z.string().url().optional(),segments:z.array(z.string()).nonempty()}).strict().transform((value=>new NodeConfiguration(value.gateway,value.repository,value.segments)));class NodeConfiguration{#gateway;#repository;#segments;constructor(gateway,repository,segments){this.#gateway=gateway,this.#repository=repository,this.#segments=segments}get gateway(){return this.#gateway}get repository(){return this.#repository}get segments(){return this.#segments}}const proxySchema=z.object({node:z.string().url().optional(),gateway:z.string().url().optional(),repository:z.string().url()}).strict().superRefine(((value,ctx)=>{void 0===value.node&&void 0===value.gateway&&ctx.addIssue({code:z.ZodIssueCode.custom,message:"Either node or gateway must be defined",path:["node","gateway"]}),void 0!==value.node&&void 0!==value.gateway&&ctx.addIssue({code:z.ZodIssueCode.custom,message:"Only node or gateway must be defined",path:["node","gateway"]})})).transform((value=>new ProxyConfiguration(value.node,value.gateway,value.repository)));class ProxyConfiguration{#node;#gateway;#repository;constructor(node,gateway,repository){this.#node=node,this.#gateway=gateway,this.#repository=repository}get node(){return this.#node}get gateway(){return this.#gateway}get repository(){return this.#repository}}const repositorySchema=z.object({source:z.string().optional(),cache:z.string().optional(),index:z.string().optional(),assets:z.array(z.string()).optional()}).strict().transform((value=>new RepositoryConfiguration(value.source,value.cache,value.index,value.assets)));class RepositoryConfiguration{#source;#cache;#index;#assets;constructor(source,cache,index,assets){this.#source=source,this.#cache=cache,this.#index=index,this.#assets=assets}get source(){return this.#source}get cache(){return this.#cache}get index(){return this.#index}get assets(){return this.#assets}}const standaloneSchema=z.object({source:z.string().optional(),cache:z.string().optional(),index:z.string().optional(),segments:z.array(z.string()).optional(),assets:z.array(z.string()).optional()}).strict().transform((value=>new StandaloneConfiguration(value.source,value.cache,value.index,value.segments,value.assets)));class StandaloneConfiguration{#source;#cache;#index;#segments;#assets;constructor(source,cache,index,segments,assets){this.#source=source,this.#cache=cache,this.#index=index,this.#segments=segments,this.#assets=assets}get source(){return this.#source}get cache(){return this.#cache}get index(){return this.#index}get segments(){return this.#segments}get assets(){return this.#assets}}const runtimeSchema=z.object({url:z.string().optional(),healthChecks:z.array(z.string()).optional(),standalone:standaloneSchema.optional(),repository:repositorySchema.optional(),gateway:gatewaySchema.optional(),node:nodeSchema.optional(),proxy:proxySchema.optional()}).strict().transform((value=>new RuntimeConfiguration(value.url,value.healthChecks,value.standalone,value.repository,value.gateway,value.node,value.proxy)));class RuntimeConfiguration{#url;#healthChecks;#standalone;#repository;#gateway;#node;#proxy;constructor(url,healthChecks,standalone,repository,gateway,node,proxy){this.#url=url,this.#healthChecks=healthChecks,this.#standalone=standalone,this.#repository=repository,this.#gateway=gateway,this.#node=node,this.#proxy=proxy}get url(){return this.#url}get healthChecks(){return this.#healthChecks}get standalone(){return this.#standalone}get repository(){return this.#repository}get gateway(){return this.#gateway}get node(){return this.#node}get proxy(){return this.#proxy}}class DataConverter{static convert(schema,dataObject){return schema.parse(dataObject)}}class RuntimeConfigurationLoader{static load(filename){const plainContents=readFileSync(filename,"utf-8"),parsedContents=JSON.parse(plainContents);return DataConverter.convert(runtimeSchema,parsedContents)}}class ApplicationCache{#segments;#modules;constructor(segments,modules){this.#segments=segments,this.#modules=modules}get segments(){return this.#segments}get modules(){return this.#modules}}class ModuleCache{#module;#segment;constructor(module,segment){this.#module=module,this.#segment=segment}get module(){return this.#module}get segment(){return this.#segment}}class ModuleCacheBuilder{build(application,module){const segment=application.getSegmentModule(module.filename);return new ModuleCache(module,segment)}}class DuplicateImplementation extends Error{constructor(fqn,version){super(`Duplicate implementation found for '${fqn}' with version '${version}'.`)}}class SegmentCache{#name;#imports;#procedures;#files;constructor(name,files,imports,procedures){this.#name=name,this.#files=files,this.#imports=imports,this.#procedures=procedures}get name(){return this.#name}get files(){return this.#files}get imports(){return this.#imports}get procedures(){return this.#procedures}}class SegmentImport{#members;#from;constructor(members,from){this.#members=members,this.#from=from}get members(){return this.#members}get from(){return this.#from}}class SegmentProcedure{#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 SegmentCacheBuilder{build(segment){const files=this.#extractFiles(segment),imports=this.#createImports(segment),procedures=this.#mergeProcedures(segment);return this.#validateProcedures(procedures),new SegmentCache(segment.name,files,imports,procedures)}#extractFiles(segment){return segment.modules.map((module=>module.filename))}#createImports(segment){const imports=[];for(const module of segment.modules){let members=[];for(const procedure of module.procedures){const ids=procedure.implementations.map((implementation=>this.#createImportMember(implementation)));members=[...members,...ids]}imports.push(new SegmentImport(members,module.filename))}return imports}#createImportMember(implementation){return`${implementation.importKey} as ${implementation.id}`}#mergeProcedures(segment){const procedures=new Map;for(const module of segment.modules)for(const procedure of module.procedures){if(procedures.has(procedure.fqn)){const existingProcedure=procedures.get(procedure.fqn);for(const implementation of procedure.implementations)existingProcedure.addImplementation(implementation);continue}const procedureCopy=new SegmentProcedure(procedure.fqn,[...procedure.implementations]);procedures.set(procedure.fqn,procedureCopy)}return[...procedures.values()]}#validateProcedures(procedures){for(const procedure of procedures)this.#checkForDuplicateImplementations(procedure)}#checkForDuplicateImplementations(procedure){for(const implementation of procedure.implementations){if(void 0!==procedure.implementations.find((other=>other.id!==implementation.id&&other.version===implementation.version)))throw new DuplicateImplementation(procedure.fqn,implementation.version)}}}class ApplicationCacheBuilder{#moduleCacheBuilder;#segmentCacheBuilder;constructor(){this.#moduleCacheBuilder=new ModuleCacheBuilder,this.#segmentCacheBuilder=new SegmentCacheBuilder}build(application){const segments=this.#buildSegmentCaches(application),modules=this.#buildModuleCaches(application);return new ApplicationCache(segments,modules)}#buildSegmentCaches(application){return application.segments.map((segment=>this.#segmentCacheBuilder.build(segment)))}#buildModuleCaches(application){return application.modules.map((module=>this.#moduleCacheBuilder.build(application,module)))}}const Keyword={DEFAULT:"default"};Object.freeze(Keyword);const IMPORT_PATTERN=/import\s(?:["'\s]*([\w*{}\n, ]+)from\s*)?["'\s]*([@\w/_-]+)["'\s].*/g,NON_SYSTEM_INDICATORS=[".","/","http:","https:"],reflector$2=new Reflector;const importRewriter=new class{rewrite(code,includeSystem){return code.replaceAll(IMPORT_PATTERN,(statement=>this.#replaceImport(statement,includeSystem)))}#replaceImport(statement,includeSystem){const dependency=reflector$2.parseImport(statement);return this.#isSystemDependency(dependency)?includeSystem?this.#rewriteSystemImport(dependency):statement:this.#rewriteApplicationImport(dependency)}#isSystemDependency(dependency){return!1===NON_SYSTEM_INDICATORS.some((indicator=>dependency.from.startsWith(indicator,1)))}#rewriteSystemImport(dependency){const from=this.#rewriteImportFrom(dependency);if(0===dependency.members.length)return`await __getDependency('${from}');`;return`const ${this.#rewriteImportMembers(dependency,":")} = await __getDependency('${from}');`}#rewriteApplicationImport(dependency){return`import ${this.#rewriteImportMembers(dependency,"as")} from '${this.#rewriteImportFrom(dependency)}';`}#rewriteImportMembers(dependency,aliasSpecifier){if(this.#mustUseAs(dependency))return dependency.members[0].as;return`{ ${dependency.members.map((member=>member.name!==member.as?`${member.name} ${aliasSpecifier} ${member.as}`:member.name)).join(", ")} }`}#rewriteImportFrom(dependency){const from=dependency.from.substring(1,dependency.from.length-1);return NON_SYSTEM_INDICATORS.some((indicator=>from.startsWith(indicator)))?from.endsWith(".js")?from:`${from}.js`:from}#mustUseAs(dependency){return this.#doesImportAll(dependency)||this.#doesImportDefault(dependency)}#doesImportAll(dependency){return 1===dependency.members.length&&"*"===dependency.members[0].name}#doesImportDefault(dependency){return 1===dependency.members.length&&dependency.members[0].name===Keyword.DEFAULT}},remoteBuilder=new class{build(module){let code="";for(const procedure of module.procedures)for(const implementation of procedure.implementations){const asDefault=implementation.importKey===Keyword.DEFAULT;code+=implementation.access===AccessLevel.PRIVATE?this.#createPrivateCode(procedure.fqn,implementation,asDefault):this.#createPublicCode(procedure.fqn,implementation,asDefault)}return code.trim()}#createPrivateCode(fqn,implementation,asDefault){const version=implementation.version,declaration=this.#createDeclaration(implementation,asDefault),body=`throw new ProcedureNotAccessible('${fqn}', '${version}');`;return this.#createFunction(declaration,body)}#createPublicCode(fqn,implementation,asDefault){const version=implementation.version,args=this.#createArguments(implementation.executable.parameters),declaration=this.#createDeclaration(implementation,asDefault),body=`return __runProcedure('${fqn}', '${version}', { ${args} }, this);`;return this.#createFunction(declaration,body)}#createParameters(parameters){const result=[];for(const parameter of parameters)parameter instanceof ReflectionField?result.push(parameter.name):(parameter instanceof ReflectionDestructuredArray||parameter instanceof ReflectionDestructuredObject)&&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 ReflectionDestructuredValue){const argumentz=this.#extractArguments(parameter.members);result.push(...argumentz)}else if(parameter instanceof ReflectionField){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,asDefault){const name=implementation.executable.name,parameters=this.#createParameters(implementation.executable.parameters);return`\nexport ${asDefault?`${Keyword.DEFAULT} `:""}async function ${name}(${parameters})`}#createFunction(declaration,body){return`${declaration} {\n\t${body}\n}\n`}};class ModuleCacheWriter{#fileManager;constructor(fileManager){this.#fileManager=fileManager}async write(cache){return Promise.all([this.#writeOriginal(cache),this.#writeLocal(cache),this.#writeRemote(cache)]).then((()=>{}))}async#writeOriginal(cache){const importCode=this.#rewriteApplicationImports(cache.module),sourceCode=this.#createSourceCode(cache.module),filename=cache.module.filename,code=`${importCode}\n${sourceCode}`;return this.#fileManager.write(filename,code.trim())}async#writeLocal(cache){const importCode=this.#rewriteAllImports(cache.module),sourceCode=this.#createSourceCode(cache.module),filename=convertToLocalFilename(cache.module.filename),code=`${importCode}\n${sourceCode}`;return this.#fileManager.write(filename,code.trim())}#rewriteApplicationImports(module){return importRewriter.rewrite(module.code,!1)}#rewriteAllImports(module){return importRewriter.rewrite(module.code,!0)}#createSourceCode(module){const filename=module.filename;return module.content.exportedClasses.map((clazz=>clazz.name)).map((className=>`${className}.source = "${filename}";`)).join("\n")}async#writeRemote(cache){if(void 0===cache.segment)return;const filename=convertToRemoteFilename(cache.module.filename),code=this.#createRemoteCode(cache.segment);return this.#fileManager.write(filename,code.trim())}#createRemoteCode(module){return remoteBuilder.build(module)}}class SegmentCacheWriter{#fileManager;constructor(fileManager){this.#fileManager=fileManager}async write(cache){return Promise.all([this.#writeNodeCache(cache),this.#writeRepositoryCache(cache)]).then((()=>{}))}async#writeNodeCache(cache){const importCode=this.#createImportCode(cache.imports),segmentCode=this.#createSegmentCode(cache.name,cache.procedures),filename=createNodeFilename(cache.name),code=`${importCode}\n${segmentCode}`;return this.#fileManager.write(filename,code)}async#writeRepositoryCache(cache){const filename=createRepositoryFilename(cache.name),code=`export const files = [\n\t"${[...cache.files].join('",\n\t"')}"\n];`;return this.#fileManager.write(filename,code)}#createImportCode(imports){const codes=[];for(const{members:members,from:from}of imports)codes.push(`import { ${members.join(", ")} } from "./${from}";`);return codes.join("\n")}#createSegmentCode(name,procedures){const codes=[];codes.push('const { Segment, Procedure, Implementation, Version, NamedParameter, ArrayParameter, ObjectParameter } = await __getDependency("jitar");'),codes.push(`export const segment = new Segment("${name}")`);for(const procedure of procedures){codes.push(`\t.addProcedure(new Procedure("${procedure.fqn}")`);for(const implementation of procedure.implementations){const version=this.#createVersionCode(implementation.version),parameters=this.#createParametersCode(implementation.executable);codes.push(`\t\t.addImplementation(new Implementation(${version}, "${implementation.access}", ${parameters}, ${implementation.id}))`)}codes.push("\t)")}return codes.join("\n")}#createVersionCode(versionString){const version=VersionParser.parse(versionString);return`new Version(${version.major}, ${version.minor}, ${version.patch})`}#createParametersCode(executable){return`[${this.#extractParameters(executable.parameters).join(", ")}]`}#extractParameters(parameters){const result=[];for(const parameter of parameters)result.push(this.#extractParameter(parameter));return result}#extractParameter(parameter){return parameter instanceof ReflectionDestructuredArray?this.#createArrayParameter(parameter):parameter instanceof ReflectionDestructuredObject?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 ApplicationCacheWriter{#moduleWriter;#segmentWriter;constructor(fileManager){this.#moduleWriter=new ModuleCacheWriter(fileManager),this.#segmentWriter=new SegmentCacheWriter(fileManager)}async write(cache){return Promise.all([this.#writeSegmentCache(cache.segments),this.#writeModuleCache(cache.modules)]).then((()=>{}))}async#writeSegmentCache(segments){return Promise.all(segments.map((async segment=>this.#segmentWriter.write(segment)))).then((()=>{}))}async#writeModuleCache(modules){return Promise.all(modules.map((async module=>this.#moduleWriter.write(module)))).then((()=>{}))}}class Application{#segments;#modules;constructor(segments,modules){this.#segments=segments,this.#modules=modules}get segments(){return this.#segments}get modules(){return this.#modules}getSegmentModule(filename){const segment=this.#segments.find((segment=>segment.hasModule(filename)));if(void 0!==segment)return segment.getModule(filename)}}class ModuleFileNotLoaded extends Error{constructor(filename,message){super(`Failed to load module file '${filename}' because of: ${message}`)}}class Module{#filename;#code;#content;constructor(filename,code,content){this.#code=code,this.#filename=filename,this.#content=content}get filename(){return this.#filename}get code(){return this.#code}get content(){return this.#content}}const reflector$1=new Reflector;class ModuleReader{#fileManager;constructor(fileManager){this.#fileManager=fileManager}async read(filename){const relativeLocation=this.#fileManager.getRelativeLocation(filename),code=await this.#loadCode(filename),module=reflector$1.parse(code);return new Module(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 ModuleFileNotLoaded(filename,message)}}}class FunctionNotAsync extends Error{constructor(filename,functionName){super(`Function '${functionName}' from file '${filename}' is not async`)}}class InvalidSegmentFilename 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 SegmentFileNotLoaded extends Error{constructor(filename,message){super(`Failed to load segment file '${filename}' because of: ${message}`)}}class SegmentModuleNotLoaded extends Error{constructor(filename,message){super(`Segment module could not be loaded from '${filename}' because of: ${message}`)}}class Segment{#name;#modules;constructor(name,modules){this.#name=name,this.#modules=modules}get name(){return this.#name}get modules(){return this.#modules}hasModule(filename){return this.#modules.some((module=>module.filename===filename))}getModule(filename){return this.#modules.find((module=>module.filename===filename))}}class SegmentImplementation{#id;#importKey;#access;#version;#executable;constructor(id,importKey,access,version,executable){this.#id=id,this.#importKey=importKey,this.#access=access,this.#version=version,this.#executable=executable}get id(){return this.#id}get importKey(){return this.#importKey}get access(){return this.#access}get version(){return this.#version}get executable(){return this.#executable}}class SegmentModule{#filename;#procedures=[];constructor(filename,procedures){this.#filename=filename,this.#procedures=procedures}get filename(){return this.#filename}get procedures(){return this.#procedures}}class IdGenerator{#id=0;next(){return"$"+ ++this.#id}}const reflector=new Reflector;class SegmentReader{#fileManager;constructor(fileManager){this.#fileManager=fileManager}async read(filename){const name=this.#extractSegmentName(filename),definition=await this.#loadSegmentDefinition(filename),modules=await this.#createSegmentModules(definition);return new Segment(name,modules)}#extractSegmentName(filename){const file=filename.split("/").pop();if(void 0===file||""===file)throw new InvalidSegmentFilename(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 SegmentFileNotLoaded(filename,message)}}async#createSegmentModules(definition){const modules=[],idGenerator=new IdGenerator;for(const[filename,moduleImports]of Object.entries(definition)){const fullFilename=filename.endsWith(".js")?filename:`${filename}.js`,absoluteFilename=this.#fileManager.getAbsoluteLocation(fullFilename),module=await this.#createSegmentModule(absoluteFilename,moduleImports,idGenerator);modules.push(module)}return modules}async#createSegmentModule(absoluteFilename,imports,idGenerator){const module=await this.#loadSegmentModule(absoluteFilename),relativeFilename=this.#fileManager.getRelativeLocation(absoluteFilename),moduleName=this.#extractModuleName(relativeFilename),procedures=this.#extractSegmentProcedures(module,moduleName,imports,idGenerator);return new SegmentModule(relativeFilename,procedures)}async#loadSegmentModule(absoluteLocation){try{const code=await this.#fileManager.getContent(absoluteLocation);return reflector.parse(code.toString())}catch(error){const message=error instanceof Error?error.message:String(error);throw new SegmentModuleNotLoaded(absoluteLocation,message)}}#extractModuleName(relativeFilename){const moduleParts=relativeFilename.split("/");return moduleParts.pop(),moduleParts.join("/")}#extractSegmentProcedures(module,moduleName,imports,idGenerator){const procedures=new Map;for(const[importKey,properties]of Object.entries(imports)){const executable=module.getExported(importKey);if(void 0===executable)throw new MissingModuleExport(moduleName,importKey);if(executable instanceof ReflectionFunction==!1)continue;if(!1===executable.isAsync)throw new FunctionNotAsync(moduleName,executable.name);const procedureName=properties.as??executable.name,access=properties.access??"private",version=properties.version??"0.0.0",id=idGenerator.next(),fqn=""!==moduleName?`${moduleName}/${procedureName}`:procedureName,implementation=new SegmentImplementation(id,importKey,access,version,executable),procedure=procedures.has(fqn)?procedures.get(fqn):new SegmentProcedure(fqn);procedure.addImplementation(implementation),procedures.set(fqn,procedure)}return[...procedures.values()]}}class ApplicationReader{#moduleReader;#segmentReader;constructor(fileManager){this.#moduleReader=new ModuleReader(fileManager),this.#segmentReader=new SegmentReader(fileManager)}async read(segmentFiles,moduleFiles){return Promise.all([this.#readSegments(segmentFiles),this.#readModules(moduleFiles)]).then((([segments,modules])=>new Application(segments,modules)))}async#readSegments(segmentFiles){return Promise.all(segmentFiles.map((async segmentFile=>this.#segmentReader.read(segmentFile))))}async#readModules(moduleFiles){return Promise.all(moduleFiles.map((async moduleFile=>this.#moduleReader.read(moduleFile))))}}class CacheManager{#projectFileManager;#appFileManager;#reader;#builder;#writer;constructor(projectFileManager,appFileManager){this.#projectFileManager=projectFileManager,this.#appFileManager=appFileManager,this.#reader=new ApplicationReader(appFileManager),this.#builder=new ApplicationCacheBuilder,this.#writer=new ApplicationCacheWriter(appFileManager)}async build(){const segmentFiles=await this.#projectFileManager.filter(Files.SEGMENT_PATTERN),moduleFiles=await this.#appFileManager.filter(Files.MODULE_PATTERN),application=await this.#reader.read(segmentFiles,moduleFiles),cache=this.#builder.build(application);return this.#writer.write(cache)}}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 read(filename){const type=await this.getType(filename),content=await this.getContent(filename);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}`)}async getNodeSegmentFiles(){return this.filter("**/*.segment.node.js")}async getRepositorySegmentFiles(){return this.filter("**/*.segment.repository.js")}async getAssetFiles(patterns){const promises=patterns.map((pattern=>this.filter(pattern)));return(await Promise.all(promises)).flat().map((filename=>this.getRelativeLocation(filename))).filter((filename=>!1===this.#isGeneratedFile(filename)))}#isGeneratedFile(filename){return filename.endsWith(".local.js")||filename.endsWith(".node.js")||filename.endsWith(".repository.js")||filename.endsWith(".remote.js")}}var RuntimeDefaults;!function(RuntimeDefaults){RuntimeDefaults.URL="http://localhost:3000",RuntimeDefaults.SOURCE="./dist",RuntimeDefaults.CACHE="./.jitar",RuntimeDefaults.INDEX="index.html"}(RuntimeDefaults||(RuntimeDefaults={}));var LogLevel,RuntimeDefaults$1=RuntimeDefaults;class UnknownRuntimeMode extends Error{constructor(){super("Unknown runtime mode")}}class RuntimeConfigurator{static async configure(configuration){const url=configuration.url??RuntimeDefaults$1.URL;if(void 0!==configuration.standalone)return this.#configureStandAlone(url,configuration.standalone);if(void 0!==configuration.repository)return this.#configureRepository(url,configuration.repository);if(void 0!==configuration.gateway)return this.#configureGateway(url,configuration.gateway);if(void 0!==configuration.node)return this.#configureNode(url,configuration.node);if(void 0!==configuration.proxy)return this.#configureProxy(url,configuration.proxy);throw new UnknownRuntimeMode}static async#configureStandAlone(url,configuration){const sourceLocation=configuration.source??RuntimeDefaults$1.SOURCE,cacheLocation=configuration.cache??RuntimeDefaults$1.CACHE,assetFilePatterns=configuration.assets;await this.#buildCache(sourceLocation,cacheLocation);const segmentNames=void 0===configuration.segments?await this.#getSegmentNames(cacheLocation):configuration.segments,repository=await this.#buildRepository(url,cacheLocation,assetFilePatterns),node=await this.#buildNode(url,segmentNames,repository);return this.#buildProxy(url,repository,node)}static async#configureRepository(url,configuration){const sourceLocation=configuration.source??RuntimeDefaults$1.SOURCE,cacheLocation=configuration.cache??RuntimeDefaults$1.CACHE,assetFilePatterns=configuration.assets??[];return await this.#buildCache(sourceLocation,cacheLocation),this.#buildRepository(url,cacheLocation,assetFilePatterns)}static async#configureGateway(url,configuration){const repository=this.#getRemoteRepository(configuration.repository);return this.#buildGateway(url,configuration.monitor,repository)}static async#configureNode(url,configuration){const segmentNames=configuration.segments??[],repository=this.#getRemoteRepository(configuration.repository),gateway=this.#getRemoteGateway(configuration.gateway);return this.#buildNode(url,segmentNames,repository,gateway)}static async#configureProxy(url,configuration){const repository=this.#getRemoteRepository(configuration.repository),gateway=this.#getRemoteGateway(configuration.gateway),node=void 0!==configuration.node?new RemoteNode(configuration.node,[]):void 0,runner=gateway??node;return this.#buildProxy(url,repository,runner)}static async#buildCache(sourceLocation,cacheLocation){const projectFileManager=new LocalFileManager("./");await projectFileManager.delete(cacheLocation),await projectFileManager.copy(sourceLocation,cacheLocation);const appFileManager=new LocalFileManager(cacheLocation),cacheManager=new CacheManager(projectFileManager,appFileManager);await cacheManager.build()}static async#getSegmentNames(cacheLocation){const fileManager=new LocalFileManager(cacheLocation);return(await fileManager.getNodeSegmentFiles()).map((filename=>this.#extractSegmentName(filename)))}static#extractSegmentName(filename){const name=filename.split("/").pop()??"",endIndex=name.indexOf(".segment");return name.substring(0,endIndex)}static async#buildRepository(url,cacheLocation,assetFilePatterns){const fileManager=new LocalFileManager(cacheLocation),assetFiles=void 0!==assetFilePatterns?await fileManager.getAssetFiles(assetFilePatterns):[],repository=new LocalRepository(fileManager,assetFiles,url),segmentNames=(await fileManager.getRepositorySegmentFiles()).map((filename=>this.#extractSegmentName(filename)));for(const name of segmentNames)await repository.loadSegment(name);return repository}static async#buildGateway(url,monitorInterval,repository){const gateway=new LocalGateway(url);void 0!==repository&&await gateway.setBaseUrl(repository);return new NodeMonitor(gateway,monitorInterval).start(),gateway}static async#buildNode(url,segmentNames,repository,gateway){const node=new LocalNode(url);void 0!==repository&&await node.setRepository(repository,segmentNames);for(const segmentName of segmentNames)await node.loadSegment(segmentName);return void 0!==gateway&&node.setGateway(gateway),node}static async#buildProxy(url,repository,runner){return new Proxy(repository,runner,url)}static#getRemoteRepository(url){return void 0!==url?new RemoteRepository(url):void 0}static#getRemoteGateway(url){return void 0!==url?new RemoteGateway(url):void 0}}!function(LogLevel){LogLevel.DEBUG="debug",LogLevel.INFO="info",LogLevel.WARN="warn",LogLevel.ERROR="error",LogLevel.FATAL="fatal"}(LogLevel||(LogLevel={}));class LogBuilder{static build(level){const logConfiguration=this.#getLogConfiguration(level);return new Logger(logConfiguration)}static#getLogConfiguration(level){return{prettyLogTemplate:"{{dateIsoStr}}\t{{logLevelName}}\t",minLevel:this.#getLogLevel(level)}}static#getLogLevel(level){switch(level){case LogLevel.FATAL:return 6;case LogLevel.ERROR:return 5;case LogLevel.WARN:return 4;case LogLevel.INFO:return 3;default:return 2}}}const serverOptionsSchema=z.object({loglevel:z.nativeEnum(LogLevel).optional(),config:z.string().endsWith(".json")}).transform((value=>new ServerOptions(value.config,value.loglevel)));class ServerOptions{#config;#loglevel;constructor(config,loglevel="info"){this.#config=config,this.#loglevel=loglevel}get config(){return this.#config}get loglevel(){return this.#loglevel}}class ServerOptionsReader{static read(){const args=yargs(process.argv).argv;return DataConverter.convert(serverOptionsSchema,args)}}class AssetsController{#repository;#indexFile;#logger;constructor(app,repository,indexFile,logger){this.#repository=repository,this.#indexFile=indexFile,this.#logger=logger,app.get("*",((request,response)=>{this.#getContent(request,response)}))}async#getContent(request,response){this.#logger.info(`Got asset -> '${request.path}'`);const path=request.path.substring(1).trim(),filename=0===path.length?this.#indexFile:path;try{const file=await this.#repository.loadAsset(filename);response.set("Content-Type",file.type),response.set("Content-Length",String(file.size)),response.status(200).send(file.content)}catch(error){if(error instanceof FileNotFound)return this.#logger.warn(`Failed to get asset -> '${filename}' | ${error.message}`),void response.status(404).send(error.message);const message=error instanceof Error?error.message:String(error);this.#logger.error(`Failed to get file content -> '${filename}' | ${message}`),response.status(500).send(message)}}}class HealthController{#node;#logger;constructor(app,node,logger){this.#node=node,this.#logger=logger,app.get("/health",((request,response)=>{this.getHealth(request,response)})),app.get("/health/status",((request,response)=>{this.isHealthy(request,response)}))}async getHealth(request,response){const health=await this.#node.getHealth(),data=Object.fromEntries(health);return this.#logger.debug("Got health"),response.status(200).send(data)}async isHealthy(request,response){const healthy=await this.#node.isHealthy();return this.#logger.debug("Got health status"),response.setHeader("Content-Type","text/plain"),response.status(200).send(healthy)}}const filePath=fileURLToPath(import.meta.url),fileLocation=path.dirname(filePath);class JitarController{constructor(app){app.use("/jitar",express.static(fileLocation))}}const clientIdHelper=new ClientIdHelper;class ModulesController{#repository;#serializer;#logger;constructor(app,repository,serializer,logger){this.#repository=repository,this.#serializer=serializer,this.#logger=logger,app.post("/modules",((request,response)=>{this.registerClient(request,response)})),app.get("/modules/:clientId/*",((request,response)=>{this.getModule(request,response)}))}async registerClient(request,response){this.#logger.info("Register client"),request.body;const segmentFiles=request.body,clientId=await this.#repository.registerClient(segmentFiles);return this.#logger.info(`Registered client -> ${clientId} [${segmentFiles.join(",")}]`),response.status(200).send(clientId)}async getModule(request,response){this.#logger.info(`Get module for -> '${request.params.clientId}'`);const clientId=request.params.clientId;if("string"!=typeof clientId||!1===clientIdHelper.validate(clientId))return response.status(400).send("Invalid client id.");const pathKey=`/${clientId}/`,pathIndex=request.path.indexOf(pathKey)+pathKey.length,filename=request.path.substring(pathIndex);try{const file=await this.#repository.loadModule(clientId,filename);return this.#logger.info(`Got module -> '${filename}' (${clientId})`),response.set("Content-Type",file.type),response.status(200).send(file.content)}catch(error){const message=error instanceof Error?error.message:String(error);this.#logger.error(`Failed to get module -> '${filename}' (${clientId}) | ${message}`);const data=this.#serializer.serialize(error);return response.setHeader("Content-Type","application/json"),response.status(500).send(data)}}}const nodeDtoSchema=z.object({url:z.string().url(),procedureNames:z.array(z.string()).optional()}).strict().transform((value=>new NodeDto(value.url,value.procedureNames)));class NodeDto{url;procedureNames;constructor(url,procedureNames=[]){this.url=url,this.procedureNames=procedureNames}}class NodesController{#gateway;#logger;constructor(app,gateway,logger){this.#gateway=gateway,this.#logger=logger,app.get("/nodes",((request,response)=>{this.getNodes(request,response)})),app.post("/nodes",((request,response)=>{this.add(request,response)}))}async getNodes(request,response){const nodes=this.#gateway.nodes.map((node=>({url:node.url,procedureNames:node.getProcedureNames()})));return this.#logger.info("Got nodes"),response.status(200).send(nodes)}async add(request,response){try{const nodeDto=DataConverter.convert(nodeDtoSchema,request.body),node=new RemoteNode(nodeDto.url,nodeDto.procedureNames);return this.#gateway.addNode(node),this.#logger.info(`Added node -> ${node.url}`),response.status(201).send()}catch(error){const status=error instanceof Array?400:500,message=error instanceof Error?error.message:String(error);return this.#logger.error(`Failed to add node | ${message}`),response.status(status).send(error)}}}class ProceduresController{#runtime;#logger;constructor(app,runtime,logger){this.#runtime=runtime,this.#logger=logger,app.get("/procedures",((request,response)=>{this.getProcedureNames(request,response)}))}async getProcedureNames(request,response){const names=this.#runtime.getProcedureNames();return this.#logger.info("Got procedure names"),response.status(200).send(names)}}class ProxyController{#logger;#repositoryUrl;#runnerUrl;constructor(app,proxy,logger){this.#logger=logger,this.#repositoryUrl=proxy.repository.url??"",this.#runnerUrl=proxy.runner.url??"",app.use("/",expressProxy((message=>this.#selectProxy(message))))}#selectProxy(message){const url=message.url??"";return this.#logger.info(`Forwarding -> ${url}`),url.startsWith("/rpc")?this.#runnerUrl:this.#repositoryUrl}}const RPC_PARAMETERS=["version","serialize"],IGNORED_HEADER_KEYS=["host","connection","content-length","accept-encoding","user-agent"],BAD_REQUEST_NAME=BadRequest.name,UNAUTHORIZED_NAME=Unauthorized.name,PAYMENT_REQUIRED_NAME=PaymentRequired.name,FORBIDDEN_NAME=Forbidden.name,NOT_FOUND_NAME=NotFound.name,TEAPOT_NAME=Teapot.name,NOT_IMPLEMENTED_NAME=NotImplemented.name;class RPCController{#runtime;#serializer;#logger;constructor(app,runtime,serializer,logger){this.#runtime=runtime,this.#serializer=serializer,this.#logger=logger,app.get("/rpc/*",((request,response)=>{this.runGet(request,response)})),app.post("/rpc/*",((request,response)=>{this.runPost(request,response)})),app.options("/rpc/*",((request,response)=>{this.runOptions(request,response)})),this.#showProcedureInfo()}#showProcedureInfo(){const procedureNames=this.#runtime.getProcedureNames();0!==procedureNames.length&&(procedureNames.sort(),this.#logger.info("Registered RPC entries",procedureNames))}async runGet(request,response){const fqn=this.#extractFqn(request),version=this.#extractVersion(request),args=this.#extractQueryArguments(request),headers=this.#extractHeaders(request),serialize=this.#extractSerialize(request);return this.#run(fqn,version,args,headers,response,serialize)}async runPost(request,response){const fqn=this.#extractFqn(request),version=this.#extractVersion(request),args=this.#extractBodyArguments(request),headers=this.#extractHeaders(request),serialize=this.#extractSerialize(request);return this.#run(fqn,version,args,headers,response,serialize)}async runOptions(request,response){return this.#setCors(response)}#extractFqn(request){return request.path.substring(5)}#extractVersion(request){return void 0!==request.query.version?VersionParser.parse(request.query.version.toString()):Version.DEFAULT}#extractSerialize(request){return"true"===request.query.serialize}#extractQueryArguments(request){const args={};for(const[key,value]of Object.entries(request.query))RPC_PARAMETERS.includes(key)||(args[key]=value);return args}#extractBodyArguments(request){return request.body}#extractHeaders(request){const headers=new Map;for(const[key,value]of Object.entries(request.headers)){if(void 0===value)continue;const lowerKey=key.toLowerCase(),stringValue=value.toString();IGNORED_HEADER_KEYS.includes(lowerKey)||headers.set(lowerKey,stringValue)}return headers}async#run(fqn,version,args,headers,response,serialize){if(!1===this.#runtime.hasProcedure(fqn))return response.status(404).send(`Procedure not found -> ${fqn}`);try{const deserializedArgs=await this.#serializer.deserialize(args),argsMap=new Map(Object.entries(deserializedArgs)),result=await this.#runtime.handle(fqn,version,argsMap,headers);return this.#logger.info(`Ran procedure -> ${fqn} (v${version.toString()})`),this.#setResponseHeaders(response,headers),this.#createResultResponse(result,response,serialize)}catch(error){const message=error instanceof Error?error.message:String(error),errorData=serialize?error:message;return this.#logger.error(`Failed to run procedure -> ${fqn} (v${version.toString()}) | ${message}`),this.#createErrorResponse(error,errorData,response,serialize)}}async#setCors(response){const cors=this.#runtime.getMiddleware(CorsMiddleware);return void 0===cors||(response.setHeader("Access-Control-Allow-Origin",cors.allowOrigin),response.setHeader("Access-Control-Allow-Methods",cors.allowMethods),response.setHeader("Access-Control-Allow-Headers",cors.allowHeaders),response.setHeader("Access-Control-Max-Age",86400)),response.status(204).send()}async#createResultResponse(result,response,serialize){const content=await this.#createResponseContent(result,serialize),contentType=this.#createResponseContentType(content),responseContent="text/plain"===contentType?String(content):content;return response.setHeader("Content-Type",contentType),response.status(200).send(responseContent)}async#createErrorResponse(error,errorData,response,serialize){const content=await this.#createResponseContent(errorData,serialize),contentType=this.#createResponseContentType(content),statusCode=this.#createResponseStatusCode(error);return response.setHeader("Content-Type",contentType),response.status(statusCode).send(content)}async#createResponseContent(data,serialize){return serialize?this.#serializer.serialize(data):data}#createResponseContentType(content){return"object"==typeof content?"application/json":"text/plain"}#setResponseHeaders(response,headers){headers.forEach(((value,key)=>response.setHeader(key,value)))}#createResponseStatusCode(error){if(error instanceof Object==!1)return 500;const errorClass=error.constructor;return this.#isClassType(errorClass,BAD_REQUEST_NAME)?400:this.#isClassType(errorClass,UNAUTHORIZED_NAME)?401:this.#isClassType(errorClass,PAYMENT_REQUIRED_NAME)?402:this.#isClassType(errorClass,FORBIDDEN_NAME)?403:this.#isClassType(errorClass,NOT_FOUND_NAME)?404:this.#isClassType(errorClass,TEAPOT_NAME)?418:this.#isClassType(errorClass,NOT_IMPLEMENTED_NAME)?501:500}#isClassType(clazz,className){if(clazz.name===className)return!0;const parentClass=Object.getPrototypeOf(clazz);return""!==parentClass.name&&this.#isClassType(parentClass,className)}}class UnknownHealthCheck extends Error{constructor(name){super(`Health check '${name}' is not registered.`)}}class DuplicateHealthCheck extends Error{constructor(name){super(`Health check '${name}' is already registered.`)}}class RuntimeNotAvailable extends Error{constructor(){super("Runtime is not available")}}class MiddlewareNotSupported extends Error{constructor(){super("Middleware is not supported")}}class JitarServer{#app;#runtime;#serializer;#classLoader;#options;#configuration;#logger;#registeredHealthChecks=new Map;constructor(){this.#classLoader=new RemoteClassLoader,this.#serializer=SerializerBuilder.build(this.#classLoader),this.#app=express(),this.#app.use(express.json()),this.#app.use(express.urlencoded({extended:!0})),this.#app.disable("x-powered-by"),this.#options=ServerOptionsReader.read(),this.#configuration=RuntimeConfigurationLoader.load(this.#options.config),this.#logger=LogBuilder.build(this.#options.loglevel),this.#printStartupMessage()}get classLoader(){return this.#classLoader}async build(){this.#runtime=await RuntimeConfigurator.configure(this.#configuration),this.#addControllers()}async start(){const url=new URL(this.#configuration.url??RuntimeDefaults$1.URL);this.#addHealthChecks(),await this.#startServer(url.port),this.#logger.info(`Server started and listening at port ${url.port}`)}registerHealthCheck(name,healthCheck){if(this.#registeredHealthChecks.has(name))throw new DuplicateHealthCheck(name);this.#registeredHealthChecks.set(name,healthCheck)}addSerializer(serializer){this.#serializer.addSerializer(serializer)}addMiddleware(middleware){if(void 0===this.#runtime)throw new RuntimeNotAvailable;if(!(this.#runtime instanceof ProcedureRuntime))throw new MiddlewareNotSupported;this.#runtime.addMiddleware(middleware)}#addHealthChecks(){if(void 0===this.#runtime)throw new RuntimeNotAvailable;if(void 0!==this.#configuration.healthChecks)for(const name of this.#configuration.healthChecks){const healthCheck=this.#registeredHealthChecks.get(name);if(void 0===healthCheck)throw new UnknownHealthCheck(name);this.#runtime.addHealthCheck(name,healthCheck)}}#addControllers(){if(void 0!==this.#configuration.standalone&&this.#runtime instanceof Proxy){const index=this.#configuration.standalone.index??RuntimeDefaults$1.INDEX;this.#addStandAloneControllers(this.#runtime,index)}else if(void 0!==this.#configuration.repository&&this.#runtime instanceof LocalRepository){const index=this.#configuration.repository.index??RuntimeDefaults$1.INDEX;this.#addRepositoryControllers(this.#runtime,index)}else void 0!==this.#configuration.gateway&&this.#runtime instanceof LocalGateway?this.#addGatewayControllers(this.#runtime):void 0!==this.#configuration.node&&this.#runtime instanceof LocalNode?this.#addNodeControllers(this.#runtime):void 0!==this.#configuration.proxy&&this.#runtime instanceof Proxy&&this.#addProxyControllers(this.#runtime)}#addStandAloneControllers(proxy,index){new HealthController(this.#app,proxy,this.#logger),new JitarController(this.#app),new ModulesController(this.#app,proxy,this.#serializer,this.#logger),new ProceduresController(this.#app,proxy,this.#logger),new RPCController(this.#app,proxy,this.#serializer,this.#logger),new AssetsController(this.#app,proxy,index,this.#logger)}#addRepositoryControllers(repository,index){new JitarController(this.#app),new ModulesController(this.#app,repository,this.#serializer,this.#logger),new AssetsController(this.#app,repository,index,this.#logger)}#addGatewayControllers(gateway){new NodesController(this.#app,gateway,this.#logger),new ProceduresController(this.#app,gateway,this.#logger),new RPCController(this.#app,gateway,this.#serializer,this.#logger)}#addNodeControllers(node){new HealthController(this.#app,node,this.#logger),new ProceduresController(this.#app,node,this.#logger),new RPCController(this.#app,node,this.#serializer,this.#logger)}#addProxyControllers(proxy){new ProxyController(this.#app,proxy,this.#logger)}async#startServer(port){return new Promise((resolve=>{this.#app.listen(port,resolve)}))}#printStartupMessage(){console.log("\n ██ ██ ████████ █████ ██████ \n ██ ██ ██ ██ ██ ██ ██ \n ██ ██ ██ ███████ ██████ \n ██ ██ ██ ██ ██ ██ ██ ██ \n █████ ██ ██ ██ ██ ██ ██\n ____________________________________\n By Masking Technology (masking.tech)\n")}}async function buildServer(moduleImporter){ModuleLoader.setImporter(moduleImporter);const server=new JitarServer;return await server.build(),server}export{CorsMiddleware,buildServer};
|
|
1
|
+
import{N as NoNodeAvailable,G as Gateway,P as ProcedureNotFound,R as Repository,M as ModuleLoader,I as InvalidSegmentFile,F as FileNotFound,a as InvalidClientId,C as ClientNotFound,b as File,c as convertToRemoteFilename,i as isSegmentFilename,d as convertToLocalFilename,e as createRepositoryFilename,f as ProcedureRuntime,g as Node,D as DummyRepository,h as Remote,j as RemoteRepository,k as RemoteGateway,l as RuntimeNotBuilt,L as LocalNode,m as Reflector,A as AccessLevels,n as ReflectionField,o as ReflectionDestructuredArray,p as ReflectionDestructuredObject,q as ReflectionDestructuredValue,r as createNodeFilename,V as VersionParser,s as ReflectionFunction,t as Files,B as BadRequest,U as Unauthorized,u as PaymentRequired,v as Forbidden,w as NotFound,T as Teapot,x as NotImplemented,y as Version,z as Request,E as RemoteClassLoader,S as SerializerBuilder,H as ExecutionScopes}from"./globals-e6900615.js";import express from"express";import{readFileSync}from"fs";import{z}from"zod";import fs from"fs-extra";import glob from"glob-promise";import mime from"mime-types";import path from"path";import yargs from"yargs";import{Logger}from"tslog";import{fileURLToPath}from"url";import expressProxy from"express-http-proxy";class CorsMiddleware{#allowOrigin;#allowMethods="GET, POST";#allowHeaders;constructor(origin="*",headers="*"){this.#allowOrigin=origin,this.#allowHeaders=headers}get allowOrigin(){return this.#allowOrigin}get allowMethods(){return this.#allowMethods}get allowHeaders(){return this.#allowHeaders}async handle(request,next){const response=await next();return this.#setHeaders(response),response}#setHeaders(response){response.setHeader("Access-Control-Allow-Origin",this.#allowOrigin),response.setHeader("Access-Control-Allow-Methods",this.#allowMethods),response.setHeader("Access-Control-Allow-Headers",this.#allowHeaders)}}class NodeBalancer{#nodes=[];#currentIndex=0;addNode(node){this.#nodes.includes(node)||this.#nodes.push(node)}removeNode(node){const index=this.#nodes.indexOf(node);-1!==index&&this.#nodes.splice(index,1)}getNextNode(){if(0!==this.#nodes.length)return this.#currentIndex>=this.#nodes.length&&(this.#currentIndex=0),this.#nodes[this.#currentIndex++]}run(request){const node=this.getNextNode();if(void 0===node)throw new NoNodeAvailable(request.fqn);return node.run(request)}}class LocalGateway extends Gateway{#nodes=new Set;#balancers=new Map;get nodes(){return[...this.#nodes.values()]}getProcedureNames(){const procedureNames=this.nodes.map((node=>node.getProcedureNames()));return[...new Set(procedureNames.flat()).values()]}hasProcedure(fqn){return this.getProcedureNames().includes(fqn)}async addNode(node){this.#nodes.add(node);for(const name of node.getProcedureNames()){this.#getOrCreateBalancer(name).addNode(node)}}removeNode(node){this.#nodes.delete(node);for(const name of node.getProcedureNames()){const balancer=this.#getBalancer(name);void 0!==balancer&&balancer.removeNode(node)}}#getBalancer(fqn){return this.#balancers.get(fqn)}#getOrCreateBalancer(fqn){let balancer=this.#getBalancer(fqn);return void 0===balancer&&(balancer=new NodeBalancer,this.#balancers.set(fqn,balancer)),balancer}run(request){const balancer=this.#getBalancer(request.fqn);if(void 0===balancer)throw new ProcedureNotFound(request.fqn);return balancer.run(request)}}const CLIENT_ID_REGEX=/^CLIENT_\d+$/;let lastClientId=0;class ClientIdHelper{generate(){return"CLIENT_"+lastClientId++}validate(clientId){return CLIENT_ID_REGEX.test(clientId)}}const clientIdHelper$1=new ClientIdHelper;class LocalRepository extends Repository{#fileManager;#segments=new Map;#clients=new Map;#segmentNames=new Set;#assets=new Set;#overrides=new Map;constructor(fileManager,url){super(url),this.#fileManager=fileManager,ModuleLoader.setBaseUrl(fileManager.getRootLocation())}set segmentNames(names){this.#segmentNames=new Set(names)}set assets(patterns){this.#assets=patterns}set overrides(overrides){this.#overrides=overrides}async start(){await super.start(),await this.#loadSegments(),this.#translateOverrides()}stop(){return this.#unregisterClients(),this.#unloadSegments(),super.stop()}async#loadSegments(){for(const name of this.#segmentNames)await this.#loadSegment(name)}async#loadSegment(name){const relativeFilename=`./${createRepositoryFilename(name)}`,absoluteFilename=this.#fileManager.getAbsoluteLocation(relativeFilename),files=(await ModuleLoader.load(absoluteFilename)).files;if(void 0===files)throw new InvalidSegmentFile(absoluteFilename);this.registerSegment(name,files)}#unloadSegments(){this.#segments.clear()}async registerSegment(name,filenames){filenames.forEach((filename=>this.#segments.set(filename,name)))}#translateOverrides(){const translated=new Map;for(const[targetName,destinationName]of this.#overrides){const relativeTargetFilename=ModuleLoader.assureExtension(targetName),relativeDestinationFilename=ModuleLoader.assureExtension(destinationName),absoluteTargetFilename=this.#fileManager.getAbsoluteLocation(relativeTargetFilename),absoluteDestinationFilename=this.#fileManager.getAbsoluteLocation(relativeDestinationFilename);translated.set(absoluteTargetFilename,absoluteDestinationFilename)}this.#overrides=translated}async registerClient(segmentFilenames){const clientId=clientIdHelper$1.generate();return this.#clients.set(clientId,segmentFilenames),clientId}#unregisterClients(){this.#clients.clear()}readAsset(filename){if(!1===this.#assets.has(filename))throw new FileNotFound(filename);return this.#readFile(filename)}readModule(name,clientId){clientId=this.#validateClientId(clientId);const segmentFilename=this.#segments.get(name);return void 0===segmentFilename||this.#hasClientSegmentFile(clientId,segmentFilename)?this.#readNodeModule(name):this.#readRemoteModule(name)}loadModule(name){const filename=this.#getModuleFilename(name);return ModuleLoader.load(filename)}#validateClientId(clientId){if(!1===clientIdHelper$1.validate(clientId))throw new InvalidClientId(clientId);if(!1===this.#clients.has(clientId))throw new ClientNotFound(clientId);return clientId}#hasClientSegmentFile(clientId,segmentFilename){const clientSegmentFiles=this.#clients.get(clientId);if(void 0===clientSegmentFiles)throw new ClientNotFound(clientId);return clientSegmentFiles.some((clientSegmentFilename=>segmentFilename.endsWith(clientSegmentFilename)))}async#readNodeModule(name){const filename=this.#getModuleFilename(name),code=(await this.#readFile(filename)).content.toString();return new File(filename,"application/javascript",code)}#readRemoteModule(name){const remoteFilename=convertToRemoteFilename(name);return this.#readFile(remoteFilename)}#getModuleFilename(name){const relativeFilename=ModuleLoader.assureExtension(name),absoluteFilename=this.#fileManager.getAbsoluteLocation(relativeFilename);if(isSegmentFilename(absoluteFilename))return absoluteFilename;const assignedFilename=this.#getAssignedFilename(absoluteFilename);return convertToLocalFilename(assignedFilename)}#getAssignedFilename(filename){return this.#overrides.get(filename)??filename}#readFile(filename){return this.#fileManager.read(filename)}}class Proxy extends ProcedureRuntime{#runner;constructor(repository,runner,url){super(repository,url),this.#runner=runner}get runner(){return this.#runner}async start(){await super.start(),await this.#runner.start()}async stop(){await this.#runner.stop(),await super.stop()}getProcedureNames(){return this.#runner.getProcedureNames()}hasProcedure(fqn){return this.getProcedureNames().includes(fqn)}readAsset(filename){return this.repository.readAsset(filename)}registerClient(segmentFiles){return this.repository.registerClient(segmentFiles)}readModule(filename,clientId){return this.repository.readModule(filename,clientId)}run(request){return this.#runner.run(request)}}class RemoteNode extends Node{#remote;#procedureNames=new Set;constructor(url){super(new DummyRepository,url),this.#remote=new Remote(url)}set procedureNames(names){this.#procedureNames=names}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 Standalone extends ProcedureRuntime{#node;constructor(repository,node,url){super(repository,url),this.#node=node}get node(){return this.#node}async start(){await this.#node.start()}async stop(){await this.#node.stop()}getProcedureNames(){return this.#node.getProcedureNames()}hasProcedure(fqn){return this.getProcedureNames().includes(fqn)}readAsset(filename){return this.repository.readAsset(filename)}registerClient(segmentFiles){return this.repository.registerClient(segmentFiles)}readModule(filename,clientId){return this.repository.readModule(filename,clientId)}run(request){return this.#node.run(request)}}class RuntimeBuilder{#url;#fileManager;#segments=new Set;#healthChecks=new Set;#middlewares=new Set;#assets=new Set;#overrides=new Map;#repository;#gateway;#node;url(url){return this.#url=url,this}fileManager(fileManager){return this.#fileManager=fileManager,this}segment(...names){return names.forEach((name=>this.#segments.add(name))),this}healthCheck(...filenames){return filenames.forEach((filename=>this.#healthChecks.add(filename))),this}middleware(...filenames){return filenames.forEach((filename=>this.#middlewares.add(filename))),this}asset(...patterns){return patterns.forEach((pattern=>this.#assets.add(pattern))),this}override(...mappings){for(const map of mappings)for(const[key,value]of Object.entries(map))this.#overrides.set(key,value);return this}repository(url){return this.#repository=void 0!==url?new RemoteRepository(url):void 0,this}gateway(url){return this.#gateway=void 0!==url?new RemoteGateway(url):void 0,this}node(url){return this.#node=void 0!==url?new RemoteNode(url):void 0,this}buildRepository(){if(void 0===this.#fileManager)throw new RuntimeNotBuilt("File manager is not set for the repository");const repository=new LocalRepository(this.#fileManager,this.#url);return repository.healthCheckFiles=this.#healthChecks,repository.segmentNames=this.#segments,repository.assets=this.#assets,repository.overrides=this.#overrides,repository}buildGateway(){if(void 0===this.#repository)throw new RuntimeNotBuilt("Repository is not set for the gateway");const gateway=new LocalGateway(this.#repository,this.#url);return gateway.healthCheckFiles=this.#healthChecks,gateway.middlewareFiles=this.#middlewares,gateway}buildNode(){if(void 0===this.#repository)throw new RuntimeNotBuilt("Repository is not set for the node");const node=new LocalNode(this.#repository,this.#gateway,this.#url);return node.segmentNames=this.#segments,node.healthCheckFiles=this.#healthChecks,node.middlewareFiles=this.#middlewares,this.#repository.segmentNames=this.#segments,void 0!==this.gateway&&(this.#gateway.node=node),node}buildProxy(){if(void 0===this.#repository)throw new RuntimeNotBuilt("Repository is not set for the proxy");const runner=this.#gateway??this.#node;if(void 0===runner)throw new RuntimeNotBuilt("Runner (gateway or node) is not set for the proxy");const proxy=new Proxy(this.#repository,runner,this.#url);return proxy.healthCheckFiles=this.#healthChecks,proxy.middlewareFiles=this.#middlewares,proxy}buildStandalone(){if(void 0===this.#fileManager)throw new RuntimeNotBuilt("File manager is not set for the standalone");const repository=new LocalRepository(this.#fileManager,this.#url);repository.segmentNames=this.#segments,repository.assets=this.#assets,repository.overrides=this.#overrides;const node=new LocalNode(repository,this.#gateway,this.#url);node.segmentNames=this.#segments;const standalone=new Standalone(repository,node,this.#url);return standalone.healthCheckFiles=this.#healthChecks,standalone.middlewareFiles=this.#middlewares,standalone}}class ProcedureRuntimeConfiguration{#middlewares;constructor(middlewares){this.#middlewares=middlewares}get middlewares(){return this.#middlewares}}const gatewaySchema=z.object({repository:z.string().url(),middlewares:z.array(z.string()).optional(),monitor:z.number().optional()}).strict().transform((value=>new GatewayConfiguration(value.repository,value.middlewares,value.monitor)));class GatewayConfiguration extends ProcedureRuntimeConfiguration{#monitor;#repository;constructor(repository,middlewares,monitor){super(middlewares),this.#monitor=monitor,this.#repository=repository}get monitor(){return this.#monitor}get repository(){return this.#repository}}const nodeSchema=z.object({gateway:z.string().url().optional(),repository:z.string().url().optional(),segments:z.array(z.string()).nonempty(),middlewares:z.array(z.string()).optional()}).strict().transform((value=>new NodeConfiguration(value.gateway,value.repository,value.segments,value.middlewares)));class NodeConfiguration extends ProcedureRuntimeConfiguration{#gateway;#repository;#segments;constructor(gateway,repository,segments,middlewares){super(middlewares),this.#gateway=gateway,this.#repository=repository,this.#segments=segments}get gateway(){return this.#gateway}get repository(){return this.#repository}get segments(){return this.#segments}}const proxySchema=z.object({node:z.string().url().optional(),gateway:z.string().url().optional(),repository:z.string().url(),middlewares:z.array(z.string()).optional()}).strict().superRefine(((value,ctx)=>{void 0===value.node&&void 0===value.gateway&&ctx.addIssue({code:z.ZodIssueCode.custom,message:"Either node or gateway must be defined",path:["node","gateway"]}),void 0!==value.node&&void 0!==value.gateway&&ctx.addIssue({code:z.ZodIssueCode.custom,message:"Only node or gateway must be defined",path:["node","gateway"]})})).transform((value=>new ProxyConfiguration(value.node,value.gateway,value.repository,value.middlewares)));class ProxyConfiguration extends ProcedureRuntimeConfiguration{#node;#gateway;#repository;constructor(node,gateway,repository,middlewares){super(middlewares),this.#node=node,this.#gateway=gateway,this.#repository=repository}get node(){return this.#node}get gateway(){return this.#gateway}get repository(){return this.#repository}}const repositorySchema=z.object({source:z.string().optional(),cache:z.string().optional(),index:z.string().optional(),assets:z.array(z.string()).optional(),overrides:z.record(z.string(),z.string()).optional()}).strict().transform((value=>new RepositoryConfiguration(value.source,value.cache,value.index,value.assets,value.overrides)));class RepositoryConfiguration{#source;#cache;#index;#assets;#overrides;constructor(source,cache,index,assets,overrides){this.#source=source,this.#cache=cache,this.#index=index,this.#assets=assets,this.#overrides=overrides}get source(){return this.#source}get cache(){return this.#cache}get index(){return this.#index}get assets(){return this.#assets}get overrides(){return this.#overrides}}const standaloneSchema=z.object({source:z.string().optional(),cache:z.string().optional(),index:z.string().optional(),segments:z.array(z.string()).optional(),assets:z.array(z.string()).optional(),middlewares:z.array(z.string()).optional(),overrides:z.record(z.string(),z.string()).optional()}).strict().transform((value=>new StandaloneConfiguration(value.source,value.cache,value.index,value.segments,value.assets,value.middlewares,value.overrides)));class StandaloneConfiguration extends ProcedureRuntimeConfiguration{#source;#cache;#index;#segments;#assets;#overrides;constructor(source,cache,index,segments,assets,middlewares,overrides){super(middlewares),this.#source=source,this.#cache=cache,this.#index=index,this.#segments=segments,this.#assets=assets,this.#overrides=overrides}get source(){return this.#source}get cache(){return this.#cache}get index(){return this.#index}get segments(){return this.#segments}get assets(){return this.#assets}get overrides(){return this.#overrides}}const runtimeSchema=z.object({url:z.string().optional(),setUp:z.string().optional(),tearDown:z.string().optional(),healthChecks:z.array(z.string()).optional(),standalone:standaloneSchema.optional(),repository:repositorySchema.optional(),gateway:gatewaySchema.optional(),node:nodeSchema.optional(),proxy:proxySchema.optional()}).strict().transform((value=>new RuntimeConfiguration(value.url,value.setUp,value.tearDown,value.healthChecks,value.standalone,value.repository,value.gateway,value.node,value.proxy)));class RuntimeConfiguration{#url;#setUp;#tearDown;#healthChecks;#standalone;#repository;#gateway;#node;#proxy;constructor(url,setUp,tearDown,healthChecks,standalone,repository,gateway,node,proxy){this.#url=url,this.#setUp=setUp,this.#tearDown=tearDown,this.#healthChecks=healthChecks,this.#standalone=standalone,this.#repository=repository,this.#gateway=gateway,this.#node=node,this.#proxy=proxy}get url(){return this.#url}get setUp(){return this.#setUp}get tearDown(){return this.#tearDown}get healthChecks(){return this.#healthChecks}get standalone(){return this.#standalone}get repository(){return this.#repository}get gateway(){return this.#gateway}get node(){return this.#node}get proxy(){return this.#proxy}}class DataConverter{static convert(schema,dataObject){return schema.parse(dataObject)}}class RuntimeConfigurationLoader{static load(filename){const plainContents=readFileSync(filename,"utf-8"),parsedContents=JSON.parse(plainContents);return DataConverter.convert(runtimeSchema,parsedContents)}}class ApplicationCache{#segments;#modules;constructor(segments,modules){this.#segments=segments,this.#modules=modules}get segments(){return this.#segments}get modules(){return this.#modules}}class ModuleCache{#module;#segment;constructor(module,segment){this.#module=module,this.#segment=segment}get module(){return this.#module}get segment(){return this.#segment}}class ModuleCacheBuilder{build(application,module){const segment=application.getSegmentModule(module.filename);return new ModuleCache(module,segment)}}class DuplicateImplementation extends Error{constructor(fqn,version){super(`Duplicate implementation found for '${fqn}' with version '${version}'.`)}}class SegmentCache{#name;#imports;#procedures;#files;constructor(name,files,imports,procedures){this.#name=name,this.#files=files,this.#imports=imports,this.#procedures=procedures}get name(){return this.#name}get files(){return this.#files}get imports(){return this.#imports}get procedures(){return this.#procedures}}class SegmentImport{#members;#from;constructor(members,from){this.#members=members,this.#from=from}get members(){return this.#members}get from(){return this.#from}}class SegmentProcedure{#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 SegmentCacheBuilder{build(segment){const files=this.#extractFiles(segment),imports=this.#createImports(segment),procedures=this.#mergeProcedures(segment);return this.#validateProcedures(procedures),new SegmentCache(segment.name,files,imports,procedures)}#extractFiles(segment){return segment.modules.map((module=>module.filename))}#createImports(segment){const imports=[];for(const module of segment.modules){let members=[];for(const procedure of module.procedures){const ids=procedure.implementations.map((implementation=>this.#createImportMember(implementation)));members=[...members,...ids]}imports.push(new SegmentImport(members,module.filename))}return imports}#createImportMember(implementation){return`${implementation.importKey} : ${implementation.id}`}#mergeProcedures(segment){const procedures=new Map;for(const module of segment.modules)for(const procedure of module.procedures){if(procedures.has(procedure.fqn)){const existingProcedure=procedures.get(procedure.fqn);for(const implementation of procedure.implementations)existingProcedure.addImplementation(implementation);continue}const procedureCopy=new SegmentProcedure(procedure.fqn,[...procedure.implementations]);procedures.set(procedure.fqn,procedureCopy)}return[...procedures.values()]}#validateProcedures(procedures){for(const procedure of procedures)this.#checkForDuplicateImplementations(procedure)}#checkForDuplicateImplementations(procedure){for(const implementation of procedure.implementations){if(void 0!==procedure.implementations.find((other=>other.id!==implementation.id&&other.version===implementation.version)))throw new DuplicateImplementation(procedure.fqn,implementation.version)}}}class ApplicationCacheBuilder{#moduleCacheBuilder;#segmentCacheBuilder;constructor(){this.#moduleCacheBuilder=new ModuleCacheBuilder,this.#segmentCacheBuilder=new SegmentCacheBuilder}build(application){const segments=this.#buildSegmentCaches(application),modules=this.#buildModuleCaches(application);return new ApplicationCache(segments,modules)}#buildSegmentCaches(application){return application.segments.map((segment=>this.#segmentCacheBuilder.build(segment)))}#buildModuleCaches(application){return application.modules.map((module=>this.#moduleCacheBuilder.build(application,module)))}}const Keyword={DEFAULT:"default"};Object.freeze(Keyword);const IMPORT_PATTERN=/import\s(?:["'\s]*([\w*{}\n, ]+)from\s*)?["'\s]*([@\w/._-]+)["'\s].*/g,APPLICATION_MODULE_INDICATORS=[".","/","http:","https:"],reflector$2=new Reflector;const importRewriter=new class{rewrite(code,filename){return code.replaceAll(IMPORT_PATTERN,(statement=>this.#replaceImport(statement,filename)))}#replaceImport(statement,filename){const dependency=reflector$2.parseImport(statement);return this.#isApplicationModule(dependency)?this.#rewriteApplicationImport(dependency,filename):this.#rewriteRuntimeImport(dependency,filename)}#isApplicationModule(dependency){return APPLICATION_MODULE_INDICATORS.some((indicator=>dependency.from.startsWith(indicator,1)))}#rewriteApplicationImport(dependency,filename){return this.#rewriteImport(dependency,"application",filename)}#rewriteRuntimeImport(dependency,filename){return this.#rewriteImport(dependency,"runtime",filename)}#rewriteImport(dependency,scope,filename){const from=this.#rewriteImportFrom(dependency,filename);if(0===dependency.members.length)return`await __import("${from}", "${scope}");`;return`const ${this.#rewriteImportMembers(dependency)} = await __import("${from}", "${scope}");`}#rewriteImportFrom(dependency,filename){const from=dependency.from.substring(1,dependency.from.length-1);return this.#isApplicationModule(dependency)?this.#mergeFilenames(filename,from):from}#rewriteImportMembers(dependency){if(this.#mustUseAs(dependency))return dependency.members[0].as;return`{ ${dependency.members.map((member=>member.name!==member.as?`${member.name} : ${member.as}`:member.name)).join(", ")} }`}#mergeFilenames(sourceFilename,importFilename){const concatenated=`${this.#extractFilepath(sourceFilename)}/${importFilename}`,translated=this.#translateFilename(concatenated),rooted=this.#ensureRoot(translated);return this.#ensureExtension(rooted)}#extractFilepath(filename){return filename.split("/").slice(0,-1).join("/")}#translateFilename(filename){const parts=filename.split("/"),translated=[];translated.push(parts[0]);for(let index=1;index<parts.length;index++){const part=parts[index].trim();switch(part){case"":case".":continue;case"..":translated.pop();continue}translated.push(part)}return translated.join("/")}#ensureRoot(filename){return filename.startsWith("./")?filename:(filename.startsWith("//")&&(filename=filename.substring(1)),filename.startsWith("/")?`.${filename}`:`./${filename}`)}#ensureExtension(filename){return filename.endsWith(".js")?filename:`${filename}.js`}#mustUseAs(dependency){return this.#doesImportAll(dependency)||this.#doesImportDefault(dependency)}#doesImportAll(dependency){return 1===dependency.members.length&&"*"===dependency.members[0].name}#doesImportDefault(dependency){return 1===dependency.members.length&&dependency.members[0].name===Keyword.DEFAULT}},remoteBuilder=new class{build(module){let code="";for(const procedure of module.procedures)for(const implementation of procedure.implementations){const asDefault=implementation.importKey===Keyword.DEFAULT;code+=implementation.access===AccessLevels.PRIVATE?this.#createPrivateCode(procedure.fqn,implementation,asDefault):this.#createPublicCode(procedure.fqn,implementation,asDefault)}return code.trim()}#createPrivateCode(fqn,implementation,asDefault){const version=implementation.version,declaration=this.#createDeclaration(implementation,asDefault),body=`throw new ProcedureNotAccessible('${fqn}', '${version}');`;return this.#createFunction(declaration,body)}#createPublicCode(fqn,implementation,asDefault){const version=implementation.version,args=this.#createArguments(implementation.executable.parameters),declaration=this.#createDeclaration(implementation,asDefault),body=`return __run('${fqn}', '${version}', { ${args} }, this);`;return this.#createFunction(declaration,body)}#createParameters(parameters){const result=[];for(const parameter of parameters)parameter instanceof ReflectionField?result.push(parameter.name):(parameter instanceof ReflectionDestructuredArray||parameter instanceof ReflectionDestructuredObject)&&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 ReflectionDestructuredValue){const argumentz=this.#extractArguments(parameter.members);result.push(...argumentz)}else if(parameter instanceof ReflectionField){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,asDefault){const name=implementation.executable.name,parameters=this.#createParameters(implementation.executable.parameters);return`\nexport ${asDefault?`${Keyword.DEFAULT} `:""}async function ${name}(${parameters})`}#createFunction(declaration,body){return`${declaration} {\n\t${body}\n}\n`}};class ModuleCacheWriter{#fileManager;constructor(fileManager){this.#fileManager=fileManager}async write(cache){return Promise.all([this.#writeLocal(cache),this.#writeRemote(cache)]).then((()=>{}))}async#writeLocal(cache){const importCode=this.#rewriteAllImports(cache.module),sourceCode=this.#createSourceCode(cache.module),filename=convertToLocalFilename(cache.module.filename),code=`${importCode}\n${sourceCode}`;return this.#fileManager.write(filename,code.trim())}#rewriteAllImports(module){return importRewriter.rewrite(module.code,module.filename)}#createSourceCode(module){const filename=module.filename;return module.content.exportedClasses.map((clazz=>clazz.name)).map((className=>`${className}.source = "./${filename}";`)).join("\n")}async#writeRemote(cache){if(void 0===cache.segment)return;const filename=convertToRemoteFilename(cache.module.filename),code=this.#createRemoteCode(cache.segment);return this.#fileManager.write(filename,code.trim())}#createRemoteCode(module){return remoteBuilder.build(module)}}class SegmentCacheWriter{#fileManager;constructor(fileManager){this.#fileManager=fileManager}async write(cache){return Promise.all([this.#writeNodeCache(cache),this.#writeRepositoryCache(cache)]).then((()=>{}))}async#writeNodeCache(cache){const importCode=this.#createImportCode(cache.imports),segmentCode=this.#createSegmentCode(cache.name,cache.procedures),filename=createNodeFilename(cache.name),code=`${importCode}\n${segmentCode}`;return this.#fileManager.write(filename,code)}async#writeRepositoryCache(cache){const filename=createRepositoryFilename(cache.name),code=`export const files = [\n\t"${[...cache.files].join('",\n\t"')}"\n];`;return this.#fileManager.write(filename,code)}#createImportCode(imports){const codes=[];for(const{members:members,from:from}of imports)codes.push(`const { ${members.join(", ")} } = await __import("./${from}", "application", false);`);return codes.join("\n")}#createSegmentCode(name,procedures){const codes=[];codes.push('const { Segment, Procedure, Implementation, Version, NamedParameter, ArrayParameter, ObjectParameter } = await __import("jitar", "runtime", false);'),codes.push(`export const segment = new Segment("${name}")`);for(const procedure of procedures){codes.push(`\t.addProcedure(new Procedure("${procedure.fqn}")`);for(const implementation of procedure.implementations){const version=this.#createVersionCode(implementation.version),parameters=this.#createParametersCode(implementation.executable);codes.push(`\t\t.addImplementation(new Implementation(${version}, "${implementation.access}", ${parameters}, ${implementation.id}))`)}codes.push("\t)")}return codes.join("\n")}#createVersionCode(versionString){const version=VersionParser.parse(versionString);return`new Version(${version.major}, ${version.minor}, ${version.patch})`}#createParametersCode(executable){return`[${this.#extractParameters(executable.parameters).join(", ")}]`}#extractParameters(parameters){const result=[];for(const parameter of parameters)result.push(this.#extractParameter(parameter));return result}#extractParameter(parameter){return parameter instanceof ReflectionDestructuredArray?this.#createArrayParameter(parameter):parameter instanceof ReflectionDestructuredObject?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 ApplicationCacheWriter{#moduleWriter;#segmentWriter;constructor(fileManager){this.#moduleWriter=new ModuleCacheWriter(fileManager),this.#segmentWriter=new SegmentCacheWriter(fileManager)}async write(cache){return Promise.all([this.#writeSegmentCache(cache.segments),this.#writeModuleCache(cache.modules)]).then((()=>{}))}async#writeSegmentCache(segments){return Promise.all(segments.map((async segment=>this.#segmentWriter.write(segment)))).then((()=>{}))}async#writeModuleCache(modules){return Promise.all(modules.map((async module=>this.#moduleWriter.write(module)))).then((()=>{}))}}class Application{#segments;#modules;constructor(segments,modules){this.#segments=segments,this.#modules=modules}get segments(){return this.#segments}get modules(){return this.#modules}getSegmentModule(filename){const segment=this.#segments.find((segment=>segment.hasModule(filename)));if(void 0!==segment)return segment.getModule(filename)}}class ModuleFileNotLoaded extends Error{constructor(filename,message){super(`Failed to load module file '${filename}' because of: ${message}`)}}class Module{#filename;#code;#content;constructor(filename,code,content){this.#code=code,this.#filename=filename,this.#content=content}get filename(){return this.#filename}get code(){return this.#code}get content(){return this.#content}}const reflector$1=new Reflector;class ModuleReader{#fileManager;constructor(fileManager){this.#fileManager=fileManager}async read(filename){const relativeLocation=this.#fileManager.getRelativeLocation(filename),code=await this.#loadCode(filename),module=reflector$1.parse(code);return new Module(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 ModuleFileNotLoaded(filename,message)}}}class FunctionNotAsync extends Error{constructor(filename,functionName){super(`Function '${functionName}' from file '${filename}' is not async`)}}class InvalidSegmentFilename 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 SegmentFileNotLoaded extends Error{constructor(filename,message){super(`Failed to load segment file '${filename}' because of: ${message}`)}}class SegmentModuleNotLoaded extends Error{constructor(filename,message){super(`Segment module could not be loaded from '${filename}' because of: ${message}`)}}class Segment{#name;#modules;constructor(name,modules){this.#name=name,this.#modules=modules}get name(){return this.#name}get modules(){return this.#modules}hasModule(filename){return this.#modules.some((module=>module.filename===filename))}getModule(filename){return this.#modules.find((module=>module.filename===filename))}}class SegmentImplementation{#id;#importKey;#access;#version;#executable;constructor(id,importKey,access,version,executable){this.#id=id,this.#importKey=importKey,this.#access=access,this.#version=version,this.#executable=executable}get id(){return this.#id}get importKey(){return this.#importKey}get access(){return this.#access}get version(){return this.#version}get executable(){return this.#executable}}class SegmentModule{#filename;#procedures=[];constructor(filename,procedures){this.#filename=filename,this.#procedures=procedures}get filename(){return this.#filename}get procedures(){return this.#procedures}}class IdGenerator{#id=0;next(){return"$"+ ++this.#id}}const reflector=new Reflector;class SegmentReader{#fileManager;constructor(fileManager){this.#fileManager=fileManager}async read(filename){const name=this.#extractSegmentName(filename),definition=await this.#loadSegmentDefinition(filename),modules=await this.#createSegmentModules(definition);return new Segment(name,modules)}#extractSegmentName(filename){const file=filename.split("/").pop();if(void 0===file||""===file)throw new InvalidSegmentFilename(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 SegmentFileNotLoaded(filename,message)}}async#createSegmentModules(definition){const modules=[],idGenerator=new IdGenerator;for(const[filename,moduleImports]of Object.entries(definition)){const fullFilename=filename.endsWith(".js")?filename:`${filename}.js`,absoluteFilename=this.#fileManager.getAbsoluteLocation(fullFilename),module=await this.#createSegmentModule(absoluteFilename,moduleImports,idGenerator);modules.push(module)}return modules}async#createSegmentModule(absoluteFilename,imports,idGenerator){const module=await this.#loadSegmentModule(absoluteFilename),relativeFilename=this.#fileManager.getRelativeLocation(absoluteFilename),moduleName=this.#extractModuleName(relativeFilename),procedures=this.#extractSegmentProcedures(module,moduleName,imports,idGenerator);return new SegmentModule(relativeFilename,procedures)}async#loadSegmentModule(absoluteLocation){try{const code=await this.#fileManager.getContent(absoluteLocation);return reflector.parse(code.toString())}catch(error){const message=error instanceof Error?error.message:String(error);throw new SegmentModuleNotLoaded(absoluteLocation,message)}}#extractModuleName(relativeFilename){const moduleParts=relativeFilename.split("/");return moduleParts.pop(),moduleParts.join("/")}#extractSegmentProcedures(module,moduleName,imports,idGenerator){const procedures=new Map;for(const[importKey,properties]of Object.entries(imports)){const executable=module.getExported(importKey);if(void 0===executable)throw new MissingModuleExport(moduleName,importKey);if(executable instanceof ReflectionFunction==!1)continue;if(!1===executable.isAsync)throw new FunctionNotAsync(moduleName,executable.name);const procedureName=properties.as??executable.name,access=properties.access??"private",version=properties.version??"0.0.0",id=idGenerator.next(),fqn=""!==moduleName?`${moduleName}/${procedureName}`:procedureName,implementation=new SegmentImplementation(id,importKey,access,version,executable),procedure=procedures.has(fqn)?procedures.get(fqn):new SegmentProcedure(fqn);procedure.addImplementation(implementation),procedures.set(fqn,procedure)}return[...procedures.values()]}}class ApplicationReader{#moduleReader;#segmentReader;constructor(fileManager){this.#moduleReader=new ModuleReader(fileManager),this.#segmentReader=new SegmentReader(fileManager)}async read(segmentFiles,moduleFiles){return Promise.all([this.#readSegments(segmentFiles),this.#readModules(moduleFiles)]).then((([segments,modules])=>new Application(segments,modules)))}async#readSegments(segmentFiles){return Promise.all(segmentFiles.map((async segmentFile=>this.#segmentReader.read(segmentFile))))}async#readModules(moduleFiles){return Promise.all(moduleFiles.map((async moduleFile=>this.#moduleReader.read(moduleFile))))}}class CacheManager{#projectFileManager;#appFileManager;#reader;#builder;#writer;constructor(projectFileManager,appFileManager){this.#projectFileManager=projectFileManager,this.#appFileManager=appFileManager,this.#reader=new ApplicationReader(appFileManager),this.#builder=new ApplicationCacheBuilder,this.#writer=new ApplicationCacheWriter(appFileManager)}async build(){const segmentFiles=await this.#projectFileManager.filter(Files.SEGMENT_PATTERN),moduleFiles=await this.#appFileManager.filter(Files.MODULE_PATTERN),application=await this.#reader.read(segmentFiles,moduleFiles),cache=this.#builder.build(application);return this.#writer.write(cache)}}var RuntimeDefaults;!function(RuntimeDefaults){RuntimeDefaults.URL="http://localhost:3000",RuntimeDefaults.SOURCE="./dist",RuntimeDefaults.CACHE="./.jitar",RuntimeDefaults.INDEX="index.html"}(RuntimeDefaults||(RuntimeDefaults={}));var LogLevel,RuntimeDefaults$1=RuntimeDefaults;class UnknownRuntimeMode extends Error{constructor(){super("Unknown runtime mode")}}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 read(filename){const type=await this.getType(filename),content=await this.getContent(filename);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}`)}async getNodeSegmentFiles(){return this.filter("**/*.segment.node.js")}async getRepositorySegmentFiles(){return this.filter("**/*.segment.repository.js")}async getAssetFiles(patterns){const promises=patterns.map((pattern=>this.filter(pattern)));return(await Promise.all(promises)).flat().map((filename=>this.getRelativeLocation(filename))).filter((filename=>!1===this.#isGeneratedFile(filename)))}#isGeneratedFile(filename){return filename.endsWith(".local.js")||filename.endsWith(".node.js")||filename.endsWith(".repository.js")||filename.endsWith(".remote.js")}}class RuntimeConfigurator{static async configure(configuration){const url=configuration.url??RuntimeDefaults$1.URL,healthChecks=configuration.healthChecks??[];if(void 0!==configuration.standalone)return this.#configureStandAlone(url,healthChecks,configuration.standalone);if(void 0!==configuration.repository)return this.#configureRepository(url,healthChecks,configuration.repository);if(void 0!==configuration.gateway)return this.#configureGateway(url,healthChecks,configuration.gateway);if(void 0!==configuration.node)return this.#configureNode(url,healthChecks,configuration.node);if(void 0!==configuration.proxy)return this.#configureProxy(url,healthChecks,configuration.proxy);throw new UnknownRuntimeMode}static async#configureStandAlone(url,healthChecks,configuration){const sourceLocation=configuration.source??RuntimeDefaults$1.SOURCE,cacheLocation=configuration.cache??RuntimeDefaults$1.CACHE,overrides=configuration.overrides??{},middlewares=configuration.middlewares??[],fileManager=new LocalFileManager(cacheLocation);await this.#buildCache(sourceLocation,cacheLocation);const segmentNames=void 0===configuration.segments?await this.#getNodeSegmentNames(fileManager):configuration.segments,assets=void 0!==configuration.assets?await fileManager.getAssetFiles(configuration.assets):[];return(new RuntimeBuilder).url(url).healthCheck(...healthChecks).middleware(...middlewares).segment(...segmentNames).asset(...assets).override(overrides).fileManager(fileManager).buildStandalone()}static async#configureRepository(url,healthChecks,configuration){const sourceLocation=configuration.source??RuntimeDefaults$1.SOURCE,cacheLocation=configuration.cache??RuntimeDefaults$1.CACHE,overrides=configuration.overrides??{},fileManager=new LocalFileManager(cacheLocation);await this.#buildCache(sourceLocation,cacheLocation);const segmentNames=await this.#getRepositorySegmentNames(fileManager),assets=void 0!==configuration.assets?await fileManager.getAssetFiles(configuration.assets):[];return(new RuntimeBuilder).url(url).healthCheck(...healthChecks).segment(...segmentNames).asset(...assets).override(overrides).fileManager(fileManager).buildRepository()}static async#configureGateway(url,healthChecks,configuration){const repositoryUrl=configuration.repository,middlewares=configuration.middlewares??[];configuration.monitor;return(new RuntimeBuilder).url(url).healthCheck(...healthChecks).middleware(...middlewares).repository(repositoryUrl).buildGateway()}static async#configureNode(url,healthChecks,configuration){const repositoryUrl=configuration.repository,gatewayUrl=configuration.gateway,segmentNames=configuration.segments??[],middlewares=configuration.middlewares??[];return(new RuntimeBuilder).url(url).healthCheck(...healthChecks).middleware(...middlewares).repository(repositoryUrl).gateway(gatewayUrl).segment(...segmentNames).buildNode()}static async#configureProxy(url,healthChecks,configuration){const repositoryUrl=configuration.repository,gatewayUrl=configuration.gateway,nodeUrl=configuration.node,middlewares=configuration.middlewares??[];return(new RuntimeBuilder).url(url).healthCheck(...healthChecks).middleware(...middlewares).repository(repositoryUrl).gateway(gatewayUrl).node(nodeUrl).buildProxy()}static async#buildCache(sourceLocation,cacheLocation){const projectFileManager=new LocalFileManager("./");await projectFileManager.delete(cacheLocation),await projectFileManager.copy(sourceLocation,cacheLocation);const appFileManager=new LocalFileManager(cacheLocation),cacheManager=new CacheManager(projectFileManager,appFileManager);await cacheManager.build()}static async#getNodeSegmentNames(fileManager){return(await fileManager.getNodeSegmentFiles()).map((filename=>this.#extractSegmentName(filename)))}static async#getRepositorySegmentNames(fileManager){return(await fileManager.getRepositorySegmentFiles()).map((filename=>this.#extractSegmentName(filename)))}static#extractSegmentName(filename){const name=filename.split("/").pop()??"",endIndex=name.indexOf(".segment");return name.substring(0,endIndex)}}!function(LogLevel){LogLevel.DEBUG="debug",LogLevel.INFO="info",LogLevel.WARN="warn",LogLevel.ERROR="error",LogLevel.FATAL="fatal"}(LogLevel||(LogLevel={}));class LogBuilder{static build(level){const logConfiguration=this.#getLogConfiguration(level);return new Logger(logConfiguration)}static#getLogConfiguration(level){return{prettyLogTemplate:"{{dateIsoStr}}\t{{logLevelName}}\t",minLevel:this.#getLogLevel(level)}}static#getLogLevel(level){switch(level){case LogLevel.FATAL:return 6;case LogLevel.ERROR:return 5;case LogLevel.WARN:return 4;case LogLevel.INFO:return 3;default:return 2}}}const serverOptionsSchema=z.object({loglevel:z.nativeEnum(LogLevel).optional(),config:z.string().endsWith(".json")}).transform((value=>new ServerOptions(value.config,value.loglevel)));class ServerOptions{#config;#loglevel;constructor(config,loglevel="info"){this.#config=config,this.#loglevel=loglevel}get config(){return this.#config}get loglevel(){return this.#loglevel}}class ServerOptionsReader{static read(){const args=yargs(process.argv).argv;return DataConverter.convert(serverOptionsSchema,args)}}class AssetsController{#repository;#indexFile;#logger;constructor(app,repository,indexFile,logger){this.#repository=repository,this.#indexFile=indexFile,this.#logger=logger,app.get("*",((request,response)=>{this.#getContent(request,response)}))}async#getContent(request,response){this.#logger.info(`Got asset -> '${request.path}'`);const path=request.path.substring(1).trim(),filename=0===path.length?this.#indexFile:path;try{const file=await this.#repository.readAsset(filename);response.set("Content-Type",file.type),response.set("Content-Length",String(file.size)),response.status(200).send(file.content)}catch(error){if(error instanceof FileNotFound)return this.#logger.warn(`Failed to get asset -> '${filename}' | ${error.message}`),void response.status(404).send(error.message);const message=error instanceof Error?error.message:String(error);this.#logger.error(`Failed to get file content -> '${filename}' | ${message}`),response.status(500).send(message)}}}class HealthController{#node;#logger;constructor(app,node,logger){this.#node=node,this.#logger=logger,app.get("/health",((request,response)=>{this.getHealth(request,response)})),app.get("/health/status",((request,response)=>{this.isHealthy(request,response)}))}async getHealth(request,response){const health=await this.#node.getHealth(),data=Object.fromEntries(health);return this.#logger.debug("Got health"),response.status(200).send(data)}async isHealthy(request,response){const healthy=await this.#node.isHealthy();return this.#logger.debug("Got health status"),response.setHeader("Content-Type","text/plain"),response.status(200).send(healthy)}}const filePath=fileURLToPath(import.meta.url),fileLocation=path.dirname(filePath);class JitarController{constructor(app){app.use("/jitar",express.static(fileLocation))}}const clientIdHelper=new ClientIdHelper;class ModulesController{#repository;#serializer;#logger;constructor(app,repository,serializer,logger){this.#repository=repository,this.#serializer=serializer,this.#logger=logger,app.post("/modules",((request,response)=>{this.registerClient(request,response)})),app.get("/modules/:clientId/*",((request,response)=>{this.getModule(request,response)}))}async registerClient(request,response){if(this.#logger.info("Register client"),request.body instanceof Array==!1)return response.status(400).send("Invalid segment file list.");const segmentFiles=request.body,clientId=await this.#repository.registerClient(segmentFiles);return this.#logger.info(`Registered client -> ${clientId} [${segmentFiles.join(",")}]`),response.status(200).send(clientId)}async getModule(request,response){this.#logger.info(`Get module for -> '${request.params.clientId}'`);const clientId=request.params.clientId;if("string"!=typeof clientId||!1===clientIdHelper.validate(clientId))return response.status(400).send("Invalid client id.");const pathKey=`/${clientId}/`,pathIndex=request.path.indexOf(pathKey)+pathKey.length,filename=request.path.substring(pathIndex);try{const file=await this.#repository.readModule(filename,clientId);return this.#logger.info(`Got module -> '${filename}' (${clientId})`),response.set("Content-Type",file.type),response.status(200).send(file.content)}catch(error){const message=error instanceof Error?error.message:String(error);this.#logger.error(`Failed to get module -> '${filename}' (${clientId}) | ${message}`);const data=this.#serializer.serialize(error);return response.setHeader("Content-Type","application/json"),response.status(500).send(data)}}}const nodeDtoSchema=z.object({url:z.string().url(),procedureNames:z.array(z.string()).optional()}).strict().transform((value=>new NodeDto(value.url,value.procedureNames)));class NodeDto{url;procedureNames;constructor(url,procedureNames=[]){this.url=url,this.procedureNames=procedureNames}}class NodesController{#gateway;#logger;constructor(app,gateway,logger){this.#gateway=gateway,this.#logger=logger,app.get("/nodes",((request,response)=>{this.getNodes(request,response)})),app.post("/nodes",((request,response)=>{this.add(request,response)}))}async getNodes(request,response){const nodes=this.#gateway.nodes.map((node=>({url:node.url,procedureNames:node.getProcedureNames()})));return this.#logger.info("Got nodes"),response.status(200).send(nodes)}async add(request,response){try{const nodeDto=DataConverter.convert(nodeDtoSchema,request.body),node=new RemoteNode(nodeDto.url);return node.procedureNames=new Set(nodeDto.procedureNames),this.#gateway.addNode(node),this.#logger.info(`Added node -> ${node.url}`),response.status(201).send()}catch(error){const status=error instanceof Array?400:500,message=error instanceof Error?error.message:String(error);return this.#logger.error(`Failed to add node | ${message}`),response.status(status).send(error)}}}class ProceduresController{#runtime;#logger;constructor(app,runtime,logger){this.#runtime=runtime,this.#logger=logger,app.get("/procedures",((request,response)=>{this.getProcedureNames(request,response)}))}async getProcedureNames(request,response){const names=this.#runtime.getProcedureNames();return this.#logger.info("Got procedure names"),response.status(200).send(names)}}class ProxyController{#logger;#repositoryUrl;#runnerUrl;constructor(app,proxy,logger){this.#logger=logger,this.#repositoryUrl=proxy.repository.url??"",this.#runnerUrl=proxy.runner.url??"",app.use("/",expressProxy((message=>this.#selectProxy(message))))}#selectProxy(message){const url=message.url??"";return this.#logger.info(`Forwarding -> ${url}`),url.startsWith("/rpc")?this.#runnerUrl:this.#repositoryUrl}}const RPC_PARAMETERS=["version","serialize"],IGNORED_HEADER_KEYS=["host","connection","content-length","accept-encoding","user-agent"],BAD_REQUEST_NAME=BadRequest.name,UNAUTHORIZED_NAME=Unauthorized.name,PAYMENT_REQUIRED_NAME=PaymentRequired.name,FORBIDDEN_NAME=Forbidden.name,NOT_FOUND_NAME=NotFound.name,TEAPOT_NAME=Teapot.name,NOT_IMPLEMENTED_NAME=NotImplemented.name;class RPCController{#runtime;#serializer;#logger;constructor(app,runtime,serializer,logger){this.#runtime=runtime,this.#serializer=serializer,this.#logger=logger,app.get("/rpc/*",((request,response)=>{this.runGet(request,response)})),app.post("/rpc/*",((request,response)=>{this.runPost(request,response)})),app.options("/rpc/*",((request,response)=>{this.runOptions(request,response)}))}async runGet(request,response){const fqn=this.#extractFqn(request),version=this.#extractVersion(request),args=this.#extractQueryArguments(request),headers=this.#extractHeaders(request),serialize=this.#extractSerialize(request);return this.#run(fqn,version,args,headers,response,serialize)}async runPost(request,response){const fqn=this.#extractFqn(request),version=this.#extractVersion(request),args=this.#extractBodyArguments(request),headers=this.#extractHeaders(request),serialize=this.#extractSerialize(request);return this.#run(fqn,version,args,headers,response,serialize)}async runOptions(request,response){return this.#setCors(response)}#extractFqn(request){return request.path.substring(5)}#extractVersion(request){return void 0!==request.query.version?VersionParser.parse(request.query.version.toString()):Version.DEFAULT}#extractSerialize(request){return"true"===request.query.serialize}#extractQueryArguments(request){const args={};for(const[key,value]of Object.entries(request.query))RPC_PARAMETERS.includes(key)||(args[key]=value);return args}#extractBodyArguments(request){return request.body}#extractHeaders(request){const headers=new Map;for(const[key,value]of Object.entries(request.headers)){if(void 0===value)continue;const lowerKey=key.toLowerCase(),stringValue=value.toString();IGNORED_HEADER_KEYS.includes(lowerKey)||headers.set(lowerKey,stringValue)}return headers}async#run(fqn,version,args,headers,response,serialize){if(!1===this.#runtime.hasProcedure(fqn))return response.status(404).send(`Procedure not found -> ${fqn}`);try{const deserializedArgs=await this.#serializer.deserialize(args),argsMap=new Map(Object.entries(deserializedArgs)),runtimeRequest=new Request(fqn,version,argsMap,headers),runtimeResponse=await this.#runtime.handle(runtimeRequest);return this.#logger.info(`Ran procedure -> ${fqn} (v${version.toString()})`),this.#setResponseHeaders(response,runtimeResponse.headers),this.#createResultResponse(runtimeResponse.result,response,serialize)}catch(error){const message=error instanceof Error?error.message:String(error),errorData=serialize?error:message;return this.#logger.error(`Failed to run procedure -> ${fqn} (v${version.toString()}) | ${message}`),this.#createErrorResponse(error,errorData,response,serialize)}}async#setCors(response){const cors=this.#runtime.getMiddleware(CorsMiddleware);return void 0===cors||(response.setHeader("Access-Control-Allow-Origin",cors.allowOrigin),response.setHeader("Access-Control-Allow-Methods",cors.allowMethods),response.setHeader("Access-Control-Allow-Headers",cors.allowHeaders),response.setHeader("Access-Control-Max-Age",86400)),response.status(204).send()}async#createResultResponse(result,response,serialize){const content=await this.#createResponseContent(result,serialize),contentType=this.#createResponseContentType(content),responseContent="text/plain"===contentType?String(content):content;return response.setHeader("Content-Type",contentType),response.status(200).send(responseContent)}async#createErrorResponse(error,errorData,response,serialize){const content=await this.#createResponseContent(errorData,serialize),contentType=this.#createResponseContentType(content),statusCode=this.#createResponseStatusCode(error);return response.setHeader("Content-Type",contentType),response.status(statusCode).send(content)}async#createResponseContent(data,serialize){return serialize?this.#serializer.serialize(data):data}#createResponseContentType(content){return"object"==typeof content?"application/json":"text/plain"}#setResponseHeaders(response,headers){headers.forEach(((value,key)=>response.setHeader(key,value)))}#createResponseStatusCode(error){if(error instanceof Object==!1)return 500;const errorClass=error.constructor;return this.#isClassType(errorClass,BAD_REQUEST_NAME)?400:this.#isClassType(errorClass,UNAUTHORIZED_NAME)?401:this.#isClassType(errorClass,PAYMENT_REQUIRED_NAME)?402:this.#isClassType(errorClass,FORBIDDEN_NAME)?403:this.#isClassType(errorClass,NOT_FOUND_NAME)?404:this.#isClassType(errorClass,TEAPOT_NAME)?418:this.#isClassType(errorClass,NOT_IMPLEMENTED_NAME)?501:500}#isClassType(clazz,className){if(clazz.name===className)return!0;const parentClass=Object.getPrototypeOf(clazz);return""!==parentClass.name&&this.#isClassType(parentClass,className)}}class RuntimeNotAvailable extends Error{constructor(){super("Runtime is not available")}}class JitarServer{#app;#server;#runtime;#serializer;#classLoader;#options;#configuration;#logger;constructor(){this.#classLoader=new RemoteClassLoader,this.#serializer=SerializerBuilder.build(this.#classLoader),this.#app=express(),this.#app.use(express.json()),this.#app.use(express.urlencoded({extended:!0})),this.#app.disable("x-powered-by"),this.#options=ServerOptionsReader.read(),this.#configuration=RuntimeConfigurationLoader.load(this.#options.config),this.#logger=LogBuilder.build(this.#options.loglevel),this.#printStartupMessage()}get classLoader(){return this.#classLoader}async build(){this.#runtime=await RuntimeConfigurator.configure(this.#configuration),this.#addControllers()}async start(){const url=new URL(this.#configuration.url??RuntimeDefaults$1.URL);await this.#startApplication(),await this.#startServer(url.port),this.#printProcedureInfo(),this.#logger.info(`Server started and listening at port ${url.port}`)}async stop(){await this.#stopServer(),await this.#stopApplication(),this.#logger.info("Server stopped")}addSerializer(serializer){this.#serializer.addSerializer(serializer)}#getRuntime(){if(void 0===this.#runtime)throw new RuntimeNotAvailable;return this.#runtime}#addControllers(){if(void 0!==this.#configuration.standalone&&this.#runtime instanceof Standalone){const index=this.#configuration.standalone.index??RuntimeDefaults$1.INDEX;this.#addStandAloneControllers(this.#runtime,index)}else if(void 0!==this.#configuration.repository&&this.#runtime instanceof LocalRepository){const index=this.#configuration.repository.index??RuntimeDefaults$1.INDEX;this.#addRepositoryControllers(this.#runtime,index)}else void 0!==this.#configuration.gateway&&this.#runtime instanceof LocalGateway?this.#addGatewayControllers(this.#runtime):void 0!==this.#configuration.node&&this.#runtime instanceof LocalNode?this.#addNodeControllers(this.#runtime):void 0!==this.#configuration.proxy&&this.#runtime instanceof Proxy&&this.#addProxyControllers(this.#runtime)}#addStandAloneControllers(standalone,index){new HealthController(this.#app,standalone,this.#logger),new JitarController(this.#app),new ModulesController(this.#app,standalone,this.#serializer,this.#logger),new ProceduresController(this.#app,standalone,this.#logger),new RPCController(this.#app,standalone,this.#serializer,this.#logger),new AssetsController(this.#app,standalone,index,this.#logger)}#addRepositoryControllers(repository,index){new JitarController(this.#app),new ModulesController(this.#app,repository,this.#serializer,this.#logger),new AssetsController(this.#app,repository,index,this.#logger)}#addGatewayControllers(gateway){new NodesController(this.#app,gateway,this.#logger),new ProceduresController(this.#app,gateway,this.#logger),new RPCController(this.#app,gateway,this.#serializer,this.#logger)}#addNodeControllers(node){new HealthController(this.#app,node,this.#logger),new ProceduresController(this.#app,node,this.#logger),new RPCController(this.#app,node,this.#serializer,this.#logger)}#addProxyControllers(proxy){new ProxyController(this.#app,proxy,this.#logger)}async#startApplication(){const runtime=this.#getRuntime();await runtime.start();const setUpScript=this.#configuration.setUp;void 0!==setUpScript&&await runtime.import(setUpScript,ExecutionScopes.APPLICATION)}async#stopApplication(){const runtime=this.#getRuntime();await runtime.stop();const tearDownScript=this.#configuration.tearDown;void 0!==tearDownScript&&await runtime.import(tearDownScript,ExecutionScopes.APPLICATION)}#startServer(port){return void 0!==this.#server?Promise.resolve():new Promise((resolve=>{this.#server=this.#app.listen(port,resolve)}))}#stopServer(){return void 0===this.#server?Promise.resolve():new Promise((resolve=>{this.#server?.close((()=>resolve()))}))}#printStartupMessage(){console.log("\n ██ ██ ████████ █████ ██████ \n ██ ██ ██ ██ ██ ██ ██ \n ██ ██ ██ ███████ ██████ \n ██ ██ ██ ██ ██ ██ ██ ██ \n █████ ██ ██ ██ ██ ██ ██\n ____________________________________\n By Masking Technology (masking.tech)\n")}#printProcedureInfo(){const runtime=this.#getRuntime();if(runtime instanceof LocalNode==!1&&runtime instanceof Standalone==!1)return;const procedureNames=runtime.getProcedureNames();0!==procedureNames.length&&(procedureNames.sort(),this.#logger.info("Registered RPC entries",procedureNames))}}async function buildServer(moduleImporter){ModuleLoader.setImporter(moduleImporter);const server=new JitarServer;return await server.build(),server}export{CorsMiddleware,buildServer};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jitar",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
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",
|
|
@@ -36,8 +36,8 @@
|
|
|
36
36
|
"zod": "^3.22.4"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@jitar/runtime": "^0.
|
|
40
|
-
"@jitar/server-nodejs": "^0.
|
|
39
|
+
"@jitar/runtime": "^0.5.0",
|
|
40
|
+
"@jitar/server-nodejs": "^0.5.0"
|
|
41
41
|
},
|
|
42
42
|
"engines": {
|
|
43
43
|
"node": ">=18.7"
|
|
@@ -59,6 +59,5 @@
|
|
|
59
59
|
"monolith",
|
|
60
60
|
"full stack",
|
|
61
61
|
"web applications"
|
|
62
|
-
]
|
|
63
|
-
"gitHead": "d97e6378eae3cbf33c8b79a6ccbb29b5dfb41793"
|
|
62
|
+
]
|
|
64
63
|
}
|
package/LICENCE
DELETED
|
@@ -1,23 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
(The MIT License)
|
|
3
|
-
|
|
4
|
-
Copyright (c) 2023 Masking Technology B.V. <https://masking.tech>
|
|
5
|
-
|
|
6
|
-
Permission is hereby granted, free of charge, to any person obtaining
|
|
7
|
-
a copy of this software and associated documentation files (the
|
|
8
|
-
'Software'), to deal in the Software without restriction, including
|
|
9
|
-
without limitation the rights to use, copy, modify, merge, publish,
|
|
10
|
-
distribute, sublicense, and/or sell copies of the Software, and to
|
|
11
|
-
permit persons to whom the Software is furnished to do so, subject to
|
|
12
|
-
the following conditions:
|
|
13
|
-
|
|
14
|
-
The above copyright notice and this permission notice shall be
|
|
15
|
-
included in all copies or substantial portions of the Software.
|
|
16
|
-
|
|
17
|
-
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
|
18
|
-
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
19
|
-
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
|
20
|
-
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
|
21
|
-
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
|
22
|
-
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
|
23
|
-
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/dist/globals-a24096f0.js
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
const AccessLevel={PRIVATE:"private",PUBLIC:"public"};Object.freeze(AccessLevel);const AccessLevels=Object.values(AccessLevel);Object.freeze(AccessLevels);const Files={MODULE_PATTERN:"**/*.js",SEGMENT_PATTERN:"**/*.segment.json",NODE_SEGMENT_PATTERN:"**/*.segment.node.js",REPOSITORY_SEGMENT_PATTERN:"**/*.segment.repository.js"};function convertToLocalFilename(filename){return filename.replace(".js",".local.js")}function convertToRemoteFilename(filename){return filename.replace(".js",".remote.js")}function createNodeFilename(name){return`${name}.segment.node.js`}function createRepositoryFilename(name){return`${name}.segment.repository.js`}function isSegmentFilename(filename){return filename.includes(".segment.")}Object.freeze(Files);class BadRequest extends Error{constructor(message="Invalid request"){super(message)}}BadRequest.source="/jitar/client.js";class Forbidden extends Error{constructor(message="Forbidden"){super(message)}}Forbidden.source="/jitar/client.js";class NotFound extends Error{constructor(message="Not found"){super(message)}}NotFound.source="/jitar/client.js";class NotImplemented extends Error{constructor(message="Not implemented"){super(message)}}NotImplemented.source="/jitar/client.js";class PaymentRequired extends Error{constructor(message="Payment required"){super(message)}}PaymentRequired.source="/jitar/client.js";class ServerError extends Error{constructor(message="Server error"){super(message)}}ServerError.source="/jitar/client.js";class Teapot extends Error{constructor(){super("I'm a teapot")}}Teapot.source="/jitar/client.js";class Unauthorized extends Error{constructor(message="Unauthorized"){super(message)}}Unauthorized.source="/jitar/client.js";class ClientNotFound extends BadRequest{#clientId;constructor(clientId){super(`Client not found for id '${clientId}'`),this.#clientId=clientId}get clientId(){return this.#clientId}}ClientNotFound.source="/jitar/client.js";class FileNotFound extends NotFound{#filename;constructor(filename){super(`The file '${filename} could not be found'`),this.#filename=filename}get filename(){return this.#filename}}FileNotFound.source="/jitar/client.js";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}}ImplementationNotFound.source="/jitar/client.js";class InvalidClientId extends BadRequest{#clientId;constructor(clientId){super(`Invalid client id '${clientId}'`),this.#clientId=clientId}get clientId(){return this.#clientId}}InvalidClientId.source="/jitar/client.js";class InvalidParameterValue extends BadRequest{#parameterName;constructor(parameterName){super(`Invalid value for parameter '${parameterName}'`),this.#parameterName=parameterName}get parameterName(){return this.#parameterName}}InvalidParameterValue.source="/jitar/client.js";class InvalidSegmentFile extends ServerError{#filename;constructor(filename){super(`Missing files array in segment file '${filename}'`),this.#filename=filename}get filename(){return this.#filename}}InvalidSegmentFile.source="/jitar/client.js";class InvalidVersionNumber extends BadRequest{#number;constructor(number){super(`Invalid version number '${number}'`),this.#number=number}get number(){return this.#number}}InvalidVersionNumber.source="/jitar/client.js";class MissingParameterValue extends BadRequest{#parameterName;constructor(parameterName){super(`Missing value for parameter '${parameterName}'`),this.#parameterName=parameterName}get parameterName(){return this.#parameterName}}MissingParameterValue.source="/jitar/client.js";class ModuleNotAccessible extends Forbidden{#url;constructor(url){super(`Module '${url}' is not accessible`),this.#url=url}get url(){return this.#url}}ModuleNotAccessible.source="/jitar/client.js";class ModuleNotLoaded extends ServerError{#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}}ModuleNotLoaded.source="/jitar/client.js";class NoNodeAvailable extends ServerError{#name;constructor(name){super(`No node available for procedure '${name}'`),this.#name=name}get name(){return this.#name}}NoNodeAvailable.source="/jitar/client.js";class ProcedureNotAccessible extends Forbidden{#fqn;#versionNumber;constructor(fqn,versionNumber){super(`Procedure '${fqn}' (v${versionNumber}) is not accessible`),this.#fqn=fqn,this.#versionNumber=versionNumber}get fqn(){return this.#fqn}get versionNumber(){return this.#versionNumber}}ProcedureNotAccessible.source="/jitar/client.js";class ProcedureNotFound extends NotFound{#fqn;constructor(fqn){super(`Procedure '${fqn}' not found`),this.#fqn=fqn}get fqn(){return this.#fqn}}ProcedureNotFound.source="/jitar/client.js";class RepositoryNotAvailable extends ServerError{constructor(){super("Repository not available")}}RepositoryNotAvailable.source="/jitar/client.js";class RuntimeNotAvailable extends ServerError{constructor(){super("Runtime not available")}}RuntimeNotAvailable.source="/jitar/client.js";class SegmentNotFound extends ServerError{#source;constructor(source){super(`Segment found for '${source}'`),this.#source=source}get source(){return this.#source}}SegmentNotFound.source="/jitar/client.js";class UnknownParameter extends BadRequest{#parameterName;constructor(parameterName){super(`Unknown parameter ${parameterName}`),this.#parameterName=parameterName}get parameterName(){return this.#parameterName}}UnknownParameter.source="/jitar/client.js";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 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 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 NamedParameter extends Parameter{}class ObjectParameter extends DestructuredParameter{}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 Runtime{#url;#healthChecks=new Map;constructor(url){this.#url=url}get url(){return this.#url}addHealthCheck(name,healthCheck){this.#healthChecks.set(name,healthCheck)}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 ProcedureRunner{#runner;constructor(runner){this.#runner=runner}async handle(fqn,version,args,headers,next){const result=await this.#runner.run(fqn,version,args,headers);return headers.clear(),result}}class ProcedureRuntime extends Runtime{#middlewares=[];constructor(url){super(url),this.#middlewares.push(new ProcedureRunner(this))}addMiddleware(middleware){const index=this.#middlewares.length-1;this.#middlewares.splice(index,0,middleware)}getMiddleware(type){return this.#middlewares.find((middleware=>middleware instanceof type))}handle(fqn,version,args,headers){return this.#getNextHandler(fqn,version,args,headers,0)()}#getNextHandler(fqn,version,args,headers,index){const next=this.#middlewares[index];if(void 0===next)return async()=>{};const nextHandler=this.#getNextHandler(fqn,version,args,headers,index+1);return async()=>next.handle(fqn,version,args,headers,nextHandler)}}class Gateway extends ProcedureRuntime{}class UrlRewriter{static addBase(url,base){return url=this.#ensureStartsWithoutSlash(url),base=this.#assureEndWithSlash(base),this.#translateRelativeParts(`${base}${url}`)}static#ensureStartsWithoutSlash(url){return url.startsWith("/")?url.substring(1):url}static#assureEndWithSlash(base){return base.endsWith("/")?base:`${base}/`}static#translateRelativeParts(url){const parts=url.split("/"),translated=[];translated.push(parts[0]);for(let index=1;index<parts.length;index++){const part=parts[index].trim();"."!==part&&(".."!==part?translated.push(part):translated.pop())}return translated.join("/")}}const NON_SYSTEM_INDICATORS=[".","/","http:","https:"];let _baseUrl,_import=async name=>import(name);class ModuleLoader{static setBaseUrl(baseUrl){_baseUrl=baseUrl}static setImporter(importer){_import=importer}static assureExtension(specifier){return this.#isSystemModule(specifier)||specifier.endsWith(".js")?specifier:`${specifier}.js`}static async load(specifier){let url=this.assureExtension(specifier);if(url.startsWith("/jitar"))return specifier="jitar",this.#import(specifier,specifier);if(void 0!==_baseUrl&&!1===url.startsWith(_baseUrl)&&(url=UrlRewriter.addBase(url,_baseUrl),!1===url.startsWith(_baseUrl)))throw new ModuleNotAccessible(specifier);return this.#import(url,specifier)}static async import(specifier){return this.#import(specifier,specifier)}static async#import(absolute,relative){try{return await _import(absolute)}catch(error){const message=error instanceof Error?error.message:String(error);throw new ModuleNotLoaded(relative,message)}}static#isSystemModule(specifier){return!1===NON_SYSTEM_INDICATORS.some((indicator=>specifier.startsWith(indicator)))}}class NodeBalancer{#nodes=[];#currentIndex=0;addNode(node){this.#nodes.includes(node)||this.#nodes.push(node)}removeNode(node){const index=this.#nodes.indexOf(node);-1!==index&&this.#nodes.splice(index,1)}getNextNode(){if(0!==this.#nodes.length)return this.#currentIndex>=this.#nodes.length&&(this.#currentIndex=0),this.#nodes[this.#currentIndex++]}run(fqn,version,args,headers){const node=this.getNextNode();if(void 0===node)throw new NoNodeAvailable(fqn);return node.run(fqn,version,args,headers)}}const NO_SEGMENTS=[];class LocalGateway extends Gateway{#nodes=new Set;#balancers=new Map;get nodes(){return[...this.#nodes.values()]}getProcedureNames(){const procedureNames=this.nodes.map((node=>node.getProcedureNames()));return[...new Set(procedureNames.flat()).values()]}hasProcedure(fqn){return this.getProcedureNames().includes(fqn)}async addNode(node){this.#nodes.add(node);for(const name of node.getProcedureNames()){this.#getOrCreateBalancer(name).addNode(node)}}removeNode(node){this.#nodes.delete(node);for(const name of node.getProcedureNames()){const balancer=this.#getBalancer(name);void 0!==balancer&&balancer.removeNode(node)}}async setBaseUrl(repository){const clientId=await repository.registerClient(NO_SEGMENTS),moduleLocation=await repository.getModuleLocation(clientId);ModuleLoader.setBaseUrl(moduleLocation)}#getBalancer(fqn){return this.#balancers.get(fqn)}#getOrCreateBalancer(fqn){let balancer=this.#getBalancer(fqn);return void 0===balancer&&(balancer=new NodeBalancer,this.#balancers.set(fqn,balancer)),balancer}run(fqn,version,args,headers){const balancer=this.#getBalancer(fqn);if(void 0===balancer)throw new ProcedureNotFound(fqn);return balancer.run(fqn,version,args,headers)}}class Context{#headers=new Map;constructor(headers){this.#headers=headers}get headers(){return this.#headers}}class ArgumentExtractor{extract(parameters,args){const argsCopy=new Map(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}#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 Node extends ProcedureRuntime{}const RUNS_IN_BROWSER="undefined"!=typeof window;let _runtime,_loader=name=>ModuleLoader.import(name);class VersionParser{static parse(number){if(0===number.trim().length)return Version.DEFAULT;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]));case 3:return new Version(Number.parseInt(parts[0]),Number.parseInt(parts[1]),Number.parseInt(parts[2]));default:throw new InvalidVersionNumber(number)}}}class LocalNode extends Node{#argumentConstructor;#segments=new Map;#gateway;#repository;#clientId="";constructor(url,argumentConstructor=new ArgumentExtractor){super(url),this.#argumentConstructor=argumentConstructor}getProcedureNames(){const names=new Set;for(const segment of this.#segments.values()){segment.getPublicProcedures().forEach((procedure=>names.add(procedure.fqn)))}return[...names.values()]}async loadSegment(name){const filename=createNodeFilename(name),segment=(await this.import(filename)).segment;this.addSegment(segment)}addSegment(segment){this.#segments.set(segment.id,segment)}hasProcedure(fqn){return this.getProcedureNames().includes(fqn)}#getProcedure(fqn){for(const segment of this.#segments.values())if(segment.hasProcedure(fqn))return segment.getProcedure(fqn)}async setGateway(gateway){(gateway instanceof LocalGateway||void 0!==this.url)&&await gateway.addNode(this),this.#gateway=gateway}async setRepository(repository,segmentNames){this.#clientId=await repository.registerClient(segmentNames),_runtime=this,_loader=name=>ModuleLoader.import(name);const moduleLocation=await repository.getModuleLocation(this.#clientId);ModuleLoader.setBaseUrl(moduleLocation),this.#repository=repository}import(url,base){if(void 0===this.#repository)throw new RepositoryNotAvailable;return void 0!==base&&(url=UrlRewriter.addBase(url,base)),this.#repository.importModule(this.#clientId,url)}run(fqn,version,args,headers){const procedure=this.#getProcedure(fqn);return void 0===procedure?this.#runGateway(fqn,version,args,headers):this.#runProcedure(procedure,version,args,headers)}#runGateway(fqn,version,args,headers){if(void 0===this.#gateway)throw new ProcedureNotFound(fqn);return this.#gateway.run(fqn,version,args,headers)}#runProcedure(procedure,version,args,headers){const implementation=procedure.getImplementation(version);if(void 0===implementation)throw new ImplementationNotFound(procedure.fqn,version.toString());const context=new Context(headers),values=this.#argumentConstructor.extract(implementation.parameters,args);return implementation.executable.call(context,...values)}}class Repository extends Runtime{}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 ReflectionAlias{#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 ReflectionValue{#definition;constructor(definition){this.#definition=definition}get definition(){return this.#definition}toString(){return this.#definition}}class ReflectionArray extends ReflectionValue{}class ReflectionMember{#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 ReflectionClass extends ReflectionMember{#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 void 0!==declaration&&declaration.isPublic||this.hasGetter(name)}canWrite(name){const declaration=this.getDeclaration(name);return void 0!==declaration&&declaration.isPublic||this.hasSetter(name)}canCall(name){const funktion=this.getFunction(name);return void 0!==funktion&&funktion.isPublic}toString(){const infix=void 0!==this.#parentName?` extends ${this.#parentName}`:"";return`class ${this.name}${infix} { ${this.#scope.toString()} }`}}class ReflectionDeclaration extends ReflectionMember{#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 ReflectionDestructuredValue{#members;constructor(members){this.#members=members}get members(){return this.#members}toString(){return this.#members.map((member=>member.toString())).join(" , ")}}class ReflectionDestructuredArray extends ReflectionDestructuredValue{toString(){return`[ ${super.toString()} ]`}}class ReflectionDestructuredObject extends ReflectionDestructuredValue{toString(){return`{ ${super.toString()} }`}}class ReflectionExport extends ReflectionMember{#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 ReflectionExpression extends ReflectionValue{}class ReflectionField{#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 ReflectionFunction extends ReflectionMember{#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 ReflectionGenerator extends ReflectionFunction{toString(){const parameters=this.parameters.map((parameter=>parameter.toString()));return`${this.isAsync?"async ":""}${this.name}*(${parameters.join(", ")}) { ${this.body} }`}}class ReflectionGetter extends ReflectionFunction{toString(){return`get ${super.toString()}`}}class ReflectionImport extends ReflectionMember{#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 ReflectionModule{#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 ReflectionObject extends ReflectionValue{}class ReflectionSetter extends ReflectionFunction{toString(){return`set ${super.toString()}`}}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{}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)}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 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}`)}}const IMPORT_NAME=ReflectionImport.name,EXPORT_NAME=ReflectionExport.name,DECLARATION_NAME=ReflectionDeclaration.name,FUNCTION_NAME=ReflectionFunction.name,GETTER_NAME=ReflectionGetter.name,SETTER_NAME=ReflectionSetter.name,GENERATOR_NAME=ReflectionGenerator.name,CLASS_NAME=ReflectionClass.name;class ReflectionScope{#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")}}class Parser{#lexer;constructor(lexer=new Lexer){this.#lexer=lexer}parse(code){const tokenList=this.#lexer.tokenize(code),scope=this.#parseScope(tokenList);return new ReflectionModule(scope)}parseFirst(code){const tokenList=this.#lexer.tokenize(code);return this.#parseNext(tokenList)}parseValue(code){const model=this.parseFirst(code);if(model instanceof ReflectionValue==!1)throw new UnexpectedParseResult("a value definition");return model}parseImport(code){const model=this.parseFirst(code);if(model instanceof ReflectionImport==!1)throw new UnexpectedParseResult("an import definition");return model}parseExport(code){const model=this.parseFirst(code);if(model instanceof ReflectionExport==!1)throw new UnexpectedParseResult("an export definition");return model}parseDeclaration(code){const model=this.parseFirst(code);if(model instanceof ReflectionDeclaration==!1)throw new UnexpectedParseResult("a declaration definition");return model}parseFunction(code){const tokenList=this.#lexer.tokenize(code),model=this.#parseMember(tokenList);if(model instanceof ReflectionFunction==!1)throw new UnexpectedParseResult("a function definition");return model}parseClass(code){const tokenList=this.#lexer.tokenize(code),model=this.#parseMember(tokenList);if(model instanceof ReflectionClass==!1)throw new UnexpectedParseResult("a class definition");return model}#parseScope(tokenList){const members=[];for(;tokenList.notAtEnd();){const member=this.#parseNext(tokenList);member instanceof ReflectionMember&&members.push(member)}return new ReflectionScope(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 void 0!==next&&next.hasValue(Operator.ARROW)?this.#parseArrowFunction(tokenList,isAsync):this.#parseExpression(tokenList)}if(token.isType(TokenType.KEYWORD))return token.hasValue(Keyword.ASYNC)?(tokenList.step(),this.#parseNext(tokenList,!0)):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 void 0!==next&&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 ReflectionImport(members,token.value);if(token.hasValue(Group.OPEN)){token=tokenList.step();const from=token.value;return tokenList.step(2),new ReflectionImport(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 ReflectionAlias(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 ReflectionImport(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=token.isType(TokenType.IDENTIFIER)?token.value:"",as=isDefault?"default":name;let from;token=tokenList.step(),void 0!==token&&token.hasValue(Keyword.FROM)&&(token=tokenList.step(),from=token.value),stepSize>0&&(stepSize++,tokenList.stepBack(stepSize));const alias=new ReflectionAlias(name,as);return new ReflectionExport([alias],from)}#parseMultiExport(tokenList){const members=this.#parseAliasList(tokenList);let from,token=tokenList.current;return void 0!==token&&token.hasValue(Keyword.FROM)&&(token=tokenList.step(),from=token.value),tokenList.step(),new ReflectionExport(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 ReflectionAlias(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 ReflectionGenerator?new ReflectionGenerator(identifier.toString(),value.parameters,value.body,isStatic,value.isAsync,isPrivate):value instanceof ReflectionFunction?new ReflectionFunction(identifier.toString(),value.parameters,value.body,isStatic,value.isAsync,isPrivate):value instanceof ReflectionClass?new ReflectionClass(identifier.toString(),value.parentName,value.scope):new ReflectionDeclaration(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()),token.isType(TokenType.IDENTIFIER)&&(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 ReflectionGenerator(name,parameters,body,isStatic,isAsync,isPrivate):isGetter?new ReflectionGetter(name,parameters,body,isStatic,isAsync,isPrivate):isSetter?new ReflectionSetter(name,parameters,body,isStatic,isAsync,isPrivate):new ReflectionFunction(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 ReflectionField(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 ReflectionFunction("",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(token.isType(TokenType.IDENTIFIER)&&(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 ReflectionClass(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 ReflectionScope(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 ReflectionArray(items)}#parseDestructuredArray(tokenList){const fields=this.#parseParameters(tokenList,List.CLOSE);return new ReflectionDestructuredArray(fields)}#parseObject(tokenList){const fields=this.#parseBlock(tokenList,Scope.OPEN,Scope.CLOSE);return new ReflectionObject(fields)}#parseDestructuredObject(tokenList){const fields=this.#parseParameters(tokenList,Scope.CLOSE);return new ReflectionDestructuredObject(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 ReflectionField(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 ReflectionExpression(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)}}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 ReflectionClass(model.name,parent.name,new ReflectionScope(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;#merger;constructor(parser=new Parser,merger=new ClassMerger){this.#parser=parser,this.#merger=merger}parse(code){return this.#parser.parse(code)}parseClass(code){return this.#parser.parseClass(code)}parseFunction(code){return this.#parser.parseFunction(code)}parseDeclaration(code){return this.#parser.parseDeclaration(code)}parseImport(code){return this.#parser.parseImport(code)}parseExport(code){return this.#parser.parseExport(code)}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 ReflectionExpression(code);members.push(new ReflectionDeclaration(key,expression))}}return new ReflectionModule(new ReflectionScope(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.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.parseClass(code)}#reflectDynamic(clazz){const object=this.createInstance(clazz),members=this.#getMembers(clazz,object),scope=new ReflectionScope(members);return new ReflectionClass(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 ReflectionValue(String(content)):void 0,model=new ReflectionDeclaration(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 ReflectionGetter(model.name,model.parameters,model.body,model.isStatic,model.isAsync,model.isPrivate)):void 0!==description.set?models.push(new ReflectionSetter(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{#classLoader;constructor(classLoader){super(),this.#classLoader=classLoader}canSerialize(value){return value instanceof Object&&reflector$1.isClassObject(value)}canDeserialize(value){const object=value;return object instanceof Object&&!0===object.serialized&&"string"==typeof object.name&&object.args instanceof Array&&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.#extractParameterNames(model);return{serialized:!0,name:clazz.name,source:clazz.source,args:await this.#extractArguments(model,parameterNames,object),fields:await this.#extractFields(model,parameterNames,object)}}#extractParameterNames(model){const constructor=model.getFunction("constructor");return(constructor?.parameters??[]).map((parameter=>parameter.name))}async#extractArguments(model,includeNames,object){const args=[];for(const name of includeNames){const objectValue=model.canRead(name)?await this.serializeOther(object[name]):void 0;args.push(objectValue)}return args}async#extractFields(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.name);if(clazz instanceof Function==!1)throw new InvalidClass(object.name);const args=await Promise.all(object.args.map((async value=>this.deserializeOther(value)))),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#getClass(clazz){return void 0===clazz.source?globalThis[clazz.name]:this.#classLoader.loadClass(clazz)}}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)}}}const defaultClassLoader=new class{async loadClass(loadable){if("string"!=typeof loadable.source)throw new ClassNotFound(loadable.name);const module=await import(loadable.source),clazz=module[loadable.name]??module.default;if(void 0===clazz)throw new ClassNotFound(loadable.name);if(clazz instanceof Function==!1)throw new InvalidClass(loadable.name);return clazz}};class SerializerBuilder{static build(loader=defaultClassLoader){const serializer=new Serializer;return serializer.addSerializer(new PrimitiveSerializer),serializer.addSerializer(new ObjectSerializer),serializer.addSerializer(new ClassSerializer(loader)),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 RemoteClassLoader{async loadClass(loadable){if("string"!=typeof loadable.source)throw new ClassNotFound(loadable.name);const module=await ModuleLoader.load(loadable.source),clazz=module[loadable.name]??module.default;if(void 0===clazz)throw new ClassNotFound(loadable.name);if(clazz instanceof Function==!1)throw new InvalidClass(loadable.name);return clazz}}const remoteClassLoader=new RemoteClassLoader,defaultSerializer=SerializerBuilder.build(remoteClassLoader);class Remote{#url;#serializer;constructor(url,serializer=defaultSerializer){this.#url=url,this.#serializer=serializer}async registerClient(segmentFiles){const url=`${this.#url}/modules`,options={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(segmentFiles)};return(await this.#callRemote(url,options,200)).text()}async loadFile(filename){const url=`${this.#url}/${filename}`,response=await this.#callRemote(url,{method:"GET"},200),type=response.headers.get("Content-Type")||"application/octet-stream",content=await response.text();return new File(filename,type,content)}importFile(filename){const url=`${this.#url}/${filename}`;return ModuleLoader.load(url)}async isHealthy(){const url=`${this.#url}/health/status`,response=await this.#callRemote(url,{method:"GET"},200),healthy=await response.text();return Boolean(healthy)}async getHealth(){const url=`${this.#url}/health`,response=await this.#callRemote(url,{method:"GET"},200),health=await response.json();return new Map(Object.entries(health))}async addNode(node){const url=`${this.#url}/nodes`,body={url:node.url,procedureNames:node.getProcedureNames()},options={method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify(body)};await this.#callRemote(url,options,201)}async run(fqn,version,args,headers){headers.set("content-type","application/json");const versionString=version.toString(),argsObject=Object.fromEntries(args),headersObject=Object.fromEntries(headers),url=`${this.#url}/rpc/${fqn}?version=${versionString}&serialize=true`,options={method:"POST",headers:headersObject,body:await this.#createRequestBody(argsObject)},response=await this.#callRemote(url,options,200);return this.#createResponseResult(response)}async#callRemote(url,options,expectedStatus){const response=await fetch(url,options);if(response.status!==expectedStatus)throw await this.#createResponseResult(response);return response}async#createRequestBody(body){const data=await this.#serializer.serialize(body);return JSON.stringify(data)}async#createResponseResult(response){const result=await this.#getResponseResult(response);return this.#serializer.deserialize(result)}#getResponseResult(response){const contentType=response.headers.get("Content-Type");return null!==contentType&&contentType.includes("json")?response.json():response.text()}}class RemoteGateway extends Gateway{#remote;constructor(url){super(url),this.#remote=new Remote(url)}getProcedureNames(){throw new NotImplemented}hasProcedure(name){throw new NotImplemented}addNode(node){return this.#remote.addNode(node)}run(fqn,version,args,headers){return this.#remote.run(fqn,version,args,headers)}}class RemoteRepository extends Repository{#remote;constructor(url){super(url),this.#remote=new Remote(url)}registerClient(segmentFiles){return this.#remote.registerClient(segmentFiles)}loadAsset(filename){return this.#remote.loadFile(filename)}async getModuleLocation(clientId){return`${this.url}/modules/${clientId}`}async loadModule(clientId,filename){return this.#remote.loadFile(`modules/${clientId}/${filename}`)}async importModule(clientId,filename){return this.#remote.importFile(`modules/${clientId}/${filename}`)}}const globals=globalThis;globals.__getDependency=async function(name){RUNS_IN_BROWSER&&"jitar"===name&&(name="/jitar/client.js");const module=await _loader(name);return void 0!==module.default?module.default:module},globals.__runProcedure=async function(fqn,versionNumber,args,context){if(void 0===_runtime)throw new RuntimeNotAvailable;const version=VersionParser.parse(versionNumber),argsMap=new Map(Object.entries(args)),headersMap=context instanceof Context?context.headers:new Map;return _runtime.run(fqn,version,argsMap,headersMap)},globals.ProcedureNotAccessible=ProcedureNotAccessible;export{SegmentNotFound as $,AccessLevel as A,BadRequest as B,ClientNotFound as C,ServerError as D,ImplementationNotFound as E,FileNotFound as F,InvalidParameterValue as G,InvalidVersionNumber as H,InvalidSegmentFile as I,MissingParameterValue as J,ModuleNotAccessible as K,LocalGateway as L,ModuleLoader as M,Node as N,ObjectParameter as O,ProcedureRuntime as P,ModuleNotLoaded as Q,Repository as R,SerializerBuilder as S,Teapot as T,Unauthorized as U,VersionParser as V,NoNodeAvailable as W,ProcedureNotAccessible as X,ProcedureNotFound as Y,RepositoryNotAvailable as Z,RuntimeNotAvailable as _,InvalidClientId as a,UnknownParameter as a0,File as b,convertToLocalFilename as c,convertToRemoteFilename as d,createRepositoryFilename as e,Remote as f,Reflector as g,ReflectionField as h,isSegmentFilename as i,ReflectionDestructuredArray as j,ReflectionDestructuredObject as k,ReflectionDestructuredValue as l,createNodeFilename as m,ReflectionFunction as n,Files as o,LocalNode as p,RemoteRepository as q,RemoteGateway as r,PaymentRequired as s,Forbidden as t,NotFound as u,NotImplemented as v,Version as w,RemoteClassLoader as x,NamedParameter as y,ArrayParameter as z};
|