Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion registry/config/default.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ module.exports = {
client: 'sqlite3',
connection: {
database: 'registry_db',
filename: path.resolve(__dirname, '../server/dbfiles/db.sqlite'),
// Anchored to the registry root so that the source and the pre-compiled
// (build/config) versions of this config point to the same database file
filename: path.join(path.resolve(__dirname, '..').replace(/[\\/]build$/, ''), 'server/dbfiles/db.sqlite'),
},
searchPath: ['public'],
useNullAsDefault: true,
Expand Down
15 changes: 13 additions & 2 deletions registry/config/knexfile.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
require('ts-node/register');

import path from 'node:path';
process.env.NODE_CONFIG_DIR = path.resolve(__dirname, '../config');

Expand All @@ -8,6 +6,7 @@ import { Knex, knex } from 'knex';

import { cascadeTruncatePlugin } from '../server/db/cascadeTruncate';
import { knexLoggerAdapter } from '../server/db/logger';
import { PrecompiledMigrationSource } from '../server/db/migrationSource';
import { syncSequencePlugin } from '../server/db/syncSequence';
import { logConnectionString } from '../server/util/db';
import { loadPlugins } from '../server/util/pluginManager';
Expand All @@ -21,8 +20,20 @@ const knexConfig: Knex.Config = config.get('database');

const connection = typeof knexConfig.connection === 'object' ? { ...knexConfig.connection } : knexConfig.connection;

let migrations = knexConfig.migrations;
if (typeof migrations?.directory === 'string') {
// Knex resets a custom migrationSource whenever FS-related options (directory, loadExtensions)
// are present, so the compiled config must pass the migration source only
const { directory, loadExtensions, sortDirsSeparately, ...restMigrations } = migrations;
migrations = {
...restMigrations,
migrationSource: new PrecompiledMigrationSource(directory),
};
}

export default {
...knexConfig,
connection,
migrations,
log: knexLoggerAdapter(),
};
230 changes: 230 additions & 0 deletions registry/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 10 additions & 6 deletions registry/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,19 @@
"main": "build/index.js",
"scripts": {
"tsc": "tsc",
"compile": "tsc --incremental",
"compile": "tsc --incremental && copyfiles \"server/seeds/data/**/*\" build",
"dev": "rimraf build && nodemon -e ts,json5 --exec \"tsc --incremental && npm run start | pino-pretty\" ",
"build": "npm run compile && cd ./client && npm run build",
"start": "dotenv -- node -r source-map-support/register ./build/server/index.js",
"start-docker": "npm run migrate && npm start",
"start-docker": "npm run migrate:compiled && npm start",
"knex": "knex",
"migrate": "dotenv -- knex --knexfile config/knexfile.ts migrate:latest",
"migrate:make": "knex --knexfile config/knexfile.ts migrate:make",
"migrate:rollback": "dotenv -- knex --knexfile config/knexfile.ts migrate:rollback",
"seed": "dotenv -- knex --knexfile config/knexfile.ts seed:run",
"migrate": "npm run compile && dotenv -- npm run migrate:compiled",
"migrate:compiled": "knex --knexfile build/config/knexfile.js migrate:latest",
"migrate:make": "knex --knexfile config/knexfile.ts migrate:make --migrations-directory ../server/migrations",
"migrate:rollback": "npm run compile && dotenv -- npm run migrate:rollback:compiled",
"migrate:rollback:compiled": "knex --knexfile build/config/knexfile.js migrate:rollback",
"seed": "npm run compile && dotenv -- npm run seed:compiled",
"seed:compiled": "knex --knexfile build/config/knexfile.js seed:run",
"seed:make": "knex --knexfile config/knexfile.ts seed:make -x ts",
"test:sqlite": "cross-env-shell DB_CLIENT=sqlite3 npm run reset && cross-env NODE_ENV=test NODE_CONFIG_ENV=sqlite-test mocha",
"test:mysql": "cross-env-shell NODE_ENV=test NODE_CONFIG_ENV=mysql-test DB_CLIENT=mysql \"npm run reset && mocha\" ",
Expand Down Expand Up @@ -48,6 +51,7 @@
"@types/supertest": "^6.0.3",
"chai": "6.2.1",
"chai-as-promised": "^8.0.2",
"copyfiles": "^2.4.1",
"cross-env": "10.1.0",
"jsonwebtoken": "^9.0.2",
"mocha": "^11.7.5",
Expand Down
4 changes: 2 additions & 2 deletions registry/scripts/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@
set -e

if [ "$DB_SEED" = 'true' ] && [ ! -f .seed ]; then
npm run migrate
npm run seed
npm run migrate:compiled
npm run seed:compiled
touch .seed
fi

Expand Down
35 changes: 35 additions & 0 deletions registry/server/db/migrationSource.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import fs from 'node:fs';
import path from 'node:path';

import type { Knex } from 'knex';

export interface MigrationFile {
file: string;
directory: string;
}

/**
* Migration source that can load pre-compiled (.js) migrations from the build output.
* Migration names are always reported with the ".ts" extension to stay compatible
* with the records knex has already stored in the "knex_migrations" table.
*/
export class PrecompiledMigrationSource implements Knex.MigrationSource<MigrationFile> {
constructor(private readonly directory: string) {}

public async getMigrations(): Promise<MigrationFile[]> {
const files = await fs.promises.readdir(this.directory);

return files
.filter((file) => (file.endsWith('.js') || file.endsWith('.ts')) && !file.endsWith('.d.ts'))
.sort()
.map((file) => ({ file, directory: this.directory }));
}

public getMigrationName(migration: MigrationFile): string {
return migration.file.replace(/\.js$/, '.ts');
}

public getMigration(migration: MigrationFile): Promise<Knex.Migration> {
return Promise.resolve(require(path.resolve(migration.directory, migration.file)));
}
}
Loading