Skip to content

Commit

Permalink
feat: allow resource controller to be a class reference or lazy import
Browse files Browse the repository at this point in the history
  • Loading branch information
thetutlage committed Mar 11, 2023
1 parent d4caa2a commit 5af5846
Show file tree
Hide file tree
Showing 4 changed files with 229 additions and 13 deletions.
4 changes: 2 additions & 2 deletions src/router/brisk.ts
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ export class BriskRoute extends Macroable {
params?: any[] | Record<string, any>,
options?: MakeUrlOptions & { status: number }
): Route {
return this.setHandler(async (ctx) => {
return this.setHandler(async function redirectsToRoute(ctx) {
const redirector = ctx.response.redirect()
if (options?.status) {
redirector.status(options.status)
Expand All @@ -101,7 +101,7 @@ export class BriskRoute extends Macroable {
* Redirect request to a fixed URL
*/
redirectToPath(url: string, options?: { status: number }): Route {
return this.setHandler(async (ctx) => {
return this.setHandler(async function redirectsToPath(ctx) {
const redirector = ctx.response.redirect()
if (options?.status) {
redirector.status(options.status)
Expand Down
7 changes: 5 additions & 2 deletions src/router/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ export class Router extends LookupStore {
/**
* Registers a route resource with conventional set of routes
*/
resource(resource: string, controller: string) {
resource(resource: string, controller: string | LazyImport<Constructor<any>> | Constructor<any>) {
const resourceInstance = new RouteResource(this.#app, this.#middleware, {
resource,
controller,
Expand All @@ -271,7 +271,10 @@ export class Router extends LookupStore {
/**
* Register a route resource with shallow nested routes.
*/
shallowResource(resource: string, controller: string) {
shallowResource(
resource: string,
controller: string | LazyImport<Constructor<any>> | Constructor<any>
) {
const resourceInstance = new RouteResource(this.#app, this.#middleware, {
resource,
controller,
Expand Down
10 changes: 7 additions & 3 deletions src/router/resource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import { RuntimeException } from '@poppinss/utils'
import type { Application } from '@adonisjs/application'

import { Route } from './route.js'
import type { Constructor, LazyImport } from '../types/base.js'
import type { ParsedGlobalMiddleware } from '../types/middleware.js'
import type { ResourceActionNames, RouteMatcher, RouteMatchers } from '../types/route.js'

Expand All @@ -29,7 +30,7 @@ export class RouteResource extends Macroable {
/**
* The controller to handle resource routing requests
*/
#controller: string
#controller: string | LazyImport<Constructor<any>> | Constructor<any>

/**
* Is it a shallow resource? Shallow resources URLs do not have parent
Expand Down Expand Up @@ -75,7 +76,7 @@ export class RouteResource extends Macroable {
routerMiddleware: ParsedGlobalMiddleware[],
options: {
resource: string
controller: string
controller: string | LazyImport<Constructor<any>> | Constructor<any>
globalMatchers: RouteMatchers
shallow: boolean
}
Expand Down Expand Up @@ -128,7 +129,10 @@ export class RouteResource extends Macroable {
const route = new Route(this.#app, this.#routerMiddleware, {
pattern,
methods,
handler: `${this.#controller}.${action}`,
handler:
typeof this.#controller === 'string'
? `${this.#controller}.${action}`
: [this.#controller, action],
globalMatchers: this.#globalMatchers,
})

Expand Down
221 changes: 215 additions & 6 deletions tests/router/resource.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ test.group('Route Resource', () => {
meta: {},
methods: ['GET', 'HEAD'],
domain: 'root',

handler: {
reference: '#controllers/photos.index',
},
name: 'photos.index',
},
{
Expand All @@ -42,7 +44,9 @@ test.group('Route Resource', () => {
meta: {},
methods: ['GET', 'HEAD'],
domain: 'root',

handler: {
reference: '#controllers/photos.create',
},
name: 'photos.create',
},
{
Expand All @@ -51,6 +55,9 @@ test.group('Route Resource', () => {
meta: {},
methods: ['POST'],
domain: 'root',
handler: {
reference: '#controllers/photos.store',
},
name: 'photos.store',
},
{
Expand All @@ -59,7 +66,9 @@ test.group('Route Resource', () => {
meta: {},
methods: ['GET', 'HEAD'],
domain: 'root',

handler: {
reference: '#controllers/photos.show',
},
name: 'photos.show',
},
{
Expand All @@ -68,7 +77,9 @@ test.group('Route Resource', () => {
meta: {},
methods: ['GET', 'HEAD'],
domain: 'root',

handler: {
reference: '#controllers/photos.edit',
},
name: 'photos.edit',
},
{
Expand All @@ -77,7 +88,9 @@ test.group('Route Resource', () => {
meta: {},
methods: ['PUT', 'PATCH'],
domain: 'root',

handler: {
reference: '#controllers/photos.update',
},
name: 'photos.update',
},
{
Expand All @@ -86,7 +99,9 @@ test.group('Route Resource', () => {
meta: {},
methods: ['DELETE'],
domain: 'root',

handler: {
reference: '#controllers/photos.destroy',
},
name: 'photos.destroy',
},
]
Expand Down Expand Up @@ -1169,4 +1184,198 @@ test.group('Route Resource', () => {
]
)
})

test('define resource controller as a class reference', ({ assert }) => {
class UsersController {}

const app = new AppFactory().create(BASE_URL, () => {})
const resource = new RouteResource(app, [], {
resource: 'photos',
controller: UsersController,
globalMatchers: {},
shallow: false,
})

assert.containsSubset(
resource.routes.map((route) => route.toJSON()),
[
{
pattern: '/photos',
matchers: {},
meta: {},
methods: ['GET', 'HEAD'],
domain: 'root',
handler: {
reference: [UsersController, 'index'],
},
name: 'photos.index',
},
{
pattern: '/photos/create',
matchers: {},
meta: {},
methods: ['GET', 'HEAD'],
domain: 'root',
handler: {
reference: [UsersController, 'create'],
},
name: 'photos.create',
},
{
pattern: '/photos',
matchers: {},
meta: {},
methods: ['POST'],
domain: 'root',
handler: {
reference: [UsersController, 'store'],
},
name: 'photos.store',
},
{
pattern: '/photos/:id',
matchers: {},
meta: {},
methods: ['GET', 'HEAD'],
domain: 'root',
handler: {
reference: [UsersController, 'show'],
},
name: 'photos.show',
},
{
pattern: '/photos/:id/edit',
matchers: {},
meta: {},
methods: ['GET', 'HEAD'],
domain: 'root',
handler: {
reference: [UsersController, 'edit'],
},
name: 'photos.edit',
},
{
pattern: '/photos/:id',
matchers: {},
meta: {},
methods: ['PUT', 'PATCH'],
domain: 'root',
handler: {
reference: [UsersController, 'update'],
},
name: 'photos.update',
},
{
pattern: '/photos/:id',
matchers: {},
meta: {},
methods: ['DELETE'],
domain: 'root',
handler: {
reference: [UsersController, 'destroy'],
},
name: 'photos.destroy',
},
]
)
})

test('define resource controller as a lazy import reference', ({ assert }) => {
const UsersController = async () => {
return {
default: class UsersControllerClass {},
}
}

const app = new AppFactory().create(BASE_URL, () => {})
const resource = new RouteResource(app, [], {
resource: 'photos',
controller: UsersController,
globalMatchers: {},
shallow: false,
})

assert.containsSubset(
resource.routes.map((route) => route.toJSON()),
[
{
pattern: '/photos',
matchers: {},
meta: {},
methods: ['GET', 'HEAD'],
domain: 'root',
handler: {
reference: [UsersController, 'index'],
},
name: 'photos.index',
},
{
pattern: '/photos/create',
matchers: {},
meta: {},
methods: ['GET', 'HEAD'],
domain: 'root',
handler: {
reference: [UsersController, 'create'],
},
name: 'photos.create',
},
{
pattern: '/photos',
matchers: {},
meta: {},
methods: ['POST'],
domain: 'root',
handler: {
reference: [UsersController, 'store'],
},
name: 'photos.store',
},
{
pattern: '/photos/:id',
matchers: {},
meta: {},
methods: ['GET', 'HEAD'],
domain: 'root',
handler: {
reference: [UsersController, 'show'],
},
name: 'photos.show',
},
{
pattern: '/photos/:id/edit',
matchers: {},
meta: {},
methods: ['GET', 'HEAD'],
domain: 'root',
handler: {
reference: [UsersController, 'edit'],
},
name: 'photos.edit',
},
{
pattern: '/photos/:id',
matchers: {},
meta: {},
methods: ['PUT', 'PATCH'],
domain: 'root',
handler: {
reference: [UsersController, 'update'],
},
name: 'photos.update',
},
{
pattern: '/photos/:id',
matchers: {},
meta: {},
methods: ['DELETE'],
domain: 'root',
handler: {
reference: [UsersController, 'destroy'],
},
name: 'photos.destroy',
},
]
)
})
})

0 comments on commit 5af5846

Please sign in to comment.