Skip to content

Commit

Permalink
refactor: class plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
tpluscode committed Jan 14, 2025
1 parent fd557ca commit 636558a
Show file tree
Hide file tree
Showing 8 changed files with 65 additions and 38 deletions.
7 changes: 7 additions & 0 deletions .changeset/tidy-mice-tell.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@kopflos-cms/express": patch
"@kopflos-cms/vite": patch
"kopflos": patch
---

Plugins are now implemented as classes
2 changes: 1 addition & 1 deletion packages/cli/lib/command/build.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default async function (args: BuildArgs) {
const plugins = await loadPlugins(config.plugins)

log.info('Running build actions...')
const buildActions = plugins.map(plugin => plugin.build?.())
const buildActions = plugins.map(Plugin => Plugin.build?.())
if (buildActions.length === 0) {
return log.warn('No plugins with build actions found')
} else {
Expand Down
4 changes: 2 additions & 2 deletions packages/core/lib/Kopflos.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,8 +61,7 @@ export interface PluginConfig {
}

export interface KopflosPlugin {
readonly name: string
build?: () => Promise<void> | void
readonly name?: string
onStart?(): Promise<void> | void
onStop?(): Promise<void> | void
apiTriples?(): Promise<DatasetCore | Stream> | DatasetCore | Stream
Expand All @@ -82,6 +81,7 @@ export interface Kopflos<D extends DatasetCore = Dataset> {

export interface KopflosPluginConstructor {
new(instance: Kopflos): KopflosPlugin
build?: () => Promise<void> | void
}

interface Clients {
Expand Down
15 changes: 9 additions & 6 deletions packages/core/plugin/shorthandTerms.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
import type { Stream } from '@rdfjs/types'
import type { KopflosPlugin } from '../lib/Kopflos.js'
import type { Kopflos, KopflosPlugin, KopflosPluginConstructor } from '../lib/Kopflos.js'

export default function (): KopflosPlugin {
return {
apiTriples(kopflos): Stream {
const { env } = kopflos
export default function (): KopflosPluginConstructor {
return class implements KopflosPlugin {
constructor(private readonly kopflos: Kopflos) {
}

apiTriples(): Stream {
const { env } = this.kopflos
return env.fromFile(new URL('../graphs/shorthands.ttl', import.meta.url))
},
}
}
}
4 changes: 2 additions & 2 deletions packages/core/plugins.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import log from './lib/log.js'
import type { KopflosConfig, KopflosPlugin } from './lib/Kopflos.js'
import type { KopflosConfig, KopflosPluginConstructor } from './lib/Kopflos.js'

export async function loadPlugins(plugins: KopflosConfig['plugins']): Promise<KopflosPlugin[]> {
export async function loadPlugins(plugins: KopflosConfig['plugins']): Promise<KopflosPluginConstructor[]> {
const pluginsCombined = Object.entries({
'@kopflos-cms/core/plugin/shorthandTerms.js': {},
...plugins,
Expand Down
16 changes: 9 additions & 7 deletions packages/core/test/lib/Kopflos.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -620,8 +620,9 @@ describe('lib/Kopflos', () => {

it('calls onStart on plugins once', async function () {
// given
const plugin = {
onStart: sinon.spy(),
const onStart = sinon.spy()
const plugin = class {
onStart = onStart
}
const instance = new Kopflos({
...config,
Expand All @@ -636,15 +637,16 @@ describe('lib/Kopflos', () => {
await instance.start()

// then
expect(plugin.onStart).to.have.been.calledOnce
expect(onStart).to.have.been.calledOnce
})
})

describe('stop', () => {
it('calls onStop on plugins', async function () {
// given
const plugin = {
onStop: sinon.spy(),
const onStop = sinon.spy()
const plugin = class {
onStop = onStop
}
const instance = new Kopflos({
...config,
Expand All @@ -659,12 +661,12 @@ describe('lib/Kopflos', () => {
await instance.stop()

// then
expect(plugin.onStop).to.have.been.called
expect(onStop).to.have.been.called
})

it('ignores plugins without onStop', async function () {
// given
const plugin = {}
const plugin = class {}
const instance = new Kopflos({
...config,
sparql: {
Expand Down
21 changes: 13 additions & 8 deletions packages/express/plugin/middleware.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { KopflosPlugin } from '@kopflos-cms/core'
import type { KopflosPlugin, KopflosPluginConstructor } from '@kopflos-cms/core'
import type { Router } from 'express'
import { createLogger } from '@kopflos-cms/logger'

Expand All @@ -17,9 +17,14 @@ declare module '@kopflos-cms/core' {
}
}

export default function ({ before = [], after = [] }: Options): KopflosPlugin {
function use(middlewares: Array<Middleware>) {
return async function (host: Router) {
export default function ({ before = [], after = [] }: Options): KopflosPluginConstructor {
return class implements KopflosPlugin {
readonly name = '@kopflos-cms/express/middleware'

declare beforeMiddleware: (host: Router) => Promise<void>
declare afterMiddleware: (host: Router) => Promise<void>

private async use(middlewares: Array<Middleware>, host: Router) {
const promises = middlewares.map(async middleware => {
let module: string
let options: unknown | undefined
Expand All @@ -41,10 +46,10 @@ export default function ({ before = [], after = [] }: Options): KopflosPlugin {
current = promises.splice(0, 1)
}
}
}

return {
beforeMiddleware: use(before),
afterMiddleware: use(after),
constructor() {
this.beforeMiddleware = this.use.bind(null, before)
this.afterMiddleware = this.use.bind(null, after)
}
}
}
34 changes: 22 additions & 12 deletions packages/vite/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { resolve } from 'node:path'
import type { Kopflos, KopflosPlugin } from '@kopflos-cms/core'
import type { Kopflos, KopflosEnvironment, KopflosPlugin, KopflosPluginConstructor } from '@kopflos-cms/core'
import express from 'express'
import { build } from 'vite'
import { createViteServer } from './lib/server.js'
Expand All @@ -21,20 +21,29 @@ declare module '@kopflos-cms/core' {
}
}

export default function ({ outDir = 'dist', ...options }: Options): KopflosPlugin {
export default function ({ outDir = 'dist', ...options }: Options): KopflosPluginConstructor {
const rootDir = resolve(process.cwd(), options.root || '')
const buildDir = resolve(process.cwd(), outDir)

return {
onStart({ env }: Kopflos): Promise<void> | void {
return class implements KopflosPlugin {
readonly name = '@kopflos-cms/vite'

private env: KopflosEnvironment

constructor(instance: Kopflos) {
this.env = instance.env
}

onStart(): Promise<void> | void {
const viteVars = {
basePath: env.kopflos.config.mode === 'development' ? rootDir : buildDir,
basePath: this.env.kopflos.config.mode === 'development' ? rootDir : buildDir,
}
log.info('Variables', viteVars)
env.kopflos.variables.VITE = Object.freeze(viteVars)
},
async beforeMiddleware(host: express.Router, { env }) {
if (env.kopflos.config.mode === 'development') {
this.env.kopflos.variables.VITE = Object.freeze(viteVars)
}

async beforeMiddleware(host: express.Router) {
if (this.env.kopflos.config.mode === 'development') {
log.info('Development UI mode. Creating Vite server...')
const viteServer = await createViteServer(options)
host.use(viteServer.middlewares)
Expand All @@ -43,10 +52,11 @@ export default function ({ outDir = 'dist', ...options }: Options): KopflosPlugi
log.debug('Build directory:', buildDir)
host.use(express.static(buildDir))
}
},
async build() {
}

static async build() {
log.info('Building UI...')
await build(await prepareConfig({ outDir, ...options }))
},
}
}
}

0 comments on commit 636558a

Please sign in to comment.