support route handler arguments; add daton::static file server
This commit is contained in:
parent
27ee1a552b
commit
601649e699
10
TODO.txt
10
TODO.txt
@ -1,14 +1,12 @@
|
|||||||
static assets
|
TLS support
|
||||||
middleware
|
|
||||||
internationalization
|
internationalization
|
||||||
uploads & universal path
|
uploads & universal path
|
||||||
CLI - view routes, template generation, start server, directives, output, args
|
CLI - view routes, template generation, start server, directives, output, args
|
||||||
request level error handler
|
nicer error and home pages
|
||||||
develop/prod/debug modes
|
|
||||||
favicon
|
favicon
|
||||||
utility - root, path, is_windows, is_linux, is_mac
|
utility - is_windows, is_linux, is_mac
|
||||||
authentication - user/session, oauth, jwt, &c.
|
authentication - user/session, oauth, jwt, &c.
|
||||||
orm relations, subqueries, enum/bit fields, json handlers, scopes
|
orm enum/bit fields, json handlers, scopes
|
||||||
redis - redis client, redis rehydrated classes, redis sessions
|
redis - redis client, redis rehydrated classes, redis sessions
|
||||||
less/scss
|
less/scss
|
||||||
notifications - gotify/push/other mechanisms
|
notifications - gotify/push/other mechanisms
|
||||||
|
2
app/assets/.gitignore
vendored
Normal file
2
app/assets/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
*
|
||||||
|
!.gitignore
|
@ -9,3 +9,4 @@ export { default as HttpServerUnit } from '../../lib/src/unit/HttpServer.ts'
|
|||||||
export { default as RoutingUnit } from '../../lib/src/unit/Routing.ts'
|
export { default as RoutingUnit } from '../../lib/src/unit/Routing.ts'
|
||||||
export { default as ServicesUnit } from '../../lib/src/unit/Services.ts'
|
export { default as ServicesUnit } from '../../lib/src/unit/Services.ts'
|
||||||
export { default as ViewEngineUnit } from '../../lib/src/unit/ViewEngine.ts'
|
export { default as ViewEngineUnit } from '../../lib/src/unit/ViewEngine.ts'
|
||||||
|
export { default as DatonMiddlewareUnit } from '../../lib/src/unit/DatonMiddleware.ts'
|
||||||
|
@ -14,5 +14,5 @@ export default {
|
|||||||
session: {
|
session: {
|
||||||
driver: 'database', // memory | database
|
driver: 'database', // memory | database
|
||||||
model: 'http:Session', // required for database
|
model: 'http:Session', // required for database
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
@ -6,5 +6,6 @@ export default {
|
|||||||
get: {
|
get: {
|
||||||
'/': 'controller::Home.get_home',
|
'/': 'controller::Home.get_home',
|
||||||
'/maybe': ['middleware::Test', 'controller::Home.get_home'],
|
'/maybe': ['middleware::Test', 'controller::Home.get_home'],
|
||||||
|
'/statics/**': { handler: 'daton::static', arg: 'assets' },
|
||||||
},
|
},
|
||||||
} as RouterDefinition
|
} as RouterDefinition
|
||||||
|
@ -10,6 +10,7 @@ import {
|
|||||||
RoutingUnit,
|
RoutingUnit,
|
||||||
ServicesUnit,
|
ServicesUnit,
|
||||||
ViewEngineUnit,
|
ViewEngineUnit,
|
||||||
|
DatonMiddlewareUnit,
|
||||||
} from './bundle/daton_units.ts'
|
} from './bundle/daton_units.ts'
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
@ -19,6 +20,7 @@ export default [
|
|||||||
ModelsUnit,
|
ModelsUnit,
|
||||||
ViewEngineUnit,
|
ViewEngineUnit,
|
||||||
HttpKernelUnit,
|
HttpKernelUnit,
|
||||||
|
DatonMiddlewareUnit,
|
||||||
MiddlewareUnit,
|
MiddlewareUnit,
|
||||||
ControllerUnit,
|
ControllerUnit,
|
||||||
RoutesUnit,
|
RoutesUnit,
|
||||||
|
2
lib/src/external/db.ts
vendored
2
lib/src/external/db.ts
vendored
@ -1,4 +1,4 @@
|
|||||||
// export * from 'https://deno.land/x/postgres@v0.4.3/mod.ts'
|
// export * from 'https://deno.land/x/postgres@v0.4.4/mod.ts'
|
||||||
|
|
||||||
// FIXME: waiting on https://github.com/deno-postgres/deno-postgres/pull/166
|
// FIXME: waiting on https://github.com/deno-postgres/deno-postgres/pull/166
|
||||||
export * from 'https://raw.githubusercontent.com/glmdev/deno-postgres/master/mod.ts'
|
export * from 'https://raw.githubusercontent.com/glmdev/deno-postgres/master/mod.ts'
|
||||||
|
1
lib/src/external/std.ts
vendored
1
lib/src/external/std.ts
vendored
@ -3,4 +3,5 @@ export { config as dotenv } from 'https://deno.land/x/dotenv/mod.ts'
|
|||||||
export * as path from 'https://deno.land/std@0.67.0/path/mod.ts'
|
export * as path from 'https://deno.land/std@0.67.0/path/mod.ts'
|
||||||
export * as fs from 'https://deno.land/std@0.67.0/fs/mod.ts'
|
export * as fs from 'https://deno.land/std@0.67.0/fs/mod.ts'
|
||||||
export { generate as uuid } from 'https://deno.land/std@0.67.0/uuid/v4.ts'
|
export { generate as uuid } from 'https://deno.land/std@0.67.0/uuid/v4.ts'
|
||||||
|
export * as file_server from 'https://deno.land/std@0.67.0/http/file_server.ts'
|
||||||
// export { moment } from 'https://deno.land/x/moment/moment.ts'
|
// export { moment } from 'https://deno.land/x/moment/moment.ts'
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import {HTTPResponse} from './type/HTTPResponse.ts'
|
import {HTTPResponse} from './type/HTTPResponse.ts'
|
||||||
import {HTTPRequest} from './type/HTTPRequest.ts'
|
import {HTTPRequest} from './type/HTTPRequest.ts'
|
||||||
import {ServerRequest} from '../external/http.ts'
|
import {ServerRequest} from '../external/http.ts'
|
||||||
|
import {file_server} from '../external/std.ts'
|
||||||
import {CookieJar} from './CookieJar.ts'
|
import {CookieJar} from './CookieJar.ts'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -49,10 +49,10 @@ export default class ApplyRouteHandlers extends Module {
|
|||||||
for ( const handler of request.route.handlers ) {
|
for ( const handler of request.route.handlers ) {
|
||||||
try {
|
try {
|
||||||
let result
|
let result
|
||||||
if ( isRouteHandlerClass(handler) ) {
|
if ( isRouteHandlerClass(handler.handler) ) {
|
||||||
result = await handler.handleRequest(current_request)
|
result = await handler.handler.handleRequest(current_request, handler.arg)
|
||||||
} else {
|
} else {
|
||||||
result = await handler(current_request)
|
result = await handler.handler(current_request, handler.arg)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( result instanceof Request ) {
|
if ( result instanceof Request ) {
|
||||||
|
45
lib/src/http/response/FileResponseFactory.ts
Normal file
45
lib/src/http/response/FileResponseFactory.ts
Normal file
@ -0,0 +1,45 @@
|
|||||||
|
import ResponseFactory from './ResponseFactory.ts'
|
||||||
|
import {Request} from '../Request.ts'
|
||||||
|
import {file_server} from '../../external/std.ts'
|
||||||
|
import {HTTPStatus} from '../../const/http.ts'
|
||||||
|
import {Logging} from '../../service/logging/Logging.ts'
|
||||||
|
import {Injectable} from '../../../../di/src/decorator/Injection.ts'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Response factory to send the contents of a file given its path.
|
||||||
|
* @extends ResponseFactory
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export default class FileResponseFactory extends ResponseFactory {
|
||||||
|
constructor(
|
||||||
|
protected readonly logger: Logging,
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The path to the file to be sent.
|
||||||
|
* @type string
|
||||||
|
*/
|
||||||
|
public readonly path: string,
|
||||||
|
) { super() }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Write this response factory to the given request's response.
|
||||||
|
* @param {Request} request
|
||||||
|
* @return Request
|
||||||
|
*/
|
||||||
|
public async write(request: Request): Promise<Request> {
|
||||||
|
request = await super.write(request)
|
||||||
|
|
||||||
|
const content = await file_server.serveFile(request.to_native, this.path)
|
||||||
|
const length = content.headers && content.headers.get('content-length')
|
||||||
|
|
||||||
|
if ( content.headers && content.body && length ) {
|
||||||
|
request.response.body = content.body
|
||||||
|
request.response.headers.set('Content-Length', length)
|
||||||
|
} else {
|
||||||
|
this.logger.debug(`Tried to serve file that does not exist: ${this.path}`)
|
||||||
|
request.response.status = HTTPStatus.NOT_FOUND
|
||||||
|
}
|
||||||
|
|
||||||
|
return request
|
||||||
|
}
|
||||||
|
}
|
@ -9,6 +9,7 @@ import {HTTPStatus} from '../../const/http.ts'
|
|||||||
import HTTPErrorResponseFactory from './HTTPErrorResponseFactory.ts'
|
import HTTPErrorResponseFactory from './HTTPErrorResponseFactory.ts'
|
||||||
import HTTPError from '../../error/HTTPError.ts'
|
import HTTPError from '../../error/HTTPError.ts'
|
||||||
import ViewResponseFactory from './ViewResponseFactory.ts'
|
import ViewResponseFactory from './ViewResponseFactory.ts'
|
||||||
|
import FileResponseFactory from './FileResponseFactory.ts'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a new JSON response factory that writes the given object as JSON.
|
* Get a new JSON response factory that writes the given object as JSON.
|
||||||
@ -76,3 +77,12 @@ export function http(status: HTTPStatus, message?: string): HTTPErrorResponseFac
|
|||||||
export function view(view: string, data?: any): ViewResponseFactory {
|
export function view(view: string, data?: any): ViewResponseFactory {
|
||||||
return make(ViewResponseFactory, view, data)
|
return make(ViewResponseFactory, view, data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a new file response factory for the given file path.
|
||||||
|
* @param {string} path
|
||||||
|
* @return FileResponseFactory
|
||||||
|
*/
|
||||||
|
export function file(path: string): FileResponseFactory {
|
||||||
|
return make(FileResponseFactory, path)
|
||||||
|
}
|
||||||
|
75
lib/src/http/system_middleware/StaticServer.ts
Normal file
75
lib/src/http/system_middleware/StaticServer.ts
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
import Middleware from '../Middleware.ts'
|
||||||
|
import {Request} from '../Request.ts'
|
||||||
|
import {Injectable} from '../../../../di/src/decorator/Injection.ts'
|
||||||
|
import {file, http} from '../response/helpers.ts'
|
||||||
|
import {HTTPStatus} from '../../const/http.ts'
|
||||||
|
import {Logging} from '../../service/logging/Logging.ts'
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Daton-provided middleware that serves files from a static directory.
|
||||||
|
* @extends Middleware
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export default class StaticServer extends Middleware {
|
||||||
|
|
||||||
|
constructor(
|
||||||
|
protected readonly logger: Logging,
|
||||||
|
) { super() }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handle an incoming request. Get the path to the file from the route params, and
|
||||||
|
* resolve it using the asset_dir argument. If the file exists, serve it.
|
||||||
|
* @param {Request} request
|
||||||
|
* @param {string} asset_dir
|
||||||
|
*/
|
||||||
|
public async handleRequest(request: Request, asset_dir?: string) {
|
||||||
|
if ( !asset_dir ) {
|
||||||
|
throw new Error(`This static server is mis-configured. You must provide, as an argument in the route definition, the relative path to the base directory of the static files to be served.`)
|
||||||
|
}
|
||||||
|
|
||||||
|
const params = request.route.params
|
||||||
|
const rel_file = params.$1
|
||||||
|
|
||||||
|
if ( !rel_file || !rel_file.trim() || rel_file.trim().startsWith('/') || rel_file.trim().startsWith('.') ) {
|
||||||
|
this.logger.info(`Blocked attempt to access invalid static file path: "${rel_file}"`)
|
||||||
|
return http(HTTPStatus.NOT_FOUND)
|
||||||
|
}
|
||||||
|
|
||||||
|
const abs_file = this.resolve(asset_dir, rel_file)
|
||||||
|
if ( !(await this.fileExists(abs_file)) ) {
|
||||||
|
this.logger.debug(`File does not exist: ${abs_file}`)
|
||||||
|
return http(HTTPStatus.NOT_FOUND)
|
||||||
|
}
|
||||||
|
|
||||||
|
return file(abs_file)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Given the asset base dir and a relative path, resolve the fully-qualified
|
||||||
|
* path to the file.
|
||||||
|
* @param {string} asset_dir
|
||||||
|
* @param {string} rel_file
|
||||||
|
* @return string
|
||||||
|
*/
|
||||||
|
protected resolve(asset_dir: string, rel_file: string): string {
|
||||||
|
return this.app.path(asset_dir, rel_file)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves true if the given path exists, and is a file.
|
||||||
|
* @param {string} path
|
||||||
|
* @return Promise<boolean>
|
||||||
|
*/
|
||||||
|
protected async fileExists(path: string): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
const stat = await Deno.lstat(path)
|
||||||
|
return stat && stat.isFile
|
||||||
|
} catch (e) {
|
||||||
|
if ( e && e instanceof Deno.errors.NotFound ) {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
throw e
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -1,4 +1,5 @@
|
|||||||
import {logger} from '../../service/logging/global.ts'
|
import {logger} from '../../service/logging/global.ts'
|
||||||
|
import {RouteHandlerDefinition} from '../../unit/Routing.ts'
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type representing valid HTTP verbs.
|
* Type representing valid HTTP verbs.
|
||||||
@ -8,7 +9,7 @@ export type RouteVerb = 'get' | 'post' | 'patch' | 'delete' | 'head' | 'put' | '
|
|||||||
/**
|
/**
|
||||||
* Type representing a route verb group from a router definition.
|
* Type representing a route verb group from a router definition.
|
||||||
*/
|
*/
|
||||||
export type RouteVerbGroup = { [key: string]: string | string[] }
|
export type RouteVerbGroup = { [key: string]: RouteHandlerDefinition | RouteHandlerDefinition[] }
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Type representing a router definition.
|
* Type representing a router definition.
|
||||||
@ -51,10 +52,24 @@ export function isRouteVerbGroup(something: any): something is RouteVerbGroup {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if (
|
if (
|
||||||
!(typeof something[key] === 'string')
|
!(Array.isArray(something[key]) && something[key].every((x: any) => {
|
||||||
&& !(Array.isArray(something[key]) && something[key].every((x: any) => typeof x === 'string'))
|
return (
|
||||||
|
typeof x === 'string'
|
||||||
|
|| (
|
||||||
|
typeof x === 'object'
|
||||||
|
&& typeof x.handler === 'string'
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}))
|
||||||
|
&& !(
|
||||||
|
typeof something[key] === 'string'
|
||||||
|
|| (
|
||||||
|
typeof something[key] === 'object'
|
||||||
|
&& typeof something[key].handler === 'string'
|
||||||
|
)
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
logger.info(`Route verb group for key ${key} is not a string or array of strings.`)
|
logger.info(`Route verb group for key ${key} is not valid. Must be valid RouteHandlerDefinition, or array of them.`)
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
14
lib/src/unit/DatonMiddleware.ts
Normal file
14
lib/src/unit/DatonMiddleware.ts
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
import {FakeCanonical} from './FakeCanonical.ts'
|
||||||
|
import Middleware from '../http/Middleware.ts'
|
||||||
|
import {Unit} from '../lifecycle/decorators.ts'
|
||||||
|
import StaticServer from '../http/system_middleware/StaticServer.ts'
|
||||||
|
|
||||||
|
@Unit()
|
||||||
|
export default class DatonMiddleware extends FakeCanonical<Middleware> {
|
||||||
|
protected canonical_item = 'daton'
|
||||||
|
|
||||||
|
public async up() {
|
||||||
|
await super.up()
|
||||||
|
this._items['static'] = this.make(StaticServer)
|
||||||
|
}
|
||||||
|
}
|
10
lib/src/unit/FakeCanonical.ts
Normal file
10
lib/src/unit/FakeCanonical.ts
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
import {Canonical} from './Canonical.ts'
|
||||||
|
import {Canon} from './Canon.ts'
|
||||||
|
|
||||||
|
export class FakeCanonical<T> extends Canonical<T> {
|
||||||
|
|
||||||
|
public async up() {
|
||||||
|
this.make(Canon).register_canonical(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -19,19 +19,28 @@ import {RegExRoute} from "../http/routing/RegExRoute.ts";
|
|||||||
export type RouteHandlerReturnValue = SyncRouteHandlerReturnValue | AsyncRouteHandlerReturnValue
|
export type RouteHandlerReturnValue = SyncRouteHandlerReturnValue | AsyncRouteHandlerReturnValue
|
||||||
export type SyncRouteHandlerReturnValue = Request | ResponseFactory | void | undefined
|
export type SyncRouteHandlerReturnValue = Request | ResponseFactory | void | undefined
|
||||||
export type AsyncRouteHandlerReturnValue = Promise<SyncRouteHandlerReturnValue>
|
export type AsyncRouteHandlerReturnValue = Promise<SyncRouteHandlerReturnValue>
|
||||||
export type RouteHandlerFunction = (request: Request) => RouteHandlerReturnValue
|
export type RouteHandlerFunction = ((request: Request, arg?: any) => RouteHandlerReturnValue) | ((request: Request) => RouteHandlerReturnValue)
|
||||||
|
export interface RouteHandlerWithArgument {
|
||||||
|
handler: string,
|
||||||
|
arg: any,
|
||||||
|
}
|
||||||
|
export type RouteHandlerDefinition = string | RouteHandlerWithArgument
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class that can handle requests.
|
* A class that can handle requests.
|
||||||
*/
|
*/
|
||||||
export interface RouteHandlerClass {
|
export interface RouteHandlerClass {
|
||||||
handleRequest(request: Request): RouteHandlerReturnValue
|
handleRequest(request: Request): RouteHandlerReturnValue
|
||||||
|
handleRequest(request: Request, arg?: any): RouteHandlerReturnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base type defining a single route handler.
|
* Base type defining a single route handler.
|
||||||
*/
|
*/
|
||||||
export type RouteHandler = RouteHandlerFunction | RouteHandlerClass
|
export interface RouteHandler {
|
||||||
|
handler: RouteHandlerFunction | RouteHandlerClass,
|
||||||
|
arg: any,
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Base type for a collection of route handlers.
|
* Base type for a collection of route handlers.
|
||||||
@ -60,8 +69,12 @@ export interface RouteDefinition {
|
|||||||
*/
|
*/
|
||||||
export function isRouteHandler(what: any): what is RouteHandler {
|
export function isRouteHandler(what: any): what is RouteHandler {
|
||||||
return (
|
return (
|
||||||
typeof what === 'function'
|
typeof what === 'object'
|
||||||
|| isRouteHandlerClass(what)
|
&& what.handler
|
||||||
|
&& (
|
||||||
|
typeof what.handler === 'function'
|
||||||
|
|| isRouteHandlerClass(what.handler)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -72,7 +85,7 @@ export function isRouteHandler(what: any): what is RouteHandler {
|
|||||||
*/
|
*/
|
||||||
export function isRouteHandlerClass(what: any): what is RouteHandlerClass {
|
export function isRouteHandlerClass(what: any): what is RouteHandlerClass {
|
||||||
return (
|
return (
|
||||||
what && typeof what.handleRequest === 'function' && what.handleRequest.length === 1
|
what && typeof what.handleRequest === 'function' && what.handleRequest.length >= 1
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,13 +152,15 @@ export default class Routing extends LifecycleUnit {
|
|||||||
* @param {Array<string>} group
|
* @param {Array<string>} group
|
||||||
* @return RouteHandlers
|
* @return RouteHandlers
|
||||||
*/
|
*/
|
||||||
public build_handler(group: string[]): RouteHandlers {
|
public build_handler(group: RouteHandlerDefinition[]): RouteHandlers {
|
||||||
const handlers: RouteHandlers = []
|
const handlers: RouteHandlers = []
|
||||||
for ( const item of group ) {
|
for ( const item of group ) {
|
||||||
const ref = Canonical.resolve(item)
|
const handler_ref = typeof item === 'object' ? item.handler : item
|
||||||
|
const arg: any = typeof item === 'object' ? item.arg : undefined
|
||||||
|
const ref = Canonical.resolve(handler_ref)
|
||||||
|
|
||||||
if ( !ref.resource ) {
|
if ( !ref.resource ) {
|
||||||
this.logger.error(`Invalid canonical reference for route: ${item}. Reference must include resource (e.g. controller::)!`)
|
this.logger.error(`Invalid canonical reference for route: ${handler_ref}. Reference must include resource (e.g. controller::)!`)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,10 +168,15 @@ export default class Routing extends LifecycleUnit {
|
|||||||
const resolved = resource.get(ref.item)
|
const resolved = resource.get(ref.item)
|
||||||
|
|
||||||
if ( !ref.particular ) {
|
if ( !ref.particular ) {
|
||||||
if ( isRouteHandler(resolved) ) {
|
const handler = {
|
||||||
handlers.push(resolved)
|
handler: resolved,
|
||||||
|
arg,
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( isRouteHandler(handler) ) {
|
||||||
|
handlers.push(handler)
|
||||||
} else {
|
} else {
|
||||||
throw new TypeError(`Invalid canonical reference for route: ${item}. Reference is not a valid route handler.`)
|
throw new TypeError(`Invalid canonical reference for route: ${handler_ref}. Reference is not a valid route handler.`)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if ( isBindable(resolved) ) {
|
if ( isBindable(resolved) ) {
|
||||||
@ -165,16 +185,21 @@ export default class Routing extends LifecycleUnit {
|
|||||||
handler = resolved.get_bound_method(ref.particular)
|
handler = resolved.get_bound_method(ref.particular)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.logger.error(e)
|
this.logger.error(e)
|
||||||
throw new Error(`Invalid canonical reference for route: ${item}. Reference particular could not be bound.`)
|
throw new Error(`Invalid canonical reference for route: ${handler_ref}. Reference particular could not be bound.`)
|
||||||
}
|
}
|
||||||
|
|
||||||
if ( isRouteHandler(handler) ) {
|
const handler_obj = {
|
||||||
handlers.push(handler)
|
handler,
|
||||||
|
arg
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( isRouteHandler(handler_obj) ) {
|
||||||
|
handlers.push(handler_obj)
|
||||||
} else {
|
} else {
|
||||||
throw new TypeError(`Invalid canonical reference for route: ${item}. Reference is not a valid route handler.`)
|
throw new TypeError(`Invalid canonical reference for route: ${handler_ref}. Reference is not a valid route handler.`)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
throw new TypeError(`Invalid canonical reference for route: ${item}. Reference specifies particular, but resolved resource is not bindable.`)
|
throw new TypeError(`Invalid canonical reference for route: ${handler_ref}. Reference specifies particular, but resolved resource is not bindable.`)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,7 +6,6 @@ import {Model} from '../Model.ts'
|
|||||||
*/
|
*/
|
||||||
export function Relation(): MethodDecorator {
|
export function Relation(): MethodDecorator {
|
||||||
return (target: any, propertyKey, descriptor) => {
|
return (target: any, propertyKey, descriptor) => {
|
||||||
console.log('relation decorator', target, propertyKey, descriptor)
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const original = descriptor.value
|
const original = descriptor.value
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user