diff --git a/.prettierignore b/.prettierignore index e77087d0..28f97633 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,3 +1,5 @@ .svelte-kit dist -mount \ No newline at end of file +mount +.data +attic \ No newline at end of file diff --git a/gitbook/SUMMARY.md b/gitbook/SUMMARY.md index 5de69506..91411dae 100644 --- a/gitbook/SUMMARY.md +++ b/gitbook/SUMMARY.md @@ -1,56 +1,60 @@ # Table of contents -* [👋 Welcome to PocketHost](README.md) +- [👋 Welcome to PocketHost](README.md) ## Overview -* [Getting Help](overview/help.md) -* [FAQ](overview/faq.md) -* [Roadmap](overview/roadmap.md) +- [Getting Help](overview/help.md) +- [FAQ](overview/faq.md) +- [Roadmap](overview/roadmap.md) ## Daily Usage -* [Creating an Instance](usage/create.md) -* [Accessing an Instance](usage/accessing-instance.md) -* [Instance Details](usage/instances/index.md) -* [Renaming an Instance](usage/rename-instance.md) -* [Maintenance Mode](usage/maintenance.md) -* [FTP Access](usage/ftp.md) -* [Backup & Restore](usage/backup-and-restore.md) -* [Worker](daily-usage/worker.md) -* [PocketBase Hooks](usage/hooks.md) -* [Upgrading](usage/upgrading.md) +- [Creating an Instance](usage/create.md) +- [Accessing an Instance](usage/accessing-instance.md) +- [Instance Details](usage/instances/index.md) +- [Renaming an Instance](usage/rename-instance.md) +- [Maintenance Mode](usage/maintenance.md) +- [FTP Access](usage/ftp.md) +- [Backup & Restore](usage/backup-and-restore.md) +- [Worker](daily-usage/worker.md) +- [PocketBase Hooks](usage/hooks.md) +- [Upgrading](usage/upgrading.md) + +## Hosting + +- [Overview](hosting/overview.md) ## Contributing -* [Overview](development/overview.md) -* [Running Just the Frontend](development/frontend.md) -* [Running Everything](development/full-stack/index.md) -* [Creating RPC Calls](development/rpc.md) -* [Production Deployment](development/production.md) +- [Overview](development/overview.md) +- [Running Just the Frontend](development/frontend.md) +- [Running Everything](development/full-stack/index.md) +- [Creating RPC Calls](development/rpc.md) +- [Production Deployment](development/production.md) ## Release History -* [next](releases/next.md) -* [0.8.0](releases/0.8.0.md) -* [0.7.2](releases/0.7.2.md) -* [0.7.1](releases/0.7.1.md) -* [0.7.0](releases/0.7.0.md) -* [0.6.1](releases/0.6.1.md) -* [0.6.0](releases/0.6.0.md) -* [0.5.7](releases/0.5.7.md) -* [0.5.6](releases/0.5.6.md) -* [0.5.5](releases/0.5.5.md) -* [0.5.4](releases/0.5.4.md) -* [0.5.3](releases/0.5.3.md) -* [0.5.2](releases/0.5.2.md) -* [0.5.1](releases/0.5.1.md) -* [0.5.0](releases/0.5.0.md) -* [0.4.2](releases/0.4.2.md) -* [0.4.1](releases/0.4.1.md) -* [0.4.0](releases/0.4.0.md) -* [0.3.2](releases/0.3.2.md) -* [0.3.1](releases/0.3.1.md) -* [0.3.0](releases/0.3.0.md) -* [0.2.0](releases/0.2.0.md) -* [0.0.1](release-history/0.0.1.md) +- [next](releases/next.md) +- [0.8.0](releases/0.8.0.md) +- [0.7.2](releases/0.7.2.md) +- [0.7.1](releases/0.7.1.md) +- [0.7.0](releases/0.7.0.md) +- [0.6.1](releases/0.6.1.md) +- [0.6.0](releases/0.6.0.md) +- [0.5.7](releases/0.5.7.md) +- [0.5.6](releases/0.5.6.md) +- [0.5.5](releases/0.5.5.md) +- [0.5.4](releases/0.5.4.md) +- [0.5.3](releases/0.5.3.md) +- [0.5.2](releases/0.5.2.md) +- [0.5.1](releases/0.5.1.md) +- [0.5.0](releases/0.5.0.md) +- [0.4.2](releases/0.4.2.md) +- [0.4.1](releases/0.4.1.md) +- [0.4.0](releases/0.4.0.md) +- [0.3.2](releases/0.3.2.md) +- [0.3.1](releases/0.3.1.md) +- [0.3.0](releases/0.3.0.md) +- [0.2.0](releases/0.2.0.md) +- [0.0.1](release-history/0.0.1.md) diff --git a/gitbook/hosting/overview.md b/gitbook/hosting/overview.md new file mode 100644 index 00000000..dc1b4061 --- /dev/null +++ b/gitbook/hosting/overview.md @@ -0,0 +1,41 @@ +# Overview + +[UNDER CONSTRUCTION] + +This guide covers how to set up a production hosting environment for PocketHost. Hosting PocketHost might be desirable if: + +- You want to create a hosting service business powered by PocketHost +- You want a private copy of PocketHost where you control all the underlying infrastructure +- You want to run PocketHost from a region not yet offered by pockethost.io + +Running a hosting service is not easy. To provide a great hosting experience for users, you need to know about: + +- Docker +- Email and DKIM+SPF and more +- DNS jargon: MX, TXT, CNAME +- SSL cert provisioning and management +- Storage +- Volume mounts +- Could computing or VPS deployment +- CDN and static asset hosting +- Amazon AWS +- Lots more - scaling, firewalls, DDoS defense, user security, log rotation, patches, updates, build tools, CPU architectures, multitenancy, on and on + +If you're still interested in creating a PocketHost hosting environment for yourself, read on... + +``` +apt-get update +apt-get install -y nginx nodejs npm +npm i -g n yarn +n lts +hash -r +git clone git@github.com:benallfree/pockethost.git pockethost-latest +cd pockethost-latest +yarn +cd .. +git clone git@github.com:benallfree/pockethost.git pockethost-lts +cd pockethost-lts +yarn +cd .. + +``` diff --git a/package.json b/package.json index 42829cdf..65adc2ea 100644 --- a/package.json +++ b/package.json @@ -32,18 +32,22 @@ "semi": false, "useTabs": false, "singleQuote": true, + "trailingComma": "all", "plugins": [ - "./node_modules/prettier-plugin-organize-imports", - "./node_modules/prettier-plugin-svelte" + "./node_modules/prettier-plugin-organize-imports/index.js", + "./node_modules/prettier-plugin-svelte/plugin.js" ] }, "devDependencies": { - "concurrently": "^7.4.0", - "patch-package": "^6.5.0", - "prettier": "^2.7.1", - "prettier-plugin-organize-imports": "^3.1.1", - "prettier-plugin-svelte": "^2.7.0", - "typescript": "^4.8.3" + "chokidar-cli": "^3.0.0", + "concurrently": "^8.2.1", + "patch-package": "^8.0.0", + "prettier": "^3.0.3", + "prettier-plugin-organize-imports": "^3.2.3", + "prettier-plugin-svelte": "^3.0.3", + "tslib": "^2.6.2", + "tsx": "^3.12.8", + "typescript": "^5.0" }, "dependencies": { "postinstall-postinstall": "^2.1.0", diff --git a/packages/cli/src/commands/build.ts b/packages/cli/src/commands/build.ts index 87182649..ab7fd5cf 100644 --- a/packages/cli/src/commands/build.ts +++ b/packages/cli/src/commands/build.ts @@ -18,7 +18,7 @@ export const addDevCommand = (program: Command) => { .description('Build the JS bundle') .option( '--src ', - `Path to source (default: /src/index.{ts|js})` + `Path to source (default: /src/index.{ts|js})`, ) .option('--dist ', `Path to dist (default: /dist/index.js)`) .action(async (options) => { diff --git a/packages/cli/src/commands/dev.ts b/packages/cli/src/commands/dev.ts index a6408cd6..387e7c6c 100644 --- a/packages/cli/src/commands/dev.ts +++ b/packages/cli/src/commands/dev.ts @@ -22,7 +22,7 @@ export const addDevCommand = (program: Command) => { .description('Watch for source code changes in development mode') .option( '--src ', - `Path to source (default: /src/index.{ts|js})` + `Path to source (default: /src/index.{ts|js})`, ) .option('--dist ', `Path to dist (default: /dist/index.js)`) .option('--host', 'PocketBase host', DEFAULT_PB_DEV_URL) diff --git a/packages/cli/src/commands/publish.ts b/packages/cli/src/commands/publish.ts index 7da70c17..5a3a29ee 100644 --- a/packages/cli/src/commands/publish.ts +++ b/packages/cli/src/commands/publish.ts @@ -70,7 +70,7 @@ export const addPublishCommand = (program: Command) => { .description('Publish JS bundle to PBScript-enabled PocketBase instance') .option( '--dist ', - `Path to dist bundle (default: /dist/index.js)` + `Path to dist bundle (default: /dist/index.js)`, ) .option('--host ', `PocketBase host (default: ${DEFAULT_PB_DEV_URL})`) .action(async (options) => { diff --git a/packages/cli/src/helpers/buildQueryFilter.ts b/packages/cli/src/helpers/buildQueryFilter.ts index 91f84194..7cf4ad72 100644 --- a/packages/cli/src/helpers/buildQueryFilter.ts +++ b/packages/cli/src/helpers/buildQueryFilter.ts @@ -6,7 +6,7 @@ export type FieldStruct = Partial<{ }> export const buildQueryFilter = ( - fields: FieldStruct + fields: FieldStruct, ): Pb_QueryParams => { const filter = map(fields, (v, k) => `${k.toString()} = "${v}"`).join(' and ') return { filter } diff --git a/packages/cli/src/helpers/getOne.ts b/packages/cli/src/helpers/getOne.ts index 846ec8ba..ddafe39c 100644 --- a/packages/cli/src/helpers/getOne.ts +++ b/packages/cli/src/helpers/getOne.ts @@ -5,14 +5,14 @@ import { Pb_Any_Record_Db, Pb_Untrusted_Db, } from '../schema/base' -import { buildQueryFilter, FieldStruct } from './buildQueryFilter' +import { FieldStruct, buildQueryFilter } from './buildQueryFilter' export const getOne = async < TRec extends Pb_Any_Record_Db, - TFields extends FieldStruct = FieldStruct + TFields extends FieldStruct = FieldStruct, >( collectionName: Pb_Any_Collection_Name, - fields: TFields + fields: TFields, ) => { const queryParams = buildQueryFilter(fields) const recs = await client.records.getList(collectionName, 1, 2, queryParams) diff --git a/packages/cli/src/helpers/mergeDeep.ts b/packages/cli/src/helpers/mergeDeep.ts index 661c4192..8ea281b9 100644 --- a/packages/cli/src/helpers/mergeDeep.ts +++ b/packages/cli/src/helpers/mergeDeep.ts @@ -6,14 +6,14 @@ export const mergeDeep = (dst: any, src: TObject) => { if (dst[k] === undefined) dst[k] = {} if (!isObject(dst[k])) { throw new Error( - `${k.toString()} is an object in default, but not in target` + `${k.toString()} is an object in default, but not in target`, ) } dst[k] = mergeDeep(dst[k], v) } else { if (isObject(dst[k])) { throw new Error( - `${k.toString()} is an object in target, but not in default` + `${k.toString()} is an object in target, but not in default`, ) } // The magic: if the target has no value for this field, use the diff --git a/packages/cli/src/helpers/onAuthStateChanged.ts b/packages/cli/src/helpers/onAuthStateChanged.ts index ae204d7c..540426e6 100644 --- a/packages/cli/src/helpers/onAuthStateChanged.ts +++ b/packages/cli/src/helpers/onAuthStateChanged.ts @@ -2,7 +2,7 @@ import { UnsubFunc } from 'store/backend/types' import { client } from '../client' export const onAuthStateChanged = ( - cb: (user: typeof client.authStore.model) => void + cb: (user: typeof client.authStore.model) => void, ): UnsubFunc => { setTimeout(() => cb(client.authStore.model), 0) return client.authStore.onChange(() => { diff --git a/packages/cli/src/helpers/upsert.ts b/packages/cli/src/helpers/upsert.ts index f1c9a9b3..7c04f8f4 100644 --- a/packages/cli/src/helpers/upsert.ts +++ b/packages/cli/src/helpers/upsert.ts @@ -8,14 +8,14 @@ import { Pb_Untrusted_Db, Pb_UserFields, } from '../schema/base' -import { buildQueryFilter, FieldStruct } from './buildQueryFilter' +import { FieldStruct, buildQueryFilter } from './buildQueryFilter' import { mergeDeep } from './mergeDeep' export const upsert = async ( collectionName: Pb_Any_Collection_Name, filterFields: FieldStruct, mutate: (draft: Draft>) => void, - defaultRec: Pb_UserFields + defaultRec: Pb_UserFields, ) => { const queryParams = buildQueryFilter(filterFields) const recs = await client.records.getList(collectionName, 1, 2, queryParams) @@ -42,7 +42,7 @@ export const upsert = async ( } return carry }, - {} as Partial> + {} as Partial>, ) client.records.update(collectionName, id, final) } diff --git a/packages/cli/src/providers/CustomAuthStore.ts b/packages/cli/src/providers/CustomAuthStore.ts index 2ef57786..825a1606 100644 --- a/packages/cli/src/providers/CustomAuthStore.ts +++ b/packages/cli/src/providers/CustomAuthStore.ts @@ -50,7 +50,7 @@ export class CustomAuthStore extends BaseAuthStore { } exportToCookie( options?: SerializeOptions | undefined, - key?: string | undefined + key?: string | undefined, ): string { throw new Error(`Unsupported exportToCookie()`) } diff --git a/packages/cli/src/util/assert.ts b/packages/cli/src/util/assert.ts index e5fc23b3..c3eb4bcf 100644 --- a/packages/cli/src/util/assert.ts +++ b/packages/cli/src/util/assert.ts @@ -1,6 +1,6 @@ export function assertExists( v: TType, - message = `Value does not exist` + message = `Value does not exist`, ): asserts v is NonNullable { if (typeof v === 'undefined') { throw new Error(message) diff --git a/packages/cli/src/util/ensureAdminClient.ts b/packages/cli/src/util/ensureAdminClient.ts index 63d1f77c..48156d56 100644 --- a/packages/cli/src/util/ensureAdminClient.ts +++ b/packages/cli/src/util/ensureAdminClient.ts @@ -20,11 +20,11 @@ export type ConnectionConfig = { export const ensureAdminClient = async ( slug: string, - config: ConnectionConfig + config: ConnectionConfig, ) => { const saver = mkProjectSaver(slug) const client = pbClient(config, (session) => - saver((config) => ({ ...config, session })) + saver((config) => ({ ...config, session })), ) const _isAdmin = await isAdmin(client) if (_isAdmin) { @@ -34,7 +34,7 @@ export const ensureAdminClient = async ( const { host } = config console.log( - `You must be logged in to ${host}/_ as a PocketBase admin to continue.` + `You must be logged in to ${host}/_ as a PocketBase admin to continue.`, ) while (true) { @@ -55,7 +55,7 @@ export const ensureAdminClient = async ( value.length > 0 ? true : `Enter a password`, }, ], - { onCancel: () => die(`Exited.`) } + { onCancel: () => die(`Exited.`) }, ) const { username, password } = response try { diff --git a/packages/cli/src/util/pbClient.ts b/packages/cli/src/util/pbClient.ts index dc36a8cd..12ef46b1 100644 --- a/packages/cli/src/util/pbClient.ts +++ b/packages/cli/src/util/pbClient.ts @@ -9,13 +9,13 @@ import { ConnectionConfig } from './ensureAdminClient' export const pbClient = ( config: ConnectionConfig, - saver: SessionStateSaver + saver: SessionStateSaver, ) => { const { host, session } = config const client = new PocketBase( host, 'en-US', - new CustomAuthStore(session, saver) + new CustomAuthStore(session, saver), ) return client } @@ -31,7 +31,7 @@ export const isAdmin = async (client: pocketbaseEs) => { export const adminPbClient = async ( config: ConnectionConfig, - saver: SessionStateSaver + saver: SessionStateSaver, ) => { const client = pbClient(config, saver) if (!client.authStore.isValid) { diff --git a/packages/common/src/CleanupManager.ts b/packages/common/src/CleanupManager.ts index f62bf9ec..7ddc31b5 100644 --- a/packages/common/src/CleanupManager.ts +++ b/packages/common/src/CleanupManager.ts @@ -38,10 +38,10 @@ export const createCleanupManager = (slug?: string) => { (c, v) => { return c.then(() => v()) }, - Promise.resolve() + Promise.resolve(), ).catch((e) => { error( - `Cleanup functions are failing. This should never happen, check all cleanup functions to make sure they are trapping their exceptions.` + `Cleanup functions are failing. This should never happen, check all cleanup functions to make sure they are trapping their exceptions.`, ) throw e }) diff --git a/packages/common/src/Logger.ts b/packages/common/src/Logger.ts index 9d2a23b3..c84fa4c4 100644 --- a/packages/common/src/Logger.ts +++ b/packages/common/src/Logger.ts @@ -58,7 +58,7 @@ export const createLogger = (config: Partial) => { return JSON.stringify(arg) } return arg - }) + }), ) } @@ -89,7 +89,7 @@ export const createLogger = (config: Partial) => { ;[..._buf.slice(_curIdx, MAX_BUF), ..._buf.slice(0, _curIdx)].forEach( (args) => { console.error(...args) - } + }, ) console.error(`========== ERROR TRACEBACK END ==============`) } diff --git a/packages/common/src/assert.ts b/packages/common/src/assert.ts index aa052949..4b631cc3 100644 --- a/packages/common/src/assert.ts +++ b/packages/common/src/assert.ts @@ -1,6 +1,6 @@ export function assertExists( v: TType, - message = `Value does not exist` + message = `Value does not exist`, ): asserts v is NonNullable { if (typeof v === 'undefined') { throw new Error(message) @@ -9,7 +9,7 @@ export function assertExists( export function assertTruthy( v: unknown, - message = `Value should be truthy` + message = `Value should be truthy`, ): asserts v is NonNullable { if (!v) { throw new Error(message) diff --git a/packages/common/src/asyncExecutionGuard.ts b/packages/common/src/asyncExecutionGuard.ts index cd31a4d3..1ee5fd65 100644 --- a/packages/common/src/asyncExecutionGuard.ts +++ b/packages/common/src/asyncExecutionGuard.ts @@ -5,10 +5,10 @@ import { SetReturnType } from 'type-fest' const limiters: { [lane: string]: Bottleneck } = {} export const serialAsyncExecutionGuard = < - T extends (...args: any[]) => Promise + T extends (...args: any[]) => Promise, >( cb: T, - lane?: SetReturnType + lane?: SetReturnType, ): T => { const uuid = uniqueId() const _lane = lane || (() => uuid) @@ -27,10 +27,10 @@ export const serialAsyncExecutionGuard = < const singletons: { [_: string]: Promise } = {} export const singletonAsyncExecutionGuard = < - T extends (...args: any[]) => Promise + T extends (...args: any[]) => Promise, >( cb: T, - key: SetReturnType + key: SetReturnType, ): T => { const uuid = uniqueId() const keyFactory = key || (() => uuid) diff --git a/packages/common/src/events.ts b/packages/common/src/events.ts index 68837f91..10d5b0fa 100644 --- a/packages/common/src/events.ts +++ b/packages/common/src/events.ts @@ -3,15 +3,15 @@ import { values } from '@s-libs/micro-dash' export type Unsubscribe = () => void export type EventSubscriber = ( - cb: EventHandler + cb: EventHandler, ) => Unsubscribe export type EventEmitter = ( payload: TPayload, - stopOnHandled?: boolean + stopOnHandled?: boolean, ) => Promise export type EventHandler = ( payload: TPayload, - isHandled: boolean + isHandled: boolean, ) => boolean | void | Promise /** @@ -20,7 +20,7 @@ export type EventHandler = ( * @returns void */ export const createEvent = ( - defaultHandler?: EventHandler + defaultHandler?: EventHandler, ): [EventSubscriber, EventEmitter] => { let i = 0 const callbacks: any = {} diff --git a/packages/common/src/index.ts b/packages/common/src/index.ts index 2c2bfb0f..bf1ede4e 100644 --- a/packages/common/src/index.ts +++ b/packages/common/src/index.ts @@ -1,11 +1,11 @@ +export * from './CleanupManager' +export * from './Logger' +export * from './TimerManager' export * from './assert' export * from './asyncExecutionGuard' -export * from './CleanupManager' export * from './events' -export * from './Logger' export * from './mkSingleton' export * from './newId' export * from './pocketbase-client-helpers' export * from './safeCatch' export * from './schema' -export * from './TimerManager' diff --git a/packages/common/src/mkSingleton.ts b/packages/common/src/mkSingleton.ts index e6cbe52a..555958d1 100644 --- a/packages/common/src/mkSingleton.ts +++ b/packages/common/src/mkSingleton.ts @@ -10,9 +10,9 @@ export type SingletonBaseConfig = { export const mkSingleton = < TConfig, - TApi extends SingletonApi | Promise + TApi extends SingletonApi | Promise, >( - factory: (config: TConfig) => TApi + factory: (config: TConfig) => TApi, ) => { let _service: TApi | undefined = undefined return (config?: TConfig) => { diff --git a/packages/common/src/pocketbase-client-helpers/RpcHelper.ts b/packages/common/src/pocketbase-client-helpers/RpcHelper.ts index 03e4a313..2ebf0936 100644 --- a/packages/common/src/pocketbase-client-helpers/RpcHelper.ts +++ b/packages/common/src/pocketbase-client-helpers/RpcHelper.ts @@ -6,11 +6,11 @@ import { logger } from '../Logger' import { newId } from '../newId' import { safeCatch } from '../safeCatch' import { + RPC_COLLECTION, RpcCommands, RpcFields, RpcRecord_Create, RpcStatus, - RPC_COLLECTION, } from '../schema' import type { WatchHelper } from './WatchHelper' @@ -30,7 +30,7 @@ export const createRpcHelper = (config: RpcHelperConfig) => { const mkRpc = ( cmd: RpcCommands, - schema: JSONSchemaType + schema: JSONSchemaType, ) => { type ConcreteRpcRecord = RpcFields const validator = new Ajv().compile(schema) @@ -39,7 +39,7 @@ export const createRpcHelper = (config: RpcHelperConfig) => { logger(), async ( payload: TPayload, - cb?: (data: RecordSubscription) => void + cb?: (data: RecordSubscription) => void, ) => { const _rpcLogger = _logger.create(cmd) const { dbg, error } = _rpcLogger @@ -82,7 +82,7 @@ export const createRpcHelper = (config: RpcHelperConfig) => { reject(new ClientResponseError(data.record.result)) } }, - { initialFetch: false, pollIntervalMs: 100 } + { initialFetch: false, pollIntervalMs: 100 }, ) dbg(`Creating ${rpcIn.id}`) const newRpc = await client.collection(RPC_COLLECTION).create(rpcIn) @@ -92,7 +92,7 @@ export const createRpcHelper = (config: RpcHelperConfig) => { reject(e) }) }) - } + }, ) } diff --git a/packages/common/src/pocketbase-client-helpers/WatchHelper.ts b/packages/common/src/pocketbase-client-helpers/WatchHelper.ts index 6149822d..05130cae 100644 --- a/packages/common/src/pocketbase-client-helpers/WatchHelper.ts +++ b/packages/common/src/pocketbase-client-helpers/WatchHelper.ts @@ -1,9 +1,9 @@ import type pocketbaseEs from 'pocketbase' import type { RecordSubscription, UnsubscribeFunc } from 'pocketbase' import { logger } from '../Logger' +import { UnixTimestampMs, createTimerManager } from '../TimerManager' import { safeCatch } from '../safeCatch' import { BaseFields, RecordId } from '../schema' -import { createTimerManager, UnixTimestampMs } from '../TimerManager' export type WatchHelperConfig = { client: pocketbaseEs @@ -23,7 +23,7 @@ export const createWatchHelper = (config: WatchHelperConfig) => { collectionName: string, id: RecordId, cb: (data: RecordSubscription, unsub: UnsubscribeFunc) => void, - options?: Partial + options?: Partial, ): Promise => { const { dbg } = logger().create(`watchById:${collectionName}:${id}`) const config: WatchConfig = { @@ -89,7 +89,7 @@ export const createWatchHelper = (config: WatchHelperConfig) => { idName: keyof TRec, idValue: RecordId, cb: (data: RecordSubscription) => void, - initialFetch = true + initialFetch = true, ): Promise => { let hasUpdate: { [_: RecordId]: boolean } = {} const unsub = client @@ -112,7 +112,7 @@ export const createWatchHelper = (config: WatchHelperConfig) => { }) } return unsub - } + }, ) return { watchById, watchAllById } diff --git a/packages/common/src/safeCatch.ts b/packages/common/src/safeCatch.ts index 8bb80a8f..478544cd 100644 --- a/packages/common/src/safeCatch.ts +++ b/packages/common/src/safeCatch.ts @@ -9,7 +9,7 @@ export const safeCatch = ( name: string, logger: Logger, cb: (...args: TIn) => Promise, - timeoutMs = SAFECATCH_TTL_MS + timeoutMs = SAFECATCH_TTL_MS, ): ((...args: TIn) => Promise) => { return async (...args: TIn) => { const uuid = `${name}:${nanoid()}` @@ -29,17 +29,17 @@ export const safeCatch = ( if (e instanceof ClientResponseError) { if (e.status === 400) { dbg( - `PocketBase API error: It looks like you don't have permission to make this request. Raw error: ${e}. Payload: ${payload}` + `PocketBase API error: It looks like you don't have permission to make this request. Raw error: ${e}. Payload: ${payload}`, ) } else if (e.status === 0) { dbg( - `Client request aborted (possible duplicate request or real error). Raw error: ${e}. Payload: ${payload}` + `Client request aborted (possible duplicate request or real error). Raw error: ${e}. Payload: ${payload}`, ) } else if (e.status === 404) { dbg(`Record not found. Raw error: ${e}. Payload: ${payload}`) } else { dbg( - `Unknown PocketBase API error. Raw error: ${e}. Payload: ${payload}` + `Unknown PocketBase API error. Raw error: ${e}. Payload: ${payload}`, ) } } else { diff --git a/packages/common/src/schema/Rpc/index.ts b/packages/common/src/schema/Rpc/index.ts index a497f7ce..5e7ece5d 100644 --- a/packages/common/src/schema/Rpc/index.ts +++ b/packages/common/src/schema/Rpc/index.ts @@ -34,7 +34,7 @@ export type RpcPayloadBase = JsonObject export type RpcFields< TPayload extends RpcPayloadBase, - TRes extends JsonObject + TRes extends JsonObject, > = BaseFields & { userId: UserId cmd: string diff --git a/packages/common/src/schema/index.ts b/packages/common/src/schema/index.ts index 03e52d6f..d6f06510 100644 --- a/packages/common/src/schema/index.ts +++ b/packages/common/src/schema/index.ts @@ -3,7 +3,7 @@ export * from './Instance' export * from './InstanceLog' export * from './Invocation' export * from './Rpc' -export * from './types' export * from './User' +export * from './types' export * from './util' // gen:export diff --git a/packages/daemon/package.json b/packages/daemon/package.json index 4f641809..e2a3500e 100644 --- a/packages/daemon/package.json +++ b/packages/daemon/package.json @@ -36,10 +36,9 @@ "pocketbase": "^0.8.0", "semver": "^7.3.8", "sqlite": "^4.1.2", - "sqlite3": "^5.1.2", + "sqlite3": "^5.1.6", "tmp": "^0.2.1", "type-fest": "^3.3.0", - "url-pattern": "^1.0.3", - "tsx": "^3.11.0" + "url-pattern": "^1.0.3" } } \ No newline at end of file diff --git a/packages/daemon/src/constants.ts b/packages/daemon/src/constants.ts index 42737a37..29d675fa 100644 --- a/packages/daemon/src/constants.ts +++ b/packages/daemon/src/constants.ts @@ -25,7 +25,7 @@ export const DAEMON_PB_MIGRATIONS_DIR = (() => { const v = env('DAEMON_PB_MIGRATIONS_DIR') if (!v) { throw new Error( - `DAEMON_PB_MIGRATIONS_DIR (${v}) environment variable must be specified` + `DAEMON_PB_MIGRATIONS_DIR (${v}) environment variable must be specified`, ) } if (!existsSync(v)) { @@ -38,7 +38,7 @@ export const DAEMON_PB_DATA_DIR = (() => { const v = env('DAEMON_PB_DATA_DIR') if (!v) { throw new Error( - `DAEMON_PB_DATA_DIR (${v}) environment variable must be specified` + `DAEMON_PB_DATA_DIR (${v}) environment variable must be specified`, ) } if (!existsSync(v)) { @@ -56,12 +56,12 @@ export const DAEMON_MAX_PORTS = envi(`DAEMON_MAX_PORTS`, 500) export const DAEMON_PB_BACKUP_SLEEP = envi(`DAEMON_PB_BACKUP_SLEEP`, 100) export const DAEMON_PB_BACKUP_PAGE_COUNT = envi( `DAEMON_PB_BACKUP_PAGE_COUNT`, - 5 + 5, ) export const PH_BIN_CACHE = env( `PH_BIN_CACHE`, - join(__dirname, `../../../.pbincache`) + join(__dirname, `../../../.pbincache`), ) export const PH_FTP_PORT = envi('PH_FTP_PORT', 21) diff --git a/packages/daemon/src/server.ts b/packages/daemon/src/server.ts index 88b7ea59..694201b7 100644 --- a/packages/daemon/src/server.ts +++ b/packages/daemon/src/server.ts @@ -25,6 +25,12 @@ import { portManager } from './services/PortManager' import { updaterService } from './services/UpdaterService/UpdaterService' // gen:import +const [major, minor, patch] = process.versions.node.split('.').map(Number) + +if ((major || 0) < 18) { + throw new Error(`Node 18 or higher required.`) +} + loggerService({ debug: DEBUG, trace: TRACE, errorTrace: !DEBUG }) // npm install eventsource --save @@ -74,7 +80,7 @@ global.EventSource = require('eventsource') error(`migrate had an unexpected stop. Check it out`) }, }, - { logger } + { logger }, ) ).exited info(`Migrating done`) @@ -91,7 +97,7 @@ global.EventSource = require('eventsource') error(`migrate had an unexpected stop. Check it out`) }, }, - { logger } + { logger }, ) /** diff --git a/packages/daemon/src/services/CentralDbService.ts b/packages/daemon/src/services/CentralDbService.ts index 05013cc2..6b08736e 100644 --- a/packages/daemon/src/services/CentralDbService.ts +++ b/packages/daemon/src/services/CentralDbService.ts @@ -20,15 +20,15 @@ export const centralDbService = mkSingleton( const target = coreInternalUrl dbg( - `Forwarding proxy request for ${req.url} to central instance ${target}` + `Forwarding proxy request for ${req.url} to central instance ${target}`, ) proxy.web(req, res, { target }) }, - `CentralDbService` + `CentralDbService`, ) return { shutdown() {}, } - } + }, ) diff --git a/packages/daemon/src/services/FtpService/FtpService.ts b/packages/daemon/src/services/FtpService/FtpService.ts index cc3d763b..bdf0a88a 100644 --- a/packages/daemon/src/services/FtpService/FtpService.ts +++ b/packages/daemon/src/services/FtpService/FtpService.ts @@ -7,7 +7,7 @@ import { SSL_KEY, } from '$constants' import { clientService, createPbClient } from '$services' -import { mkSingleton, SingletonBaseConfig } from '@pockethost/common' +import { SingletonBaseConfig, mkSingleton } from '@pockethost/common' import { readFileSync } from 'fs' import { FtpSrv } from 'ftp-srv' import { PhFs } from './PhFs' @@ -77,7 +77,7 @@ export const ftpService = mkSingleton((config: FtpConfig) => { reject(new Error(`Invalid username or password`)) return } - } + }, ) ftpServer.listen().then(() => { diff --git a/packages/daemon/src/services/FtpService/PhFs.ts b/packages/daemon/src/services/FtpService/PhFs.ts index 9bc0bc10..0e082060 100644 --- a/packages/daemon/src/services/FtpService/PhFs.ts +++ b/packages/daemon/src/services/FtpService/PhFs.ts @@ -3,24 +3,24 @@ import { assert } from '$util' import { InstanceFields, Logger } from '@pockethost/common' import { compact, map } from '@s-libs/micro-dash' import { + Mode, constants, createReadStream, createWriteStream, existsSync, mkdirSync, - Mode, } from 'fs' import { FileStat, FileSystem, FtpConnection } from 'ftp-srv' import { customAlphabet } from 'nanoid' import { isAbsolute, join, normalize, resolve, sep } from 'path' import { PocketbaseClientApi } from '../clientService/PbClient' -import * as fsAsync from './fs-async' import { FolderNames, INSTANCE_ROOT_FOLDER_NAMES, - isInstanceRootFolder, MAINTENANCE_ONLY_FOLDER_NAMES, + isInstanceRootFolder, } from './FtpService' +import * as fsAsync from './fs-async' const nanoid = customAlphabet(`abcdefghijklmnop`) @@ -51,7 +51,7 @@ export class PhFs implements FileSystem { constructor( connection: FtpConnection, client: PocketbaseClientApi, - logger: Logger + logger: Logger, ) { const cwd = `/` const root = DAEMON_PB_DATA_DIR @@ -109,12 +109,12 @@ export class PhFs implements FileSystem { dbg({ rootFolderName, instance }) if ( MAINTENANCE_ONLY_FOLDER_NAMES.includes( - rootFolderName as FolderNames + rootFolderName as FolderNames, ) && !instance.maintenance ) { throw new Error( - `Instance must be in maintenance mode to access ${rootFolderName}` + `Instance must be in maintenance mode to access ${rootFolderName}`, ) } fsPathParts.push(rootFolderName) @@ -122,7 +122,7 @@ export class PhFs implements FileSystem { const rootFolderFsPath = resolve( join(...fsPathParts) .replace(UNIX_SEP_REGEX, sep) - .replace(WIN_SEP_REGEX, sep) + .replace(WIN_SEP_REGEX, sep), ) if (!existsSync(rootFolderFsPath)) { mkdirSync(rootFolderFsPath) @@ -137,7 +137,7 @@ export class PhFs implements FileSystem { const fsPath = resolve( join(...fsPathParts) .replace(UNIX_SEP_REGEX, sep) - .replace(WIN_SEP_REGEX, sep) + .replace(WIN_SEP_REGEX, sep), ) // Create FTP client path using unix separator @@ -210,7 +210,7 @@ export class PhFs implements FileSystem { */ if (!instance) { throw new Error( - `Something as gone wrong. An instance without a subdomain is not possible.` + `Something as gone wrong. An instance without a subdomain is not possible.`, ) } @@ -247,7 +247,7 @@ export class PhFs implements FileSystem { }) }) .catch(() => null) - }) + }), ) }) .then(compact) @@ -322,7 +322,7 @@ export class PhFs implements FileSystem { async write( fileName: string, - options?: { append?: boolean | undefined; start?: any } | undefined + options?: { append?: boolean | undefined; start?: any } | undefined, ) { const { dbg, error } = this.log .create(`write`) @@ -366,7 +366,7 @@ export class PhFs implements FileSystem { async read( fileName: string, - options: { start?: any } | undefined + options: { start?: any } | undefined, ): Promise { const { dbg, error } = this.log .create(`read`) @@ -374,9 +374,8 @@ export class PhFs implements FileSystem { .breadcrumb(fileName) dbg(`read`) - const { fsPath, clientPath, pathFromRootFolder } = await this._resolvePath( - fileName - ) + const { fsPath, clientPath, pathFromRootFolder } = + await this._resolvePath(fileName) const { start } = options || {} @@ -433,9 +432,8 @@ export class PhFs implements FileSystem { .breadcrumb(path) dbg(`mkdir`) - const { fsPath, clientPath, pathFromRootFolder } = await this._resolvePath( - path - ) + const { fsPath, clientPath, pathFromRootFolder } = + await this._resolvePath(path) /* Disallow making directories if not inside root folder @@ -485,7 +483,7 @@ export class PhFs implements FileSystem { Promise.all([ this.restartInstanceGuard(fromRootFolderName, instance), this.restartInstanceGuard(toRootFolderName, instance), - ]) + ]), ) } @@ -497,9 +495,8 @@ export class PhFs implements FileSystem { .breadcrumb(mode.toString()) dbg(`chmod`) - const { fsPath, clientPath, pathFromRootFolder } = await this._resolvePath( - path - ) + const { fsPath, clientPath, pathFromRootFolder } = + await this._resolvePath(path) /* Disallow making directories if not inside root folder @@ -517,7 +514,7 @@ export class PhFs implements FileSystem { async restartInstanceGuard( rootFolderName: FolderNames | undefined, - instance: InstanceFields + instance: InstanceFields, ) { // Not needed? // const { dbg, error } = this.log diff --git a/packages/daemon/src/services/FtpService/fs-async.ts b/packages/daemon/src/services/FtpService/fs-async.ts index 5da1537a..20eebe80 100644 --- a/packages/daemon/src/services/FtpService/fs-async.ts +++ b/packages/daemon/src/services/FtpService/fs-async.ts @@ -10,4 +10,4 @@ const mkdir = promisify(fs.mkdir) const rename = promisify(fs.rename) const chmod = promisify(fs.chmod) -export { stat, readdir, access, unlink, rmdir, mkdir, rename, chmod } +export { access, chmod, mkdir, readdir, rename, rmdir, stat, unlink } diff --git a/packages/daemon/src/services/InstanceLoggerService/SqliteLogger.ts b/packages/daemon/src/services/InstanceLoggerService/SqliteLogger.ts index 1c87240f..1def1b89 100644 --- a/packages/daemon/src/services/InstanceLoggerService/SqliteLogger.ts +++ b/packages/daemon/src/services/InstanceLoggerService/SqliteLogger.ts @@ -2,11 +2,11 @@ import { SqliteChangeEvent, sqliteService } from '$services' import { InstanceLogFields, InstanceLogFields_Create, + RecordId, + StreamNames, newId, pocketNow, - RecordId, safeCatch, - StreamNames, } from '@pockethost/common' import knex from 'knex' import { AsyncReturnType } from 'type-fest' @@ -15,7 +15,7 @@ import { DaemonContext } from './DaemonContext' export type SqliteLogger = AsyncReturnType export const createSqliteLogger = async ( logDbPath: string, - context: DaemonContext + context: DaemonContext, ) => { const { parentLogger } = context const _dbLogger = parentLogger.create(`${logDbPath}`) @@ -46,7 +46,7 @@ export const createSqliteLogger = async ( const sql = conn('logs').insert(_in).toString() trace(`Writing log ${JSON.stringify(_in)} ${sql}`) await db.exec(sql) - } + }, ) const subscribe = (cb: (e: SqliteChangeEvent) => void) => { @@ -66,7 +66,7 @@ export const createSqliteLogger = async ( const fetch = async (limit: number = 100) => { return db.all( - `select * from logs order by created desc limit ${limit}` + `select * from logs order by created desc limit ${limit}`, ) } diff --git a/packages/daemon/src/services/InstanceLoggerService/index.ts b/packages/daemon/src/services/InstanceLoggerService/index.ts index 2f007267..7fa059de 100644 --- a/packages/daemon/src/services/InstanceLoggerService/index.ts +++ b/packages/daemon/src/services/InstanceLoggerService/index.ts @@ -17,7 +17,7 @@ const instances: { export const createInstanceLogger = async ( instanceId: InstanceId, - context: DaemonContext + context: DaemonContext, ) => { const { parentLogger } = context const _instanceLogger = parentLogger.create(`InstanceLogger`) @@ -31,7 +31,7 @@ export const createInstanceLogger = async ( DAEMON_PB_DATA_DIR, instanceId, 'pb_data', - 'instance_logs.db' + 'instance_logs.db', ) dbg(`logs path`, logDbPath) @@ -69,5 +69,5 @@ export const instanceLoggerService = mkSingleton( dbg(`Shutting down`) }, } - } + }, ) diff --git a/packages/daemon/src/services/InstanceService/Deno/DenoProcess.ts b/packages/daemon/src/services/InstanceService/Deno/DenoProcess.ts index 2c3a5c19..58a9a719 100644 --- a/packages/daemon/src/services/InstanceService/Deno/DenoProcess.ts +++ b/packages/daemon/src/services/InstanceService/Deno/DenoProcess.ts @@ -43,7 +43,7 @@ export const createDenoProcess = async (config: DenoProcessConfig) => { const denoWrite = ( message: string, - stream: StreamNames = StreamNames.Info + stream: StreamNames = StreamNames.Info, ) => { dbg(`[${instance.id}:${path}:${stream}] ${message}`) return denoLogger.write(message, stream) @@ -76,12 +76,12 @@ export const createDenoProcess = async (config: DenoProcessConfig) => { if (code) { await denoWrite( `Unexpected 'deno' exit code: ${code}.`, - StreamNames.Error + StreamNames.Error, ) } else { await denoWrite( `Worker has exited with code ${code}`, - StreamNames.System + StreamNames.System, ) } resolve() diff --git a/packages/daemon/src/services/InstanceService/InstanceService.ts b/packages/daemon/src/services/InstanceService/InstanceService.ts index 5892fe85..2670f8ef 100644 --- a/packages/daemon/src/services/InstanceService/InstanceService.ts +++ b/packages/daemon/src/services/InstanceService/InstanceService.ts @@ -111,13 +111,13 @@ export const instanceService = mkSingleton( const { id, subdomain, version } = instance const systemInstanceLogger = instanceServiceLogger.create( - `${subdomain}:${id}:${version}` + `${subdomain}:${id}:${version}`, ) const { dbg, warn, error, info } = systemInstanceLogger if (instanceApis[id]) { throw new Error( - `Attempted to create an instance API when one is already available for ${id}` + `Attempted to create an instance API when one is already available for ${id}`, ) } @@ -154,7 +154,7 @@ export const instanceService = mkSingleton( internalUrl: () => { if (status !== InstanceApiStatus.Healthy) { throw new Error( - `Attempt to access instance URL when instance is not in a healthy state.` + `Attempt to access instance URL when instance is not in a healthy state.`, ) } return internalUrl @@ -162,7 +162,7 @@ export const instanceService = mkSingleton( startRequest: () => { if (status !== InstanceApiStatus.Healthy) { throw new Error( - `Attempt to start an instance request when instance is not in a healthy state.` + `Attempt to start an instance request when instance is not in a healthy state.`, ) } return startRequest() @@ -193,7 +193,7 @@ export const instanceService = mkSingleton( const healthyGuard = () => { if (status !== InstanceApiStatus.ShuttingDown) return throw new Error( - `HealthyGuard detected instance is shutting down. Aborting further initialization.` + `HealthyGuard detected instance is shutting down. Aborting further initialization.`, ) } @@ -202,7 +202,7 @@ export const instanceService = mkSingleton( */ const clientLimiter = new Bottleneck({ maxConcurrent: 1 }) const updateInstanceStatus = clientLimiter.wrap( - client.updateInstanceStatus + client.updateInstanceStatus, ) const updateInstance = clientLimiter.wrap(client.updateInstance) const createInvocation = clientLimiter.wrap(client.createInvocation) @@ -235,15 +235,15 @@ export const instanceService = mkSingleton( instance.id, { parentLogger: systemInstanceLogger, - } + }, ) const writeUserLog = serialAsyncExecutionGuard( userInstanceLogger.write, - () => `${instance.id}:userLog` + () => `${instance.id}:userLog`, ) shutdownManager.add(() => - writeUserLog(`Shutting down instance`).catch(error) + writeUserLog(`Shutting down instance`).catch(error), ) /* @@ -272,7 +272,7 @@ export const instanceService = mkSingleton( version, onUnexpectedStop: (code, stdout, stderr) => { warn( - `PocketBase processes exited unexpectedly with ${code}. Putting in maintenance mode.` + `PocketBase processes exited unexpectedly with ${code}. Putting in maintenance mode.`, ) warn(stdout) warn(stderr) @@ -282,24 +282,24 @@ export const instanceService = mkSingleton( }) await writeUserLog( `Putting instance in maintenance mode because it shut down with return code ${code}. `, - StreamNames.Error + StreamNames.Error, ) await Promise.all( stdout.map((data) => - writeUserLog(data, StreamNames.Error).catch(error) - ) + writeUserLog(data, StreamNames.Error).catch(error), + ), ) await Promise.all( stderr.map((data) => - writeUserLog(data, StreamNames.Error).catch(error) - ) + writeUserLog(data, StreamNames.Error).catch(error), + ), ) }) setImmediate(() => { _safeShutdown( new Error( - `PocketBase processes exited unexpectedly with ${code}. Putting in maintenance mode.` - ) + `PocketBase processes exited unexpectedly with ${code}. Putting in maintenance mode.`, + ), ).catch(error) }) }, @@ -308,7 +308,7 @@ export const instanceService = mkSingleton( } catch (e) { warn(`Error spawning: ${e}`) throw new Error( - `Could not launch PocketBase ${instance.version}. It may be time to upgrade.` + `Could not launch PocketBase ${instance.version}. It may be time to upgrade.`, ) } })() @@ -340,7 +340,7 @@ export const instanceService = mkSingleton( DAEMON_PB_DATA_DIR, instance.id, `worker`, - `index.ts` + `index.ts`, ) dbg(`Checking ${workerPath} for a worker entry point`) if (existsSync(workerPath)) { @@ -400,7 +400,7 @@ export const instanceService = mkSingleton( } return true }), - RECHECK_TTL + RECHECK_TTL, ) } @@ -413,7 +413,7 @@ export const instanceService = mkSingleton( warn(`_pingInvocation failed with ${e}`) return true }), - 1000 + 1000, ) } @@ -437,7 +437,7 @@ export const instanceService = mkSingleton( .catch((e: ClientResponseError) => { if (e.status !== 404) { throw new Error( - `Unexpected response ${JSON.stringify(e)} from mothership` + `Unexpected response ${JSON.stringify(e)} from mothership`, ) } return [] @@ -450,7 +450,7 @@ export const instanceService = mkSingleton( { dbg(`Trying to get instance by subdomain: ${idOrSubdomain}`) const [instance, owner] = await client.getInstanceBySubdomain( - idOrSubdomain + idOrSubdomain, ) if (instance && owner) { dbg(`${idOrSubdomain} is a subdomain`) @@ -472,14 +472,14 @@ export const instanceService = mkSingleton( if (instanceIdOrSubdomain === PUBLIC_APP_DB) return const { instance, owner } = await getInstanceByIdOrSubdomain( - instanceIdOrSubdomain + instanceIdOrSubdomain, ) if (!owner) { throw new Error(`Instance owner is invalid`) } if (!instance) { throw new Error( - `Subdomain ${instanceIdOrSubdomain} does not resolve to an instance` + `Subdomain ${instanceIdOrSubdomain} does not resolve to an instance`, ) } @@ -489,7 +489,7 @@ export const instanceService = mkSingleton( dbg(`Checking for maintenance mode`) if (instance.maintenance) { throw new Error( - `This instance is in Maintenance Mode. See https://pockethost.gitbook.io/manual/daily-usage/maintenance for more information.` + `This instance is in Maintenance Mode. See https://pockethost.gitbook.io/manual/daily-usage/maintenance for more information.`, ) } @@ -499,7 +499,7 @@ export const instanceService = mkSingleton( dbg(`Checking for verified account`) if (!owner?.verified) { throw new Error( - `Log in at ${PUBLIC_APP_PROTOCOL}://${PUBLIC_APP_DOMAIN} to verify your account.` + `Log in at ${PUBLIC_APP_PROTOCOL}://${PUBLIC_APP_DOMAIN} to verify your account.`, ) } @@ -513,12 +513,12 @@ export const instanceService = mkSingleton( dbg( `Forwarding proxy request for ${ req.url - } to instance ${api.internalUrl()}` + } to instance ${api.internalUrl()}`, ) proxy.web(req, res, { target: api.internalUrl() }) }, - `InstanceService` + `InstanceService`, ) const { getNextPort } = await portManager() @@ -532,5 +532,5 @@ export const instanceService = mkSingleton( const getInstanceApiIfExistsById = (id: InstanceId) => instanceApis[id] return { shutdown, getInstanceApiIfExistsById } - } + }, ) diff --git a/packages/daemon/src/services/PocketBaseService.ts b/packages/daemon/src/services/PocketBaseService.ts index f1dab819..6d5f07a9 100644 --- a/packages/daemon/src/services/PocketBaseService.ts +++ b/packages/daemon/src/services/PocketBaseService.ts @@ -2,8 +2,8 @@ import { DAEMON_PB_DATA_DIR, DAEMON_PB_MIGRATIONS_DIR } from '$constants' import { mkInternalAddress, mkInternalUrl, tryFetch } from '$util' import { createCleanupManager, createTimerManager } from '@pockethost/common' import { - mkSingleton, SingletonBaseConfig, + mkSingleton, } from '@pockethost/common/src/mkSingleton' import { spawn } from 'child_process' import { existsSync } from 'fs' @@ -23,7 +23,7 @@ export type SpawnConfig = { onUnexpectedStop: ( code: number | null, stdout: string[], - stderr: string[] + stderr: string[], ) => void } export type PocketbaseServiceApi = AsyncReturnType< @@ -49,7 +49,7 @@ function pidIsRunning(pid: number) { } export const createPocketbaseService = async ( - config: PocketbaseServiceConfig + config: PocketbaseServiceConfig, ) => { const { logger } = config const _serviceLogger = logger.create('PocketbaseService') @@ -77,7 +77,7 @@ export const createPocketbaseService = async ( const bin = realVersion.binPath if (!existsSync(bin)) { throw new Error( - `PocketBase binary (${bin}) not found. Contact pockethost.io.` + `PocketBase binary (${bin}) not found. Contact pockethost.io.`, ) } @@ -93,7 +93,7 @@ export const createPocketbaseService = async ( args.push( isMothership ? DAEMON_PB_MIGRATIONS_DIR - : `${DAEMON_PB_DATA_DIR}/${slug}/pb_migrations` + : `${DAEMON_PB_DATA_DIR}/${slug}/pb_migrations`, ) } if (command === 'serve') { @@ -157,7 +157,7 @@ export const createPocketbaseService = async ( const { pid } = ls if (!pid) { throw new Error( - `Attempt to kill a PocketBase process that was never running.` + `Attempt to kill a PocketBase process that was never running.`, ) } const p = new Promise((resolve, reject) => { diff --git a/packages/daemon/src/services/PortManager.ts b/packages/daemon/src/services/PortManager.ts index 2a1c5da7..6a740377 100644 --- a/packages/daemon/src/services/PortManager.ts +++ b/packages/daemon/src/services/PortManager.ts @@ -38,8 +38,8 @@ export const portManager = mkSingleton(async (cfg: PortManagerConfig) => { const removed = remove(exclude, (v) => v === newPort) dbg( `Removed ${removed.join(',')} from excluded ports: ${exclude.join( - ',' - )}` + ',', + )}`, ) }, ] diff --git a/packages/daemon/src/services/ProxyService.ts b/packages/daemon/src/services/ProxyService.ts index 8fb8acbc..d8fbb8ac 100644 --- a/packages/daemon/src/services/ProxyService.ts +++ b/packages/daemon/src/services/ProxyService.ts @@ -22,7 +22,7 @@ export type ProxyMiddleware = ( proxy: Server host: string }, - logger: Logger + logger: Logger, ) => void | Promise export type ProxyServiceConfig = SingletonBaseConfig & { @@ -44,7 +44,7 @@ export const proxyService = mkSingleton(async (config: ProxyServiceConfig) => { dbg(`Incoming request ${req.method} ${req.headers.host}/${req.url}`) if (!req.headers.host?.endsWith(PUBLIC_APP_DOMAIN)) { warn( - `Request for ${req.headers.host} rejected because host does not end in ${PUBLIC_APP_DOMAIN}` + `Request for ${req.headers.host} rejected because host does not end in ${PUBLIC_APP_DOMAIN}`, ) res.writeHead(502, { 'Content-Type': `text/plain`, @@ -54,7 +54,7 @@ export const proxyService = mkSingleton(async (config: ProxyServiceConfig) => { } { const { warn } = _proxyLogger.create( - `${req.method} ${req.headers.host}/${req.url}` + `${req.method} ${req.headers.host}/${req.url}`, ) try { for (let i = 0; i < middleware.length; i++) { @@ -94,7 +94,7 @@ export const proxyService = mkSingleton(async (config: ProxyServiceConfig) => { subdomainFilter: string | ((subdomain: string) => boolean), urlFilters: string | string[], handler: ProxyMiddleware, - handlerName: string + handlerName: string, ) => { const _handlerLogger = _proxyLogger.create(`${handlerName}`) const { dbg, trace } = _handlerLogger @@ -149,7 +149,7 @@ export const proxyService = mkSingleton(async (config: ProxyServiceConfig) => { req, res, { host, subdomain, coreInternalUrl, proxy }, - _requestLogger + _requestLogger, ) }) } diff --git a/packages/daemon/src/services/RealtimeLog.ts b/packages/daemon/src/services/RealtimeLog.ts index 29970245..c00c8986 100644 --- a/packages/daemon/src/services/RealtimeLog.ts +++ b/packages/daemon/src/services/RealtimeLog.ts @@ -59,7 +59,7 @@ export const realtimeLog = mkSingleton(async (config: RealtimeLogConfig) => { res.setHeader('Access-Control-Allow-Methods', 'POST, OPTIONS') res.setHeader( 'Access-Control-Allow-Headers', - 'authorization,content-type,cache-control' + 'authorization,content-type,cache-control', ) res.setHeader('Access-Control-Max-Age', 86400) res.statusCode = 204 @@ -106,7 +106,7 @@ export const realtimeLog = mkSingleton(async (config: RealtimeLogConfig) => { .getOne(instanceId) if (!instance) { throw new Error( - `instanceId ${instanceId} not found for user ${user.id}` + `instanceId ${instanceId} not found for user ${user.id}`, ) } dbg(`Instance is `, instance) @@ -142,14 +142,14 @@ export const realtimeLog = mkSingleton(async (config: RealtimeLogConfig) => { const evt = mkEvent(`log`, record) trace( `Dispatching SSE log event from ${instance.subdomain} (${instance.id})`, - evt + evt, ) limiter.schedule(() => write(evt)).catch(error) }) req.on('close', () => { limiter.stop() dbg( - `SSE request for ${instance.subdomain} (${instance.id}) closed. Unsubscribing.` + `SSE request for ${instance.subdomain} (${instance.id}) closed. Unsubscribing.`, ) unsub() }) @@ -172,7 +172,7 @@ export const realtimeLog = mkSingleton(async (config: RealtimeLogConfig) => { const evt = mkEvent(`log`, rec) trace( `Dispatching SSE initial log event from ${instance.subdomain} (${instance.id})`, - evt + evt, ) return write(evt) }) @@ -186,7 +186,7 @@ export const realtimeLog = mkSingleton(async (config: RealtimeLogConfig) => { .catch(error) } }, - `RealtimeLogService` + `RealtimeLogService`, ) return { diff --git a/packages/daemon/src/services/RpcService/RpcService.ts b/packages/daemon/src/services/RpcService/RpcService.ts index 49025583..c27f253c 100644 --- a/packages/daemon/src/services/RpcService/RpcService.ts +++ b/packages/daemon/src/services/RpcService/RpcService.ts @@ -1,12 +1,12 @@ import { clientService } from '$services' import { - assertTruthy, - mkSingleton, + RPC_COMMANDS, RpcCommands, RpcFields, RpcStatus, - RPC_COMMANDS, SingletonBaseConfig, + assertTruthy, + mkSingleton, } from '@pockethost/common' import { isObject } from '@s-libs/micro-dash' import Ajv, { JSONSchemaType, ValidateFunction } from 'ajv' @@ -22,12 +22,12 @@ export type KnexApi = ReturnType export type CommandModuleInitializer = ( register: RpcServiceApi['registerCommand'], client: pocketbaseEs, - knex: KnexApi + knex: KnexApi, ) => void export type RpcRunner< TPayload extends JsonObject, - TResult extends JsonObject + TResult extends JsonObject, > = (job: RpcFields) => Promise export type RpcServiceConfig = SingletonBaseConfig & {} @@ -58,8 +58,8 @@ export const rpcService = mkSingleton(async (config: RpcServiceConfig) => { if (!RPC_COMMANDS.find((c) => c === cmd)) { throw new Error( `RPC command '${cmd}' is invalid. It must be one of: ${RPC_COMMANDS.join( - '|' - )}.` + '|', + )}.`, ) } return cmd as RpcCommands @@ -76,7 +76,7 @@ export const rpcService = mkSingleton(async (config: RpcServiceConfig) => { const { validate, run } = handler if (!validate(payload)) { throw new Error( - `Payload for ${cmd} fails validation: ${JSON.stringify(payload)}` + `Payload for ${cmd} fails validation: ${JSON.stringify(payload)}`, ) } dbg(`Running RPC ${rpc.id}`, rpc) @@ -115,11 +115,11 @@ export const rpcService = mkSingleton(async (config: RpcServiceConfig) => { const registerCommand = < TPayload extends JsonObject, - TResult extends JsonObject + TResult extends JsonObject, >( commandName: RpcCommands, schema: JSONSchemaType, - runner: RpcRunner + runner: RpcRunner, ) => { if (jobHandlers[commandName]) { throw new Error(`${commandName} job handler already registered.`) diff --git a/packages/daemon/src/services/RpcService/commands.ts b/packages/daemon/src/services/RpcService/commands.ts index 7ad3a660..e6365680 100644 --- a/packages/daemon/src/services/RpcService/commands.ts +++ b/packages/daemon/src/services/RpcService/commands.ts @@ -20,9 +20,9 @@ import { type SetInstanceMaintenanceResult, } from '@pockethost/common' import { valid, validRange } from 'semver' -import { clientService } from '../clientService/clientService' import { instanceService } from '../InstanceService/InstanceService' import { updaterService } from '../UpdaterService/UpdaterService' +import { clientService } from '../clientService/clientService' import { rpcService } from './RpcService' export const registerRpcCommands = async (logger: Logger) => { @@ -48,7 +48,7 @@ export const registerRpcCommands = async (logger: Logger) => { maintenance: false, }) return { instance } - } + }, ) registerCommand( @@ -65,7 +65,7 @@ export const registerRpcCommands = async (logger: Logger) => { } await client.updateInstance(instanceId, { version }) return { status: 'ok' } - } + }, ) registerCommand( @@ -76,7 +76,7 @@ export const registerRpcCommands = async (logger: Logger) => { const { instanceId, secrets } = payload await client.updateInstance(instanceId, { secrets }) return { status: 'ok' } - } + }, ) registerCommand( @@ -90,7 +90,7 @@ export const registerRpcCommands = async (logger: Logger) => { await client.updateInstance(instanceId, { subdomain }) dbg(`Instance updated successfully `) return {} - } + }, ) registerCommand( @@ -112,7 +112,7 @@ export const registerRpcCommands = async (logger: Logger) => { } } return {} - } + }, ) // gen:command diff --git a/packages/daemon/src/services/SqliteService/SqliteService.ts b/packages/daemon/src/services/SqliteService/SqliteService.ts index 215f0028..fafa71a2 100644 --- a/packages/daemon/src/services/SqliteService/SqliteService.ts +++ b/packages/daemon/src/services/SqliteService/SqliteService.ts @@ -5,13 +5,13 @@ import { serialAsyncExecutionGuard, SingletonBaseConfig, } from '@pockethost/common' -import { Database as SqliteDatabase, open } from 'sqlite' +import { open, Database as SqliteDatabase } from 'sqlite' import { Database } from 'sqlite3' import { JsonObject } from 'type-fest' export type SqliteUnsubscribe = () => void export type SqliteChangeHandler = ( - e: SqliteChangeEvent + e: SqliteChangeEvent, ) => void export type SqliteEventType = 'update' | 'insert' | 'delete' export type SqliteChangeEvent = { @@ -25,7 +25,7 @@ export type SqliteServiceApi = { migrate: SqliteDatabase['migrate'] exec: SqliteDatabase['exec'] subscribe: ( - cb: SqliteChangeHandler + cb: SqliteChangeHandler, ) => SqliteUnsubscribe } export type SqliteServiceConfig = SingletonBaseConfig & {} @@ -43,7 +43,7 @@ export const sqliteService = mkSingleton((config: SqliteServiceConfig) => { This function */ const _unsafe_getDatabase = async ( - filename: string + filename: string, ): Promise => { const _dbLogger = logger.create(`SqliteService`) _dbLogger.breadcrumb(filename) @@ -62,7 +62,7 @@ export const sqliteService = mkSingleton((config: SqliteServiceConfig) => { eventType: SqliteEventType, database: string, table: string, - rowId: number + rowId: number, ) => { trace(`Got a raw change event`, { eventType, @@ -73,7 +73,7 @@ export const sqliteService = mkSingleton((config: SqliteServiceConfig) => { if (eventType === 'delete') return // Not supported const record = await db.get( - `select * from ${table} where rowid = '${rowId}'` + `select * from ${table} where rowid = '${rowId}'`, ) const e: SqliteChangeEvent = { table, @@ -81,7 +81,7 @@ export const sqliteService = mkSingleton((config: SqliteServiceConfig) => { record, } fireChange(e) - } + }, ) cm.add(() => { @@ -110,7 +110,7 @@ export const sqliteService = mkSingleton((config: SqliteServiceConfig) => { } const getDatabase = serialAsyncExecutionGuard( _unsafe_getDatabase, - (fileName) => fileName + (fileName) => fileName, ) const shutdown = async () => { diff --git a/packages/daemon/src/services/UpdaterService/UpdaterService.ts b/packages/daemon/src/services/UpdaterService/UpdaterService.ts index 9ba6e114..c4793b40 100644 --- a/packages/daemon/src/services/UpdaterService/UpdaterService.ts +++ b/packages/daemon/src/services/UpdaterService/UpdaterService.ts @@ -1,9 +1,9 @@ import { downloadAndExtract, smartFetch } from '$util' import { + SingletonBaseConfig, createCleanupManager, createTimerManager, mkSingleton, - SingletonBaseConfig, } from '@pockethost/common' import { keys } from '@s-libs/micro-dash' import { chmodSync, existsSync } from 'fs' @@ -49,7 +49,7 @@ export const updaterService = mkSingleton( const check = async () => { const releases = await smartFetch( `https://api.github.com/repos/pocketbase/pocketbase/releases?per_page=100`, - join(cachePath, `releases.json`) + join(cachePath, `releases.json`), ) // dbg({ releases }) @@ -77,7 +77,7 @@ export const updaterService = mkSingleton( await Promise.all(promises) if (keys(binPaths).length === 0) { throw new Error( - `No version found, probably mismatched architecture and OS (${osName}/${cpuArchitecture})` + `No version found, probably mismatched architecture and OS (${osName}/${cpuArchitecture})`, ) } maxVersion = `~${rsort(keys(binPaths))[0]}` @@ -94,7 +94,7 @@ export const updaterService = mkSingleton( const version = maxSatisfying(keys(binPaths), semVer) if (!version) throw new Error( - `No version satisfies ${semVer} (${keys(binPaths).join(', ')})` + `No version satisfies ${semVer} (${keys(binPaths).join(', ')})`, ) const binPath = binPaths[version] if (!binPath) throw new Error(`binPath for ${version} not found`) @@ -109,5 +109,5 @@ export const updaterService = mkSingleton( getVersion, shutdown: async () => {}, } - } + }, ) diff --git a/packages/daemon/src/services/clientService/InstanceMIxin.ts b/packages/daemon/src/services/clientService/InstanceMIxin.ts index 978f0e7d..6f0a5f46 100644 --- a/packages/daemon/src/services/clientService/InstanceMIxin.ts +++ b/packages/daemon/src/services/clientService/InstanceMIxin.ts @@ -1,12 +1,12 @@ import { - assertExists, + INSTANCE_COLLECTION, InstanceFields, InstanceFields_Create, InstanceId, InstanceStatus, - INSTANCE_COLLECTION, - safeCatch, UserFields, + assertExists, + safeCatch, } from '@pockethost/common' import { reduce } from '@s-libs/micro-dash' import Bottleneck from 'bottleneck' @@ -25,7 +25,7 @@ export const createInstanceMixin = (context: MixinContext) => { const resetInstances = safeCatch(`resetRpcs`, logger, async () => rawDb(INSTANCE_COLLECTION).update({ status: InstanceStatus.Idle, - }) + }), ) const createInstance = safeCatch( @@ -35,7 +35,7 @@ export const createInstanceMixin = (context: MixinContext) => { return client .collection(INSTANCE_COLLECTION) .create(payload) - } + }, ) const getInstanceBySubdomain = safeCatch( @@ -57,12 +57,12 @@ export const createInstanceMixin = (context: MixinContext) => { .then((user) => { return [instance, user] }) - }) + }), ) const getInstanceById = async ( instanceId: InstanceId, - context?: AsyncContext + context?: AsyncContext, ): Promise<[InstanceFields, UserFields] | []> => client .collection(INSTANCE_COLLECTION) @@ -86,7 +86,7 @@ export const createInstanceMixin = (context: MixinContext) => { logger, async (instanceId: InstanceId, fields: Partial) => { await client.collection(INSTANCE_COLLECTION).update(instanceId, fields) - } + }, ) const updateInstanceStatus = safeCatch( @@ -94,7 +94,7 @@ export const createInstanceMixin = (context: MixinContext) => { logger, async (instanceId: InstanceId, status: InstanceStatus) => { await updateInstance(instanceId, { status }) - } + }, ) const getInstance = safeCatch( @@ -104,7 +104,7 @@ export const createInstanceMixin = (context: MixinContext) => { return client .collection(INSTANCE_COLLECTION) .getOne(instanceId) - } + }, ) const getInstances = safeCatch(`getInstances`, logger, async () => { @@ -129,14 +129,14 @@ export const createInstanceMixin = (context: MixinContext) => { return client .collection(INSTANCE_COLLECTION) .update(r.id, toUpdate) - }) + }), ) return c }, - [] as Promise[] + [] as Promise[], ) await Promise.all(promises) - } + }, ) const updateInstanceSeconds = safeCatch( @@ -156,7 +156,7 @@ export const createInstanceMixin = (context: MixinContext) => { assertExists(row, `Expected row here`) const secondsThisMonth = row.t await updateInstance(instanceId, { secondsThisMonth }) - } + }, ) return { diff --git a/packages/daemon/src/services/clientService/InvocationMixin.ts b/packages/daemon/src/services/clientService/InvocationMixin.ts index 887b0837..663c3383 100644 --- a/packages/daemon/src/services/clientService/InvocationMixin.ts +++ b/packages/daemon/src/services/clientService/InvocationMixin.ts @@ -9,7 +9,7 @@ import { MixinContext } from './PbClient' export const createInvocationMixin = ( context: MixinContext, - instanceApi: InstanceApi + instanceApi: InstanceApi, ) => { const { logger } = context const { dbg } = logger.create('InvocationMixin') @@ -32,7 +32,7 @@ export const createInvocationMixin = ( $cancelKey: `createInvocation:${instance.id}:${pid}`, }) return _inv - } + }, ) const pingInvocation = safeCatch( @@ -49,7 +49,7 @@ export const createInvocationMixin = ( .update(invocation.id, toUpdate) await instanceApi.updateInstanceSeconds(invocation.instanceId) return _inv - } + }, ) const finalizeInvocation = safeCatch( @@ -69,7 +69,7 @@ export const createInvocationMixin = ( .update(invocation.id, toUpdate) await instanceApi.updateInstanceSeconds(invocation.instanceId) return _inv - } + }, ) return { finalizeInvocation, pingInvocation, createInvocation } diff --git a/packages/daemon/src/services/clientService/PbClient.ts b/packages/daemon/src/services/clientService/PbClient.ts index 0d917fe8..704a17e0 100644 --- a/packages/daemon/src/services/clientService/PbClient.ts +++ b/packages/daemon/src/services/clientService/PbClient.ts @@ -18,7 +18,7 @@ export const createPbClient = (url: string, logger: Logger) => { info(`Initializing client: ${url}`) const rawDb = createRawPbClient( `${DAEMON_PB_DATA_DIR}/${PUBLIC_APP_DB}/pb_data/data.db`, - _clientLogger + _clientLogger, ) const client = new PocketBase(url) @@ -27,7 +27,7 @@ export const createPbClient = (url: string, logger: Logger) => { `adminAuthViaEmail`, _clientLogger, (email: string, password: string) => - client.admins.authWithPassword(email, password) + client.admins.authWithPassword(email, password), ) const createFirstAdmin = safeCatch( @@ -40,7 +40,7 @@ export const createPbClient = (url: string, logger: Logger) => { console.log({ email, password }) console.log(JSON.stringify(res, null, 2)) return res - }) + }), ) const context: MixinContext = { client, rawDb, logger: _clientLogger } diff --git a/packages/daemon/src/services/clientService/RpcHelper.ts b/packages/daemon/src/services/clientService/RpcHelper.ts index 85e03b3c..29a6933b 100644 --- a/packages/daemon/src/services/clientService/RpcHelper.ts +++ b/packages/daemon/src/services/clientService/RpcHelper.ts @@ -1,7 +1,7 @@ import { + RPC_COLLECTION, RpcFields, RpcStatus, - RPC_COLLECTION, safeCatch, } from '@pockethost/common' import { ClientResponseError } from 'pocketbase' @@ -31,7 +31,7 @@ export const createRpcHelper = (config: RpcHelperConfig) => { cb(e.record) }) return unsub - } + }, ) const resetRpcs = safeCatch(`resetRpcs`, logger, async () => @@ -43,7 +43,7 @@ export const createRpcHelper = (config: RpcHelperConfig) => { .update>({ status: RpcStatus.FinishedError, result: `Canceled by reset`, - }) + }), ) const incompleteRpcs = safeCatch(`incompleteRpcs`, logger, async () => { @@ -65,7 +65,7 @@ export const createRpcHelper = (config: RpcHelperConfig) => { return client .collection(RPC_COLLECTION) .update>(rpc.id, fields) - } + }, ) const setRpcStatus = safeCatch( @@ -74,12 +74,12 @@ export const createRpcHelper = (config: RpcHelperConfig) => { async ( rpc: RpcFields, status: RpcStatus, - result: JsonObject = {} + result: JsonObject = {}, ) => { return client .collection(RPC_COLLECTION) .update(rpc.id, { status, result }) - } + }, ) return { diff --git a/packages/daemon/src/services/clientService/clientService.ts b/packages/daemon/src/services/clientService/clientService.ts index e464e1cd..c720e0ec 100644 --- a/packages/daemon/src/services/clientService/clientService.ts +++ b/packages/daemon/src/services/clientService/clientService.ts @@ -31,7 +31,7 @@ export const clientService = mkSingleton(async (cfg: ClientServiceConfig) => { dbg(`Logged in`) } catch (e) { error( - `CANNOT AUTHENTICATE TO ${PUBLIC_APP_PROTOCOL}://${PUBLIC_APP_DB}.${PUBLIC_APP_DOMAIN}/_/` + `CANNOT AUTHENTICATE TO ${PUBLIC_APP_PROTOCOL}://${PUBLIC_APP_DB}.${PUBLIC_APP_DOMAIN}/_/`, ) process.exit(-1) } diff --git a/packages/daemon/src/services/index.ts b/packages/daemon/src/services/index.ts index d769b958..d68f55d9 100644 --- a/packages/daemon/src/services/index.ts +++ b/packages/daemon/src/services/index.ts @@ -1,5 +1,3 @@ -export * from './clientService/clientService' -export * from './clientService/PbClient' export * from './FtpService/FtpService' export * from './InstanceService/InstanceService' export * from './PocketBaseService' @@ -7,3 +5,5 @@ export * from './ProxyService' export * from './RealtimeLog' export * from './RpcService/RpcService' export * from './SqliteService/SqliteService' +export * from './clientService/PbClient' +export * from './clientService/clientService' diff --git a/packages/daemon/src/stresser/commands/cleanup/deleteInstance.ts b/packages/daemon/src/stresser/commands/cleanup/deleteInstance.ts index a0efcf22..904c8c2a 100644 --- a/packages/daemon/src/stresser/commands/cleanup/deleteInstance.ts +++ b/packages/daemon/src/stresser/commands/cleanup/deleteInstance.ts @@ -1,12 +1,12 @@ import { clientService } from '$services' import { - InstanceFields, INSTANCE_COLLECTION, - InvocationFields, INVOCATION_COLLECTION, - logger, - RpcFields, + InstanceFields, + InvocationFields, RPC_COLLECTION, + RpcFields, + logger, singletonAsyncExecutionGuard, } from '@pockethost/common' import Bottleneck from 'bottleneck' @@ -17,7 +17,7 @@ export const deleteInvocation = singletonAsyncExecutionGuard( const { client } = await clientService() await client.client.collection(INVOCATION_COLLECTION).delete(invocation.id) }, - (invocation) => `deleteInvocation:${invocation.id}` + (invocation) => `deleteInvocation:${invocation.id}`, ) export const deleteInvocationsForInstance = singletonAsyncExecutionGuard( @@ -50,7 +50,7 @@ export const deleteInvocationsForInstance = singletonAsyncExecutionGuard( } } }, - (instance) => `deleteInvocationsForInstance:${instance.id}` + (instance) => `deleteInvocationsForInstance:${instance.id}`, ) export const deleteRpc = singletonAsyncExecutionGuard( @@ -58,7 +58,7 @@ export const deleteRpc = singletonAsyncExecutionGuard( const { client } = await clientService() await client.client.collection(RPC_COLLECTION).delete(rpc.id) }, - (rpc) => `deleteRpc:${rpc.id}` + (rpc) => `deleteRpc:${rpc.id}`, ) export const getAllRpcs = singletonAsyncExecutionGuard( @@ -70,7 +70,7 @@ export const getAllRpcs = singletonAsyncExecutionGuard( console.log(`Loaded rpcs`) return rpcs }, - () => `getAllRpcs` + () => `getAllRpcs`, ) export const deleteRpcsForInstance = singletonAsyncExecutionGuard( @@ -80,7 +80,7 @@ export const deleteRpcsForInstance = singletonAsyncExecutionGuard( const instanceRpcs = allRpcs.filter((rpc) => rpc.payload?.instanceId === id) await Promise.all(instanceRpcs.map(deleteRpc)) }, - (instance) => `deleteRpcsForInstance:${instance.id}` + (instance) => `deleteRpcsForInstance:${instance.id}`, ) export const deleteInstance = singletonAsyncExecutionGuard( @@ -95,7 +95,7 @@ export const deleteInstance = singletonAsyncExecutionGuard( await deleteInvocationsForInstance(instance).catch((e) => { console.error( `deleteInvocationsForInstance error`, - JSON.stringify(e, null, 2) + JSON.stringify(e, null, 2), ) throw e }) @@ -110,7 +110,7 @@ export const deleteInstance = singletonAsyncExecutionGuard( }) console.log(`Instance deleted ${id}`) }, - (instance) => `deleteInstance:${instance.id}` + (instance) => `deleteInstance:${instance.id}`, ) export const deleteInstancesByFilter = singletonAsyncExecutionGuard( @@ -122,9 +122,9 @@ export const deleteInstancesByFilter = singletonAsyncExecutionGuard( const limiter = new Bottleneck({ maxConcurrent: 50 }) await Promise.all( instances.map((instance) => - limiter.schedule(() => deleteInstance(instance)) - ) + limiter.schedule(() => deleteInstance(instance)), + ), ) }, - (filter) => `deleteInstancesByFilter:${filter}` + (filter) => `deleteInstancesByFilter:${filter}`, ) diff --git a/packages/daemon/src/stresser/commands/cleanup/index.ts b/packages/daemon/src/stresser/commands/cleanup/index.ts index 4f972d98..b5d85d43 100644 --- a/packages/daemon/src/stresser/commands/cleanup/index.ts +++ b/packages/daemon/src/stresser/commands/cleanup/index.ts @@ -16,7 +16,7 @@ export const createCleanup = (context: { program: Command } & ContextBase) => { .option( `-f, --filter `, `Filter to use when deleting instances`, - `stress-%` + `stress-%`, ) .action(async () => { const options = cleanupCmd.optsWithGlobals() diff --git a/packages/daemon/src/stresser/commands/seed.ts b/packages/daemon/src/stresser/commands/seed.ts index b0e01fa8..d247fcf3 100644 --- a/packages/daemon/src/stresser/commands/seed.ts +++ b/packages/daemon/src/stresser/commands/seed.ts @@ -38,7 +38,7 @@ export const createSeed = (context: { program: Command } & ContextBase) => { `-c, --count`, `Number of new seed instances to create`, parseInt, - 10 + 10, ) .action(async () => { const options = seedCmd.optsWithGlobals() diff --git a/packages/daemon/src/stresser/commands/stress.ts b/packages/daemon/src/stresser/commands/stress.ts index 93c743d1..bc3ca2a2 100644 --- a/packages/daemon/src/stresser/commands/stress.ts +++ b/packages/daemon/src/stresser/commands/stress.ts @@ -24,25 +24,25 @@ export const createStress = (context: { program: Command } & ContextBase) => { '-ic, --instance-count ', `Number of simultaneous instances to hit`, parseInt, - 100 + 100, ) .option( '-rc, --requests-per-instance ', `Number of simultaneous requests per instance`, parseInt, - 50 + 50, ) .option( '-mind, --min-delay ', `Minimum number of milliseconds to delay before sending another request`, parseInt, - 50 + 50, ) .option( '-maxd, --max-delay ', `Maximum number of milliseconds to delay before sending another request`, parseInt, - 500 + 500, ) .action(async () => { const options = seedCmd.optsWithGlobals() @@ -63,7 +63,7 @@ export const createStress = (context: { program: Command } & ContextBase) => { if (excluded[instanceId]) return await client.updateInstance(instanceId, { maintenance: false }) }, - (id) => `reset:${id}` + (id) => `reset:${id}`, ) const instances = await client.getInstances() @@ -80,7 +80,7 @@ export const createStress = (context: { program: Command } & ContextBase) => { dbg( `There are ${instances.length} instances and ${ values(excluded).length - } excluded` + } excluded`, ) if (!instance) throw new Error(`No instance to grab`) @@ -108,7 +108,7 @@ export const createStress = (context: { program: Command } & ContextBase) => { return // Timeout } } - }) + }), ) } } catch (e) { diff --git a/packages/daemon/src/stresser/index.ts b/packages/daemon/src/stresser/index.ts index 1176b107..ab62e990 100644 --- a/packages/daemon/src/stresser/index.ts +++ b/packages/daemon/src/stresser/index.ts @@ -22,7 +22,7 @@ program .option( '-u, --mothership-url', 'URL to central database', - 'http://127.0.0.1:8090' + 'http://127.0.0.1:8090', ) createCleanup({ program, logger }) diff --git a/packages/daemon/src/util/downloadAndExtract.ts b/packages/daemon/src/util/downloadAndExtract.ts index 5627edf7..de0ac10b 100644 --- a/packages/daemon/src/util/downloadAndExtract.ts +++ b/packages/daemon/src/util/downloadAndExtract.ts @@ -7,7 +7,7 @@ import { dirname } from 'path' export function assert( v: T | undefined | void | null, - msg?: string + msg?: string, ): asserts v is T { if (!v) { throw new Error(msg || `Assertion failure`) @@ -28,7 +28,7 @@ const downloadFile = async (url: string, path: string) => { const _unsafe_downloadAndExtract = async ( url: string, binPath: string, - logger: Logger + logger: Logger, ) => { const { dbg, error } = logger.create('downloadAndExtract') @@ -48,5 +48,5 @@ const _unsafe_downloadAndExtract = async ( export const downloadAndExtract = singletonAsyncExecutionGuard( _unsafe_downloadAndExtract, - (url) => url + (url) => url, ) diff --git a/packages/daemon/src/util/smartFetch.ts b/packages/daemon/src/util/smartFetch.ts index 19560d89..35f5f9d4 100644 --- a/packages/daemon/src/util/smartFetch.ts +++ b/packages/daemon/src/util/smartFetch.ts @@ -5,7 +5,7 @@ import { dirname } from 'path' export const smartFetch = async ( url: string, - path: string + path: string, ): Promise => { const { dbg } = logger().create(`smartFetch`) diff --git a/packages/daemon/src/util/tryFetch.ts b/packages/daemon/src/util/tryFetch.ts index 81c02e1f..4094efaf 100644 --- a/packages/daemon/src/util/tryFetch.ts +++ b/packages/daemon/src/util/tryFetch.ts @@ -40,7 +40,7 @@ export const tryFetch = async (url: string, config?: Partial) => { resolve() } catch (e) { dbg( - `Could not fetch ${url}, trying again in ${retryMs}ms. Raw error ${e}` + `Could not fetch ${url}, trying again in ${retryMs}ms. Raw error ${e}`, ) setTimeout(tryFetch, retryMs) } diff --git a/packages/deno-worker/EventSource.ts b/packages/deno-worker/EventSource.ts index ae7ab864..c95b03c7 100644 --- a/packages/deno-worker/EventSource.ts +++ b/packages/deno-worker/EventSource.ts @@ -250,7 +250,7 @@ export class EventSource extends EventTarget { await new Promise((res) => { const id = setTimeout( () => res(clearTimeout(id)), - this.#settings.reconnectionTime + this.#settings.reconnectionTime, ) }) diff --git a/packages/deno-worker/index.d.ts b/packages/deno-worker/index.d.ts index a7f12f30..0551989e 100644 --- a/packages/deno-worker/index.d.ts +++ b/packages/deno-worker/index.d.ts @@ -19,7 +19,7 @@ declare class EventSource { constructor( url: string, - eventSourceInitDict?: EventSource.EventSourceInitDict + eventSourceInitDict?: EventSource.EventSourceInitDict, ) readonly CLOSED: number diff --git a/packages/deno-worker/index.ts b/packages/deno-worker/index.ts index 50dba8a7..36764713 100644 --- a/packages/deno-worker/index.ts +++ b/packages/deno-worker/index.ts @@ -23,7 +23,7 @@ export const init = (klass: typeof PocketBase) => { const adminAuthWithPassword = async ( login = ADMIN_LOGIN, - password = ADMIN_PASSWORD + password = ADMIN_PASSWORD, ) => { console.log(`Connecting to ${POCKETBASE_URL} with ${ADMIN_LOGIN}`) await client.admins.authWithPassword(login, password) diff --git a/packages/pockethost.io/.prettierrc b/packages/pockethost.io/.prettierrc deleted file mode 100644 index 0b157833..00000000 --- a/packages/pockethost.io/.prettierrc +++ /dev/null @@ -1,16 +0,0 @@ -{ - "useTabs": false, - "singleQuote": true, - "semi": false, - "trailingComma": "none", - "printWidth": 100, - "pluginSearchDirs": [".", "../.."], - "overrides": [ - { - "files": "*.svelte", - "options": { - "parser": "svelte" - } - } - ] -} diff --git a/packages/pockethost.io/package.json b/packages/pockethost.io/package.json index bbddc6ea..c30c0c4b 100644 --- a/packages/pockethost.io/package.json +++ b/packages/pockethost.io/package.json @@ -10,28 +10,25 @@ "check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch", "lint": "prettier --check .", "format": "prettier --write .", - "start": "HOST=localhost PORT=5173 node dist-server/index.js", + "start": "HOST=localhost PORT=5173 dotenv -e ../../.env node -- dist-server/index.js", "pm2": "pm2 del www ; pm2 start \"yarn start\" --name=www -o ~/logs/www.log -e ~/logs/www.log", "watch": "chokidar 'src/**' -c 'yarn build' --initial" }, "devDependencies": { - "@sveltejs/adapter-node": "^1.0.0-next.99", - "@sveltejs/kit": "next", - "chokidar-cli": "^3.0.0", - "node-html-parser": "^6.1.4", - "svelte": "^3.44.0", - "svelte-check": "^2.7.1", - "svelte-preprocess": "^4.10.6", - "tslib": "^2.3.1", - "typescript": "^4.8.0", - "vite": "^3.1.0" + "@sveltejs/adapter-node": "^1.3.1", + "@sveltejs/kit": "^1.24.1", + "node-html-parser": "^6.1.8", + "svelte": "^4.2.0", + "svelte-check": "^3.5.1", + "svelte-preprocess": "^5.0.4", + "vite": "^4.4.9" }, "type": "module", "dependencies": { "@dansvel/vite-plugin-markdown": "^2.0.5", "@microsoft/fetch-event-source": "https://github.com/Almar/fetch-event-source.git#pr/make_web_worker_friendly", "@pockethost/common": "0.0.1", - "@s-libs/micro-dash": "^15.1.0", + "@s-libs/micro-dash": "^16.1.0", "@types/bootstrap": "^5.2.6", "@types/d3-scale": "^4.0.3", "@types/d3-scale-chromatic": "^3.0.0", diff --git a/packages/pockethost.io/src/components/AccordionItem.svelte b/packages/pockethost.io/src/components/AccordionItem.svelte index 940b9b2b..dbd175c9 100644 --- a/packages/pockethost.io/src/components/AccordionItem.svelte +++ b/packages/pockethost.io/src/components/AccordionItem.svelte @@ -10,7 +10,7 @@
-

+