diff --git a/packages/jitar/src/client.ts b/packages/jitar/src/client.ts index 1174e3dc..ee8a4692 100644 --- a/packages/jitar/src/client.ts +++ b/packages/jitar/src/client.ts @@ -22,22 +22,8 @@ export Teapot, Unauthorized, FileNotFound, - // ImplementationNotFound, - // InvalidParameterValue, - // InvalidSegmentFile, - // InvalidVersionNumber, - // MissingParameterValue, - // ModuleNotAccessible, ModuleNotLoaded, - // NoWorkerAvailable, - // ProcedureNotAccessible, - // ProcedureNotFound, - // RepositoryNotAvailable, - // RuntimeNotAvailable, - // SegmentNotFound, - // UnknownParameter, - // startClient, - getClient + startClient } from '@jitar/runtime'; export diff --git a/packages/runtime/src/RuntimeBuilder.ts b/packages/runtime/src/RuntimeBuilder.ts index 26bc6aec..b5a1e392 100644 --- a/packages/runtime/src/RuntimeBuilder.ts +++ b/packages/runtime/src/RuntimeBuilder.ts @@ -2,7 +2,7 @@ import { Serializer, SerializerBuilder } from '@jitar/serialization'; import { ExecutionManager } from './execution'; -import { RemoteRepository, LocalRepository, RemoteGateway, LocalGateway, RemoteWorker, LocalWorker, Proxy, Remote, RunnerService } from './services'; +import { RemoteRepository, LocalRepository, RemoteGateway, LocalGateway, RemoteWorker, LocalWorker, Proxy, Remote, Client } from './services'; import { HealthManager } from './health'; import { MiddlewareManager } from './middleware'; import { SourceManager, ClassModuleLoader } from './source'; @@ -43,6 +43,13 @@ type ProxyConfiguration = ServiceConfiguration & type StandaloneConfiguration = LocalWorkerConfiguration & LocalRepositoryConfiguration; +type ClientConfiguration = +{ + remoteUrl: string; + segmentNames: string[]; + middlewares: string[]; +}; + export default class RuntimeBuilder { #sourceManager: SourceManager; @@ -130,6 +137,15 @@ export default class RuntimeBuilder return new Proxy({ url, repository, runner }); } + async buildClient(configuration: ClientConfiguration): Promise + { + const gateway = this.buildRemoteGateway(configuration.remoteUrl); + const middlewareManager = await this.#buildMiddlewareManager(configuration.middlewares); + const executionManager = await this.#buildExecutionManager(configuration.segmentNames); + + return new Client({ gateway, middlewareManager, executionManager }); + } + #buildRemote(url: string): Remote { const serializer = this.#buildSerializer(); diff --git a/packages/runtime/src/client.ts b/packages/runtime/src/client.ts index 483d54f4..49d8b3fc 100644 --- a/packages/runtime/src/client.ts +++ b/packages/runtime/src/client.ts @@ -1,36 +1,14 @@ -import { LocalWorker, RemoteGateway } from './services'; +import { SourceManager, ImportFunction, RemoteFileManager } from './source'; +import type { Client } from './services'; -let client: LocalWorker | undefined = undefined; -const resolvers: ((client: LocalWorker) => void)[] = []; +import RuntimeBuilder from './RuntimeBuilder'; -// export async function startClient(remoteUrl: string, segmentNames: string[] = [], middlewares: string[] = []): Promise -// { -// const gateway = new RemoteGateway(remoteUrl); - -// const worker = new LocalWorker(gateway); -// worker.segmentNames = new Set(segmentNames); -// worker.middlewareFiles = new Set(middlewares); - -// await worker.start(); - -// client = worker; - -// resolvers.forEach((resolve) => resolve(worker)); -// resolvers.length = 0; - -// return worker; -// } - -export async function getClient(): Promise +export async function startClient(remoteUrl: string, importFunction: ImportFunction, segmentNames: string[] = [], middlewares: string[] = []): Promise { - if (client === undefined) - { - return new Promise((resolve) => - { - resolvers.push(resolve); - }); - } + const fileManager = new RemoteFileManager(remoteUrl); + const sourceManager = new SourceManager(importFunction, fileManager); + const runtimeBuilder = new RuntimeBuilder(sourceManager); - return client; + return runtimeBuilder.buildClient({ remoteUrl, segmentNames, middlewares }); } diff --git a/packages/runtime/src/hooks.ts b/packages/runtime/src/hooks.ts index a87c5225..e7a9a4f5 100644 --- a/packages/runtime/src/hooks.ts +++ b/packages/runtime/src/hooks.ts @@ -1,11 +1,11 @@ import { ServerError } from './errors'; +import { Runner } from './execution'; import Request from './execution/models/Request.js'; -import ProcedureRuntime from './services/RunnerService.js'; import VersionParser from './execution/utils/VersionParser.js'; -let _runtime: ProcedureRuntime; +let _runtime: Runner; export class RuntimeNotAvailable extends ServerError { @@ -15,12 +15,12 @@ export class RuntimeNotAvailable extends ServerError } } -export function setRuntime(runtime: ProcedureRuntime): void +export function setRuntime(runtime: Runner): void { _runtime = runtime; } -export function getRuntime(): ProcedureRuntime +export function getRuntime(): Runner { if (_runtime === undefined) { diff --git a/packages/runtime/src/lib.ts b/packages/runtime/src/lib.ts index cc17eee2..c98b913c 100644 --- a/packages/runtime/src/lib.ts +++ b/packages/runtime/src/lib.ts @@ -6,7 +6,8 @@ export { MiddlewareManager, Middleware, NextHandler } from './middleware'; export { Gateway, LocalGateway, RemoteGateway, Proxy, Repository, LocalRepository, RemoteRepository, Worker, LocalWorker, RemoteWorker, Service, RunnerService } from './services'; export { File, Files, FileManager, FileNotFound, ImportFunction, ClassModuleLoader, SourceManager, ModuleNotLoaded } from './source'; -export { default as RuntimeBuilder } from './RuntimeBuilder.js'; +export { default as RuntimeBuilder } from './RuntimeBuilder'; -export * from './client.js'; -import './globals.js'; +export { startClient } from './client'; + +import './globals'; diff --git a/packages/runtime/src/services/Client.ts b/packages/runtime/src/services/Client.ts new file mode 100644 index 00000000..94768006 --- /dev/null +++ b/packages/runtime/src/services/Client.ts @@ -0,0 +1,57 @@ + +import { Request, Response, ExecutionManager, Runner } from '../execution'; +import { MiddlewareManager, ProcedureRunner } from '../middleware'; + +import { setRuntime } from '../hooks.js'; + +import RemoteGateway from './gateway/RemoteGateway'; + +type Configuration = +{ + gateway: RemoteGateway; + middlewareManager: MiddlewareManager; // object with all middleware loaded + executionManager: ExecutionManager; // object with all segments loaded +}; + +export default class Client implements Runner +{ + #gateway: RemoteGateway; + + #middlewareManager: MiddlewareManager; + #executionManager: ExecutionManager; + + constructor(configuration: Configuration) + { + this.#gateway = configuration.gateway; + + this.#middlewareManager = configuration.middlewareManager; + this.#executionManager = configuration.executionManager; + + // TODO: Should be done when constructing the middleware manager + this.#middlewareManager.addMiddleware(new ProcedureRunner(this.#executionManager)); + + setRuntime(this); + } + + run(request: Request): Promise + { + return this.#mustRunLocal(request) + ? this.#runLocal(request) + : this.#runRemote(request); + } + + #mustRunLocal(request: Request): boolean + { + return this.#executionManager.hasProcedure(request.fqn); + } + + #runLocal(request: Request): Promise + { + return this.#middlewareManager.handle(request); + } + + #runRemote(request: Request): Promise + { + return this.#gateway.run(request); + } +} diff --git a/packages/runtime/src/services/index.ts b/packages/runtime/src/services/index.ts index e4515d81..e865bcba 100644 --- a/packages/runtime/src/services/index.ts +++ b/packages/runtime/src/services/index.ts @@ -13,6 +13,7 @@ export { default as Worker } from './worker/Worker'; export { default as LocalWorker } from './worker/LocalWorker'; export { default as RemoteWorker } from './worker/RemoteWorker'; +export { default as Client } from './Client'; export { default as Remote } from './Remote'; export { default as Service } from './Service'; diff --git a/packages/runtime/src/source/SourceManager.ts b/packages/runtime/src/source/SourceManager.ts index a763a396..32d3279c 100644 --- a/packages/runtime/src/source/SourceManager.ts +++ b/packages/runtime/src/source/SourceManager.ts @@ -10,9 +10,9 @@ export default class SourceManager #import: ImportFunction; #fileManager: FileManager; - constructor(moduleImporter: ImportFunction, fileManager: FileManager) + constructor(importFunction: ImportFunction, fileManager: FileManager) { - this.#import = moduleImporter; + this.#import = importFunction; this.#fileManager = fileManager; } diff --git a/packages/runtime/src/source/index.ts b/packages/runtime/src/source/index.ts index 0a980de7..e4c65b9b 100644 --- a/packages/runtime/src/source/index.ts +++ b/packages/runtime/src/source/index.ts @@ -13,5 +13,6 @@ export { default as Module } from './types/Module'; export { default as File } from './models/File'; export { default as ClassModuleLoader } from './utils/ClassModuleLoader'; +export { default as RemoteFileManager } from './utils/RemoteFileManager'; export { default as SourceManager } from './SourceManager'; diff --git a/packages/runtime/src/source/utils/RemoteFileManager.ts b/packages/runtime/src/source/utils/RemoteFileManager.ts new file mode 100644 index 00000000..8b4f2dd5 --- /dev/null +++ b/packages/runtime/src/source/utils/RemoteFileManager.ts @@ -0,0 +1,60 @@ + +import { NotImplemented } from '../../errors'; + +import FileManager from '../interfaces/FileManager'; +import File from '../models/File'; + +export default class RemoteFileManager implements FileManager +{ + #rootUrl: string; + + constructor(rootUrl: string) + { + this.#rootUrl = rootUrl; + } + + getRootLocation(): string + { + return this.#rootUrl; + } + + getAbsoluteLocation(filename: string): string + { + return `${this.#rootUrl}/${filename}`; + } + + getRelativeLocation(filename: string): string + { + throw new NotImplemented(); + } + + getType(filename: string): Promise + { + throw new NotImplemented(); + } + + getContent(filename: string): Promise + { + throw new NotImplemented(); + } + + read(filename: string): Promise + { + throw new NotImplemented(); + } + + write(filename: string, content: string): Promise + { + throw new NotImplemented(); + } + + delete(filename: string): Promise + { + throw new NotImplemented(); + } + + filter(pattern: string): Promise + { + throw new NotImplemented(); + } +}