Skip to content

Commit

Permalink
plugin system working
Browse files Browse the repository at this point in the history
  • Loading branch information
beagleknight committed Dec 3, 2024
1 parent a7a4c9f commit d39eef7
Show file tree
Hide file tree
Showing 14 changed files with 276 additions and 282 deletions.
5 changes: 3 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,8 @@
## Plugins

- [x] shadowdog-rake
- [ ] shadowdog-local-cache
- [ ] shadowdog-remote-cache (minio, aws)
- [x] shadowdog-local-cache
- [x] shadowdog-tag
- [ ] shadowdog-remote-aws-s3-cache (minio, aws)
- [ ] shadowdog-tree
- [ ] shadowdog-git
30 changes: 12 additions & 18 deletions shadowdog.json
Original file line number Diff line number Diff line change
@@ -1,48 +1,42 @@
{
"$schema": "./src/config/schema.json",
"plugins": [
{
"name": "shadowdog-rake"
},
{
"name": "shadowdog-local-cache",
"options": {
"path": "/tmp/shadowdog/cache"
"boira": true
}
},
{
"name": "shadowdog-tag"
}
],
"cache": {
"enabled": false
},
"watchers": [
{
"files": ["./src/config/build-schema.ts", "./src/config.ts"],
"files": ["./src/config/build-schema.ts", "./src/config.ts", "./src/plugins/index.ts"],
"commands": [
{
"artifacts": [
{
"output": "./src/config/schema.json"
"output": "./src/config/schema.json",
"tags": ["schema"]
}
],
"command": "npm run build-schema"
}
]
},
{
"files": ["./file1"],
"files": [],
"commands": [
{
"artifacts": [
{
"output": "./file1a.output"
}
],
"command": "cat file1 > ./file1a.output"
},
{
"artifacts": [
{
"output": "./file1b.output"
}
],
"command": "cat file1 > ./file1b.output"
"command": "echo 'hello shadowdog'"
}
]
}
Expand Down
5 changes: 2 additions & 3 deletions src/cli.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,8 @@ cli
.command('generate')
.description('TBA')
.addOption(configOption)
.option('-t, --tag <tag>', 'TBA')
.action(({ config: configFilePath, tag }) => {
generate(configFilePath, tag)
.action(({ config: configFilePath }) => {
generate(configFilePath)
})

cli.parse(process.argv)
14 changes: 4 additions & 10 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,7 @@ import fs from 'fs-extra'
import { logMessage } from './utils'
import { z } from 'zod'
import chalk from 'chalk'

// TODO: rake plugin
// const PluginTypeEnum = z.enum(['shadowdog-rake', 'shadowdog-local-cache'])
const PluginTypeEnum = z.enum(['shadowdog-local-cache'])
import { PluginNameEnum } from './plugins'

export const configSchema = z
.object({
Expand All @@ -22,12 +19,7 @@ export const configSchema = z
.default(['.git', '**/node_modules'])
.describe('Default ignored files when watching files'),
plugins: z
.array(
z.union([
PluginTypeEnum.describe('Plugin name'),
z.object({ name: PluginTypeEnum, options: z.any() }).strict(),
]),
)
.array(z.object({ name: PluginNameEnum, options: z.any() }).strict())
.optional()
.default([])
.describe('List of plugins to use'),
Expand Down Expand Up @@ -144,6 +136,8 @@ export type CommandConfig = WatcherConfig['commands'][number]

export type ArtifactConfig = NonNullable<CommandConfig['artifacts']>[number]

export type PluginsConfig = ConfigFile['plugins']

export const loadConfig = (configFilePath: string): ConfigFile => {
logMessage(`✨ Reading config file from ${chalk.blue(configFilePath)}...`)

Expand Down
25 changes: 8 additions & 17 deletions src/config/schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,25 +22,16 @@
"plugins": {
"type": "array",
"items": {
"anyOf": [
{
"type": "object",
"properties": {
"name": {
"type": "string",
"enum": ["shadowdog-local-cache"],
"description": "Plugin name"
"enum": ["shadowdog-rake", "shadowdog-local-cache", "shadowdog-tag"]
},
{
"type": "object",
"properties": {
"name": {
"type": "string",
"enum": ["shadowdog-local-cache"]
},
"options": {}
},
"required": ["name"],
"additionalProperties": false
}
]
"options": {}
},
"required": ["name"],
"additionalProperties": false
},
"default": [],
"description": "List of plugins to use"
Expand Down
80 changes: 14 additions & 66 deletions src/daemon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,62 +5,16 @@ import debounce from 'lodash/debounce'
import uniq from 'lodash/uniq'
import path from 'path'

import { restoreCache } from './cache'
import { ConfigFile, loadConfig } from './config'
import { createClient } from './global-cache'
import { notifyState } from './notifications'
import { runTask } from './tasks'
import { logMessage } from './utils'
import chalk from 'chalk'
import { Client } from 'minio'

// TODO: Add the rest of the plugins
import shadowdogRake from './plugins/shadowdog-rake'
import shadowdogLocalCache from './plugins/shadowdog-local-cache'
import { TaskRunner } from './task-runner'
import { filterMiddlewarePlugins } from './plugins'

const PLUGINS_MAP = {
'shadowdog-local-cache': shadowdogLocalCache,
} as const

type Result = any

export type Middleware<Context = any> = (
ctx: Context,
next: () => Promise<Result>,
abort: () => void,
) => Promise<Result>

class TaskManager {
middlewares: Array<{ middleware: Middleware; options: any }>

constructor() {
this.middlewares = []
}

use(middleware: Middleware, options: any = {}) {
this.middlewares.push({ middleware, options })
}

async execute(context: any) {
let index = -1
let isAborted = false

const abort = () => {
isAborted = true
}

const next = async () => {
if (isAborted || ++index >= this.middlewares.length) return context.result
const current = this.middlewares[index]
return current.middleware({ ...context, options: current.options }, next, abort)
}

context.result = await next()
return context.result
}
}

const setupWatchers = (config: ConfigFile, socketPath: string, client: Client | null) => {
const setupWatchers = (config: ConfigFile) => {
return Promise.all<chokidar.FSWatcher>(
config.watchers
.filter(({ files, enabled = true }) => {
Expand Down Expand Up @@ -150,30 +104,24 @@ const setupWatchers = (config: ConfigFile, socketPath: string, client: Client |

await Promise.all(
watcherConfig.commands.map(async (commandConfig) => {
const taskManager = new TaskManager()
const taskRunner = new TaskRunner(watcherConfig, commandConfig)

config.plugins.forEach((pluginName) => {
if (typeof pluginName === 'object') {
return taskManager.use(PLUGINS_MAP[pluginName.name], pluginName.options)
}
taskManager.use(PLUGINS_MAP[pluginName])
filterMiddlewarePlugins(config.plugins).forEach((pluginFn) => {
taskRunner.use(pluginFn.middleware)
})

taskManager.use(() => {
taskRunner.use(() => {
return runTask({
command: commandConfig.command,
workingDirectory: process.cwd(),
filePath,
changedFilePath: filePath,
onSpawn: (task) => {
tasks.push(task)
},
})
})

return taskManager.execute({
watcherConfig,
commandConfig,
})
return taskRunner.execute()

///////////////////////////// REVIEW THIS CODE /////////////////////////////

Expand Down Expand Up @@ -256,13 +204,13 @@ const setupWatchers = (config: ConfigFile, socketPath: string, client: Client |
)
}

const watchFiles = async (configFilePath: string, socketPath: string) => {
const watchFiles = async (configFilePath: string) => {
let currentWatchers: chokidar.FSWatcher[] = []
let currentConfig = loadConfig(configFilePath)

fs.mkdirpSync(currentConfig.cache.path)

const client = currentConfig.cache.enabled ? createClient() : null
// const client = currentConfig.cache.enabled ? createClient() : null

const configWatcher = chokidar.watch(configFilePath, {
ignoreInitial: true,
Expand All @@ -275,15 +223,15 @@ const watchFiles = async (configFilePath: string, socketPath: string) => {
try {
currentConfig = loadConfig(configFilePath)
await Promise.all(currentWatchers.map((watcher) => watcher.close()))
currentWatchers = await setupWatchers(currentConfig, socketPath, client)
currentWatchers = await setupWatchers(currentConfig)
logMessage(`🐕 Shadowdog has been restarted successfully.`)
} catch (error) {
logMessage(`🚨 Error while restarting Shadowdog: ${(error as Error).message}`)
}
}, currentConfig.debounceTime),
)

currentWatchers = await setupWatchers(currentConfig, socketPath, client)
currentWatchers = await setupWatchers(currentConfig)

return currentWatchers
}
Expand All @@ -301,7 +249,7 @@ export const runDaemon = async (configFilePath: string, socketPath: string) => {
false,
)

await watchFiles(configFilePath, socketPath)
await watchFiles(configFilePath)

logMessage('🚀 Shadowdog is ready to watch your files!')

Expand Down
Loading

0 comments on commit d39eef7

Please sign in to comment.