feat(multi): doSettingsFilter

This commit is contained in:
Ben Allfree 2024-06-29 14:09:35 -07:00
parent b2d33cfdbb
commit c32b845dee
17 changed files with 80 additions and 197 deletions

View File

@ -0,0 +1,11 @@
---
'@pockethost/plugin-cloudflare-request-logger': minor
'@pockethost/plugin-console-logger': minor
'@pockethost/plugin-launcher-spawn': minor
'@pockethost/plugin-auto-admin': minor
'@pockethost/plugin-ftp-server': minor
'@pockethost/plugin-maildev': minor
'pockethost': minor
---
Added support for Settings filter whereby all settings are collected and displayed in DEBUG() mode

View File

@ -1,19 +1,12 @@
import { join } from 'path'
import { DEBUG } from 'pockethost'
import {
PH_HOME,
Settings,
logSettings,
mkPath,
mkString,
} from 'pockethost/core'
import { PH_HOME, Settings, mkPath, mkString } from 'pockethost/core'
export const PLUGIN_NAME = `plugin-auto-admin`
export const HOME_DIR =
process.env.PH_AUTO_ADMIN_HOME || join(PH_HOME(), PLUGIN_NAME)
const settings = Settings({
export const settings = Settings({
PH_AUTO_ADMIN_HOME: mkPath(HOME_DIR, { create: true }),
PH_AUTO_ADMIN_LOGIN: mkString(`admin@pockethost.lvh.me`),
PH_AUTO_ADMIN_PASSWORD: mkString(`0123456789`),
@ -21,7 +14,3 @@ const settings = Settings({
export const LOGIN = () => settings.PH_AUTO_ADMIN_LOGIN
export const PASSWORD = () => settings.PH_AUTO_ADMIN_PASSWORD
if (DEBUG()) {
logSettings(settings)
}

View File

@ -2,9 +2,10 @@ import PocketBase from 'pocketbase'
import {
PocketHostPlugin,
onAfterInstanceStartedAction,
onSettingsFilter,
parseError,
} from 'pockethost'
import { LOGIN, PASSWORD, PLUGIN_NAME } from './constants'
import { LOGIN, PASSWORD, PLUGIN_NAME, settings } from './constants'
import { dbg, info } from './log'
export const plugin: PocketHostPlugin = async ({}) => {
@ -25,4 +26,6 @@ export const plugin: PocketHostPlugin = async ({}) => {
info(`Default admin login for ${subdomain} is ${email}/${password}`)
}
})
onSettingsFilter(async (allSettings) => ({ ...allSettings, ...settings }))
}

View File

@ -1,16 +1,11 @@
import { join } from 'path'
import { DEBUG } from 'pockethost'
import { PH_HOME, Settings, logSettings, mkPath } from 'pockethost/core'
import { PH_HOME, Settings, mkPath } from 'pockethost/core'
export const PLUGIN_NAME = `plugin-cloudflare-request-logger`
export const HOME_DIR =
process.env.PH_CLOUDFLARE_REQUEST_LOGGER_HOME || join(PH_HOME(), PLUGIN_NAME)
const settings = Settings({
export const settings = Settings({
PH_CLOUDFLARE_REQUEST_LOGGER_HOME: mkPath(HOME_DIR, { create: true }),
})
if (DEBUG()) {
logSettings(settings)
}

View File

@ -1,6 +1,10 @@
import { info } from 'console'
import { PocketHostPlugin, onIncomingRequestAction } from 'pockethost'
import { PLUGIN_NAME } from './constants'
import {
PocketHostPlugin,
onIncomingRequestAction,
onSettingsFilter,
} from 'pockethost'
import { PLUGIN_NAME, settings } from './constants'
import { dbg } from './log'
export const plugin: PocketHostPlugin = async ({}) => {
@ -20,4 +24,6 @@ export const plugin: PocketHostPlugin = async ({}) => {
info(`Incoming request ${sig}`)
res.locals.sig = sig
})
onSettingsFilter(async (allSettings) => ({ ...allSettings, ...settings }))
}

View File

@ -1,16 +1,11 @@
import { join } from 'path'
import { DEBUG } from 'pockethost'
import { PH_HOME, Settings, logSettings, mkPath } from 'pockethost/core'
import { PH_HOME, Settings, mkPath } from 'pockethost/core'
export const PLUGIN_NAME = `plugin-console-logger`
export const HOME_DIR =
process.env.PH_CONSOLE_LOGGER_HOME || join(PH_HOME(), PLUGIN_NAME)
const settings = Settings({
PH_CONSOLE_LOGGER__HOME: mkPath(HOME_DIR, { create: true }),
export const settings = Settings({
PH_CONSOLE_LOGGER_HOME: mkPath(HOME_DIR, { create: true }),
})
if (DEBUG()) {
logSettings(settings)
}

View File

@ -5,8 +5,9 @@ import {
isLevelGte,
isLevelLte,
onLogAction,
onSettingsFilter,
} from 'pockethost'
import { PLUGIN_NAME } from './constants'
import { PLUGIN_NAME, settings } from './constants'
import { dbg } from './log'
export const LogLevelConsoleMap = {
@ -53,4 +54,6 @@ export const plugin: PocketHostPlugin = async ({}) => {
})
dbg(`initializing ${PLUGIN_NAME}`)
onSettingsFilter(async (allSettings) => ({ ...allSettings, ...settings }))
}

View File

@ -8,7 +8,7 @@ export const HOME_DIR =
export const TLS_PFX = `tls`
const settings = Settings({
export const settings = Settings({
PH_FTP_HOME: mkPath(HOME_DIR, { create: true }),
PH_FTP_PORT: mkNumber(21),
PH_FTP_SSL_KEY: mkPath(join(HOME_DIR, `${TLS_PFX}.key`), {

View File

@ -6,11 +6,17 @@ import {
onCliCommandsFilter,
onServeAction,
onServeSlugsFilter,
onSettingsFilter,
} from 'pockethost'
import { APEX_DOMAIN, gracefulExit } from 'pockethost/core'
import { FtpCommand } from './FtpCommand'
import { ftp } from './FtpCommand/ServeCommand/ftp'
import { HOME_DIR, PLUGIN_NAME, SSL_CERT, SSL_KEY } from './constants'
import {
HOME_DIR,
PLUGIN_NAME,
SSL_CERT,
SSL_KEY,
settings,
} from './constants'
import { error, info } from './log'
export const plugin: PocketHostPlugin = async ({}) => {
@ -27,6 +33,7 @@ export const plugin: PocketHostPlugin = async ({}) => {
ftp()
})
onSettingsFilter(async (allSettings) => ({ ...allSettings, ...settings }))
if (!existsSync(SSL_KEY())) {
if (!existsSync(SSL_CERT())) {
const answers = await inquirer.prompt<{ ssl: boolean }>([

View File

@ -7,10 +7,6 @@ export const PLUGIN_NAME = `plugin-launcher-spawn`
export const HOME_DIR =
process.env.PH_LAUNCHER_SPAWN_HOME || join(PH_HOME(), PLUGIN_NAME)
const settings = Settings({
export const settings = Settings({
PH_LAUNCHER_SPAWN_HOME: mkPath(HOME_DIR, { create: true }),
})
if (DEBUG()) {
logSettings(settings)
}

View File

@ -26,8 +26,8 @@ import {
exitHook,
tryFetch,
} from 'pockethost/core'
import { gte } from 'semver'
import { PLUGIN_NAME } from './constants'
import { PLUGIN_NAME, settings } from './constants'
import { DbService } from './db'
import { dbg, info } from './log'
const deleteFiles = (globPattern: string) => {
@ -146,138 +146,10 @@ export const plugin: PocketHostPlugin = async ({}) => {
if (subdomain in instances) return instances[subdomain]!
dbg({ instance })
return (instances[subdomain] = new Promise<string>(
async (resolve, reject) => {
const bot = await gobot(`pocketbase`, { version })
const realVersion = await bot.maxSatisfyingVersion(version)
if (!realVersion) {
throw new Error(`No PocketBase version satisfying ${version}`)
}
return (instances[subdomain] = mkLauncher(instance))
})
const instanceConfig = await doInstanceConfigFilter({
env: {},
binds: {
data: [],
hooks: [],
migrations: [],
public: [],
},
})
onSettingsFilter(async (allSettings) => ({ ...allSettings, ...settings }))
dbg(`instanceConfig`, { instanceConfig })
const dataDir = INSTANCE_DATA_DIR(subdomain, `pb_data`)
const hooksDir = INSTANCE_DATA_DIR(subdomain, `pb_hooks`)
const migrationsDir = INSTANCE_DATA_DIR(subdomain, `pb_migrations`)
const publicDir = INSTANCE_DATA_DIR(subdomain, `pb_public`)
;[dataDir, hooksDir, migrationsDir, publicDir].forEach((dir) => {
return mkdirSync(dir, { recursive: true })
})
const { binds, env } = instanceConfig
copyFiles(binds.data, dataDir)
copyFiles(binds.hooks, hooksDir)
copyFiles(binds.migrations, migrationsDir)
copyFiles(binds.public, publicDir)
return launchMutex.runExclusive(async () => {
dbg(`got lock`)
const port = await getPort()
const args = [
`serve`,
`--dir`,
escape(dataDir),
`--hooksDir`,
escape(hooksDir),
`--migrationsDir`,
escape(migrationsDir),
`--publicDir`,
escape(publicDir),
`--http`,
`0.0.0.0:${port}`,
]
if (dev && gte(realVersion, `0.20.1`)) args.push(`--dev`)
doInstanceLogAction({
instance,
type: 'stdout',
data: `Launching: ${await bot.getBinaryFilePath()} ${args.join(
' ',
)}`,
})
bot.run(args, { env: { ...secrets, ...env } }, (proc) => {
proc.stdout.on('data', (data) => {
data
.toString()
.trim()
.split(`\n`)
.forEach((line: string) => {
doInstanceLogAction({
instance,
type: 'stdout',
data: line,
})
})
})
proc.stderr.on('data', (data) => {
data
.toString()
.trim()
.split(`\n`)
.forEach((line: string) => {
doInstanceLogAction({
instance,
type: 'stderr',
data: line,
})
})
})
const unsub = exitHook(() => {
dbg(`killing ${subdomain}`)
doInstanceLogAction({
instance,
type: 'stdout',
data: `Forcibly killing PocketBase process`,
})
proc.kill()
})
proc.on('exit', (code) => {
unsub()
delete instances[subdomain]
doInstanceLogAction({
instance,
type: 'stdout',
data: `PocketBase process exited with code ${code}`,
})
doAfterInstanceStoppedAction({ instance, url })
dbg(`${subdomain} process exited with code ${code}`)
})
const url = `http://localhost:${port}`
doInstanceLogAction({
instance,
type: 'stdout',
data: `Waiting for PocketBase to start on ${url}`,
})
tryFetch(url)
.then(() => {
doInstanceLogAction({
instance,
type: 'stdout',
data: `PocketBase started on ${url}`,
})
doAfterInstanceStartedAction({ instance, url })
return resolve(url)
})
.catch((e) => {
doInstanceLogAction({
instance,
type: 'stderr',
data: `PocketBase failed to start on ${url}: ${e}`,
})
reject(e)
})
})
})
},
))
})
}

View File

@ -1,14 +1,6 @@
import { underscore } from 'inflection'
import { dirname, join } from 'path'
import { DEBUG } from 'pockethost'
import {
PH_HOME,
Settings,
logSettings,
mkBoolean,
mkNumber,
mkPath,
} from 'pockethost/core'
import { PH_HOME, Settings, mkBoolean, mkNumber, mkPath } from 'pockethost/core'
import { fileURLToPath } from 'url'
export const PLUGIN_NAME = `plugin-maildev`
@ -22,7 +14,7 @@ const __dirname = dirname(fileURLToPath(import.meta.url))
export const PROJECT_DIR = (...paths: string[]) =>
join(__dirname, '..', ...paths)
const settings = Settings({
export const settings = Settings({
PH_MAILDEV_HOME: mkPath(HOME_DIR, { create: true }),
PH_MAILDEV_SMTP_PORT: mkNumber(1025),
PH_MAILDEV_WEB_ADMIN_PORT: mkNumber(1080),
@ -31,7 +23,3 @@ const settings = Settings({
export const PORT = () => settings.PH_MAILDEV_SMTP_PORT
export const WEB_ADMIN_PORT = () => settings.PH_MAILDEV_WEB_ADMIN_PORT
if (DEBUG()) {
logSettings(settings)
}

View File

@ -6,6 +6,7 @@ import {
onInstanceConfigFilter,
onServeAction,
onServeSlugsFilter,
onSettingsFilter,
} from 'pockethost'
import { MailDevCommand, serve } from '.'
import {
@ -13,6 +14,7 @@ import {
PLUGIN_NAME_CONSTANT_CASE,
PORT,
PROJECT_DIR,
settings,
} from './constants'
import { dbg } from './log'
@ -50,4 +52,6 @@ export const plugin: PocketHostPlugin = async ({}) => {
if (!only.includes('maildev')) return
serve()
})
onSettingsFilter(async (allSettings) => ({ ...allSettings, ...settings }))
}

View File

@ -4,6 +4,7 @@ import { DEBUG } from '../debug'
import { InstanceFields, InstanceId } from '../schema'
export enum CoreFilters {
Settings = 'core_settings',
CliCommands = 'core_cli_commands',
ServeSlugs = 'core_serve_slugs',
SpawnConfig = 'core_spawn_config',
@ -78,6 +79,16 @@ function createCustomFilter<TCarry>(filterName: string) {
] as const
}
export const [doSettingsFilter, onSettingsFilter] = createCustomFilter<{
[_: string]: any
}>(CoreFilters.Settings)
export const [doAuthenticateUserFilter, onAuthenticateUserFilter] =
createCustomFilterWithContext<
UserId | undefined,
{ username: string; password: string }
>(CoreFilters.AuthenticateUser)
export const [
doGetInstanceByRequestInfoFilter,
onGetInstanceByRequestInfoFilter,

View File

@ -3,6 +3,5 @@ export * from './Settings'
export * from './asyncExecutionGuard'
export * from './exit'
export * from './internal'
export * from './logSettings'
export * from './smartFetch'
export * from './tryFetch'

View File

@ -1,7 +0,0 @@
import { forEach } from '@s-libs/micro-dash'
export const logSettings = (settings: { [_: string]: any }) => {
forEach(settings, (v, k) => {
console.log(`${k}: ${v}`)
})
}

View File

@ -1,14 +1,17 @@
import { forEach } from '@s-libs/micro-dash'
import { produce } from 'immer'
import {
PocketHostPlugin,
doSettingsFilter,
namespace,
onAfterPluginsLoadedAction,
onInstanceConfigFilter,
onInstanceLogAction,
onServeAction,
onServeSlugsFilter,
} from '../common'
import { dbg } from './cli'
import { PH_PROJECT_DIR } from './constants'
import { dbg, info } from './cli'
import { INTERNAL_APP_SECRET, PH_PROJECT_DIR, settings } from './constants'
import { serve } from './server'
export const pockethost: PocketHostPlugin = async ({}) => {
@ -33,4 +36,12 @@ export const pockethost: PocketHostPlugin = async ({}) => {
onServeSlugsFilter(async (slugs) => {
return [...slugs, `pockethost`]
})
onAfterPluginsLoadedAction(async () => {
const allSettings = await doSettingsFilter(settings)
forEach(allSettings, (v, k) => {
dbg(`${k}: ${v}`)
})
}, 99)
}