Skip to content

Commit

Permalink
feat: add edge tags
Browse files Browse the repository at this point in the history
  • Loading branch information
thetutlage committed Aug 22, 2023
1 parent e9e9006 commit 610ee1a
Show file tree
Hide file tree
Showing 4 changed files with 336 additions and 55 deletions.
29 changes: 29 additions & 0 deletions providers/session_provider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,10 @@
* file that was distributed with this source code.
*/

import type { Edge } from 'edge.js'
import type { ApplicationService } from '@adonisjs/core/types'

import debug from '../src/debug.js'
import { registerSessionDriver } from '../src/helpers.js'
import SessionMiddleware from '../src/session_middleware.js'

Expand All @@ -19,6 +21,22 @@ import SessionMiddleware from '../src/session_middleware.js'
export default class SessionProvider {
constructor(protected app: ApplicationService) {}

/**
* Returns edge when it's installed
*/
protected async getEdge(): Promise<Edge | null> {
try {
const { default: edge } = await import('edge.js')
debug('Detected edge.js package. Adding session primitives to it')
return edge
} catch {
return null
}
}

/**
* Registering muddleware
*/
register() {
this.app.container.singleton(SessionMiddleware, async (resolver) => {
const config = this.app.config.get<any>('session', {})
Expand All @@ -27,10 +45,21 @@ export default class SessionProvider {
})
}

/**
* Registering the active driver when middleware is used
* +
* Adding edge tags (if edge is installed)
*/
async boot() {
this.app.container.resolving(SessionMiddleware, async () => {
const config = this.app.config.get<any>('session')
await registerSessionDriver(this.app, config.driver)
})

const edge = await this.getEdge()
if (edge) {
const { edgePluginAdonisJSSession } = await import('../src/edge_plugin_adonisjs_session.js')
edge.use(edgePluginAdonisJSSession)
}
}
}
135 changes: 135 additions & 0 deletions src/edge_plugin_adonisjs_session.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
/*
* @adonisjs/session
*
* (c) AdonisJS
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

import type { PluginFn } from 'edge.js/types'
import debug from './debug.js'

/**
* The edge plugin for AdonisJS Session adds tags to read
* flash messages
*/
export const edgePluginAdonisJSSession: PluginFn<undefined> = (edge) => {
debug('registering session tags with edge')

edge.registerTag({
tagName: 'flashMessage',
seekable: true,
block: true,
compile(parser, buffer, token) {
const expression = parser.utils.transformAst(
parser.utils.generateAST(token.properties.jsArg, token.loc, token.filename),
token.filename,
parser
)

const key = parser.utils.stringify(expression)

/**
* Write an if statement
*/
buffer.writeStatement(
`if (state.flashMessages.has(${key})) {`,
token.filename,
token.loc.start.line
)

/**
* Define a local variable
*/
buffer.writeExpression(
`let message = state.flashMessages.get(${key})`,
token.filename,
token.loc.start.line
)

/**
* Create a local variables scope and tell the parser about
* the existence of the "message" variable
*/
parser.stack.defineScope()
parser.stack.defineVariable('message')

/**
* Process component children using the parser
*/
token.children.forEach((child) => {
parser.processToken(child, buffer)
})

/**
* Clear the scope of the local variables before we
* close the if statement
*/
parser.stack.clearScope()

/**
* Close if statement
*/
buffer.writeStatement(`}`, token.filename, token.loc.start.line)
},
})

edge.registerTag({
tagName: 'error',
seekable: true,
block: true,
compile(parser, buffer, token) {
const expression = parser.utils.transformAst(
parser.utils.generateAST(token.properties.jsArg, token.loc, token.filename),
token.filename,
parser
)

const key = parser.utils.stringify(expression)

/**
* Write an if statement
*/
buffer.writeStatement(
`if (!!state.flashMessages.get('errors')[${key}]) {`,
token.filename,
token.loc.start.line
)

/**
* Define a local variable
*/
buffer.writeExpression(
`let messages = state.flashMessages.get('errors')[${key}]`,
token.filename,
token.loc.start.line
)

/**
* Create a local variables scope and tell the parser about
* the existence of the "messages" variable
*/
parser.stack.defineScope()
parser.stack.defineVariable('messages')

/**
* Process component children using the parser
*/
token.children.forEach((child) => {
parser.processToken(child, buffer)
})

/**
* Clear the scope of the local variables before we
* close the if statement
*/
parser.stack.clearScope()

/**
* Close if statement
*/
buffer.writeStatement(`}`, token.filename, token.loc.start.line)
},
})
}
3 changes: 3 additions & 0 deletions src/session.ts
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,9 @@ export class Session {
this.#ctx.view.share({
session: new ReadOnlyStore(this.#store.all()),
flashMessages: new ReadOnlyStore(this.flashMessages.all()),
old: function (key: string, defaultValue?: any) {
return this.flashMessages.get(key, defaultValue)
},
})
}

Expand Down

0 comments on commit 610ee1a

Please sign in to comment.