From 341872b62dbfedcb352391d8c3e8fada38adf1bc Mon Sep 17 00:00:00 2001 From: neonp Date: Tue, 30 Jan 2024 07:36:47 +0000 Subject: [PATCH] feat: switch to URL handler for processor registration --- .vscode/settings.json | 2 +- packages/commands/src/akala.mts | 14 +++-- packages/commands/src/net-socket-adapter.ts | 48 ++++++++-------- packages/commands/src/processors/event.ts | 4 +- packages/commands/src/processors/fs.ts | 11 ++-- .../commands/src/processors/http-client.ts | 23 ++++---- packages/commands/src/processors/jsonrpc.ts | 17 +++--- packages/commands/src/processors/log.ts | 7 ++- packages/commands/src/protocol-handler.ts | 56 +++++++------------ 9 files changed, 85 insertions(+), 97 deletions(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 32502ab646..dd49d82b9c 100755 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -32,7 +32,7 @@ "**/node_modules/*/**": true }, "sync.quietSync": true, - "debug.javascript.autoAttachFilter": "smart", + "debug.javascript.autoAttachFilter": "always", "liveshare.connectionMode": "relay", "editor.suggestSelection": "first", "vsintellicode.modify.editor.suggestSelection": "automaticallyOverrodeDefaultValue", diff --git a/packages/commands/src/akala.mts b/packages/commands/src/akala.mts index bed79d67a5..c998f6b89a 100644 --- a/packages/commands/src/akala.mts +++ b/packages/commands/src/akala.mts @@ -1,13 +1,13 @@ import { program as root, ErrorMessage, NamespaceMiddleware } from "@akala/cli" import { Injector, mapAsync } from "@akala/core" import commands from "./commands.js"; -import { Cli, ServeOptions, registerCommands } from "./index.js"; +import { Cli, ICommandProcessor, ServeOptions, registerCommands } from "./index.js"; import { Container } from "./model/container.js"; import $serve from "./commands/$serve.js"; import { Configurations } from "./metadata/configurations.js"; -import getHandler, { getHandlers } from "./protocol-handler.js"; import { dirname, isAbsolute, resolve } from "node:path"; import { Local } from "./processors/local.js"; +import { HandlerResult, handlers } from "./protocol-handler.js"; const serveDefinition: Configurations = await import('../' + '../src/commands/$serve.json', { assert: { type: 'json' } }).then(x => x.default) export default function (config, program: NamespaceMiddleware<{ configFile: string }>) @@ -40,7 +40,10 @@ export default function (config, program: NamespaceMiddleware<{ configFile: stri uri = new URL('file://' + path); } } - const handler = await getHandler(uri.protocol, uri) + let handler: HandlerResult = { + processor: null, getMetadata() { return Promise.resolve(null) } + }; + await handlers.process(uri, handler) cliContainer.processor.useMiddleware(51, handler.processor); @@ -80,10 +83,13 @@ export default function (config, program: NamespaceMiddleware<{ configFile: stri try { const url = new URL(context.options.path); - getHandlers(url.protocol.substring(0, url.protocol.length - 1)) + handlers.protocol.process(url, { processor: null, getMetadata: () => void 0 }) + console.log('pwet'); } catch (e) { + console.error('pwet'); + console.error(e); } context.state.commands[context.options.name] = context.options.path; return context.state.commit(); diff --git a/packages/commands/src/net-socket-adapter.ts b/packages/commands/src/net-socket-adapter.ts index a0899c7444..d897e97637 100644 --- a/packages/commands/src/net-socket-adapter.ts +++ b/packages/commands/src/net-socket-adapter.ts @@ -2,63 +2,59 @@ import { Socket } from 'net'; import { TLSSocket, connect as tlsconnect } from 'tls' import * as jsonrpcws from '@akala/json-rpc-ws'; import { EventEmitter } from 'events'; -import { addHandler } from './protocol-handler.js'; -import { JsonRpc } from './processors/jsonrpc.js'; +import { handlers } from './protocol-handler.js'; +import { JsonRpc, handler } from './processors/jsonrpc.js'; import { Command } from './metadata/command.js'; -addHandler('tcp', async (url) => +handlers.useProtocol('tcp', async (url, handler) => { const socket = new Socket(); await new Promise(resolve => socket.connect({ port: url.port && Number(url.port) || 31416, host: url.hostname }, resolve)); const connection = JsonRpc.getConnection(new NetSocketAdapter(socket)); - return { - processor: new JsonRpc(connection, true), getMetadata: () => new Promise((resolve, reject) => connection.sendMethod('$metadata', { param: true }, (err, metadata) => - typeof (err) == 'undefined' ? resolve(metadata.commands) : reject(err) - )) - }; + handler.processor = new JsonRpc(connection, true); + handler.getMetadata = () => new Promise((resolve, reject) => connection.sendMethod('$metadata', { param: true }, (err, metadata) => + typeof (err) == 'undefined' ? resolve(metadata.commands) : reject(err) + )) }); -addHandler('tcps', async (url) => +handlers.useProtocol('tcps', async (url, handler) => { const socket = await new Promise(resolve => { const socket = tlsconnect({ port: url.port && Number(url.port) || 31416, host: url.hostname, servername: url.hostname }, () => resolve(socket)) }); const connection = JsonRpc.getConnection(new NetSocketAdapter(socket)); - return { - processor: new JsonRpc(connection, true), getMetadata: () => new Promise((resolve, reject) => connection.sendMethod('$metadata', { param: true }, (err, metadata) => - typeof (err) == 'undefined' ? resolve(metadata) : reject(err) - )) - }; + handler.processor = new JsonRpc(connection, true); + handler.getMetadata = () => new Promise((resolve, reject) => connection.sendMethod('$metadata', { param: true }, (err, metadata) => + typeof (err) == 'undefined' ? resolve(metadata) : reject(err) + )) }); -addHandler('unix', async (url) => +handlers.useProtocol('unix', async (url, handler) => { const socket = new Socket(); await new Promise(resolve => socket.connect({ path: url.hostname + url.pathname }, resolve)); const connection = JsonRpc.getConnection(new NetSocketAdapter(socket)); - return { - processor: new JsonRpc(connection, true), getMetadata: () => new Promise((resolve, reject) => connection.sendMethod('$metadata', undefined, (err, metadata) => - typeof (err) == 'undefined' ? resolve(metadata) : reject(err) - )) - }; + handler.processor = new JsonRpc(connection, true); + handler.getMetadata = () => new Promise((resolve, reject) => connection.sendMethod('$metadata', undefined, (err, metadata) => + typeof (err) == 'undefined' ? resolve(metadata) : reject(err) + )) }); -addHandler('unixs', async (url) => +handlers.useProtocol('unixs', async (url, handler) => { const socket = await new Promise(resolve => { const socket = tlsconnect({ path: url.hostname + url.pathname }, () => resolve(socket)) }); const connection = JsonRpc.getConnection(new NetSocketAdapter(socket)); - return { - processor: new JsonRpc(connection, true), getMetadata: () => new Promise((resolve, reject) => connection.sendMethod('$metadata', undefined, (err, metadata) => - typeof (err) == 'undefined' ? resolve(metadata) : reject(err) - )) - }; + handler.processor = new JsonRpc(connection, true); + handler.getMetadata = () => new Promise((resolve, reject) => connection.sendMethod('$metadata', undefined, (err, metadata) => + typeof (err) == 'undefined' ? resolve(metadata) : reject(err) + )) }); export class NetSocketAdapter implements jsonrpcws.SocketAdapter diff --git a/packages/commands/src/processors/event.ts b/packages/commands/src/processors/event.ts index 714317a7d1..285ccaedd4 100755 --- a/packages/commands/src/processors/event.ts +++ b/packages/commands/src/processors/event.ts @@ -3,9 +3,9 @@ import { StructuredParameters, ICommandProcessor, CommandMetadataProcessorSignat import { MiddlewarePromise, EventEmitter } from "@akala/core"; import { Command } from '../metadata/index.js'; import { Container } from '../model/container.js'; -import { addHandler } from '../protocol-handler.js'; +import { handlers } from '../protocol-handler.js'; -addHandler('event', async (_url, inner) => ({ processor: new EventProcessor(inner.processor), getMetadata: inner.getMetadata })); +handlers.useProtocol('event', async (_url, inner) => ({ processor: new EventProcessor(inner.processor), getMetadata: inner.getMetadata })); export class EventProcessor extends EventEmitter<{ processing: CommandMetadataProcessorSignature, diff --git a/packages/commands/src/processors/fs.ts b/packages/commands/src/processors/fs.ts index 2705a9c081..ca11976aea 100755 --- a/packages/commands/src/processors/fs.ts +++ b/packages/commands/src/processors/fs.ts @@ -10,12 +10,12 @@ import { ExtendedConfigurations, jsonObject } from '../metadata/index.js'; import { MiddlewarePromise } from '@akala/core'; import { eachAsync } from '@akala/core'; import { createRequire } from 'module'; -import { addHandler, parseQueryString } from '../protocol-handler.js'; +import { HandlerResult, handlers, parseQueryString } from '../protocol-handler.js'; import { stat } from 'fs/promises'; import os from 'node:os' import { fileURLToPath, pathToFileURL } from 'url'; -async function protocolHandler(url: URL) +async function protocolHandler(url: URL, handler: HandlerResult) { let options: DiscoveryOptions = parseQueryString(url); if (url.searchParams.has('ignoreFileWithNoDefaultExport')) @@ -40,11 +40,12 @@ async function protocolHandler(url: URL) else options.relativeTo = p; - return { processor: new FileSystem(options.relativeTo), getMetadata: () => FileSystem.discoverMetaCommands(p, options) } + handler.processor = new FileSystem(options.relativeTo); + handler.getMetadata = () => FileSystem.discoverMetaCommands(p, options); } -addHandler('fs', protocolHandler); -addHandler('file', protocolHandler); +handlers.useProtocol('fs', protocolHandler); +handlers.useProtocol('file', protocolHandler); export interface FileSystemConfiguration extends Metadata.Configuration diff --git a/packages/commands/src/processors/http-client.ts b/packages/commands/src/processors/http-client.ts index 99453cf3ca..00f65a5ed2 100755 --- a/packages/commands/src/processors/http-client.ts +++ b/packages/commands/src/processors/http-client.ts @@ -3,26 +3,27 @@ import * as pathRegexp from 'path-to-regexp'; import { CommandProcessor } from '../model/processor.js'; import { Command, Configuration } from '../metadata/index.js'; import { Container } from '../model/container.js'; -import { HandlerResult, addHandler } from '../protocol-handler.js'; +import { HandlerResult, handlers } from '../protocol-handler.js'; +import { handler } from './jsonrpc.js'; export class HttpClient extends CommandProcessor { - public static handler(protocol: 'http' | 'https'): (url: URL) => Promise> + public static handler(protocol: 'http' | 'https'): (url: URL, handler: HandlerResult) => Promise { const injector = new Injector(); - return function (url) + return async function (url, handler) { url = new URL(url); url.protocol = protocol; const resolveUrl = (s: string) => new URL(s, url).toString(); injector.register('$resolveUrl', resolveUrl); - return Promise.resolve({ - processor: new HttpClient(injector), getMetadata() - { - return injector.injectWithName(['$http'], async (http: Http) => (await http.call(HttpClient.buildCall({ method: 'GET', route: '$metadata' }, resolveUrl))).json())(this) - } - }) + handler. + processor = new HttpClient(injector); + handler.getMetadata = function () + { + return injector.injectWithName(['$http'], async (http: Http) => (await http.call(HttpClient.buildCall({ method: 'GET', route: '$metadata' }, resolveUrl))).json())(this) + } } } @@ -139,8 +140,8 @@ export class HttpClient extends CommandProcessor } } -addHandler('http', HttpClient.handler('http')); -addHandler('https', HttpClient.handler('https')); +handlers.useProtocol('http', HttpClient.handler('http')); +handlers.useProtocol('https', HttpClient.handler('https')); export interface HttpConfiguration extends Configuration { diff --git a/packages/commands/src/processors/jsonrpc.ts b/packages/commands/src/processors/jsonrpc.ts index 905211ed6d..f5fb91ecb2 100755 --- a/packages/commands/src/processors/jsonrpc.ts +++ b/packages/commands/src/processors/jsonrpc.ts @@ -5,11 +5,11 @@ import { Container } from '../model/container.js'; import { Local } from './local.js'; import { Readable } from 'stream'; import { lazy, Logger, MiddlewarePromise, noop, OptionsResponse, SpecialNextParam, SerializableObject, TypedSerializableObject } from '@akala/core'; -import { HandlerResult, addHandler } from '../protocol-handler.js'; +import { HandlerResult, handlers } from '../protocol-handler.js'; type OnlyArray = Extract; -export async function handler(url): Promise> +export async function handler(url: URL, handler: HandlerResult): Promise { const socket = await new Promise((resolve) => { @@ -21,15 +21,14 @@ export async function handler(url): Promise> }); const connection = JsonRpc.getConnection(socket); - return { - processor: new JsonRpc(connection, true), getMetadata: () => new Promise((resolve, reject) => connection.sendMethod('$metadata', { param: true }, (err, metadata) => - typeof (err) == 'undefined' ? resolve(metadata) : reject(err) - )) - }; + handler.processor = new JsonRpc(connection, true); + handler.getMetadata = () => new Promise((resolve, reject) => connection.sendMethod('$metadata', { param: true }, (err, metadata) => + typeof (err) == 'undefined' ? resolve(metadata) : reject(err) + )) } -addHandler('ws', handler); -addHandler('wss', handler); +handlers.useProtocol('ws', handler); +handlers.useProtocol('wss', handler); export class JsonRpc extends CommandProcessor { diff --git a/packages/commands/src/processors/log.ts b/packages/commands/src/processors/log.ts index 81e06b69e6..aa28155996 100755 --- a/packages/commands/src/processors/log.ts +++ b/packages/commands/src/processors/log.ts @@ -1,5 +1,5 @@ import { CommandMetadataProcessorSignature, ICommandProcessor } from '../model/processor.js'; -import { addHandler } from '../protocol-handler.js'; +import { handlers } from '../protocol-handler.js'; import { EventProcessor } from './event.js'; export class LogProcessor extends EventProcessor @@ -18,7 +18,8 @@ export class LogProcessor extends EventProcessor } } -addHandler('log', (_url, inner) => +handlers.useProtocol('log', async (_url, handler) => { - return Promise.resolve({ processor: new LogProcessor(inner.processor, (...args) => console.log(args), (...args) => console.log(args)), getMetadata: inner.getMetadata }); + const inner = { ...handler }; + handler.processor = new LogProcessor(inner.processor, (...args) => console.log(args), (...args) => console.log(args)); }) \ No newline at end of file diff --git a/packages/commands/src/protocol-handler.ts b/packages/commands/src/protocol-handler.ts index 44c30efaec..117ef9530c 100644 --- a/packages/commands/src/protocol-handler.ts +++ b/packages/commands/src/protocol-handler.ts @@ -1,45 +1,29 @@ -import { ErrorWithStatus, eachAsync } from "@akala/core"; +import { ErrorWithStatus, UrlHandler, eachAsync } from "@akala/core"; import { CommandProcessor, ICommandProcessor, Metadata } from "./index.browser.js"; -export default function getHandler(protocol: string, url: URL) -{ - const processors = getHandlers(protocol.substring(0, protocol.length - 1)); - return processors.reduce((previous, current) => - { - return previous.then(p => current(url, p)) - }, Promise.resolve>>(null)) -} +// export default function getHandler(protocol: string, url: URL) +// { +// const processors = getHandlers(protocol.substring(0, protocol.length - 1)); +// return processors.reduce((previous, current) => +// { +// return previous.then(p => current(url, p)) +// }, Promise.resolve>>(null)) +// } -export function getHandlers(protocol: string) -{ - const protocols = protocol.split('+'); - const result = protocols.map(v => handlers[v]); - let x: number; - if ((x = result.findIndex(x => x === undefined)) !== -1) - throw new ErrorWithStatus(404, `No handler could be found for the protocol ${protocols[x]}`) - return result; -} +// export function getHandlers(protocol: string) +// { +// const protocols = protocol.split('+'); +// const result = protocols.map(v => handlers[v]); +// let x: number; +// if ((x = result.findIndex(x => x === undefined)) !== -1) +// throw new ErrorWithStatus(404, `No handler could be found for the protocol ${protocols[x]}`) +// return result; +// } export type HandlerResult = { processor: T, getMetadata(): Promise }; -export type handler = (arg1: URL, arg2: HandlerResult) => Promise> - -const handlers: Record> = {} +export type handler = (arg1: URL, arg2: HandlerResult) => Promise -export function addHandler(protocol: string, handler: handler) -{ - if (!handlers[protocol]) - handlers[protocol] = handler; - else - throw new ErrorWithStatus(409, 'Another handler is already registered for the protocol ' + protocol) -} - -export function removeHandler(protocol: string) -{ - if (handlers[protocol]) - delete handlers[protocol] - else - throw new ErrorWithStatus(404, 'There is no handler registered for the protocol ' + protocol) -} +export const handlers = new UrlHandler<[URL, HandlerResult]>(); export function parseQueryString(url: URL) {