Skip to content

Commit

Permalink
🎉 feat: plugin checksum
Browse files Browse the repository at this point in the history
  • Loading branch information
SaltyAom committed Dec 9, 2023
1 parent 47b0bf9 commit 327760d
Show file tree
Hide file tree
Showing 5 changed files with 94 additions and 36 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ Feature:
- new life-cycle
- `resolve`: derive after validation
- `mapResponse`: custom response mapping
- add stack trace to plugin checksum

Improvement:
- lazy query reference
Expand Down
21 changes: 18 additions & 3 deletions example/a.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,22 @@
import { Elysia, t } from '../src'

const a = new Elysia({ name: 'a', seed: 'awdawd' }).extends(
({ onBeforeHandle }) => ({
a(fn: () => void) {
onBeforeHandle(fn)
}
})
)
const b = new Elysia({ name: 'b', seed: 'add' }).use(a).decorate('b', 'b')

const app = new Elysia()
.ws('/ws', {
message() {}
.use(a)
.use(b)
.get('/', () => 'Hello World', {
a() {
console.log('a')
}
})
// .listen(0)
.listen(3000)

console.dir({ main: app.dependencies }, { depth: 10 })
79 changes: 51 additions & 28 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,8 @@ import type {
BaseExtension,
ExtensionToProperty,
ExtensionManager,
MapResponse
MapResponse,
Checksum
} from './types'
import { t } from './type-system'

Expand Down Expand Up @@ -119,7 +120,7 @@ export default class Elysia<
Scoped extends boolean = false
> {
config: ElysiaConfig<BasePath>
private dependencies: Record<string, number[]> = {}
private dependencies: Record<string, Checksum[]> = {}

store: Decorators['store'] = {}
private decorators = {} as Decorators['request']
Expand Down Expand Up @@ -180,6 +181,7 @@ export default class Elysia<
private dynamicRouter = new Memoirist<DynamicHandler>()
private lazyLoadModules: Promise<Elysia<any, any>>[] = []
path: BasePath = '' as any
stack: string | undefined = undefined

constructor(config?: Partial<ElysiaConfig<BasePath, Scoped>>) {
this.config = {
Expand All @@ -192,6 +194,9 @@ export default class Elysia<
...config,
seed: config?.seed === undefined ? '' : config?.seed
} as any

if (config?.name || config?.seed !== undefined)
this.stack = new Error().stack
}

private add(
Expand Down Expand Up @@ -315,8 +320,7 @@ export default class Elysia<
)
} as any

const globalHook = Object.assign({}, this.event)
localHook = Object.assign({}, localHook)
const globalHook = this.event

const loosePath = path.endsWith('/')
? path.slice(0, path.length - 1)
Expand All @@ -335,6 +339,8 @@ export default class Elysia<
fn?: MaybeArray<Function>
) => {
if (typeof type === 'function' || Array.isArray(type)) {
if (!localHook[stackName]) localHook[stackName] = []

if (Array.isArray(type))
localHook[stackName] = (
localHook[stackName] as unknown[]
Expand Down Expand Up @@ -369,11 +375,11 @@ export default class Elysia<

return
} else {
if (!localHook[stackName]) localHook[stackName] = []

if (!Array.isArray(fn)) {
if (insert === 'before') {
;(localHook[stackName] as any[]).unshift(
fn
)
;(localHook[stackName] as any[]).unshift(fn)
} else {
;(localHook[stackName] as any[]).push(fn)
}
Expand Down Expand Up @@ -406,7 +412,13 @@ export default class Elysia<
}

for (const extension of this.extensions)
traceBackExtension(extension(manager), localHook as any)
traceBackExtension(
extension(manager),
localHook as any,
checksum(
this.config.name + JSON.stringify(this.config.seed)
)
)
}

const hooks = mergeHook(globalHook, localHook)
Expand Down Expand Up @@ -1246,13 +1258,13 @@ export default class Elysia<
>
) => NewElysia
): Elysia<
BasePath,
Decorators,
Definitions,
ParentSchema,
Extension,
Prettify<Routes & NewElysia['schema']>
>
BasePath,
Decorators,
Definitions,
ParentSchema,
Extension,
Prettify<Routes & NewElysia['schema']>
>

/**
* ### group
Expand Down Expand Up @@ -1291,7 +1303,6 @@ export default class Elysia<
const sandbox = (isSchema ? run! : schemaOrRun)(instance)
this.decorators = mergeDeep(this.decorators, instance.decorators)


if (sandbox.event.request.length)
this.event.request = [
...this.event.request,
Expand Down Expand Up @@ -1406,13 +1417,13 @@ export default class Elysia<
>
) => NewElysia
): Elysia<
BasePath,
Decorators,
Definitions,
ParentSchema,
Extension,
Prettify<Routes & NewElysia['schema']>
>
BasePath,
Decorators,
Definitions,
ParentSchema,
Extension,
Prettify<Routes & NewElysia['schema']>
>

/**
* ### guard
Expand Down Expand Up @@ -1800,12 +1811,18 @@ export default class Elysia<

if (
this.dependencies[name].some(
(checksum) => current === checksum
({ checksum }) => current === checksum
)
)
return this

this.dependencies[name].push(current)
this.dependencies[name].push({
name: plugin.config.name,
seed: plugin.config.seed,
checksum: current,
stack: plugin.stack,
dependencies: plugin.dependencies
})
}

plugin.model(this.definitions.type as any)
Expand Down Expand Up @@ -1839,7 +1856,7 @@ export default class Elysia<

if (
!this.dependencies[name].some(
(checksum) => current === checksum
({ checksum }) => current === checksum
)
)
this.extensions.push(...plugin.extensions)
Expand Down Expand Up @@ -1878,12 +1895,18 @@ export default class Elysia<

if (
this.dependencies[name].some(
(checksum) => current === checksum
({ checksum }) => current === checksum
)
)
return this

this.dependencies[name].push(current)
this.dependencies[name].push({
name: plugin.config.name,
seed: plugin.config.seed,
checksum: current,
stack: plugin.stack,
dependencies: plugin.dependencies
})
this.event = mergeLifeCycle(
this.event,
filterGlobalHook(plugin.event),
Expand Down
8 changes: 8 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,14 @@ export type BaseExtension = Record<
BaseExtension | ((a: any) => unknown)
>

export type Checksum = {
name?: string
seed?: unknown
checksum: number
stack?: string
dependencies?: Record<string, Checksum[]>
}

export type ExtensionToProperty<T extends BaseExtension> = Prettify<{
[K in keyof T]: T[K] extends Function
? T[K] extends (a: infer Params) => any
Expand Down
21 changes: 16 additions & 5 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ export const mergeCookie = <const A extends Object, const B extends Object>(
skipKeys: ['properties']
})

export const mergeObjectArray = <T,>(a: T | T[], b: T | T[]): T[] => {
export const mergeObjectArray = <T>(a: T | T[], b: T | T[]): T[] => {
// ! Must copy to remove side-effect
const array = [...(Array.isArray(a) ? a : [a])]
const checksums = []
Expand Down Expand Up @@ -280,7 +280,10 @@ export const getResponseSchemaValidator = (
'additionalProperties' in schema === false

// Inherits model maybe already compiled
record[+status] = Kind in schema ? compile(schema, Object.values(models)) : schema
record[+status] =
Kind in schema
? compile(schema, Object.values(models))
: schema
}

return undefined
Expand Down Expand Up @@ -555,13 +558,21 @@ export const unsignCookie = async (input: string, secret: string | null) => {
export const traceBackExtension = (
extension: BaseExtension,
property: Record<string, unknown>,
checksum: number | undefined,
hooks = property
) => {
for (const [key, value] of Object.entries(property)) {
if (primitiveHooks.includes(key as any) || !(key in extension)) continue

if (typeof extension[key] === 'function') extension[key](value)
else if (typeof extension[key] === 'object')
traceBackExtension(extension[key], value as any, hooks)
if (typeof extension[key] === 'function') {
// Property is reference to the original object
// @ts-ignore
if (!property[key]?.$elysiaChecksum) {
// @ts-ignore
property[key].$elysiaChecksum = checksum
extension[key](value)
}
} else if (typeof extension[key] === 'object')
traceBackExtension(extension[key], value as any, checksum, hooks)
}
}

0 comments on commit 327760d

Please sign in to comment.