diff --git a/.mocharc.json b/.mocharc.json index db4429b9..b661af50 100644 --- a/.mocharc.json +++ b/.mocharc.json @@ -5,5 +5,6 @@ "file": [ "./src/backend/tests/setup.ts" ], + "require": [ "./src/backend/tests/globalHooks.ts"], "exit": true } diff --git a/package-lock.json b/package-lock.json index cacd52ce..365bb7c9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,6 +33,7 @@ "@minisylar/express-typed-router": "^1.9.7", "@pierre/diffs": "^1.2.4", "@rocksky/sdk": "^0.3.0", + "@russellthehippo/honker-node": "^0.5.0", "@supercharge/promise-pool": "^3.0.0", "@svrooij/sonos": "^2.5.0", "@xhayper/discord-rpc": "1.3.0", @@ -5057,6 +5058,153 @@ } } }, + "node_modules/@russellthehippo/honker-ext-darwin-arm64": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/@russellthehippo/honker-ext-darwin-arm64/-/honker-ext-darwin-arm64-0.4.6.tgz", + "integrity": "sha512-WAGssCw2kA5Qlbv2c0PzNwpx9BLmB2Rmf4aovQjGXxP8kI496o2y5VnTnTKBgOi0TWvVLYVYa1PKfrng/UC8sg==", + "cpu": [ + "arm64" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@russellthehippo/honker-ext-darwin-x64": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/@russellthehippo/honker-ext-darwin-x64/-/honker-ext-darwin-x64-0.4.6.tgz", + "integrity": "sha512-gGlEGPgiFbysF/NFb88PYY8PMZjXI6T7oqH2O2FSRu5ktwkSQUyELID9G/zC9Wi5blw/Hx1iTsI3hQl1rcRfkQ==", + "cpu": [ + "x64" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ] + }, + "node_modules/@russellthehippo/honker-ext-linux-arm64-gnu": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/@russellthehippo/honker-ext-linux-arm64-gnu/-/honker-ext-linux-arm64-gnu-0.4.6.tgz", + "integrity": "sha512-1SpEfmAlvG9dgIXFHkYWHdp8cyaqZdnEoupmVvuOe7ecXwQUzNCeBsATFGD737fE+BfrrV0yUPI3cfx07uB5AQ==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@russellthehippo/honker-ext-linux-x64-gnu": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/@russellthehippo/honker-ext-linux-x64-gnu/-/honker-ext-linux-x64-gnu-0.4.6.tgz", + "integrity": "sha512-cqD9kAn01tTNdIM+DxJ1ZlNuCan7PM2hO1ZXxSmPkR5SZ93APz+4SKLvmnBkWtVKz4Z95W0yzUY6Lmag6uCG+g==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ] + }, + "node_modules/@russellthehippo/honker-node": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@russellthehippo/honker-node/-/honker-node-0.5.0.tgz", + "integrity": "sha512-94eLqW5KKFpSOAAb7h7fxP0Ka+i67KIDcMDTS4Mf5J7fllCdrQj/wJ8mnCjo1s5uauUAMcExa7yBh3VGATx/bQ==", + "license": "MIT OR Apache-2.0", + "engines": { + "node": ">= 20" + }, + "optionalDependencies": { + "@russellthehippo/honker-ext-darwin-arm64": "0.4.6", + "@russellthehippo/honker-ext-darwin-x64": "0.4.6", + "@russellthehippo/honker-ext-linux-arm64-gnu": "0.4.6", + "@russellthehippo/honker-ext-linux-x64-gnu": "0.4.6", + "@russellthehippo/honker-node-darwin-arm64": "0.5.0", + "@russellthehippo/honker-node-darwin-x64": "0.5.0", + "@russellthehippo/honker-node-linux-arm64-gnu": "0.5.0", + "@russellthehippo/honker-node-linux-x64-gnu": "0.5.0" + } + }, + "node_modules/@russellthehippo/honker-node-darwin-arm64": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@russellthehippo/honker-node-darwin-arm64/-/honker-node-darwin-arm64-0.5.0.tgz", + "integrity": "sha512-74MEi4yKbDtiw8NweqkHYa0Ou/TdtmgkflmxKLbNZdbyMwbacOtquVGThWXsU1d+TLjrH7PIhYL8mmx4W3Jdag==", + "cpu": [ + "arm64" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@russellthehippo/honker-node-darwin-x64": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@russellthehippo/honker-node-darwin-x64/-/honker-node-darwin-x64-0.5.0.tgz", + "integrity": "sha512-WGV3Wp7Ari9s4PaQS78QdXdc1NBw3TfL5DW5ubtj0PYtgtfbwc/5r83hAU5EuD0RH6YTkTnd3nPKqIe0qE90qw==", + "cpu": [ + "x64" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@russellthehippo/honker-node-linux-arm64-gnu": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@russellthehippo/honker-node-linux-arm64-gnu/-/honker-node-linux-arm64-gnu-0.5.0.tgz", + "integrity": "sha512-8Ljln6Lifeg2642LIpBjo3yTPds44kmxraijcFSGOyd4y9QcYEIVDiyKHuur0JpiZmALOqmmYZpDh4f2bl/Kuw==", + "cpu": [ + "arm64" + ], + "libc": [ + "glibc" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, + "node_modules/@russellthehippo/honker-node-linux-x64-gnu": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@russellthehippo/honker-node-linux-x64-gnu/-/honker-node-linux-x64-gnu-0.5.0.tgz", + "integrity": "sha512-pyvvJz24uNq88HzZRZ6m9gu+bgT1SSdk6qPhaXEX41r3a8TSHCYspvXxpYHyXTCIlVZpVXtawS2p4qUU76dj8A==", + "cpu": [ + "x64" + ], + "libc": [ + "glibc" + ], + "license": "MIT OR Apache-2.0", + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 20" + } + }, "node_modules/@sapphire/async-queue": { "version": "1.5.5", "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.5.5.tgz", diff --git a/package.json b/package.json index 75e784f1..d7c61eef 100644 --- a/package.json +++ b/package.json @@ -73,6 +73,7 @@ "@minisylar/express-typed-router": "^1.9.7", "@pierre/diffs": "^1.2.4", "@rocksky/sdk": "^0.3.0", + "@russellthehippo/honker-node": "^0.5.0", "@supercharge/promise-pool": "^3.0.0", "@svrooij/sonos": "^2.5.0", "@xhayper/discord-rpc": "1.3.0", diff --git a/src/backend/common/database/drizzle/drizzleUtils.ts b/src/backend/common/database/drizzle/drizzleUtils.ts index da9d7275..76814d7a 100644 --- a/src/backend/common/database/drizzle/drizzleUtils.ts +++ b/src/backend/common/database/drizzle/drizzleUtils.ts @@ -13,6 +13,7 @@ import { addToContext, executeQuery } from './logContext.ts'; import { migrateApp, getAppMigrationStatus } from '../appMigrator.ts'; import type {MigrationStatus} from '../../infrastructure/Atomic.ts'; import { projectRootDir } from "../../infrastructure/Atomic.ts"; +import { extensionPath } from '@russellthehippo/honker-node/extension'; export async function getDbMigrationStatus(dbVal: string | DbConcrete, opts: {logger?: Logger, migrationsFolder?: string} = {}): Promise { const { @@ -77,7 +78,13 @@ export const getDb = (dbVal: string, opts: { logger?: Logger, backupPath?: strin const { logger = loggerNoop, } = opts; - return drizzle(dbVal, {relations: relations, logger: createDrizzleLogger(logger)}); + const db = drizzle({relations: relations, logger: createDrizzleLogger(logger), connection: {path: dbVal, allowExtension: true}}); + if(dbVal !== ':memory:') { + logger.debug('Loading honker extension'); + db.$client.loadExtension(extensionPath()); + db.run('SELECT honker_bootstrap()'); + } + return db; } export type DbConcrete = ReturnType; diff --git a/src/backend/common/index.ts b/src/backend/common/index.ts index c8f1f5ce..f56b220a 100644 --- a/src/backend/common/index.ts +++ b/src/backend/common/index.ts @@ -25,4 +25,6 @@ export const getDataDir = (): string => { return path.resolve(dataDirVal); } +export const getTempDir = (): string => osPaths.temp; + export const getPathFromCWD = (...relativePaths: string[]) => path.resolve(process.cwd(), ...relativePaths); \ No newline at end of file diff --git a/src/backend/tests/globalHooks.ts b/src/backend/tests/globalHooks.ts new file mode 100644 index 00000000..610736cd --- /dev/null +++ b/src/backend/tests/globalHooks.ts @@ -0,0 +1,21 @@ +import { mkdirSync } from 'node:fs'; +import path from 'node:path'; +import { getTempDir } from '../common/index.ts'; +import { deleteBaseDb, deleteTestDb, setBaseDbPath } from './utils/TransientTestUtils.ts'; +import { getDb, migrateDb } from '../common/database/drizzle/drizzleUtils.ts'; + +export const mochaHooks = { + async beforeAll() { + mkdirSync(getTempDir(), {recursive: true}); + const baseDbPath = path.resolve(getTempDir(),'base.db'); + setBaseDbPath(baseDbPath); + const db = getDb(baseDbPath); + await migrateDb(db); + }, + afterEach() { + deleteTestDb(); + }, + afterAll() { + deleteBaseDb(); + } +}; \ No newline at end of file diff --git a/src/backend/tests/utils/TransientTestUtils.ts b/src/backend/tests/utils/TransientTestUtils.ts index 39750f52..2dbfd9ed 100644 --- a/src/backend/tests/utils/TransientTestUtils.ts +++ b/src/backend/tests/utils/TransientTestUtils.ts @@ -1,11 +1,39 @@ import { loggerTest } from "@foxxmd/logging"; import { MSCache } from "../../common/Cache.ts"; import { getDb, migrateDb } from "../../common/database/drizzle/drizzleUtils.ts"; +import { cpSync, rmSync } from "node:fs"; +import { resolve } from "node:path"; +import { getTempDir } from "../../common/index.ts"; +import { nanoid } from "nanoid"; export const transientCache = () => new MSCache(loggerTest); +let blankDb: string, + testdb: string; + export const transientDb = async () => { + if(blankDb !== undefined) { + testdb = resolve(getTempDir(),`${nanoid()}.db`); + cpSync(blankDb, testdb); + const db = getDb(testdb); + return db; + } const db = getDb(':memory:'); await migrateDb(db); return db; +} + +export const setBaseDbPath = (path: string) => { + blankDb = path; +} + +export const deleteTestDb = () => { + if(testdb !== undefined) { + rmSync(testdb, {force: true}); + } +} +export const deleteBaseDb = () => { + if(blankDb !== undefined) { + rmSync(blankDb, {force: true}); + } } \ No newline at end of file